waxwing/tests/test_knowledge_query.py
pyr0ball c81fa3a93a feat: add Plex integration, update knowledge API and config
- Add app/api/endpoints/plex.py with Plex webhook receiver (fail-closed on missing secret)
- Add app/services/plex/ with Plex API client and gardening content filter
- Wire plex router into routes.py at /plex prefix
- Add Plex + cf-video config vars to app/core/config.py and .env.example
- Rename /knowledge/ingest endpoint to /knowledge/glean (pipeline verb alignment)
- Update tests to use /knowledge/glean endpoint
- Add python-multipart to environment.yml for form/webhook body parsing
- Add dev/dev-stop/dev-logs commands to manage.sh (hot-reload without Docker)
- Fix frontend/tsconfig.node.json to extend tsconfig.json (not tsconfig.node.json)
- Add .dev-pids/ to .gitignore
- Add frontend/package-lock.json
2026-07-11 22:38:37 -07:00

95 lines
3.7 KiB
Python

"""Knowledge query endpoint tests."""
_SOURCE_A = {
"video_path": "/media/GW/s59e01.mkv",
"presenter": "Monty Don",
"location": "Longmeadow",
"source_domain": "gardening",
}
_SOURCE_B = {
"video_path": "/media/GW/s59e02.mkv",
"presenter": "Adam Frost",
"location": "Adam's Garden",
"source_domain": "gardening",
}
def _ingest(client, source, facts):
return client.post("/api/v1/knowledge/glean", json={"source": source, "facts": facts}).json()
def test_query_all_returns_inserted_facts(client):
_ingest(client, _SOURCE_A, [
{"fact_type": "instruction", "confidence": 0.9, "payload": {"action": "mulch", "subject": "border", "steps": [], "timing": None}},
])
resp = client.get("/api/v1/knowledge")
assert resp.status_code == 200
assert len(resp.json()) == 1
def test_query_filter_by_fact_type(client):
_ingest(client, _SOURCE_A, [
{"fact_type": "companion_planting", "confidence": 0.9, "payload": {"plants": ["tomato", "basil"], "relationship": "beneficial", "benefit": None, "spacing": None}},
{"fact_type": "instruction", "confidence": 0.8, "payload": {"action": "prune", "subject": "roses", "steps": [], "timing": None}},
])
resp = client.get("/api/v1/knowledge?fact_type=companion_planting")
assert resp.status_code == 200
data = resp.json()
assert len(data) == 1
assert data[0]["fact_type"] == "companion_planting"
def test_query_filter_by_presenter(client):
_ingest(client, _SOURCE_A, [
{"fact_type": "instruction", "confidence": 0.9, "payload": {"action": "water", "subject": "seedlings", "steps": [], "timing": None}},
])
_ingest(client, _SOURCE_B, [
{"fact_type": "soil_amendment", "confidence": 0.85, "payload": {"amendment": "compost", "purpose": "feed soil", "application_rate": "2cm", "timing": "spring", "target_plants": []}},
])
resp = client.get("/api/v1/knowledge?presenter=Adam")
assert resp.status_code == 200
data = resp.json()
assert all(d["presenter"] == "Adam Frost" for d in data)
def test_query_filter_by_min_confidence(client):
_ingest(client, _SOURCE_A, [
{"fact_type": "instruction", "confidence": 0.95, "payload": {"action": "sow", "subject": "tithonia", "steps": [], "timing": None}},
{"fact_type": "medicinal", "confidence": 0.40, "payload": {"plant": "calendula", "use": "topical", "preparation": None, "cautions": None}},
])
resp = client.get("/api/v1/knowledge?min_confidence=0.8")
assert resp.status_code == 200
data = resp.json()
assert all(d["confidence"] >= 0.8 for d in data)
assert len(data) == 1
def test_query_payload_is_dict_not_string(client):
_ingest(client, _SOURCE_A, [
{"fact_type": "history_context", "confidence": 0.7, "payload": {
"subject": "Wisteria", "origin": "China", "period": None, "summary": "Introduced in 1816.",
}},
])
resp = client.get("/api/v1/knowledge")
assert resp.status_code == 200
payload = resp.json()[0]["payload"]
assert isinstance(payload, dict)
assert payload["subject"] == "Wisteria"
def test_get_single_fact_by_id(client):
_ingest(client, _SOURCE_A, [
{"fact_type": "harvest_timing", "confidence": 0.88, "payload": {
"plant": "Courgette", "indicators": ["20cm length"], "harvest_method": "twist off", "post_harvest": None,
}},
])
facts = client.get("/api/v1/knowledge").json()
fact_id = facts[0]["id"]
resp = client.get(f"/api/v1/knowledge/{fact_id}")
assert resp.status_code == 200
assert resp.json()["payload"]["plant"] == "Courgette"
def test_get_fact_not_found(client):
resp = client.get("/api/v1/knowledge/9999")
assert resp.status_code == 404