File size: 4,516 Bytes
41fae03
 
 
 
 
 
 
 
bbbfba8
41fae03
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
"""Tests for geometry primitives and Geometry model."""

from __future__ import annotations

import pytest
from pydantic import ValidationError
from src.app.domain.models import (
    Baseline,
    BBox,
    ClipRect,
    Geometry,
    GeometryContext,
    GeometryStatus,
    Point,
)


class TestPoint:
    def test_valid(self) -> None:
        p = Point(x=10.0, y=20.0)
        assert p.x == 10.0
        assert p.y == 20.0

    def test_origin(self) -> None:
        p = Point(x=0, y=0)
        assert p.x == 0.0

    def test_negative_x_rejected(self) -> None:
        with pytest.raises(ValidationError):
            Point(x=-1, y=0)

    def test_negative_y_rejected(self) -> None:
        with pytest.raises(ValidationError):
            Point(x=0, y=-1)

    def test_frozen(self) -> None:
        p = Point(x=1, y=2)
        with pytest.raises(ValidationError):
            p.x = 5  # type: ignore[misc]


class TestBBox:
    def test_valid(self) -> None:
        b = BBox(x=10, y=20, width=100, height=50)
        assert b.x2 == 110.0
        assert b.y2 == 70.0

    def test_as_tuple(self) -> None:
        b = BBox(x=10, y=20, width=100, height=50)
        assert b.as_tuple() == (10.0, 20.0, 100.0, 50.0)

    def test_zero_width_rejected(self) -> None:
        with pytest.raises(ValidationError):
            BBox(x=0, y=0, width=0, height=10)

    def test_zero_height_rejected(self) -> None:
        with pytest.raises(ValidationError):
            BBox(x=0, y=0, width=10, height=0)

    def test_negative_x_rejected(self) -> None:
        with pytest.raises(ValidationError):
            BBox(x=-1, y=0, width=10, height=10)


class TestBaseline:
    def test_valid(self) -> None:
        bl = Baseline(start=Point(x=0, y=100), end=Point(x=200, y=100))
        assert bl.start.x == 0
        assert bl.end.x == 200


class TestClipRect:
    def test_valid(self) -> None:
        cr = ClipRect(x=0, y=0, width=100, height=100)
        assert cr.width == 100

    def test_zero_dimension_rejected(self) -> None:
        with pytest.raises(ValidationError):
            ClipRect(x=0, y=0, width=0, height=100)


class TestGeometry:
    def test_valid_exact(self) -> None:
        g = Geometry(bbox=(100, 200, 300, 50), status=GeometryStatus.EXACT)
        assert g.bbox == (100, 200, 300, 50)
        assert g.polygon is None

    def test_valid_with_polygon(self) -> None:
        g = Geometry(
            bbox=(100, 200, 300, 50),
            polygon=[(100, 200), (400, 200), (400, 250), (100, 250)],
            status=GeometryStatus.EXACT,
        )
        assert len(g.polygon) == 4

    def test_zero_width_rejected(self) -> None:
        with pytest.raises(ValidationError, match="width and height must be > 0"):
            Geometry(bbox=(100, 200, 0, 50), status=GeometryStatus.EXACT)

    def test_zero_height_rejected(self) -> None:
        with pytest.raises(ValidationError, match="width and height must be > 0"):
            Geometry(bbox=(100, 200, 300, 0), status=GeometryStatus.EXACT)

    def test_negative_x_rejected(self) -> None:
        with pytest.raises(ValidationError, match="x and y must be >= 0"):
            Geometry(bbox=(-1, 200, 300, 50), status=GeometryStatus.EXACT)

    def test_negative_y_rejected(self) -> None:
        with pytest.raises(ValidationError, match="x and y must be >= 0"):
            Geometry(bbox=(100, -1, 300, 50), status=GeometryStatus.EXACT)

    def test_all_statuses_accepted(self) -> None:
        for status in GeometryStatus:
            g = Geometry(bbox=(10, 10, 10, 10), status=status)
            assert g.status == status

    def test_frozen(self) -> None:
        g = Geometry(bbox=(10, 20, 30, 40), status=GeometryStatus.EXACT)
        with pytest.raises(ValidationError):
            g.status = GeometryStatus.INFERRED  # type: ignore[misc]


class TestGeometryContext:
    def test_valid_minimal(self) -> None:
        gc = GeometryContext(source_width=2480, source_height=3508)
        assert gc.source_width == 2480
        assert gc.resize_factor is None

    def test_valid_full(self) -> None:
        gc = GeometryContext(
            source_width=2480,
            source_height=3508,
            provided_width=1240,
            provided_height=1754,
            resize_factor=0.5,
            rotation=90.0,
        )
        assert gc.resize_factor == 0.5

    def test_zero_source_rejected(self) -> None:
        with pytest.raises(ValidationError):
            GeometryContext(source_width=0, source_height=100)