pyPhotoAlbum/tests/test_models.py
2025-11-11 16:02:02 +00:00

425 lines
15 KiB
Python

"""
Unit tests for pyPhotoAlbum models
"""
import pytest
from pyPhotoAlbum.models import ImageData, PlaceholderData, TextBoxData, BaseLayoutElement
class TestBaseLayoutElement:
"""Tests for BaseLayoutElement abstract class"""
def test_cannot_instantiate_abstract_class(self):
"""Test that BaseLayoutElement cannot be instantiated directly"""
with pytest.raises(TypeError):
BaseLayoutElement()
class TestImageData:
"""Tests for ImageData class"""
def test_initialization_default(self):
"""Test ImageData initialization with default values"""
img = ImageData()
assert img.image_path == ""
assert img.position == (0, 0)
assert img.size == (100, 100)
assert img.rotation == 0
assert img.z_index == 0
assert img.crop_info == (0, 0, 1, 1)
def test_initialization_with_parameters(self, temp_image_file):
"""Test ImageData initialization with custom parameters"""
img = ImageData(
image_path=temp_image_file,
x=10.0,
y=20.0,
width=200.0,
height=150.0,
rotation=45.0,
z_index=5
)
assert img.image_path == temp_image_file
assert img.position == (10.0, 20.0)
assert img.size == (200.0, 150.0)
assert img.rotation == 45.0
assert img.z_index == 5
def test_initialization_with_crop_info(self):
"""Test ImageData initialization with custom crop info"""
crop = (0.1, 0.2, 0.8, 0.9)
img = ImageData(image_path="test.jpg", crop_info=crop)
assert img.crop_info == crop
def test_serialization(self, temp_image_file):
"""Test ImageData serialization to dictionary"""
img = ImageData(
image_path=temp_image_file,
x=15.0,
y=25.0,
width=180.0,
height=120.0,
rotation=30.0,
z_index=3
)
data = img.serialize()
assert data["type"] == "image"
assert data["image_path"] == temp_image_file
assert data["position"] == (15.0, 25.0)
assert data["size"] == (180.0, 120.0)
assert data["rotation"] == 30.0
assert data["z_index"] == 3
assert data["crop_info"] == (0, 0, 1, 1)
def test_deserialization(self):
"""Test ImageData deserialization from dictionary"""
img = ImageData()
data = {
"position": (30.0, 40.0),
"size": (220.0, 180.0),
"rotation": 90.0,
"z_index": 7,
"image_path": "new_image.jpg",
"crop_info": (0.2, 0.3, 0.7, 0.8)
}
img.deserialize(data)
assert img.position == (30.0, 40.0)
assert img.size == (220.0, 180.0)
assert img.rotation == 90.0
assert img.z_index == 7
assert img.image_path == "new_image.jpg"
assert img.crop_info == (0.2, 0.3, 0.7, 0.8)
def test_deserialization_with_defaults(self):
"""Test ImageData deserialization with missing fields uses defaults"""
img = ImageData()
data = {"image_path": "test.jpg"}
img.deserialize(data)
assert img.position == (0, 0)
assert img.size == (100, 100)
assert img.rotation == 0
assert img.z_index == 0
assert img.crop_info == (0, 0, 1, 1)
def test_serialize_deserialize_roundtrip(self, temp_image_file):
"""Test that serialize and deserialize are inverse operations"""
original = ImageData(
image_path=temp_image_file,
x=50.0,
y=60.0,
width=300.0,
height=200.0,
rotation=15.0,
z_index=2,
crop_info=(0.1, 0.1, 0.9, 0.9)
)
data = original.serialize()
restored = ImageData()
restored.deserialize(data)
assert restored.image_path == original.image_path
assert restored.position == original.position
assert restored.size == original.size
assert restored.rotation == original.rotation
assert restored.z_index == original.z_index
assert restored.crop_info == original.crop_info
def test_position_modification(self):
"""Test modifying position after initialization"""
img = ImageData()
img.position = (100.0, 200.0)
assert img.position == (100.0, 200.0)
def test_size_modification(self):
"""Test modifying size after initialization"""
img = ImageData()
img.size = (400.0, 300.0)
assert img.size == (400.0, 300.0)
class TestPlaceholderData:
"""Tests for PlaceholderData class"""
def test_initialization_default(self):
"""Test PlaceholderData initialization with default values"""
placeholder = PlaceholderData()
assert placeholder.placeholder_type == "image"
assert placeholder.default_content == ""
assert placeholder.position == (0, 0)
assert placeholder.size == (100, 100)
assert placeholder.rotation == 0
assert placeholder.z_index == 0
def test_initialization_with_parameters(self):
"""Test PlaceholderData initialization with custom parameters"""
placeholder = PlaceholderData(
placeholder_type="text",
default_content="Sample",
x=20.0,
y=30.0,
width=150.0,
height=100.0,
rotation=10.0,
z_index=4
)
assert placeholder.placeholder_type == "text"
assert placeholder.default_content == "Sample"
assert placeholder.position == (20.0, 30.0)
assert placeholder.size == (150.0, 100.0)
assert placeholder.rotation == 10.0
assert placeholder.z_index == 4
def test_serialization(self):
"""Test PlaceholderData serialization to dictionary"""
placeholder = PlaceholderData(
placeholder_type="image",
default_content="placeholder.jpg",
x=40.0,
y=50.0,
width=200.0,
height=150.0,
rotation=20.0,
z_index=2
)
data = placeholder.serialize()
assert data["type"] == "placeholder"
assert data["placeholder_type"] == "image"
assert data["default_content"] == "placeholder.jpg"
assert data["position"] == (40.0, 50.0)
assert data["size"] == (200.0, 150.0)
assert data["rotation"] == 20.0
assert data["z_index"] == 2
def test_deserialization(self):
"""Test PlaceholderData deserialization from dictionary"""
placeholder = PlaceholderData()
data = {
"position": (60.0, 70.0),
"size": (250.0, 180.0),
"rotation": 45.0,
"z_index": 6,
"placeholder_type": "text",
"default_content": "Default Text"
}
placeholder.deserialize(data)
assert placeholder.position == (60.0, 70.0)
assert placeholder.size == (250.0, 180.0)
assert placeholder.rotation == 45.0
assert placeholder.z_index == 6
assert placeholder.placeholder_type == "text"
assert placeholder.default_content == "Default Text"
def test_deserialization_with_defaults(self):
"""Test PlaceholderData deserialization with missing fields uses defaults"""
placeholder = PlaceholderData()
data = {"placeholder_type": "image"}
placeholder.deserialize(data)
assert placeholder.position == (0, 0)
assert placeholder.size == (100, 100)
assert placeholder.rotation == 0
assert placeholder.z_index == 0
assert placeholder.default_content == ""
def test_serialize_deserialize_roundtrip(self):
"""Test that serialize and deserialize are inverse operations"""
original = PlaceholderData(
placeholder_type="image",
default_content="test.jpg",
x=80.0,
y=90.0,
width=300.0,
height=250.0,
rotation=60.0,
z_index=8
)
data = original.serialize()
restored = PlaceholderData()
restored.deserialize(data)
assert restored.placeholder_type == original.placeholder_type
assert restored.default_content == original.default_content
assert restored.position == original.position
assert restored.size == original.size
assert restored.rotation == original.rotation
assert restored.z_index == original.z_index
class TestTextBoxData:
"""Tests for TextBoxData class"""
def test_initialization_default(self):
"""Test TextBoxData initialization with default values"""
textbox = TextBoxData()
assert textbox.text_content == ""
assert textbox.font_settings == {"family": "Arial", "size": 12, "color": (0, 0, 0)}
assert textbox.alignment == "left"
assert textbox.position == (0, 0)
assert textbox.size == (100, 100)
assert textbox.rotation == 0
assert textbox.z_index == 0
def test_initialization_with_parameters(self):
"""Test TextBoxData initialization with custom parameters"""
font_settings = {"family": "Times", "size": 14, "color": (255, 0, 0)}
textbox = TextBoxData(
text_content="Hello World",
font_settings=font_settings,
alignment="center",
x=25.0,
y=35.0,
width=180.0,
height=60.0,
rotation=5.0,
z_index=3
)
assert textbox.text_content == "Hello World"
assert textbox.font_settings == font_settings
assert textbox.alignment == "center"
assert textbox.position == (25.0, 35.0)
assert textbox.size == (180.0, 60.0)
assert textbox.rotation == 5.0
assert textbox.z_index == 3
def test_serialization(self):
"""Test TextBoxData serialization to dictionary"""
font_settings = {"family": "Helvetica", "size": 16, "color": (0, 0, 255)}
textbox = TextBoxData(
text_content="Test Text",
font_settings=font_settings,
alignment="right",
x=45.0,
y=55.0,
width=220.0,
height=80.0,
rotation=15.0,
z_index=5
)
data = textbox.serialize()
assert data["type"] == "textbox"
assert data["text_content"] == "Test Text"
assert data["font_settings"] == font_settings
assert data["alignment"] == "right"
assert data["position"] == (45.0, 55.0)
assert data["size"] == (220.0, 80.0)
assert data["rotation"] == 15.0
assert data["z_index"] == 5
def test_deserialization(self):
"""Test TextBoxData deserialization from dictionary"""
textbox = TextBoxData()
font_settings = {"family": "Courier", "size": 18, "color": (128, 128, 128)}
data = {
"position": (65.0, 75.0),
"size": (260.0, 100.0),
"rotation": 30.0,
"z_index": 7,
"text_content": "Deserialized Text",
"font_settings": font_settings,
"alignment": "justify"
}
textbox.deserialize(data)
assert textbox.position == (65.0, 75.0)
assert textbox.size == (260.0, 100.0)
assert textbox.rotation == 30.0
assert textbox.z_index == 7
assert textbox.text_content == "Deserialized Text"
assert textbox.font_settings == font_settings
assert textbox.alignment == "justify"
def test_deserialization_with_defaults(self):
"""Test TextBoxData deserialization with missing fields uses defaults"""
textbox = TextBoxData()
data = {"text_content": "Minimal"}
textbox.deserialize(data)
assert textbox.position == (0, 0)
assert textbox.size == (100, 100)
assert textbox.rotation == 0
assert textbox.z_index == 0
assert textbox.font_settings == {"family": "Arial", "size": 12, "color": (0, 0, 0)}
assert textbox.alignment == "left"
def test_serialize_deserialize_roundtrip(self):
"""Test that serialize and deserialize are inverse operations"""
font_settings = {"family": "Georgia", "size": 20, "color": (255, 255, 0)}
original = TextBoxData(
text_content="Round Trip Test",
font_settings=font_settings,
alignment="center",
x=85.0,
y=95.0,
width=320.0,
height=120.0,
rotation=25.0,
z_index=9
)
data = original.serialize()
restored = TextBoxData()
restored.deserialize(data)
assert restored.text_content == original.text_content
assert restored.font_settings == original.font_settings
assert restored.alignment == original.alignment
assert restored.position == original.position
assert restored.size == original.size
assert restored.rotation == original.rotation
assert restored.z_index == original.z_index
def test_text_content_modification(self):
"""Test modifying text content after initialization"""
textbox = TextBoxData()
textbox.text_content = "Modified Text"
assert textbox.text_content == "Modified Text"
def test_font_settings_modification(self):
"""Test modifying font settings after initialization"""
textbox = TextBoxData()
new_font = {"family": "Verdana", "size": 24, "color": (100, 200, 50)}
textbox.font_settings = new_font
assert textbox.font_settings == new_font
def test_alignment_modification(self):
"""Test modifying alignment after initialization"""
textbox = TextBoxData()
textbox.alignment = "right"
assert textbox.alignment == "right"
class TestElementComparison:
"""Tests comparing different element types"""
def test_different_element_types_serialize_differently(self):
"""Test that different element types have different serialization"""
img = ImageData(x=10, y=10)
placeholder = PlaceholderData(x=10, y=10)
textbox = TextBoxData(x=10, y=10)
img_data = img.serialize()
placeholder_data = placeholder.serialize()
textbox_data = textbox.serialize()
assert img_data["type"] == "image"
assert placeholder_data["type"] == "placeholder"
assert textbox_data["type"] == "textbox"
def test_z_index_comparison(self):
"""Test that z_index can be used for layering"""
img1 = ImageData(z_index=1)
img2 = ImageData(z_index=5)
img3 = ImageData(z_index=3)
elements = [img1, img2, img3]
sorted_elements = sorted(elements, key=lambda e: e.z_index)
assert sorted_elements[0].z_index == 1
assert sorted_elements[1].z_index == 3
assert sorted_elements[2].z_index == 5