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

107 lines
4.8 KiB
Python

"""E2E test for bl_info parsing in built addon package."""
import ast
import zipfile
import subprocess
import tempfile
from pathlib import Path
def test_built_package_bl_info_is_parseable():
"""
CRITICAL E2E TEST: Validates that the built addon package has a parseable bl_info.
This test rebuilds the package, extracts it, and parses bl_info exactly as Blender does.
"""
project_root = Path(__file__).parent.parent.parent
# Step 1: Rebuild the package to ensure latest code
result = subprocess.run(
["python", "scripts/build_addon.py"],
cwd=project_root,
capture_output=True,
text=True
)
assert result.returncode == 0, f"Build failed: {result.stderr}"
# Step 2: Extract the built package
dist_zip = project_root / "dist" / "text_texture_generator_v1.0.0.zip"
assert dist_zip.exists(), f"Built package not found: {dist_zip}"
with tempfile.TemporaryDirectory() as tmpdir:
with zipfile.ZipFile(dist_zip, 'r') as z:
z.extractall(tmpdir)
init_file = Path(tmpdir) / "text_texture_generator" / "__init__.py"
assert init_file.exists(), f"__init__.py not found in package"
# Step 3: Read and parse exactly as Blender does
content = init_file.read_text()
tree = ast.parse(content)
bl_info_found = False
for node in tree.body:
if isinstance(node, ast.Assign):
for target in node.targets:
if isinstance(target, ast.Name) and target.id == 'bl_info':
bl_info_found = True
# This is THE critical test - ast.literal_eval() exactly as Blender uses
try:
parsed_bl_info = ast.literal_eval(node.value)
# Validate required keys
assert "name" in parsed_bl_info, "bl_info missing 'name'"
assert "author" in parsed_bl_info, "bl_info missing 'author'"
assert "version" in parsed_bl_info, "bl_info missing 'version'"
assert "blender" in parsed_bl_info, "bl_info missing 'blender'"
# Success!
print(f"\n✅ bl_info parsed successfully:")
print(f" name: {parsed_bl_info['name']}")
print(f" version: {parsed_bl_info['version']}")
except ValueError as e:
# Print diagnostic info before failing
print(f"\n❌ FAILED at line {node.lineno}")
print(f"Error: {e}")
print(f"\nProblematic AST node:")
print(ast.dump(node.value, indent=2))
print(f"\nFirst 30 lines of __init__.py:")
print('\n'.join(content.split('\n')[:30]))
raise AssertionError(f"bl_info failed ast.literal_eval() at line {node.lineno}: {e}")
assert bl_info_found, "bl_info not found in __init__.py"
def test_manifest_not_in_source():
"""Verify blender_manifest.toml is NOT in source directory (legacy mode)."""
manifest_path = Path(__file__).parent.parent.parent / "src" / "blender_manifest.toml"
assert not manifest_path.exists(), \
"blender_manifest.toml should not exist in src/ for legacy addon mode"
def test_manifest_not_in_built_package():
"""Verify blender_manifest.toml is NOT in built packages (both FREE and FULL)."""
project_root = Path(__file__).parent.parent.parent
# Check both FREE and FULL versions
zip_files = [
project_root / "dist" / "text_texture_generator_v1.0.0.zip", # FULL
project_root / "dist" / "text_texture_generator_v1.0.0_free.zip", # FREE
]
for zip_path in zip_files:
if not zip_path.exists():
continue # Skip if not built yet
with zipfile.ZipFile(zip_path, 'r') as z:
files = z.namelist()
manifest_files = [f for f in files if 'blender_manifest.toml' in f]
assert len(manifest_files) == 0, \
f"blender_manifest.toml should not be in {zip_path.name}. Found: {manifest_files}"
def test_manifest_template_not_exists():
"""Verify blender_manifest.toml.template doesn't exist (prevents regeneration)."""
template_path = Path(__file__).parent.parent.parent / "build" / "templates" / "blender_manifest.toml.template"
assert not template_path.exists(), \
"blender_manifest.toml.template should not exist to prevent automatic regeneration during builds"