Limit order discovery and Open Food Facts searches

This commit is contained in:
Edward Betts 2026-10-07 11:16:50 +01:00
parent 628e5c3823
commit 41772b4d1a
5 changed files with 185 additions and 78 deletions

View file

@ -83,19 +83,54 @@ def test_two_exact_barcodes_are_ambiguous():
assert match is None
def test_truncated_catalog_is_split_and_pages_must_be_complete(tmp_path):
def test_product_search_is_bounded_and_includes_name_and_brand(tmp_path):
from ocado_grocy.openfoodfacts import OpenFoodFacts
calls = []
class OFF(OpenFoodFacts):
def fetch(self, path, params, **kwargs):
if params['q'] == 'brands_tags:(a OR b)':
return {'is_count_exact':False, 'hits':[]}
code = '00000048' if params['q'] == 'brands_tags:(a)' else '00000055'
return {'is_count_exact':True, 'count':1, 'page_count':1, 'hits':[{'code':code,'brands':['a']}]}
off = OFF(tmp_path, 'test@example.com')
assert len(off.catalog({'a','b'})) == 2
off.fetch = lambda *args, **kwargs: {'is_count_exact':True, 'count':2, 'page_count':1, 'hits':[]}
with pytest.raises(ValueError, match='Incomplete'):
off.catalog({'a'})
calls.append(params)
return {'is_count_exact': True, 'count': 9000,
'hits': [{**candidate(), 'brands': ['Marks & Spencer']}]}
candidates, result = OFF(tmp_path, 'test@example.com').search(product(), metadata())
assert len(calls) == 1
assert calls[0]['page_size'] == 100 and calls[0]['page'] == 1
assert 'ginger' in calls[0]['q'] and 'snaps' in calls[0]['q']
assert 'marks-spencer' in calls[0]['q']
assert candidates[candidate()['code']]['brands'] == 'Marks & Spencer'
assert not result['search_complete']
@pytest.mark.parametrize('complete', [True, False])
def test_matching_searches_only_selected_products_and_requires_complete_results(tmp_path, monkeypatch, complete):
from ocado_grocy import openfoodfacts as module
searched = []
class OFF:
def __init__(self, *args): pass
def search(self, p, m, offline):
searched.append(p['id'])
return {candidate()['code']: candidate()}, {'search_complete': complete}
class Client:
def get(self, path):
assert path == '/objects/product_barcodes'
return []
monkeypatch.setattr(module, 'OpenFoodFacts', OFF)
nonfood = {**product(), 'id': 43}
nonfood['description'] = replace_metadata(nonfood['description'],
{**metadata(), 'ocado': {'brand': 'Miniml'}})
result = module.run_openfoodfacts(Client(), [nonfood, product(), {**product(), 'id': 44}],
tmp_path, 'test@example.com', apply=False, limit=1)
assert searched == [42]
assert [r['status'] for r in result['products']] == [
'non_food', 'matched' if complete else 'review', 'not_searched']
@pytest.mark.parametrize('error', [{'timed_out': True}, {'warnings': ['partial']}, {'errors': ['bad query']}])
def test_failed_search_is_not_reported_as_no_match(tmp_path, error):
from ocado_grocy.openfoodfacts import OpenFoodFacts
off = OpenFoodFacts(tmp_path, 'test@example.com')
off.fetch = lambda *args, **kwargs: error
with pytest.raises(ValueError, match='Incomplete product search'):
off.search(product(), metadata())
def test_ms_food_brand_and_missing_barcode_recovery():
@ -116,7 +151,7 @@ def test_established_barcode_match_survives_a_missing_catalog_entry(tmp_path, mo
p['description'] = replace_metadata(p['description'], m)
class OFF:
def __init__(self, *a): pass
def catalog(self, *a): return []
def search(self, *a): pytest.fail("Established match must not trigger search")
def product(self, code, offline):
assert code == candidate()['code']
return candidate()