All checks were successful
Python CI / test (push) Successful in 1m44s
Lint / lint (push) Successful in 1m29s
Tests / test (3.11) (push) Successful in 1m49s
Tests / test (3.12) (push) Successful in 1m52s
Tests / test (3.13) (push) Successful in 1m45s
Tests / test (3.14) (push) Successful in 1m28s
Improved pdf generation speed
408 lines
14 KiB
Python
408 lines
14 KiB
Python
"""
|
|
Unit tests for ImageStyle class and related styling functionality
|
|
"""
|
|
|
|
import pytest
|
|
from pyPhotoAlbum.models import ImageStyle, ImageData, PlaceholderData
|
|
|
|
|
|
class TestImageStyleInit:
|
|
"""Tests for ImageStyle initialization"""
|
|
|
|
def test_default_initialization(self):
|
|
"""Test ImageStyle with default values"""
|
|
style = ImageStyle()
|
|
assert style.corner_radius == 0.0
|
|
assert style.border_width == 0.0
|
|
assert style.border_color == (0, 0, 0)
|
|
assert style.shadow_enabled is False
|
|
assert style.shadow_offset == (2.0, 2.0)
|
|
assert style.shadow_blur == 3.0
|
|
assert style.shadow_color == (0, 0, 0, 128)
|
|
assert style.frame_style is None
|
|
assert style.frame_color == (0, 0, 0)
|
|
assert style.frame_corners == (True, True, True, True)
|
|
|
|
def test_custom_initialization(self):
|
|
"""Test ImageStyle with custom values"""
|
|
style = ImageStyle(
|
|
corner_radius=15.0,
|
|
border_width=2.5,
|
|
border_color=(255, 0, 0),
|
|
shadow_enabled=True,
|
|
shadow_offset=(3.0, 4.0),
|
|
shadow_blur=5.0,
|
|
shadow_color=(0, 0, 0, 200),
|
|
frame_style="leafy_corners",
|
|
frame_color=(0, 128, 0),
|
|
frame_corners=(True, False, True, False),
|
|
)
|
|
assert style.corner_radius == 15.0
|
|
assert style.border_width == 2.5
|
|
assert style.border_color == (255, 0, 0)
|
|
assert style.shadow_enabled is True
|
|
assert style.shadow_offset == (3.0, 4.0)
|
|
assert style.shadow_blur == 5.0
|
|
assert style.shadow_color == (0, 0, 0, 200)
|
|
assert style.frame_style == "leafy_corners"
|
|
assert style.frame_color == (0, 128, 0)
|
|
assert style.frame_corners == (True, False, True, False)
|
|
|
|
def test_frame_corners_none_defaults_to_all(self):
|
|
"""Test that frame_corners=None defaults to all corners"""
|
|
style = ImageStyle(frame_corners=None)
|
|
assert style.frame_corners == (True, True, True, True)
|
|
|
|
|
|
class TestImageStyleCopy:
|
|
"""Tests for ImageStyle.copy()"""
|
|
|
|
def test_copy_creates_identical_style(self):
|
|
"""Test that copy creates an identical style"""
|
|
original = ImageStyle(
|
|
corner_radius=10.0,
|
|
border_width=1.5,
|
|
border_color=(128, 128, 128),
|
|
shadow_enabled=True,
|
|
frame_style="simple_line",
|
|
frame_corners=(True, True, False, False),
|
|
)
|
|
copied = original.copy()
|
|
|
|
assert copied.corner_radius == original.corner_radius
|
|
assert copied.border_width == original.border_width
|
|
assert copied.border_color == original.border_color
|
|
assert copied.shadow_enabled == original.shadow_enabled
|
|
assert copied.frame_style == original.frame_style
|
|
assert copied.frame_corners == original.frame_corners
|
|
|
|
def test_copy_is_independent(self):
|
|
"""Test that modifying copy doesn't affect original"""
|
|
original = ImageStyle(corner_radius=5.0)
|
|
copied = original.copy()
|
|
copied.corner_radius = 20.0
|
|
|
|
assert original.corner_radius == 5.0
|
|
assert copied.corner_radius == 20.0
|
|
|
|
|
|
class TestImageStyleHasStyling:
|
|
"""Tests for ImageStyle.has_styling()"""
|
|
|
|
def test_default_style_has_no_styling(self):
|
|
"""Test that default style has no styling"""
|
|
style = ImageStyle()
|
|
assert style.has_styling() is False
|
|
|
|
def test_corner_radius_counts_as_styling(self):
|
|
"""Test that corner_radius > 0 counts as styling"""
|
|
style = ImageStyle(corner_radius=5.0)
|
|
assert style.has_styling() is True
|
|
|
|
def test_border_width_counts_as_styling(self):
|
|
"""Test that border_width > 0 counts as styling"""
|
|
style = ImageStyle(border_width=1.0)
|
|
assert style.has_styling() is True
|
|
|
|
def test_shadow_enabled_counts_as_styling(self):
|
|
"""Test that shadow_enabled counts as styling"""
|
|
style = ImageStyle(shadow_enabled=True)
|
|
assert style.has_styling() is True
|
|
|
|
def test_frame_style_counts_as_styling(self):
|
|
"""Test that frame_style counts as styling"""
|
|
style = ImageStyle(frame_style="simple_line")
|
|
assert style.has_styling() is True
|
|
|
|
|
|
class TestImageStyleSerialization:
|
|
"""Tests for ImageStyle.serialize() and deserialize()"""
|
|
|
|
def test_serialize_default_style(self):
|
|
"""Test serialization of default style"""
|
|
style = ImageStyle()
|
|
data = style.serialize()
|
|
|
|
assert data["corner_radius"] == 0.0
|
|
assert data["border_width"] == 0.0
|
|
assert data["border_color"] == [0, 0, 0]
|
|
assert data["shadow_enabled"] is False
|
|
assert data["frame_style"] is None
|
|
assert data["frame_corners"] == [True, True, True, True]
|
|
|
|
def test_serialize_custom_style(self):
|
|
"""Test serialization of custom style"""
|
|
style = ImageStyle(
|
|
corner_radius=10.0,
|
|
border_color=(255, 128, 0),
|
|
frame_style="ornate_flourish",
|
|
frame_corners=(False, True, False, True),
|
|
)
|
|
data = style.serialize()
|
|
|
|
assert data["corner_radius"] == 10.0
|
|
assert data["border_color"] == [255, 128, 0]
|
|
assert data["frame_style"] == "ornate_flourish"
|
|
assert data["frame_corners"] == [False, True, False, True]
|
|
|
|
def test_deserialize_creates_correct_style(self):
|
|
"""Test deserialization creates correct style"""
|
|
data = {
|
|
"corner_radius": 15.0,
|
|
"border_width": 2.0,
|
|
"border_color": [100, 100, 100],
|
|
"shadow_enabled": True,
|
|
"shadow_offset": [3.0, 3.0],
|
|
"shadow_blur": 4.0,
|
|
"shadow_color": [0, 0, 0, 150],
|
|
"frame_style": "leafy_corners",
|
|
"frame_color": [50, 50, 50],
|
|
"frame_corners": [True, False, True, False],
|
|
}
|
|
style = ImageStyle.deserialize(data)
|
|
|
|
assert style.corner_radius == 15.0
|
|
assert style.border_width == 2.0
|
|
assert style.border_color == (100, 100, 100)
|
|
assert style.shadow_enabled is True
|
|
assert style.shadow_offset == (3.0, 3.0)
|
|
assert style.shadow_blur == 4.0
|
|
assert style.shadow_color == (0, 0, 0, 150)
|
|
assert style.frame_style == "leafy_corners"
|
|
assert style.frame_color == (50, 50, 50)
|
|
assert style.frame_corners == (True, False, True, False)
|
|
|
|
def test_deserialize_none_returns_default(self):
|
|
"""Test that deserialize(None) returns default style"""
|
|
style = ImageStyle.deserialize(None)
|
|
assert style.corner_radius == 0.0
|
|
assert style.frame_style is None
|
|
|
|
def test_deserialize_empty_dict_returns_defaults(self):
|
|
"""Test that deserialize({}) returns default values"""
|
|
style = ImageStyle.deserialize({})
|
|
assert style.corner_radius == 0.0
|
|
assert style.border_width == 0.0
|
|
assert style.frame_style is None
|
|
assert style.frame_corners == (True, True, True, True)
|
|
|
|
def test_serialize_deserialize_roundtrip(self):
|
|
"""Test that serialize/deserialize are inverse operations"""
|
|
original = ImageStyle(
|
|
corner_radius=12.0,
|
|
border_width=1.5,
|
|
border_color=(200, 100, 50),
|
|
shadow_enabled=True,
|
|
shadow_offset=(2.5, 3.5),
|
|
shadow_blur=6.0,
|
|
shadow_color=(10, 20, 30, 180),
|
|
frame_style="victorian",
|
|
frame_color=(100, 150, 200),
|
|
frame_corners=(True, True, False, False),
|
|
)
|
|
|
|
data = original.serialize()
|
|
restored = ImageStyle.deserialize(data)
|
|
|
|
assert restored == original
|
|
|
|
def test_deserialize_handles_missing_frame_corners(self):
|
|
"""Test backward compatibility - missing frame_corners defaults correctly"""
|
|
data = {
|
|
"corner_radius": 5.0,
|
|
"border_width": 1.0,
|
|
"border_color": [0, 0, 0],
|
|
# No frame_corners key
|
|
}
|
|
style = ImageStyle.deserialize(data)
|
|
assert style.frame_corners == (True, True, True, True)
|
|
|
|
|
|
class TestImageStyleEquality:
|
|
"""Tests for ImageStyle.__eq__()"""
|
|
|
|
def test_identical_styles_are_equal(self):
|
|
"""Test that identical styles are equal"""
|
|
style1 = ImageStyle(corner_radius=10.0, frame_style="simple_line")
|
|
style2 = ImageStyle(corner_radius=10.0, frame_style="simple_line")
|
|
assert style1 == style2
|
|
|
|
def test_different_styles_are_not_equal(self):
|
|
"""Test that different styles are not equal"""
|
|
style1 = ImageStyle(corner_radius=10.0)
|
|
style2 = ImageStyle(corner_radius=20.0)
|
|
assert style1 != style2
|
|
|
|
def test_different_frame_corners_are_not_equal(self):
|
|
"""Test that different frame_corners make styles unequal"""
|
|
style1 = ImageStyle(frame_corners=(True, True, True, True))
|
|
style2 = ImageStyle(frame_corners=(True, False, True, False))
|
|
assert style1 != style2
|
|
|
|
def test_style_not_equal_to_non_style(self):
|
|
"""Test that style is not equal to non-style objects"""
|
|
style = ImageStyle()
|
|
assert style != "not a style"
|
|
assert style != 123
|
|
assert style != None
|
|
|
|
|
|
class TestImageDataWithStyle:
|
|
"""Tests for ImageData with styling"""
|
|
|
|
def test_image_data_has_default_style(self):
|
|
"""Test that ImageData has a default style"""
|
|
img = ImageData()
|
|
assert hasattr(img, "style")
|
|
assert isinstance(img.style, ImageStyle)
|
|
assert img.style.corner_radius == 0.0
|
|
|
|
def test_image_data_serialize_includes_style(self):
|
|
"""Test that ImageData serialization includes style"""
|
|
img = ImageData()
|
|
img.style.corner_radius = 15.0
|
|
img.style.frame_style = "ornate_flourish"
|
|
img.style.frame_corners = (True, False, False, True)
|
|
|
|
data = img.serialize()
|
|
|
|
assert "style" in data
|
|
assert data["style"]["corner_radius"] == 15.0
|
|
assert data["style"]["frame_style"] == "ornate_flourish"
|
|
assert data["style"]["frame_corners"] == [True, False, False, True]
|
|
|
|
def test_image_data_deserialize_restores_style(self):
|
|
"""Test that ImageData deserialization restores style"""
|
|
img = ImageData()
|
|
data = {
|
|
"style": {
|
|
"corner_radius": 20.0,
|
|
"border_width": 2.0,
|
|
"frame_style": "leafy_corners",
|
|
"frame_corners": [False, True, False, True],
|
|
}
|
|
}
|
|
img.deserialize(data)
|
|
|
|
assert img.style.corner_radius == 20.0
|
|
assert img.style.border_width == 2.0
|
|
assert img.style.frame_style == "leafy_corners"
|
|
assert img.style.frame_corners == (False, True, False, True)
|
|
|
|
def test_image_data_deserialize_without_style(self):
|
|
"""Test backward compatibility - deserialize without style"""
|
|
img = ImageData()
|
|
data = {"image_path": "test.jpg"}
|
|
img.deserialize(data)
|
|
|
|
# Should have default style
|
|
assert img.style.corner_radius == 0.0
|
|
assert img.style.frame_style is None
|
|
|
|
|
|
class TestPlaceholderDataWithStyle:
|
|
"""Tests for PlaceholderData with styling"""
|
|
|
|
def test_placeholder_has_default_style(self):
|
|
"""Test that PlaceholderData has a default style"""
|
|
placeholder = PlaceholderData()
|
|
assert hasattr(placeholder, "style")
|
|
assert isinstance(placeholder.style, ImageStyle)
|
|
|
|
def test_placeholder_serialize_includes_style(self):
|
|
"""Test that PlaceholderData serialization includes style"""
|
|
placeholder = PlaceholderData()
|
|
placeholder.style.corner_radius = 10.0
|
|
placeholder.style.shadow_enabled = True
|
|
placeholder.style.frame_corners = (True, True, False, False)
|
|
|
|
data = placeholder.serialize()
|
|
|
|
assert "style" in data
|
|
assert data["style"]["corner_radius"] == 10.0
|
|
assert data["style"]["shadow_enabled"] is True
|
|
|
|
def test_placeholder_deserialize_restores_style(self):
|
|
"""Test that PlaceholderData deserialization restores style"""
|
|
placeholder = PlaceholderData()
|
|
data = {
|
|
"style": {
|
|
"corner_radius": 5.0,
|
|
"border_width": 1.5,
|
|
"frame_style": "double_line",
|
|
}
|
|
}
|
|
placeholder.deserialize(data)
|
|
|
|
assert placeholder.style.corner_radius == 5.0
|
|
assert placeholder.style.border_width == 1.5
|
|
assert placeholder.style.frame_style == "double_line"
|
|
|
|
|
|
class TestFrameCorners:
|
|
"""Tests specifically for frame_corners functionality"""
|
|
|
|
def test_all_corners_true(self):
|
|
"""Test all corners enabled"""
|
|
style = ImageStyle(frame_corners=(True, True, True, True))
|
|
assert all(style.frame_corners)
|
|
|
|
def test_no_corners(self):
|
|
"""Test no corners enabled"""
|
|
style = ImageStyle(frame_corners=(False, False, False, False))
|
|
assert not any(style.frame_corners)
|
|
|
|
def test_diagonal_corners_only(self):
|
|
"""Test diagonal corners (TL, BR)"""
|
|
style = ImageStyle(frame_corners=(True, False, True, False))
|
|
tl, tr, br, bl = style.frame_corners
|
|
assert tl is True
|
|
assert tr is False
|
|
assert br is True
|
|
assert bl is False
|
|
|
|
def test_opposite_diagonal_corners(self):
|
|
"""Test opposite diagonal corners (TR, BL)"""
|
|
style = ImageStyle(frame_corners=(False, True, False, True))
|
|
tl, tr, br, bl = style.frame_corners
|
|
assert tl is False
|
|
assert tr is True
|
|
assert br is False
|
|
assert bl is True
|
|
|
|
def test_left_corners_only(self):
|
|
"""Test left side corners only"""
|
|
style = ImageStyle(frame_corners=(True, False, False, True))
|
|
tl, tr, br, bl = style.frame_corners
|
|
assert tl is True
|
|
assert tr is False
|
|
assert br is False
|
|
assert bl is True
|
|
|
|
def test_right_corners_only(self):
|
|
"""Test right side corners only"""
|
|
style = ImageStyle(frame_corners=(False, True, True, False))
|
|
tl, tr, br, bl = style.frame_corners
|
|
assert tl is False
|
|
assert tr is True
|
|
assert br is True
|
|
assert bl is False
|
|
|
|
def test_top_corners_only(self):
|
|
"""Test top corners only"""
|
|
style = ImageStyle(frame_corners=(True, True, False, False))
|
|
tl, tr, br, bl = style.frame_corners
|
|
assert tl is True
|
|
assert tr is True
|
|
assert br is False
|
|
assert bl is False
|
|
|
|
def test_bottom_corners_only(self):
|
|
"""Test bottom corners only"""
|
|
style = ImageStyle(frame_corners=(False, False, True, True))
|
|
tl, tr, br, bl = style.frame_corners
|
|
assert tl is False
|
|
assert tr is False
|
|
assert br is True
|
|
assert bl is True
|