# flake8: noqa # yapf: disable import io import unittest import json from check_bounding_boxes import get_bounding_box_messages # Currently this is not run automatically in CI; it's just for documentation and manual checking. class TestGetBoundingBoxMessages(unittest.TestCase): def create_json_stream(self, data): """Helper to create a JSON stream from data""" return io.StringIO(json.dumps(data)) def test_no_intersections(self): """Test case with no bounding box intersections""" data = { 'form_fields': [{ 'description': 'Name', 'page_number': 1, 'label_bounding_box': [10, 10, 50, 30], 'entry_bounding_box': [60, 10, 150, 30] }, { 'description': 'Email', 'page_number': 1, 'label_bounding_box': [10, 40, 50, 60], 'entry_bounding_box': [60, 40, 150, 60] }] } stream = self.create_json_stream(data) messages = get_bounding_box_messages(stream) self.assertTrue(any('SUCCESS' in msg for msg in messages)) self.assertFalse(any('FAILURE' in msg for msg in messages)) def test_label_entry_intersection_same_field(self): """Test intersection between label and entry of the same field""" data = { 'form_fields': [{ 'description': 'Name', 'page_number': 1, 'label_bounding_box': [10, 10, 60, 30], 'entry_bounding_box': [50, 10, 150, 30] # Overlaps with label }] } stream = self.create_json_stream(data) messages = get_bounding_box_messages(stream) self.assertTrue( any('FAILURE' in msg and 'intersection' in msg for msg in messages)) self.assertFalse(any('SUCCESS' in msg for msg in messages)) def test_intersection_between_different_fields(self): """Test intersection between bounding boxes of different fields""" data = { 'form_fields': [ { 'description': 'Name', 'page_number': 1, 'label_bounding_box': [10, 10, 50, 30], 'entry_bounding_box': [60, 10, 150, 30] }, { 'description': 'Email', 'page_number': 1, 'label_bounding_box': [40, 20, 80, 40], # Overlaps with Name's boxes 'entry_bounding_box': [160, 10, 250, 30] } ] } stream = self.create_json_stream(data) messages = get_bounding_box_messages(stream) self.assertTrue( any('FAILURE' in msg and 'intersection' in msg for msg in messages)) self.assertFalse(any('SUCCESS' in msg for msg in messages)) def test_different_pages_no_intersection(self): """Test that boxes on different pages don't count as intersecting""" data = { 'form_fields': [ { 'description': 'Name', 'page_number': 1, 'label_bounding_box': [10, 10, 50, 30], 'entry_bounding_box': [60, 10, 150, 30] }, { 'description': 'Email', 'page_number': 2, 'label_bounding_box': [10, 10, 50, 30], # Same coordinates but different page 'entry_bounding_box': [60, 10, 150, 30] } ] } stream = self.create_json_stream(data) messages = get_bounding_box_messages(stream) self.assertTrue(any('SUCCESS' in msg for msg in messages)) self.assertFalse(any('FAILURE' in msg for msg in messages)) def test_entry_height_too_small(self): """Test that entry box height is checked against font size""" data = { 'form_fields': [{ 'description': 'Name', 'page_number': 1, 'label_bounding_box': [10, 10, 50, 30], 'entry_bounding_box': [60, 10, 150, 20], # Height is 10 'entry_text': { 'font_size': 14 # Font size larger than height } }] } stream = self.create_json_stream(data) messages = get_bounding_box_messages(stream) self.assertTrue( any('FAILURE' in msg and 'height' in msg for msg in messages)) self.assertFalse(any('SUCCESS' in msg for msg in messages)) def test_entry_height_adequate(self): """Test that adequate entry box height passes""" data = { 'form_fields': [{ 'description': 'Name', 'page_number': 1, 'label_bounding_box': [10, 10, 50, 30], 'entry_bounding_box': [60, 10, 150, 30], # Height is 20 'entry_text': { 'font_size': 14 # Font size smaller than height } }] } stream = self.create_json_stream(data) messages = get_bounding_box_messages(stream) self.assertTrue(any('SUCCESS' in msg for msg in messages)) self.assertFalse(any('FAILURE' in msg for msg in messages)) def test_default_font_size(self): """Test that default font size is used when not specified""" data = { 'form_fields': [{ 'description': 'Name', 'page_number': 1, 'label_bounding_box': [10, 10, 50, 30], 'entry_bounding_box': [60, 10, 150, 20], # Height is 10 'entry_text': {} # No font_size specified, should use default 14 }] } stream = self.create_json_stream(data) messages = get_bounding_box_messages(stream) self.assertTrue( any('FAILURE' in msg and 'height' in msg for msg in messages)) self.assertFalse(any('SUCCESS' in msg for msg in messages)) def test_no_entry_text(self): """Test that missing entry_text doesn't cause height check""" data = { 'form_fields': [{ 'description': 'Name', 'page_number': 1, 'label_bounding_box': [10, 10, 50, 30], 'entry_bounding_box': [60, 10, 150, 20] # Small height but no entry_text }] } stream = self.create_json_stream(data) messages = get_bounding_box_messages(stream) self.assertTrue(any('SUCCESS' in msg for msg in messages)) self.assertFalse(any('FAILURE' in msg for msg in messages)) def test_multiple_errors_limit(self): """Test that error messages are limited to prevent excessive output""" fields = [] # Create many overlapping fields for i in range(25): fields.append({ 'description': f'Field{i}', 'page_number': 1, 'label_bounding_box': [10, 10, 50, 30], # All overlap 'entry_bounding_box': [20, 15, 60, 35] # All overlap }) data = {'form_fields': fields} stream = self.create_json_stream(data) messages = get_bounding_box_messages(stream) # Should abort after ~20 messages self.assertTrue(any('Aborting' in msg for msg in messages)) # Should have some FAILURE messages but not hundreds failure_count = sum(1 for msg in messages if 'FAILURE' in msg) self.assertGreater(failure_count, 0) self.assertLess(len(messages), 30) # Should be limited def test_edge_touching_boxes(self): """Test that boxes touching at edges don't count as intersecting""" data = { 'form_fields': [{ 'description': 'Name', 'page_number': 1, 'label_bounding_box': [10, 10, 50, 30], 'entry_bounding_box': [50, 10, 150, 30] # Touches at x=50 }] } stream = self.create_json_stream(data) messages = get_bounding_box_messages(stream) self.assertTrue(any('SUCCESS' in msg for msg in messages)) self.assertFalse(any('FAILURE' in msg for msg in messages)) if __name__ == '__main__': unittest.main()