""" E2E tests for version differentiation between free and pro builds. These tests verify that Blender can recognize pro as an upgrade over free by checking that built packages have different version tuples and edition indicators. Tests informed by DEBUG investigation: - Root cause: Both versions have identical bl_info["version"] tuples: (1, 0, 0) - Both use same folder name: text_texture_generator/ - No edition indicator in bl_info["name"] - Result: Blender sees them as identical, not as an upgrade """ import ast import subprocess import tempfile import zipfile from pathlib import Path import pytest @pytest.fixture def build_artifacts(tmp_path): """Build both free and pro packages and return their paths.""" project_root = Path(__file__).parent.parent.parent # Run build script to create both packages result = subprocess.run( ["python", "scripts/build_addon.py", "--type", "all"], cwd=project_root, capture_output=True, text=True, timeout=30 ) if result.returncode != 0: pytest.fail(f"Build script failed: {result.stderr}") # Find the generated ZIP files in dist/ dist_dir = project_root / "dist" # Get version from git or default to 1.0.0 free_zip = None pro_zip = None for zip_file in dist_dir.glob("text_texture_generator_v*.zip"): if "_free.zip" in zip_file.name: free_zip = zip_file else: pro_zip = zip_file if not free_zip or not free_zip.exists(): pytest.fail(f"Free build not found in {dist_dir}") if not pro_zip or not pro_zip.exists(): pytest.fail(f"Pro build not found in {dist_dir}") yield { "free_zip": free_zip, "pro_zip": pro_zip, "extract_dir": tmp_path / "extracted" } # Note: Build artifacts are in dist/ - not cleaned up here # They may be needed for other tests or deployment def extract_bl_info(zip_path: Path, extract_dir: Path) -> dict: """Extract bl_info dictionary from addon package using ast.literal_eval().""" edition = "free" if "_free" in zip_path.name else "pro" extract_path = extract_dir / edition extract_path.mkdir(parents=True, exist_ok=True) with zipfile.ZipFile(zip_path, 'r') as zip_ref: zip_ref.extractall(extract_path) # Find __init__.py in the extracted addon init_file = extract_path / "text_texture_generator" / "__init__.py" if not init_file.exists(): pytest.fail(f"__init__.py not found in {zip_path.name}") # Parse bl_info using ast.literal_eval() (Blender's method) content = init_file.read_text() # Extract bl_info dictionary exactly as Blender does tree = ast.parse(content) for node in ast.walk(tree): if isinstance(node, ast.Assign): for target in node.targets: if isinstance(target, ast.Name) and target.id == "bl_info": return ast.literal_eval(node.value) pytest.fail(f"bl_info not found in {init_file}") def test_built_packages_have_different_version_tuples(build_artifacts): """ Test that free and pro builds have different version tuples. Blender identifies addons by (name, version) tuple. If both free and pro have the same version, Blender won't recognize pro as an upgrade. This test is informed by DEBUG investigation showing both versions have identical version tuples: (1, 0, 0), causing Blender to see them as the same addon rather than an upgrade path. Expected to FAIL because currently both are (1, 0, 0). """ free_bl_info = extract_bl_info( build_artifacts["free_zip"], build_artifacts["extract_dir"] ) pro_bl_info = extract_bl_info( build_artifacts["pro_zip"], build_artifacts["extract_dir"] ) free_version = free_bl_info["version"] pro_version = pro_bl_info["version"] assert free_version != pro_version, ( f"Free and Pro versions must have different version tuples for Blender " f"to recognize upgrade. Expected different, got both: {free_version}" ) def test_bl_info_name_includes_edition_indicator(build_artifacts): """ Test that bl_info names include edition indicators (Free/Pro). Users need to clearly see which edition they have installed in Blender's addon preferences. The bl_info["name"] should include "Free" or "Pro". This test is informed by DEBUG investigation showing both versions use the same name "Text Texture Generator" with no edition indicator, making it impossible for users to distinguish them in Blender's UI. Expected to FAIL because currently both just say "Text Texture Generator". """ free_bl_info = extract_bl_info( build_artifacts["free_zip"], build_artifacts["extract_dir"] ) pro_bl_info = extract_bl_info( build_artifacts["pro_zip"], build_artifacts["extract_dir"] ) free_name = free_bl_info["name"] pro_name = pro_bl_info["name"] # Assert Free version has edition indicator assert "Free" in free_name, ( f"bl_info name must indicate Free edition. " f"Expected 'Free' in name, got: '{free_name}'" ) # Assert Pro version has edition indicator assert "Pro" in pro_name, ( f"bl_info name must indicate Pro edition. " f"Expected 'Pro' in name, got: '{pro_name}'" ) # Assert they are different assert free_name != pro_name, ( f"bl_info name must indicate edition. " f"Free: '{free_name}', Pro: '{pro_name}'" )