""" 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