This commit is contained in:
Danilo Reyes
2025-11-02 14:13:56 -06:00
parent cd8ce33f5e
commit ce0b692aee
23 changed files with 2049 additions and 50 deletions

View File

@@ -0,0 +1,236 @@
"""Tests for image transformation validation."""
import pytest
from pydantic import ValidationError
from app.images.schemas import BoardImageUpdate
def test_valid_transformations():
"""Test that valid transformations are accepted."""
data = BoardImageUpdate(
transformations={
"scale": 1.5,
"rotation": 45,
"opacity": 0.8,
"flipped_h": True,
"flipped_v": False,
"greyscale": False,
}
)
assert data.transformations is not None
assert data.transformations["scale"] == 1.5
assert data.transformations["rotation"] == 45
assert data.transformations["opacity"] == 0.8
assert data.transformations["flipped_h"] is True
assert data.transformations["greyscale"] is False
def test_minimal_transformations():
"""Test that minimal transformation data is accepted."""
data = BoardImageUpdate(
transformations={
"scale": 1.0,
"rotation": 0,
"opacity": 1.0,
}
)
assert data.transformations is not None
def test_transformation_scale_bounds():
"""Test scale bounds validation."""
# Valid scales
valid_scales = [0.01, 0.5, 1.0, 5.0, 10.0]
for scale in valid_scales:
data = BoardImageUpdate(transformations={"scale": scale})
assert data.transformations["scale"] == scale
def test_transformation_rotation_bounds():
"""Test rotation bounds (any value allowed, normalized client-side)."""
# Various rotation values
rotations = [0, 45, 90, 180, 270, 360, 450, -90]
for rotation in rotations:
data = BoardImageUpdate(transformations={"rotation": rotation})
assert data.transformations["rotation"] == rotation
def test_transformation_opacity_bounds():
"""Test opacity bounds."""
# Valid opacity values
valid_opacities = [0.0, 0.25, 0.5, 0.75, 1.0]
for opacity in valid_opacities:
data = BoardImageUpdate(transformations={"opacity": opacity})
assert data.transformations["opacity"] == opacity
def test_transformation_boolean_flags():
"""Test boolean transformation flags."""
data = BoardImageUpdate(
transformations={
"flipped_h": True,
"flipped_v": True,
"greyscale": True,
}
)
assert data.transformations["flipped_h"] is True
assert data.transformations["flipped_v"] is True
assert data.transformations["greyscale"] is True
def test_transformation_crop_data():
"""Test crop transformation data."""
data = BoardImageUpdate(
transformations={
"crop": {
"x": 10,
"y": 10,
"width": 100,
"height": 100,
}
}
)
assert data.transformations["crop"] is not None
assert data.transformations["crop"]["x"] == 10
assert data.transformations["crop"]["width"] == 100
def test_transformation_null_crop():
"""Test that crop can be null (no crop)."""
data = BoardImageUpdate(
transformations={
"crop": None,
}
)
assert data.transformations["crop"] is None
def test_partial_transformation_update():
"""Test updating only some transformation fields."""
# Only update scale
data = BoardImageUpdate(transformations={"scale": 2.0})
assert data.transformations["scale"] == 2.0
# Only update rotation
data = BoardImageUpdate(transformations={"rotation": 90})
assert data.transformations["rotation"] == 90
# Only update opacity
data = BoardImageUpdate(transformations={"opacity": 0.5})
assert data.transformations["opacity"] == 0.5
def test_complete_transformation_update():
"""Test updating all transformation fields."""
data = BoardImageUpdate(
transformations={
"scale": 1.5,
"rotation": 45,
"opacity": 0.8,
"flipped_h": True,
"flipped_v": False,
"greyscale": True,
"crop": {
"x": 20,
"y": 20,
"width": 150,
"height": 150,
},
}
)
assert data.transformations is not None
assert len(data.transformations) == 7
def test_position_validation_with_transformations():
"""Test that position and transformations can be updated together."""
data = BoardImageUpdate(
position={"x": 100, "y": 200},
transformations={"scale": 1.5, "rotation": 45},
)
assert data.position == {"x": 100, "y": 200}
assert data.transformations["scale"] == 1.5
assert data.transformations["rotation"] == 45
def test_invalid_position_missing_x():
"""Test that position without x coordinate is rejected."""
with pytest.raises(ValidationError) as exc_info:
BoardImageUpdate(position={"y": 100})
assert "must contain 'x' and 'y'" in str(exc_info.value)
def test_invalid_position_missing_y():
"""Test that position without y coordinate is rejected."""
with pytest.raises(ValidationError) as exc_info:
BoardImageUpdate(position={"x": 100})
assert "must contain 'x' and 'y'" in str(exc_info.value)
def test_z_order_update():
"""Test Z-order update."""
data = BoardImageUpdate(z_order=5)
assert data.z_order == 5
# Negative Z-order allowed (layering)
data = BoardImageUpdate(z_order=-1)
assert data.z_order == -1
# Large Z-order allowed
data = BoardImageUpdate(z_order=999999)
assert data.z_order == 999999
def test_group_id_update():
"""Test group ID update."""
from uuid import uuid4
group_id = uuid4()
data = BoardImageUpdate(group_id=group_id)
assert data.group_id == group_id
# Null group ID (remove from group)
data = BoardImageUpdate(group_id=None)
assert data.group_id is None
def test_empty_update():
"""Test that empty update (no fields) is valid."""
data = BoardImageUpdate()
assert data.position is None
assert data.transformations is None
assert data.z_order is None
assert data.group_id is None
def test_transformation_data_types():
"""Test that transformation data types are validated."""
# Valid types
data = BoardImageUpdate(
transformations={
"scale": 1.5, # float
"rotation": 45, # int (converted to float)
"opacity": 0.8, # float
"flipped_h": True, # bool
"flipped_v": False, # bool
"greyscale": True, # bool
}
)
assert isinstance(data.transformations["scale"], (int, float))
assert isinstance(data.transformations["flipped_h"], bool)