- Implements core ORA reading/writing functions - Layer add, rename, delete, reorder, visibility operations - Full test suite with 8 passing tests
357 lines
11 KiB
Python
357 lines
11 KiB
Python
#!/usr/bin/env python3
|
|
"""Tests for ora_ops module."""
|
|
|
|
import io
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
import zipfile
|
|
from pathlib import Path
|
|
|
|
from PIL import Image
|
|
|
|
# Add parent directory to path
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
from ora_editor.ora_ops import (
|
|
load_ora, create_ora_from_png, add_masked_layer, rename_layer,
|
|
delete_layer, reorder_layer, get_layer_visibility, set_layer_visibility,
|
|
save_ora, parse_stack_xml, get_image_size, get_groups_and_layers
|
|
)
|
|
|
|
|
|
def test_create_ora_from_png():
|
|
"""Test creating an ORA from a PNG file."""
|
|
# Create a simple test PNG
|
|
test_img = Image.new('RGBA', (100, 100), (255, 0, 0, 255))
|
|
|
|
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
|
|
test_img.save(png_f.name)
|
|
png_path = png_f.name
|
|
|
|
with tempfile.NamedTemporaryFile(suffix='.ora', delete=False) as ora_f:
|
|
ora_path = ora_f.name
|
|
|
|
try:
|
|
result = create_ora_from_png(png_path, ora_path)
|
|
|
|
assert result['success'], f"Failed to create ORA: {result.get('error')}"
|
|
assert os.path.exists(ora_path), "ORA file was not created"
|
|
|
|
# Verify we can load it back
|
|
loaded = load_ora(ora_path)
|
|
assert 'layers' in loaded, "Loaded ORA has no layers"
|
|
assert len(loaded['layers']) == 1, f"Expected 1 layer, got {len(loaded['layers'])}"
|
|
|
|
print("✓ create_ora_from_png passed")
|
|
return True
|
|
finally:
|
|
os.unlink(png_path)
|
|
if os.path.exists(ora_path):
|
|
os.unlink(ora_path)
|
|
|
|
|
|
def test_load_ora():
|
|
"""Test loading an existing ORA file."""
|
|
with tempfile.NamedTemporaryFile(suffix='.ora', delete=False) as ora_f:
|
|
ora_path = ora_f.name
|
|
|
|
try:
|
|
# Create a test PNG first
|
|
test_img = Image.new('RGBA', (200, 150), (0, 255, 0, 255))
|
|
|
|
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
|
|
test_img.save(png_f.name)
|
|
png_path = png_f.name
|
|
|
|
try:
|
|
create_ora_from_png(png_path, ora_path)
|
|
|
|
loaded = load_ora(ora_path)
|
|
|
|
assert loaded['width'] == 200, f"Expected width 200, got {loaded['width']}"
|
|
assert loaded['height'] == 150, f"Expected height 150, got {loaded['height']}"
|
|
assert len(loaded['layers']) > 0, "No layers found in ORA"
|
|
|
|
print("✓ load_ora passed")
|
|
return True
|
|
finally:
|
|
os.unlink(png_path)
|
|
finally:
|
|
if os.path.exists(ora_path):
|
|
os.unlink(ora_path)
|
|
|
|
|
|
def test_add_masked_layer():
|
|
"""Test adding a masked layer to an ORA."""
|
|
# Create base PNG
|
|
base_img = Image.new('RGBA', (100, 100), (255, 0, 0, 255))
|
|
|
|
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
|
|
base_img.save(png_f.name)
|
|
png_path = png_f.name
|
|
|
|
ora_path = png_path.replace('.png', '.ora')
|
|
|
|
# Create mask (white where visible, black where transparent)
|
|
mask_img = Image.new('L', (100, 100), 255)
|
|
|
|
with tempfile.NamedTemporaryFile(suffix='.mask.png', delete=False) as mask_f:
|
|
mask_img.save(mask_f.name)
|
|
mask_path = mask_f.name
|
|
|
|
try:
|
|
result = add_masked_layer(ora_path, 'door', mask_path)
|
|
|
|
assert result['success'], f"Failed to add masked layer: {result.get('error')}"
|
|
assert 'layer_name' in result, "No layer_name in result"
|
|
assert result['layer_name'] == 'door_0', f"Expected door_0, got {result['layer_name']}"
|
|
|
|
# Verify the layer was added
|
|
loaded = load_ora(ora_path)
|
|
layer_names = [l['name'] for l in loaded['layers']]
|
|
assert 'base' in layer_names, "Base layer missing"
|
|
assert 'door_0' in layer_names, "Door layer not found"
|
|
|
|
print("✓ add_masked_layer passed")
|
|
return True
|
|
finally:
|
|
os.unlink(png_path)
|
|
if os.path.exists(ora_path):
|
|
os.unlink(ora_path)
|
|
os.unlink(mask_path)
|
|
|
|
|
|
def test_rename_layer():
|
|
"""Test renaming a layer."""
|
|
# Create base PNG
|
|
base_img = Image.new('RGBA', (100, 100), (255, 0, 0, 255))
|
|
|
|
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
|
|
base_img.save(png_f.name)
|
|
png_path = png_f.name
|
|
|
|
ora_path = png_path.replace('.png', '.ora')
|
|
|
|
# Create mask for a new layer
|
|
mask_img = Image.new('L', (100, 100), 255)
|
|
with tempfile.NamedTemporaryFile(suffix='.mask.png', delete=False) as mask_f:
|
|
mask_img.save(mask_f.name)
|
|
mask_path = mask_f.name
|
|
|
|
try:
|
|
# First add a layer to rename
|
|
result = add_masked_layer(ora_path, 'door', mask_path)
|
|
assert result['success']
|
|
|
|
# Now rename it
|
|
result = rename_layer(ora_path, 'door_0', 'wooden_door_0')
|
|
|
|
assert result['success'], f"Failed to rename: {result.get('error')}"
|
|
|
|
loaded = load_ora(ora_path)
|
|
layer_names = [l['name'] for l in loaded['layers']]
|
|
assert 'wooden_door_0' in layer_names, "Renamed layer not found"
|
|
assert 'door_0' not in layer_names, "Old layer name still exists"
|
|
|
|
print("✓ rename_layer passed")
|
|
return True
|
|
finally:
|
|
os.unlink(png_path)
|
|
if os.path.exists(ora_path):
|
|
os.unlink(ora_path)
|
|
os.unlink(mask_path)
|
|
|
|
|
|
def test_delete_layer():
|
|
"""Test deleting a layer."""
|
|
# Create base PNG
|
|
base_img = Image.new('RGBA', (100, 100), (255, 0, 0, 255))
|
|
|
|
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
|
|
base_img.save(png_f.name)
|
|
png_path = png_f.name
|
|
|
|
ora_path = png_path.replace('.png', '.ora')
|
|
|
|
# Create mask for a new layer
|
|
mask_img = Image.new('L', (100, 100), 255)
|
|
with tempfile.NamedTemporaryFile(suffix='.mask.png', delete=False) as mask_f:
|
|
mask_img.save(mask_f.name)
|
|
mask_path = mask_f.name
|
|
|
|
try:
|
|
# First add a layer to delete
|
|
result = add_masked_layer(ora_path, 'door', mask_path)
|
|
assert result['success']
|
|
|
|
# Now delete it
|
|
result = delete_layer(ora_path, 'door_0')
|
|
|
|
assert result['success'], f"Failed to delete: {result.get('error')}"
|
|
|
|
loaded = load_ora(ora_path)
|
|
layer_names = [l['name'] for l in loaded['layers']]
|
|
assert 'door_0' not in layer_names, "Deleted layer still exists"
|
|
|
|
print("✓ delete_layer passed")
|
|
return True
|
|
finally:
|
|
os.unlink(png_path)
|
|
if os.path.exists(ora_path):
|
|
os.unlink(ora_path)
|
|
os.unlink(mask_path)
|
|
|
|
|
|
def test_reorder_layer():
|
|
"""Test reordering layers."""
|
|
# Create base PNG
|
|
base_img = Image.new('RGBA', (100, 100), (255, 0, 0, 255))
|
|
|
|
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
|
|
base_img.save(png_f.name)
|
|
png_path = png_f.name
|
|
|
|
ora_path = png_path.replace('.png', '.ora')
|
|
|
|
# Create mask for new layers
|
|
mask_img = Image.new('L', (100, 100), 255)
|
|
|
|
layer_paths = []
|
|
for i in range(3):
|
|
with tempfile.NamedTemporaryFile(suffix='.mask.png', delete=False) as mask_f:
|
|
mask_img.save(mask_f.name)
|
|
layer_paths.append(mask_f.name)
|
|
|
|
try:
|
|
# Add multiple layers
|
|
for i, mask_path in enumerate(layer_paths):
|
|
result = add_masked_layer(ora_path, f'layer{i}', mask_path)
|
|
assert result['success'], f"Failed to add layer {i}"
|
|
|
|
# Get initial order
|
|
loaded = load_ora(ora_path)
|
|
initial_order = [l['name'] for l in loaded['layers']]
|
|
|
|
# Move layer0_0 down (it should stay or move one position)
|
|
result = reorder_layer(ora_path, 'layer0_0', 'down')
|
|
assert result['success'], f"Failed to reorder: {result.get('error')}"
|
|
|
|
loaded = load_ora(ora_path)
|
|
new_order = [l['name'] for l in loaded['layers']]
|
|
|
|
# Verify order changed or stayed valid
|
|
assert len(new_order) == len(initial_order), "Layer count changed during reorder"
|
|
|
|
print("✓ reorder_layer passed")
|
|
return True
|
|
finally:
|
|
os.unlink(png_path)
|
|
if os.path.exists(ora_path):
|
|
os.unlink(ora_path)
|
|
for path in layer_paths:
|
|
os.unlink(path)
|
|
|
|
|
|
def test_set_layer_visibility():
|
|
"""Test setting layer visibility."""
|
|
base_img = Image.new('RGBA', (100, 100), (255, 0, 0, 255))
|
|
|
|
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
|
|
base_img.save(png_f.name)
|
|
png_path = png_f.name
|
|
|
|
ora_path = png_path.replace('.png', '.ora')
|
|
|
|
mask_img = Image.new('L', (100, 100), 255)
|
|
with tempfile.NamedTemporaryFile(suffix='.mask.png', delete=False) as mask_f:
|
|
mask_img.save(mask_f.name)
|
|
mask_path = mask_f.name
|
|
|
|
try:
|
|
add_masked_layer(ora_path, 'door', mask_path)
|
|
|
|
# Set visibility to false
|
|
result = set_layer_visibility(ora_path, 'door_0', False)
|
|
assert result['success'], f"Failed to set visibility: {result.get('error')}"
|
|
|
|
visible = get_layer_visibility(ora_path, 'door_0')
|
|
assert visible is False, "Layer should be hidden"
|
|
|
|
# Set visibility back to true
|
|
result = set_layer_visibility(ora_path, 'door_0', True)
|
|
assert result['success']
|
|
|
|
visible = get_layer_visibility(ora_path, 'door_0')
|
|
assert visible is True, "Layer should be visible"
|
|
|
|
print("✓ set_layer_visibility passed")
|
|
return True
|
|
finally:
|
|
os.unlink(png_path)
|
|
if os.path.exists(ora_path):
|
|
os.unlink(ora_path)
|
|
os.unlink(mask_path)
|
|
|
|
|
|
def test_save_ora():
|
|
"""Test saving an ORA file."""
|
|
base_img = Image.new('RGBA', (100, 100), (255, 0, 0, 255))
|
|
|
|
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
|
|
base_img.save(png_f.name)
|
|
png_path = png_f.name
|
|
|
|
ora_path = png_path.replace('.png', '.ora')
|
|
|
|
try:
|
|
create_ora_from_png(png_path, ora_path)
|
|
|
|
# Save should work without errors
|
|
result = save_ora(ora_path)
|
|
assert result, "Failed to save ORA"
|
|
|
|
# Verify we can still load it
|
|
loaded = load_ora(ora_path)
|
|
assert len(loaded['layers']) > 0, "Layers missing after save"
|
|
|
|
print("✓ save_ora passed")
|
|
return True
|
|
finally:
|
|
os.unlink(png_path)
|
|
if os.path.exists(ora_path):
|
|
os.unlink(ora_path)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
tests = [
|
|
test_create_ora_from_png,
|
|
test_load_ora,
|
|
test_add_masked_layer,
|
|
test_rename_layer,
|
|
test_delete_layer,
|
|
test_reorder_layer,
|
|
test_set_layer_visibility,
|
|
test_save_ora,
|
|
]
|
|
|
|
passed = 0
|
|
failed = 0
|
|
|
|
for test in tests:
|
|
try:
|
|
if test():
|
|
passed += 1
|
|
else:
|
|
failed += 1
|
|
except Exception as e:
|
|
print(f"✗ {test.__name__} failed with exception: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
failed += 1
|
|
|
|
print(f"\n{passed}/{len(tests)} tests passed")
|
|
|
|
if failed > 0:
|
|
sys.exit(1)
|