import io import unittest from unittest.mock import patch import numpy as np import cv2 from fastapi.testclient import TestClient from app import main def _fake_jpeg_bytes(color=(200, 200, 200), size=(300, 200)): img = np.full((size[1], size[0], 3), color, dtype=np.uint8) ok, buf = cv2.imencode(".jpg", img) assert ok return buf.tobytes() class TestAnalyzeEndpoint(unittest.TestCase): def setUp(self): self.client = TestClient(main.app) def test_consistent_reading_returns_success(self): fake_fields = [ {"field": "prix", "text": "10000", "confidence": 0.95}, {"field": "volume", "text": "14.28", "confidence": 0.9}, {"field": "prix_litre", "text": "700", "confidence": 0.85}, ] fake_quality = {"image_quality": "valid", "quality_score": 0.95, "blur_variance": 500.0, "brightness": 120.0} with patch.object(main, "_get_model", return_value=(None, None)), \ patch.object(main, "recognize_screen", return_value=fake_fields), \ patch.object(main, "estimate_image_quality", return_value=fake_quality): resp = self.client.post( "/analyze", files={"image": ("pompe.jpg", _fake_jpeg_bytes(), "image/jpeg")}, data={"fuel_price": "700", "driver_id": "chauffeur-42"}, ) self.assertEqual(resp.status_code, 200) body = resp.json() self.assertTrue(body["success"]) self.assertEqual(body["detected_amount"], 10000.0) self.assertAlmostEqual(body["detected_liters"], 14.28, places=2) self.assertEqual(body["fuel_price"], 700.0) self.assertEqual(body["driver_id"], "chauffeur-42") self.assertIn("photo_reference", body) # Champs techniques (moteur OCR, variante...) volontairement absents # de la réponse — seuls les champs du cahier des charges sont exposés. self.assertNotIn("ocr_engine", body) self.assertNotIn("best_variant", body) def test_inconsistent_reading_blocks(self): fake_fields = [ {"field": "prix", "text": "10000", "confidence": 0.95}, {"field": "volume", "text": "20.00", "confidence": 0.9}, ] fake_quality = {"image_quality": "valid", "quality_score": 0.95, "blur_variance": 500.0, "brightness": 120.0} with patch.object(main, "_get_model", return_value=(None, None)), \ patch.object(main, "recognize_screen", return_value=fake_fields), \ patch.object(main, "estimate_image_quality", return_value=fake_quality): resp = self.client.post( "/analyze", files={"image": ("pompe.jpg", _fake_jpeg_bytes(), "image/jpeg")}, data={"fuel_price": "875"}, ) body = resp.json() self.assertFalse(body["success"]) self.assertIn("Incohérence", body["message"]) def test_unsupported_content_type_rejected(self): resp = self.client.post( "/analyze", files={"image": ("pompe.txt", b"not an image", "text/plain")}, data={"fuel_price": "700"}, ) self.assertEqual(resp.status_code, 400) if __name__ == "__main__": unittest.main()