File size: 3,317 Bytes
b510add
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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()