File size: 1,701 Bytes
47a6953 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | from __future__ import annotations
from app import demo_gap
from app.models import Tenant
class _Chunk:
pass
async def test_gap_report_labels_hit_and_miss(db_session, monkeypatch):
t = Tenant(slug="demo-x", name="X", brand_name="Tienda X", is_demo=True)
db_session.add(t)
await db_session.flush()
# Deterministic retrieval: only the shipping questions are "answered" by the
# store's pages (score above threshold); everything else is a gap.
async def fake_search(db, q, k=3, tenant_id=None):
score = 0.55 if "env" in q.lower() else 0.10
return [(_Chunk(), score)]
monkeypatch.setattr(demo_gap.rag_index, "search", fake_search)
rep = await demo_gap.generate_gap_report(db_session, t, lang="es")
assert rep["brand"] == "Tienda X"
assert rep["total"] == len(demo_gap.GAP_QUESTIONS["es"])
hits = [r for r in rep["questions"] if r["status"] == "hit"]
assert hits and all("env" in r["q"].lower() for r in hits) # only shipping = HIT
assert rep["answered"] == len(hits)
assert rep["gap_count"] == rep["total"] - len(hits)
assert all(g not in [h["q"] for h in hits] for g in rep["gaps"])
async def test_gap_report_all_miss_when_nothing_indexed(db_session, monkeypatch):
t = Tenant(slug="demo-empty", is_demo=True)
db_session.add(t)
await db_session.flush()
async def empty_search(db, q, k=3, tenant_id=None):
return [] # store crawled nothing useful -> every buyer question is a gap
monkeypatch.setattr(demo_gap.rag_index, "search", empty_search)
rep = await demo_gap.generate_gap_report(db_session, t, lang="en")
assert rep["gap_count"] == rep["total"] and rep["answered"] == 0
|