2026-09-12 16:59:24 +02:00
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
2026-09-12 16:14:24 +02:00
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 " ] == [ ]
2026-09-12 16:59:24 +02:00
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 % F ett " )
def test_joghurt_10_ranks_above_35 ( ) :
light = { " id " : " a " , " name_de " : " Joghurt >3,5 % F ett " , " name_en " : " " , " bls_code " : " M " , " catalog_kind " : " official_bls " }
full = {
" id " : " b " ,
" name_de " : " Joghurt, aus Kuhmilch, 10 % F ett " ,
" 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 " ] )
2026-09-14 12:47:12 +02:00
def test_personal_food_ranks_above_bls_on_tie ( ) :
bls = { " id " : " bls " , " name_de " : " Omega-3 Öl " , " name_en " : " " , " bls_code " : " X " , " catalog_kind " : " official_bls " }
mine = { " id " : " me " , " name_de " : " Omega-3 Öl " , " name_en " : " " , " bls_code " : None , " catalog_kind " : " manual_user " , " owner_profile_id " : " u1 " }
packed = suggest_for_name ( _index ( bls , mine ) , " Omega-3 Öl " , limit = 2 )
assert packed [ " suggestions " ] [ 0 ] [ " id " ] == " me "
assert packed [ " suggestions " ] [ 0 ] [ " visibility " ] == " personal "