#!/usr/bin/env python3 """ Blender Python script that runs INSIDE Blender to test texture generation. This script has NO mocks - it uses the real addon code with real bpy. CRITICAL: This test calls the ACTUAL Blender operator (bpy.ops.text_texture.generate_shader) because the bug is in the OPERATOR's truthiness check at generation_ops.py:241-247, not in the generate_texture_image() function itself. """ import sys import bpy def test_shader_creation_with_texture(): """ E2E test: Call the ACTUAL Blender operator to expose truthiness bug. BUG LOCATION: src/operators/generation_ops.py:241-247 ```python result = generate_texture_image(props, final_width, final_height) if not result: # ❌ BUG: (None, None) is TRUTHY in Python! self.report({'ERROR'}, "Failed to generate texture image") return {'CANCELLED'} ``` When generate_texture_image() returns (None, None): - `not result` evaluates to False (non-empty tuple is truthy) - Error check is bypassed - Code continues until line 263 where it tries to use None values This test MUST call bpy.ops.text_texture.generate_shader() (the operator) NOT generate_texture_image() (the function) to expose the bug. """ # Clean slate - remove default objects bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete() # Create a new cube (we need an object to attach material to) bpy.ops.mesh.primitive_cube_add() cube = bpy.context.active_object # Set up scene properties for texture generation props = bpy.context.scene.text_texture_props # Configure text using the actual property structure props.text = "böhm Kabel" props.append_text = "NYY" # Set dimensions (user-specified, not generated) props.texture_width = 4096 props.texture_height = 512 # Configure shader settings props.shader_type = 'PRINCIPLED' props.shader_connection = 'BASE_COLOR' props.auto_assign_material = True props.generate_normal_map = False props.background_transparent = True print(f"\nTest scenario:") print(f" Main text: {props.text}") print(f" Append text: {props.append_text}") print(f" Dimensions: {props.texture_width}x{props.texture_height}") print(f"\nCalling bpy.ops.text_texture.generate_shader()...") # CRITICAL: Call the OPERATOR (not the function!) # This is the REAL code path that users trigger from the UI try: result = bpy.ops.text_texture.generate_shader() print(f"Operator returned: {result}") except Exception as e: print(f"FAILURE: Operator raised exception: {e}") import traceback traceback.print_exc() sys.exit(1) # Assert 1: Operator should return {'FINISHED'} on success # Current bug: Will return {'CANCELLED'} because truthiness check at line 241 is wrong if result != {'FINISHED'}: print(f"FAILURE: Operator returned {result} instead of {{'FINISHED'}}") print(f"This confirms the truthiness bug at generation_ops.py:241-247") print(f"The check 'if not result:' fails when result is (None, None)") print(f"because non-empty tuples are truthy in Python!") sys.exit(1) # Assert 2: Material should be created # The material name is based on sanitized text materials = [m.name for m in bpy.data.materials] print(f"Available materials: {materials}") # Check for TextTexture_Mat prefix (the actual naming pattern used) material_found = any("TextTexture_Mat" in m for m in materials) if not material_found: print(f"FAILURE: No TextTexture_Mat material found") print(f"This indicates the operator failed to complete shader creation") sys.exit(1) # Assert 3: Texture image should be created images = [i.name for i in bpy.data.images] print(f"Available images: {images}") # Check for TextTexture prefix (the actual naming pattern used) image_found = any("TextTexture" in i for i in images) if not image_found: print(f"FAILURE: No TextTexture image found") print(f"This indicates generate_texture_image() returned None or (None, None)") sys.exit(1) # Get the actual image img = None for image in bpy.data.images: if "TextTexture" in image.name and "Normal" not in image.name: img = image break if not img: print(f"FAILURE: Could not retrieve texture image") sys.exit(1) # Assert 4: Verify dimensions actual_width = img.size[0] actual_height = img.size[1] if actual_width != 4096 or actual_height != 512: print(f"FAILURE: Wrong dimensions. Expected 4096x512, got {actual_width}x{actual_height}") sys.exit(1) # Assert 5: Material should be assigned to cube if not cube.data.materials or len(cube.data.materials) == 0: print(f"FAILURE: No material assigned to cube") sys.exit(1) # Success markers for test_addon_real_blender.py to detect print("SUCCESS: Texture generated successfully with correct dimensions and shader connected") print(f"SUCCESS: Texture '{img.name}' created with size {actual_width}x{actual_height}") print(f"SUCCESS: Shader nodes created and connected") sys.exit(0) if __name__ == "__main__": test_shader_creation_with_texture()