# ============================================================================== # Author: Simon-Pierre Boucher # File: tests/test_menullm.py # Desc: Validation aval des menus structurés par LLM — la barre de qualité # est STRICTE : jamais de menu douteux en base (prix implausibles # neutralisés, volume minimal, ratio de prix minimal). # ============================================================================== from restoka.menullm import validate def _raw(items, is_menu=True): return {"is_menu": is_menu, "sections": [{"name": "Plats", "items": items}]} def test_menu_valide(): out = validate(_raw([{"name": f"Plat {i}", "price": 10.0 + i} for i in range(6)])) assert out and len(out["sections"][0]["items"]) == 6 assert out["sections"][0]["items"][0]["price"] == 10.0 assert out["sections"][0]["items"][0]["currency"] == "CAD" def test_pas_un_menu(): assert validate(_raw([{"name": "Plat", "price": 10.0}], is_menu=False)) is None assert validate(None) is None def test_trop_peu_de_prix(): # 4 plats avec prix < minimum de 5 -> rejeté assert validate(_raw([{"name": f"P{i}", "price": 12.0} for i in range(4)])) is None def test_ratio_de_prix_insuffisant(): items = ([{"name": f"P{i}", "price": 12.0} for i in range(5)] + [{"name": f"S{i}", "price": None} for i in range(10)]) assert validate(_raw(items)) is None # 5/15 = 33 % < 40 % def test_prix_implausible_neutralise(): items = ([{"name": f"P{i}", "price": 12.0} for i in range(5)] + [{"name": "Erreur OCR", "price": 12345.0}]) out = validate(_raw(items)) assert out is not None bad = next(i for i in out["sections"][0]["items"] if i["name"] == "Erreur OCR") assert bad["price"] is None # jamais un prix aberrant en base def test_nom_trop_long_ecarte(): items = ([{"name": f"P{i}", "price": 12.0} for i in range(5)] + [{"name": "x" * 300, "price": 9.0}]) out = validate(_raw(items)) assert all(len(i["name"]) <= 120 for i in out["sections"][0]["items"])