feat: product enrichment observability, lab KB study, benchmark, copy + local-Hub E2E, docs; 1.3.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,7 @@ def test_health_is_unavailable_when_database_is_down():
|
||||
|
||||
def test_version_endpoint_reports_release_and_fiscal_versions():
|
||||
body = TestClient(create_app(database_probe=lambda: True)).get("/version").json()
|
||||
assert body["version"] == "1.2.5" and body["api_compat"] == "1.0" and body["engine_version"] and body["decision_version"]
|
||||
assert body["version"] == "1.3.0" and body["api_compat"] == "1.0" and body["engine_version"] and body["decision_version"]
|
||||
|
||||
|
||||
def test_production_refuses_the_dev_token(monkeypatch):
|
||||
|
||||
@@ -94,3 +94,67 @@ def test_features_route_is_admin_only_csrf_and_audited():
|
||||
assert "INSTALLATION_FEATURES" in [e.action for e in s.scalars(select(AuditEvent))]
|
||||
page = client.get(f"/agents/{agent_id}")
|
||||
assert "Funcionalidades" in page.text and "Enriquecimento" in page.text
|
||||
|
||||
|
||||
def test_dashboard_shows_sources_without_tokens_and_official_freshness(monkeypatch):
|
||||
from central.app.enrichment import observability, providers
|
||||
monkeypatch.setattr(observability, "build_providers", lambda _s: providers.build_providers(type("S", (), {"cosmos_token": "SEGREDO-NAO-VAZAR", "allow_paid_providers": False})()))
|
||||
client, agent_id, _ = _panel_client()
|
||||
page = client.get("/").text
|
||||
assert "Fontes de produtos" in page and "cosmos" in page and "configurado: sim" in page and "upcitemdb" in page and "openfoodfacts" in page
|
||||
assert "SEGREDO-NAO-VAZAR" not in page and "Fontes oficiais" in page and "NCM (Siscomex)" in page
|
||||
|
||||
|
||||
def _second_agent(engine, mode="ENABLED", corrector=True):
|
||||
from central.app.auth import token_hash
|
||||
from central.app.models import Agent, Tenant
|
||||
with Session(engine) as s:
|
||||
first = s.scalars(select(Installation)).first()
|
||||
agent = Agent(tenant_id=first.tenant_id, name="second", token_hash=token_hash("second-token"), enabled=True)
|
||||
s.add(agent)
|
||||
s.flush()
|
||||
s.add(Installation(agent_id=agent.id, tenant_id=first.tenant_id, installation_id="00000000-0000-4000-8000-0000000000bb", display_name="B", features_configured=True, corrector_enabled=corrector, enrichment_mode=mode))
|
||||
s.commit()
|
||||
return {"Authorization": "Bearer second-token"}
|
||||
|
||||
|
||||
def test_same_product_in_another_installation_costs_zero_extra_provider_requests(monkeypatch):
|
||||
client, engine = setup(monkeypatch)
|
||||
h2 = _second_agent(engine)
|
||||
providers = enrich_api.PROVIDERS_OVERRIDE
|
||||
first = resolve(client)
|
||||
calls_after_first = [p.calls for p in providers]
|
||||
second = client.post("/v1/products/resolve", json={"product_code": "X9", "gtin": G1, "description": "REFRIGERANTE COLA LATA 350ML", "current": {}}, headers=h2).json()
|
||||
assert [p.calls for p in providers] == calls_after_first # other installation: served by KB, zero external calls
|
||||
assert second["state"] == "EXACT_GTIN_VERIFIED" and second["fields"]["CLASSIFICACAO_FISCAL"]["value"] == first["fields"]["CLASSIFICACAO_FISCAL"]["value"]
|
||||
with Session(engine) as s:
|
||||
assert {r.installation_id for r in s.scalars(select(ProductEnrichment))} == {1, 2}
|
||||
|
||||
|
||||
def test_installations_are_isolated_by_their_own_feature_flags(monkeypatch):
|
||||
client, engine = setup(monkeypatch, "DISABLED")
|
||||
h2 = _second_agent(engine, "ENABLED")
|
||||
assert resolve(client)["state"] == "FEATURE_DISABLED"
|
||||
body = client.post("/v1/products/resolve", json={"product_code": "N1", "gtin": G1, "description": "REFRIGERANTE COLA LATA 350ML", "current": {}}, headers=h2).json()
|
||||
assert body["state"] != "FEATURE_DISABLED" and body["fields"]["CLASSIFICACAO_FISCAL"]["status"] == "AUTO_FILL_SAFE"
|
||||
|
||||
|
||||
def test_quota_exhausted_gives_pending_state_and_retry_time_through_the_api(monkeypatch):
|
||||
client, engine = setup(monkeypatch)
|
||||
monkeypatch.setattr(enrich_api, "PROVIDERS_OVERRIDE", [Fake("cosmos", COSMOS(), True, daily_limit=1)])
|
||||
resolve(client, "A1", G1)
|
||||
body = resolve(client, "A2", G4, "OUTRO PRODUTO")
|
||||
assert body["state"] == "PENDING_PROVIDER_QUOTA" and body["retry_at"]
|
||||
with Session(engine) as s:
|
||||
row = s.scalars(select(ProductEnrichment).where(ProductEnrichment.product_code == "A2")).one()
|
||||
assert row.status == "PENDING" and row.next_attempt_at is not None
|
||||
assert s.scalars(select(BlockedProduct).where(BlockedProduct.reason_code == "PENDING_PROVIDER_QUOTA")).one().field == "ENRICHMENT"
|
||||
|
||||
|
||||
def test_corrector_switch_off_stops_jobs_but_not_enrichment(monkeypatch):
|
||||
client, engine = setup(monkeypatch)
|
||||
with Session(engine) as s:
|
||||
s.scalars(select(Installation)).one().corrector_enabled = False
|
||||
s.commit()
|
||||
assert client.get("/v1/jobs/next", headers=H).json() is None
|
||||
assert resolve(client)["state"] != "FEATURE_DISABLED"
|
||||
|
||||
@@ -223,7 +223,7 @@ def test_cosmos_without_token_is_not_configured_and_costs_nothing(env):
|
||||
|
||||
def test_paid_provider_guard():
|
||||
class S: allow_paid_providers = False; cosmos_token = None
|
||||
assert [p.name for p in build_providers(S())] == ["cosmos", "upcitemdb", "openfoodfacts"]
|
||||
assert [p.name for p in build_providers(S())] == ["cosmos", "upcitemdb", "openfoodfacts", "openproductsfacts", "openbeautyfacts"]
|
||||
|
||||
|
||||
# ---- provider contract tests against recorded fixtures (httpx.MockTransport, no network) ----------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user