"""Tests for low-contrast visibility analysis. No GUI dependency.""" import shutil import sys import tempfile import unittest from pathlib import Path from PIL import Image sys.path.insert(0, str(Path(__file__).parent.parent / "src")) from core.models import TransformState, VisibilityStatus from core.visibility import analyze_visibility class TestVisibilityAnalysis(unittest.TestCase): def setUp(self): self.tmp = Path(tempfile.mkdtemp()) def tearDown(self): shutil.rmtree(str(self.tmp), ignore_errors=True) def _save(self, image, name): path = self.tmp / name image.save(str(path)) return path def _rgba(self, w, h, color): return Image.new("RGBA", (w, h), color) def test_white_garment_with_light_print_is_unclear_or_low(self): garment = self._save(self._rgba(100, 100, (245, 245, 245, 255)), "garment.png") print_img = self._save(self._rgba(20, 20, (250, 250, 250, 255)), "print.png") state = TransformState(x=30, y=30, width=20, height=20) result = analyze_visibility(garment, print_img, state) self.assertIn(result.status, (VisibilityStatus.UNCLEAR, VisibilityStatus.LOW)) self.assertFalse(result.error) def test_dark_garment_with_dark_print_is_unclear_or_low(self): garment = self._save(self._rgba(100, 100, (20, 20, 20, 255)), "garment.png") print_img = self._save(self._rgba(20, 20, (25, 25, 25, 255)), "print.png") state = TransformState(x=30, y=30, width=20, height=20) result = analyze_visibility(garment, print_img, state) self.assertIn(result.status, (VisibilityStatus.UNCLEAR, VisibilityStatus.LOW)) self.assertFalse(result.error) def test_high_contrast_pair_is_normal(self): garment = self._save(self._rgba(100, 100, (250, 250, 250, 255)), "garment.png") print_img = self._save(self._rgba(20, 20, (10, 10, 10, 255)), "print.png") state = TransformState(x=30, y=30, width=20, height=20) result = analyze_visibility(garment, print_img, state) self.assertEqual(result.status, VisibilityStatus.NORMAL) self.assertGreater(result.rgb_distance, 75) def test_transparent_pixels_do_not_affect_print_color(self): garment = self._save(self._rgba(100, 100, (10, 10, 10, 255)), "garment.png") print_img = Image.new("RGBA", (20, 20), (255, 255, 255, 0)) for x in range(10): for y in range(20): print_img.putpixel((x, y), (12, 12, 12, 255)) print_path = self._save(print_img, "print.png") state = TransformState(x=30, y=30, width=20, height=20) result = analyze_visibility(garment, print_path, state) self.assertIn(result.status, (VisibilityStatus.UNCLEAR, VisibilityStatus.LOW)) def test_fully_transparent_print_is_unknown(self): garment = self._save(self._rgba(100, 100, (10, 10, 10, 255)), "garment.png") print_img = self._save(self._rgba(20, 20, (10, 10, 10, 0)), "print.png") state = TransformState(x=30, y=30, width=20, height=20) result = analyze_visibility(garment, print_img, state) self.assertEqual(result.status, VisibilityStatus.UNKNOWN) self.assertTrue(result.error) def test_uses_target_region_not_whole_garment(self): garment_img = self._rgba(100, 100, (255, 255, 255, 255)) for x in range(30, 50): for y in range(30, 50): garment_img.putpixel((x, y), (10, 10, 10, 255)) garment = self._save(garment_img, "garment.png") print_img = self._save(self._rgba(20, 20, (12, 12, 12, 255)), "print.png") state = TransformState(x=30, y=30, width=20, height=20) result = analyze_visibility(garment, print_img, state) self.assertIn(result.status, (VisibilityStatus.UNCLEAR, VisibilityStatus.LOW)) def test_target_area_outside_canvas_is_unknown(self): garment = self._save(self._rgba(100, 100, (255, 255, 255, 255)), "garment.png") print_img = self._save(self._rgba(20, 20, (255, 255, 255, 255)), "print.png") state = TransformState(x=200, y=200, width=20, height=20) result = analyze_visibility(garment, print_img, state) self.assertEqual(result.status, VisibilityStatus.UNKNOWN) if __name__ == "__main__": unittest.main()