"""Tests for the output parsing module.""" from src.parsing import BBox, ParseResult, parse_boxes, parse_points class TestBBox: def test_valid_box_within_bounds(self): box = BBox(x1=10, y1=20, x2=100, y2=200) assert box.is_valid(640, 480) assert box.width == 90 assert box.height == 180 assert box.area == 16200 def test_box_center(self): box = BBox(x1=0, y1=0, x2=100, y2=100) assert box.center == (50.0, 50.0) def test_invalid_box_zero_area(self): box = BBox(x1=50, y1=50, x2=50, y2=50) assert not box.is_valid(640, 480) def test_invalid_box_out_of_bounds(self): box = BBox(x1=-10, y1=0, x2=100, y2=100) assert not box.is_valid(640, 480) def test_clamp(self): box = BBox(x1=-10, y1=-5, x2=700, y2=500) clamped = box.clamp(640, 480) assert clamped.x1 == 0 assert clamped.y1 == 0 assert clamped.x2 == 640 assert clamped.y2 == 480 def test_to_dict(self): box = BBox(x1=10, y1=20, x2=100, y2=200, confidence=0.9, label="test") d = box.to_dict() assert d["x1"] == 10 assert d["label"] == "test" assert d["confidence"] == 0.9 class TestParseBoxes: def test_single_box(self): raw = "<100><200><300><400>" result = parse_boxes(raw, 1000, 1000) assert result.num_detections == 1 assert result.boxes[0].x1 == 100.0 assert result.boxes[0].y1 == 200.0 assert result.boxes[0].x2 == 300.0 assert result.boxes[0].y2 == 400.0 def test_multiple_boxes(self): raw = "<100><100><200><200> some text <500><500><600><600>" result = parse_boxes(raw, 1000, 1000) assert result.num_detections == 2 def test_duplicate_boxes_deduplicated(self): raw = "<100><100><200><200> <100><100><200><200>" result = parse_boxes(raw, 1000, 1000) assert result.num_detections == 1 def test_no_boxes(self): raw = "No objects detected in this image." result = parse_boxes(raw, 1000, 1000) assert result.num_detections == 0 def test_coordinate_scaling(self): raw = "<500><500><1000><1000>" result = parse_boxes(raw, 640, 480) assert result.num_detections == 1 assert abs(result.boxes[0].x2 - 640.0) < 0.1 assert abs(result.boxes[0].y2 - 480.0) < 0.1 def test_out_of_bounds_box_discarded(self): raw = "<999><999><1001><1001>" result = parse_boxes(raw, 100, 100) assert result.num_detections == 0 assert len(result.parse_errors) > 0 def test_alt_format(self): raw = "100, 200, 300, 400" result = parse_boxes(raw, 1000, 1000) assert result.num_detections == 1 class TestParsePoints: def test_single_point(self): raw = "<500><500>" points = parse_points(raw, 1000, 1000) assert len(points) == 1 assert points[0]["x"] == 500.0 assert points[0]["y"] == 500.0 def test_no_points(self): raw = "nothing here" points = parse_points(raw, 1000, 1000) assert len(points) == 0 class TestParseResult: def test_empty_result(self): r = ParseResult() assert r.num_detections == 0 d = r.to_dict() assert d["num_detections"] == 0 def test_result_with_boxes(self): r = ParseResult( boxes=[BBox(10, 20, 100, 200)], raw_output="<10><20><100><200>", ) assert r.num_detections == 1 d = r.to_dict() assert len(d["boxes"]) == 1