import numpy as np from app.vision import BBox, crop_image, detect_animal, detect_subject, select_primary_bbox, square_bbox def test_square_bbox_is_square_and_inside_bounds(): bbox = BBox(x=10, y=20, w=40, h=20) square = square_bbox(bbox, (100, 120, 3), buffer_ratio=0.1) assert square.w == square.h assert square.x >= 0 assert square.y >= 0 assert square.right <= 120 assert square.bottom <= 100 def test_crop_image_uses_bbox(): image = np.zeros((60, 80, 3), dtype=np.uint8) image[10:30, 20:50] = 255 bbox = BBox(x=20, y=10, w=30, h=20) crop = crop_image(image, bbox) assert crop.shape[:2] == (20, 30) def test_detect_subject_finds_rectangle(): image = np.zeros((100, 100, 3), dtype=np.uint8) image[25:75, 30:80] = 255 bbox = detect_subject(image) assert bbox is not None assert bbox.w >= 45 assert bbox.h >= 45 def test_detect_animal_uses_contour_fallback(): image = np.zeros((100, 100, 3), dtype=np.uint8) image[20:70, 15:85] = 255 bbox = detect_animal(image) assert bbox is not None assert bbox.w >= 50 def test_select_primary_bbox_defaults_to_subject(): image = np.zeros((100, 120, 3), dtype=np.uint8) bbox, method = select_primary_bbox(image) assert method == "center_fallback" assert bbox.w == bbox.h