Resto·Ka — tous les restaurants du Québec, menus complets et prix réels (famille ·Ka)
Python 69.3%
TypeScript 16.7%
CSS 7.9%
JavaScript 4.7%
HTML 1.4%
1# ==============================================================================2# Author: Simon-Pierre Boucher <contact@spboucher.ai>3# File: tests/test_ueat.py4# Desc: Régression du connecteur UEAT — rejeu HORS LIGNE d'une fixture réelle5# (extrait Poulet Rouge capté sur api.ueat.io). Vérifie : une fiche par6# succursale QC, filtrage hors-province, prix exacts, options7# (variations + questions), contexte takeout, tags diète.8# ==============================================================================9import json10from pathlib import Path1112import pytest1314from restoka.connectors.ueat import UeatConnector1516FIXTURE = json.loads(17 (Path(__file__).parent / "fixtures" / "ueat" / "poulet_rouge.json")18 .read_text(encoding="utf-8"))192021class OfflineUeat(UeatConnector):22 """Connecteur rejoué depuis la fixture (aucun appel réseau)."""23 use_detail_cache = False2425 def _integrations(self):26 return [{"key": "fixture-guid", "label": "Poulet Rouge (fixture)"}]2728 def _gql(self, api_key, query, variables=None, operation=None):29 if operation == "getFranchises":30 return FIXTURE["getFranchises"]31 if operation == "menuCategories" or "menuCategories" in query:32 return FIXTURE["menuCategories"]33 if operation == "items":34 return {"items": FIXTURE["items"][str(variables["categoryId"])]}35 if operation == "questions":36 return FIXTURE["questions"][str(variables["menuItemId"])]37 raise AssertionError(f"requête inattendue : {operation}")383940@pytest.fixture(scope="module")41def restos():42 return [r.finalize() for r in OfflineUeat().fetch()]434445def test_une_fiche_par_succursale_quebec(restos):46 # 3 succursales dans la fixture, mais Ottawa (Ontario) est hors périmètre47 assert len(restos) == 248 assert {r.city for r in restos} == {"Québec", "Sherbrooke"}49 assert all(r.chain == "Poulet Rouge" for r in restos)50 assert len({r.uid for r in restos}) == 2515253def test_regions_rattachees(restos):54 regions = {r.city: r.region for r in restos}55 assert regions["Québec"] == "Capitale-Nationale"56 assert regions["Sherbrooke"] == "Estrie"575859def test_prix_exacts(restos):60 """Les prix sont l'actif le plus critique : ils doivent être EXACTS."""61 menu = restos[0].menu62 assert menu["price_context"] == "takeout"63 assert menu["price_source"] == "ueat"64 prix = {it["name"]: it["price"]65 for sec in menu["sections"] for it in sec["items"]}66 assert prix["Créez Votre Rouge Bol (1 Saveur)"] == 14.2967 assert prix["Rouge Bol (Végé)"] == 11.2968 assert prix["Patates Frites"] == 4.99697071def test_sections(restos):72 noms = [s["name"] for s in restos[0].menu["sections"]]73 assert noms == ["Rouge Bol", "À-Côtés & Desserts"]747576def test_options_variations(restos):77 frites = next(it for sec in restos[0].menu["sections"]78 for it in sec["items"] if it["name"] == "Patates Frites")79 fmt = next(op for op in frites["options"] if op["group"] == "Format")80 assert fmt["required"] is True81 deltas = {c["name"]: c["price_delta"] for c in fmt["choices"]}82 assert deltas["Régulière"] == 0.083 assert deltas["Grande"] == 2.0 # 6,99 − 4,99848586def test_options_questions(restos):87 bol = next(it for sec in restos[0].menu["sections"]88 for it in sec["items"]89 if it["name"] == "Créez Votre Rouge Bol (1 Saveur)")90 base = next(op for op in bol["options"]91 if op["group"] == "Choisissez votre base")92 assert base["required"] is True93 deltas = {c["name"]: c["price_delta"] for c in base["choices"]}94 assert deltas["Riz basmati"] == 0.095 assert deltas["Salade César"] == 1.5969798def test_tags_diete(restos):99 vege = next(it for sec in restos[0].menu["sections"]100 for it in sec["items"] if it["name"] == "Rouge Bol (Végé)")101 assert "vegetarien" in vege["tags"]102 assert "vegetarien" in restos[0].dietary_options103