main
1import unittest
2import json
3import io
4from check_bounding_boxes import get_bounding_box_messages
5
6
7# Currently this is not run automatically in CI; it's just for documentation and manual checking.
8class TestGetBoundingBoxMessages(unittest.TestCase):
9
10 def create_json_stream(self, data):
11 """Helper to create a JSON stream from data"""
12 return io.StringIO(json.dumps(data))
13
14 def test_no_intersections(self):
15 """Test case with no bounding box intersections"""
16 data = {
17 "form_fields": [
18 {
19 "description": "Name",
20 "page_number": 1,
21 "label_bounding_box": [10, 10, 50, 30],
22 "entry_bounding_box": [60, 10, 150, 30]
23 },
24 {
25 "description": "Email",
26 "page_number": 1,
27 "label_bounding_box": [10, 40, 50, 60],
28 "entry_bounding_box": [60, 40, 150, 60]
29 }
30 ]
31 }
32
33 stream = self.create_json_stream(data)
34 messages = get_bounding_box_messages(stream)
35 self.assertTrue(any("SUCCESS" in msg for msg in messages))
36 self.assertFalse(any("FAILURE" in msg for msg in messages))
37
38 def test_label_entry_intersection_same_field(self):
39 """Test intersection between label and entry of the same field"""
40 data = {
41 "form_fields": [
42 {
43 "description": "Name",
44 "page_number": 1,
45 "label_bounding_box": [10, 10, 60, 30],
46 "entry_bounding_box": [50, 10, 150, 30] # Overlaps with label
47 }
48 ]
49 }
50
51 stream = self.create_json_stream(data)
52 messages = get_bounding_box_messages(stream)
53 self.assertTrue(any("FAILURE" in msg and "intersection" in msg for msg in messages))
54 self.assertFalse(any("SUCCESS" in msg for msg in messages))
55
56 def test_intersection_between_different_fields(self):
57 """Test intersection between bounding boxes of different fields"""
58 data = {
59 "form_fields": [
60 {
61 "description": "Name",
62 "page_number": 1,
63 "label_bounding_box": [10, 10, 50, 30],
64 "entry_bounding_box": [60, 10, 150, 30]
65 },
66 {
67 "description": "Email",
68 "page_number": 1,
69 "label_bounding_box": [40, 20, 80, 40], # Overlaps with Name's boxes
70 "entry_bounding_box": [160, 10, 250, 30]
71 }
72 ]
73 }
74
75 stream = self.create_json_stream(data)
76 messages = get_bounding_box_messages(stream)
77 self.assertTrue(any("FAILURE" in msg and "intersection" in msg for msg in messages))
78 self.assertFalse(any("SUCCESS" in msg for msg in messages))
79
80 def test_different_pages_no_intersection(self):
81 """Test that boxes on different pages don't count as intersecting"""
82 data = {
83 "form_fields": [
84 {
85 "description": "Name",
86 "page_number": 1,
87 "label_bounding_box": [10, 10, 50, 30],
88 "entry_bounding_box": [60, 10, 150, 30]
89 },
90 {
91 "description": "Email",
92 "page_number": 2,
93 "label_bounding_box": [10, 10, 50, 30], # Same coordinates but different page
94 "entry_bounding_box": [60, 10, 150, 30]
95 }
96 ]
97 }
98
99 stream = self.create_json_stream(data)
100 messages = get_bounding_box_messages(stream)
101 self.assertTrue(any("SUCCESS" in msg for msg in messages))
102 self.assertFalse(any("FAILURE" in msg for msg in messages))
103
104 def test_entry_height_too_small(self):
105 """Test that entry box height is checked against font size"""
106 data = {
107 "form_fields": [
108 {
109 "description": "Name",
110 "page_number": 1,
111 "label_bounding_box": [10, 10, 50, 30],
112 "entry_bounding_box": [60, 10, 150, 20], # Height is 10
113 "entry_text": {
114 "font_size": 14 # Font size larger than height
115 }
116 }
117 ]
118 }
119
120 stream = self.create_json_stream(data)
121 messages = get_bounding_box_messages(stream)
122 self.assertTrue(any("FAILURE" in msg and "height" in msg for msg in messages))
123 self.assertFalse(any("SUCCESS" in msg for msg in messages))
124
125 def test_entry_height_adequate(self):
126 """Test that adequate entry box height passes"""
127 data = {
128 "form_fields": [
129 {
130 "description": "Name",
131 "page_number": 1,
132 "label_bounding_box": [10, 10, 50, 30],
133 "entry_bounding_box": [60, 10, 150, 30], # Height is 20
134 "entry_text": {
135 "font_size": 14 # Font size smaller than height
136 }
137 }
138 ]
139 }
140
141 stream = self.create_json_stream(data)
142 messages = get_bounding_box_messages(stream)
143 self.assertTrue(any("SUCCESS" in msg for msg in messages))
144 self.assertFalse(any("FAILURE" in msg for msg in messages))
145
146 def test_default_font_size(self):
147 """Test that default font size is used when not specified"""
148 data = {
149 "form_fields": [
150 {
151 "description": "Name",
152 "page_number": 1,
153 "label_bounding_box": [10, 10, 50, 30],
154 "entry_bounding_box": [60, 10, 150, 20], # Height is 10
155 "entry_text": {} # No font_size specified, should use default 14
156 }
157 ]
158 }
159
160 stream = self.create_json_stream(data)
161 messages = get_bounding_box_messages(stream)
162 self.assertTrue(any("FAILURE" in msg and "height" in msg for msg in messages))
163 self.assertFalse(any("SUCCESS" in msg for msg in messages))
164
165 def test_no_entry_text(self):
166 """Test that missing entry_text doesn't cause height check"""
167 data = {
168 "form_fields": [
169 {
170 "description": "Name",
171 "page_number": 1,
172 "label_bounding_box": [10, 10, 50, 30],
173 "entry_bounding_box": [60, 10, 150, 20] # Small height but no entry_text
174 }
175 ]
176 }
177
178 stream = self.create_json_stream(data)
179 messages = get_bounding_box_messages(stream)
180 self.assertTrue(any("SUCCESS" in msg for msg in messages))
181 self.assertFalse(any("FAILURE" in msg for msg in messages))
182
183 def test_multiple_errors_limit(self):
184 """Test that error messages are limited to prevent excessive output"""
185 fields = []
186 # Create many overlapping fields
187 for i in range(25):
188 fields.append({
189 "description": f"Field{i}",
190 "page_number": 1,
191 "label_bounding_box": [10, 10, 50, 30], # All overlap
192 "entry_bounding_box": [20, 15, 60, 35] # All overlap
193 })
194
195 data = {"form_fields": fields}
196
197 stream = self.create_json_stream(data)
198 messages = get_bounding_box_messages(stream)
199 # Should abort after ~20 messages
200 self.assertTrue(any("Aborting" in msg for msg in messages))
201 # Should have some FAILURE messages but not hundreds
202 failure_count = sum(1 for msg in messages if "FAILURE" in msg)
203 self.assertGreater(failure_count, 0)
204 self.assertLess(len(messages), 30) # Should be limited
205
206 def test_edge_touching_boxes(self):
207 """Test that boxes touching at edges don't count as intersecting"""
208 data = {
209 "form_fields": [
210 {
211 "description": "Name",
212 "page_number": 1,
213 "label_bounding_box": [10, 10, 50, 30],
214 "entry_bounding_box": [50, 10, 150, 30] # Touches at x=50
215 }
216 ]
217 }
218
219 stream = self.create_json_stream(data)
220 messages = get_bounding_box_messages(stream)
221 self.assertTrue(any("SUCCESS" in msg for msg in messages))
222 self.assertFalse(any("FAILURE" in msg for msg in messages))
223
224
225if __name__ == '__main__':
226 unittest.main()