Files
Text-Texture-Generator-for-…/tests/unit/test_version_differentiation.py
2025-10-10 14:41:18 +02:00

300 lines
16 KiB
Python

"""
Comprehensive tests for version differentiation in the Blender text texture generator addon.
Tests the quadruple-layer detection system:
1. Template-generated constants (VERSION_TYPE, is_free_version(), ENABLED_FEATURES)
2. Runtime import detection flags (PRESETS_AVAILABLE, UTILITY_OPERATORS_AVAILABLE)
3. Version limits (get_version_limits() returns correct values)
4. UI helper functions (version display and feature gating)
"""
import pytest
import sys
from unittest.mock import Mock, patch, MagicMock
from types import ModuleType
class TestVersionDetection:
"""Test suite for version detection methods."""
def test_version_type_constant(self):
"""Test VERSION_TYPE constant is properly set."""
from src.utils.constants import VERSION_TYPE
assert VERSION_TYPE in ["free", "full"], f"VERSION_TYPE should be 'free' or 'full', got '{VERSION_TYPE}'"
def test_is_free_version_function(self):
"""Test is_free_version() function returns correct boolean."""
from src.utils.constants import is_free_version, VERSION_TYPE
result = is_free_version()
assert isinstance(result, bool), "is_free_version() should return a boolean"
# Result should match VERSION_TYPE
expected = VERSION_TYPE == "free"
assert result == expected, f"is_free_version() returned {result}, expected {expected} based on VERSION_TYPE='{VERSION_TYPE}'"
def test_is_full_version_function(self):
"""Test is_full_version() function returns correct boolean."""
from src.utils.constants import is_full_version, VERSION_TYPE
result = is_full_version()
assert isinstance(result, bool), "is_full_version() should return a boolean"
# Result should match VERSION_TYPE
expected = VERSION_TYPE == "full"
assert result == expected, f"is_full_version() returned {result}, expected {expected} based on VERSION_TYPE='{VERSION_TYPE}'"
def test_enabled_features_list(self):
"""Test ENABLED_FEATURES contains appropriate features for version."""
from src.utils.constants import ENABLED_FEATURES, VERSION_TYPE
assert isinstance(ENABLED_FEATURES, list), "ENABLED_FEATURES should be a list"
assert len(ENABLED_FEATURES) > 0, "ENABLED_FEATURES should not be empty"
# Basic features should always be present
assert "basic" in ENABLED_FEATURES, "Basic features should always be enabled"
assert "preview" in ENABLED_FEATURES, "Preview features should always be enabled"
if VERSION_TYPE == "free":
# Free version should have limited features - only basic and preview
expected_free_features = ["basic", "preview"]
for feature in ENABLED_FEATURES:
assert feature in expected_free_features, f"Free version should only have basic features, found '{feature}'"
else:
# Full version should have additional features beyond basic and preview
assert len(ENABLED_FEATURES) > 2, "Full version should have more than just basic and preview features"
def test_get_version_limits_function(self):
"""Test get_version_limits() returns correct technical limits."""
from src.utils.constants import get_version_limits, VERSION_TYPE
limits = get_version_limits()
assert isinstance(limits, dict), "get_version_limits() should return a dictionary"
# Check required keys
required_keys = ["max_texture_size", "max_concurrent_operations"]
for key in required_keys:
assert key in limits, f"Missing required key '{key}' in version limits"
# Check value types
assert isinstance(limits["max_texture_size"], int), "max_texture_size should be an integer"
assert isinstance(limits["max_concurrent_operations"], int), "max_concurrent_operations should be an integer"
# Check version-specific limits
if VERSION_TYPE == "free":
assert limits["max_texture_size"] == 1024, f"Free version should have 1024px limit, got {limits['max_texture_size']}"
assert limits["max_concurrent_operations"] == 1, f"Free version should have 1 concurrent operation, got {limits['max_concurrent_operations']}"
else:
assert limits["max_texture_size"] == 4096, f"Full version should have 4096px limit, got {limits['max_texture_size']}"
assert limits["max_concurrent_operations"] == 4, f"Full version should have 4 concurrent operations, got {limits['max_concurrent_operations']}"
def test_get_version_limits_full_returns_pro_limits(self):
"""Verify full version returns correct limits for texture size and concurrent operations."""
from src.utils.constants import get_version_limits
from unittest.mock import patch
with patch('src.utils.constants.VERSION_TYPE', 'full'):
limits = get_version_limits()
assert limits["max_texture_size"] == 4096, \
f"Expected full version max_texture_size=4096, got {limits['max_texture_size']}"
assert limits["max_concurrent_operations"] == 4, \
f"Expected full version max_concurrent_operations=4, got {limits['max_concurrent_operations']}"
def test_get_version_limits_free_returns_restricted_limits(self):
"""Verify free version returns restricted limits for texture size and concurrent operations."""
from src.utils.constants import get_version_limits
from unittest.mock import patch
with patch('src.utils.constants.VERSION_TYPE', 'free'):
limits = get_version_limits()
assert limits["max_texture_size"] == 1024, \
f"Expected free version max_texture_size=1024, got {limits['max_texture_size']}"
assert limits["max_concurrent_operations"] == 1, \
f"Expected free version max_concurrent_operations=1, got {limits['max_concurrent_operations']}"
def test_has_text_fitting_returns_correct_value_per_version(self):
"""Test that has_text_fitting() returns correct value based on VERSION_TYPE."""
from src.utils.constants import has_text_fitting
from unittest.mock import patch
# Test free version - need to patch ENABLED_FEATURES since it's computed at import
with patch('src.utils.constants.VERSION_TYPE', 'free'), \
patch('src.utils.constants.ENABLED_FEATURES', ['basic', 'preview']):
assert has_text_fitting() is False
# Test full version - need to patch ENABLED_FEATURES since it's computed at import
with patch('src.utils.constants.VERSION_TYPE', 'full'), \
patch('src.utils.constants.ENABLED_FEATURES', ['basic', 'preview', 'text_fitting']):
assert has_text_fitting() is True
class TestRuntimeImportDetection:
"""Test suite for runtime import detection flags."""
def test_presets_available_flag(self):
"""Test PRESETS_AVAILABLE flag is properly set based on import success."""
from src import PRESETS_AVAILABLE
assert isinstance(PRESETS_AVAILABLE, bool), "PRESETS_AVAILABLE should be a boolean"
def test_utility_operators_available_flag(self):
"""Test UTILITY_OPERATORS_AVAILABLE flag is properly set based on import success."""
from src import UTILITY_OPERATORS_AVAILABLE
assert isinstance(UTILITY_OPERATORS_AVAILABLE, bool), "UTILITY_OPERATORS_AVAILABLE should be a boolean"
class TestFeatureAvailability:
"""Test suite for feature availability and gating."""
def test_feature_gating_based_on_version(self):
"""Test that features are properly gated based on version type."""
from src.utils.constants import is_free_version, ENABLED_FEATURES
if is_free_version():
# Free version should only have basic and preview features
expected_features = ["basic", "preview"]
assert set(ENABLED_FEATURES) == set(expected_features), f"Free version should only have {expected_features}"
else:
# Full version should have more features
assert len(ENABLED_FEATURES) > 2, "Full version should have more than just basic features"
assert "basic" in ENABLED_FEATURES, "Full version should include basic features"
assert "preview" in ENABLED_FEATURES, "Full version should include preview features"
def test_runtime_import_detection_flags_exist(self):
"""Test that runtime import detection flags exist."""
try:
from src import PRESETS_AVAILABLE, UTILITY_OPERATORS_AVAILABLE
assert isinstance(PRESETS_AVAILABLE, bool), "PRESETS_AVAILABLE should be a boolean"
assert isinstance(UTILITY_OPERATORS_AVAILABLE, bool), "UTILITY_OPERATORS_AVAILABLE should be a boolean"
except ImportError as e:
pytest.fail(f"Runtime detection flags should be available: {e}")
class TestUIComponents:
"""Test suite for UI component version display."""
def test_get_version_badge_text(self):
"""Test get_version_badge_text() returns appropriate badge text."""
from src.utils.constants import get_version_badge_text, is_free_version
badge_text = get_version_badge_text()
assert isinstance(badge_text, str), "get_version_badge_text() should return a string"
assert len(badge_text) > 0, "Badge text should not be empty"
if is_free_version():
assert "FREE" in badge_text.upper(), "Free version badge should contain 'FREE'"
else:
assert "PRO" in badge_text.upper() or "FULL" in badge_text.upper(), "Full version badge should contain 'PRO' or 'FULL'"
def test_should_show_feature_lock(self):
"""Test should_show_feature_lock() returns correct values for features."""
from src.utils.constants import should_show_feature_lock, is_free_version
# Test premium features from the actual implementation
premium_features = ["presets", "utility_operators", "image_overlays", "batch_processing", "advanced_positioning"]
for feature in premium_features:
result = should_show_feature_lock(feature)
assert isinstance(result, bool), f"should_show_feature_lock('{feature}') should return boolean"
if is_free_version():
assert result == True, f"Feature lock should be shown for '{feature}' in free version"
else:
assert result == False, f"Feature lock should not be shown for '{feature}' in full version"
def test_get_upgrade_hint_text(self):
"""Test get_upgrade_hint_text() returns appropriate upgrade messages."""
from src.utils.constants import get_upgrade_hint_text, is_free_version
# The function requires a feature_name parameter
feature_name = "Test Feature"
hint_text = get_upgrade_hint_text(feature_name)
assert isinstance(hint_text, str), "get_upgrade_hint_text() should return a string"
if is_free_version():
assert len(hint_text) > 0, "Free version should have upgrade hint text"
assert feature_name in hint_text, "Upgrade hint should mention the feature name"
assert "Pro" in hint_text, "Upgrade hint should mention Pro version"
else:
assert len(hint_text) == 0, "Full version should have empty upgrade hint text"
def test_get_version_info_details(self):
"""Test get_version_info_details() returns comprehensive version information."""
from src.utils.constants import get_version_info_details, is_free_version, get_version_limits
info_details = get_version_info_details()
assert isinstance(info_details, dict), "get_version_info_details() should return a dictionary"
assert len(info_details) > 0, "Version info details should not be empty"
class TestIntegrationScenarios:
"""Test suite for cross-system integration validation."""
def test_template_and_runtime_consistency(self):
"""Test that template-generated constants and runtime flags are consistent."""
from src.utils.constants import is_free_version, ENABLED_FEATURES
from src import PRESETS_AVAILABLE, UTILITY_OPERATORS_AVAILABLE
# In a properly built system, runtime availability should align with template configuration
if is_free_version():
# Free version should have limited features in template
expected_features = ["basic", "preview"]
assert set(ENABLED_FEATURES) == set(expected_features), f"Template should only enable basic features in free version, got {ENABLED_FEATURES}"
else:
# Full version should have more features enabled in template
assert len(ENABLED_FEATURES) > 2, "Template should enable more features in full version"
assert "basic" in ENABLED_FEATURES, "Template should enable basic features in full version"
assert "preview" in ENABLED_FEATURES, "Template should enable preview features in full version"
def test_mock_operators_dont_crash(self):
"""Test that mock operators are properly implemented and don't crash."""
# This test ensures that when premium features are missing,
# the system gracefully handles it with mock implementations
# Test that we can import the main module without crashes
try:
import src
assert True, "Main module import should not crash"
except Exception as e:
pytest.fail(f"Main module import crashed: {e}")
# Test that runtime flags are properly set
assert hasattr(src, 'PRESETS_AVAILABLE'), "Runtime should set PRESETS_AVAILABLE flag"
assert hasattr(src, 'UTILITY_OPERATORS_AVAILABLE'), "Runtime should set UTILITY_OPERATORS_AVAILABLE flag"
class TestVersionDifferentiationScenarios:
"""Test specific free vs full version difference scenarios."""
def test_free_version_complete_scenario(self):
"""Test complete free version scenario with all restrictions."""
from src.utils.constants import is_free_version, get_version_limits, ENABLED_FEATURES
if is_free_version():
# Feature restrictions - free version should only have basic features
expected_features = ["basic", "preview"]
assert set(ENABLED_FEATURES) == set(expected_features), f"Free version should only have {expected_features}"
# Technical limitations
limits = get_version_limits()
assert limits["max_texture_size"] == 1024, "Should have 1024px texture limit"
assert limits["max_concurrent_operations"] == 1, "Should have 1 concurrent operation limit"
def test_full_version_complete_scenario(self):
"""Test complete full version scenario with all features enabled."""
from src.utils.constants import is_free_version, is_full_version, get_version_limits, ENABLED_FEATURES
if not is_free_version():
# Version detection
assert is_full_version() == True, "Should detect full version"
# Full version should have more features than free
assert len(ENABLED_FEATURES) > 2, "Full version should have more than just basic features"
assert "basic" in ENABLED_FEATURES, "Full version should include basic features"
assert "preview" in ENABLED_FEATURES, "Full version should include preview features"
# Generous technical limits
limits = get_version_limits()
assert limits["max_texture_size"] == 4096, "Should have 4096px texture limit"
assert limits["max_concurrent_operations"] == 4, "Should have 4 concurrent operations limit"