mitai-jinkendo/backend/tests/test_food_suggest.py
Lars a7e5511039
All checks were successful
Deploy Development / deploy (push) Successful in 1m1s
Build Test / pytest-backend (push) Successful in 8s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 29s
feat: Rezepte beim Zuordnen anlegen und offene Zutaten listen
Lebensmittel oder Rezept wählbar; gemappte Zutaten werden übernommen, offene erscheinen in der Liste. Dazu Fettgehalt-Suche, EPA-Stoffe, Rezept-CRUD und Wechsel bestehender Zuordnungen.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-12 16:59:24 +02:00

108 lines
4.5 KiB
Python

from data_layer.food_suggest import (
collapse_key,
name_tokens,
score_name_match,
suggest_batch,
suggest_for_name,
)
def _index(*foods):
index = {"foods": [], "by_collapse": {}, "by_token": {}, "by_prefix": {}, "by_suffix": {}}
for food in foods:
food["_c"] = collapse_key(food["name_de"])
food["_t"] = name_tokens(food["name_de"])
if food["_c"]:
index["by_collapse"].setdefault(food["_c"], []).append(food)
index["by_prefix"].setdefault(food["_c"][:4], []).append(food)
if len(food["_c"]) >= 4:
index["by_suffix"].setdefault(food["_c"][-4:], []).append(food)
for tok in food["_t"]:
index["by_token"].setdefault(tok, []).append(food)
return index
def test_collapse_treats_space_as_same():
assert collapse_key("Haferflocken") == collapse_key("Hafer Flocken")
def test_haferflocken_ranks_simple_name_first():
index = {
"foods": [],
"by_collapse": {},
"by_token": {},
"by_prefix": {},
"by_suffix": {},
}
simple = {"id": "1", "name_de": "Hafer Flocken", "name_en": "oat flakes", "bls_code": "C131111", "catalog_kind": "official_bls"}
dish = {"id": "2", "name_de": "Milch-Getreide-Brei, mit Haferflocken und Apfelsaft (geeignet für Beikost)", "name_en": "", "bls_code": "X", "catalog_kind": "official_bls"}
for food in (simple, dish):
food["_c"] = collapse_key(food["name_de"])
index["by_collapse"].setdefault(food["_c"], []).append(food)
index["by_prefix"].setdefault(food["_c"][:4], []).append(food)
index["by_suffix"].setdefault(food["_c"][-4:], []).append(food)
packed = suggest_for_name(index, "Haferflocken", limit=3)
assert packed["suggestions"][0]["name_de"] == "Hafer Flocken"
assert packed["suggestions"][0]["score"] >= score_name_match("Haferflocken", dish["name_de"])
def test_close_scores_are_ambiguous():
a = {"id": "1", "name_de": "Olivenöl nativ", "name_en": "", "bls_code": "A", "catalog_kind": "official_bls"}
b = {"id": "2", "name_de": "Olivenöl raffiniert", "name_en": "", "bls_code": "B", "catalog_kind": "official_bls"}
index = {"foods": [], "by_collapse": {}, "by_token": {}, "by_prefix": {}, "by_suffix": {}}
for food in (a, b):
food["_c"] = collapse_key(food["name_de"])
index["by_prefix"].setdefault(food["_c"][:4], []).append(food)
for tok in food["name_de"].lower().replace(",", "").split():
if len(tok) >= 2:
index["by_token"].setdefault(tok, []).append(food)
packed = suggest_for_name(index, "Olivenöl", limit=3)
assert packed["ambiguous"] is True
assert packed["suggestion_count"] >= 2
def test_large_prefix_bucket_keeps_exact_collapse():
index = {"foods": [], "by_collapse": {}, "by_token": {}, "by_prefix": {}, "by_suffix": {}}
target = {"id": "hit", "name_de": "Hafer Flocken", "name_en": "", "bls_code": "C", "catalog_kind": "official_bls"}
target["_c"] = collapse_key(target["name_de"])
index["by_collapse"][target["_c"]] = [target]
index["by_prefix"][target["_c"][:4]] = [target] + [
{"id": str(i), "name_de": f"Hafer Gericht {i}", "name_en": "", "_c": f"hafergericht{i}"}
for i in range(80)
]
packed = suggest_for_name(index, "Haferflocken", limit=3)
assert packed["suggestions"][0]["name_de"] == "Hafer Flocken"
def test_suggest_batch_dedupes_names():
class _Cur:
def execute(self, *args, **kwargs):
return None
def fetchall(self):
return []
out = suggest_batch(_Cur(), None, ["Haferflocken", "Haferflocken", ""], limit=2)
assert "Haferflocken" in out
assert out["Haferflocken"]["suggestions"] == []
def test_number_tokens_keep_decimal_fat():
assert "9.5" in name_tokens("Joghurt 9,5%")
assert "10" in name_tokens("Joghurt, aus Kuhmilch, 10 % Fett")
def test_joghurt_10_ranks_above_35():
light = {"id": "a", "name_de": "Joghurt >3,5% Fett", "name_en": "", "bls_code": "M", "catalog_kind": "official_bls"}
full = {
"id": "b",
"name_de": "Joghurt, aus Kuhmilch, 10 % Fett",
"name_en": "",
"bls_code": "N",
"catalog_kind": "official_bls",
}
index = _index(light, full)
for query in ("Joghurt 10%", "Joghurt 9,5%", "Joghurt 10"):
packed = suggest_for_name(index, query, limit=3)
assert packed["suggestions"][0]["name_de"] == full["name_de"], query
assert packed["suggestions"][0]["score"] > score_name_match(query, light["name_de"])