generated from coulomb/repo-seed
Implement RecentlyOnScope domain digest
This commit is contained in:
173
tests/test_recently_on_scope.py
Normal file
173
tests/test_recently_on_scope.py
Normal file
@@ -0,0 +1,173 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import UTC, datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from api.services import recently_on_scope as ros
|
||||
from api.services.markitect_templates import MarkitectUnavailable
|
||||
|
||||
|
||||
async def _create_domain(client, slug="digest", name="Digest Domain"):
|
||||
response = await client.post("/domains/", json={"slug": slug, "name": name})
|
||||
assert response.status_code == 201, response.text
|
||||
return response.json()
|
||||
|
||||
|
||||
async def _create_topic(client, domain_slug="digest", slug="digest-topic", title="Digest Topic"):
|
||||
response = await client.post("/topics/", json={"slug": slug, "title": title, "domain": domain_slug})
|
||||
assert response.status_code == 201, response.text
|
||||
return response.json()
|
||||
|
||||
|
||||
async def _create_workstream(client, topic_id, slug="digest-ws", title="Digest Workstream"):
|
||||
response = await client.post("/workstreams/", json={"topic_id": topic_id, "slug": slug, "title": title})
|
||||
assert response.status_code == 201, response.text
|
||||
return response.json()
|
||||
|
||||
|
||||
async def _create_task(client, workstream_id, title="Digest task"):
|
||||
response = await client.post("/tasks/", json={"workstream_id": workstream_id, "title": title})
|
||||
assert response.status_code == 201, response.text
|
||||
return response.json()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_markitect(monkeypatch):
|
||||
def _inspect(_template_path):
|
||||
return {"valid": True, "variables": []}
|
||||
|
||||
def _render(_template_path, data):
|
||||
counts = data["source_counts"]
|
||||
return f"""---
|
||||
type: recently_on_scope_digest
|
||||
domain_slug: "{data["domain"]["slug"]}"
|
||||
domain_name: "{data["domain"]["name"]}"
|
||||
range: "{data["window"]["range"]}"
|
||||
since: "{data["window"]["since"]}"
|
||||
until: "{data["window"]["until"]}"
|
||||
generated_at: "{data["generated_at"]}"
|
||||
template_version: "{data["template_version"]}"
|
||||
source_counts:
|
||||
progress_events: {counts["progress_events"]}
|
||||
decisions: {counts["decisions"]}
|
||||
workstreams: {counts["workstreams"]}
|
||||
tasks: {counts["tasks"]}
|
||||
repos: {counts["repos"]}
|
||||
attention_items: {counts["attention_items"]}
|
||||
---
|
||||
|
||||
# RecentlyOnScope - {data["domain"]["name"]}
|
||||
|
||||
{data["progress_section"]}
|
||||
"""
|
||||
|
||||
monkeypatch.setattr(ros, "inspect_markdown_template", _inspect)
|
||||
monkeypatch.setattr(ros, "render_markdown_template", _render)
|
||||
|
||||
|
||||
def test_resolve_window_defaults_to_one_hour():
|
||||
now = datetime(2026, 5, 22, 12, 0, tzinfo=UTC)
|
||||
window = ros.resolve_window(now=now)
|
||||
|
||||
assert window.range == "1h"
|
||||
assert window.since == datetime(2026, 5, 22, 11, 0, tzinfo=UTC)
|
||||
assert window.until == now
|
||||
assert ros.report_id_for(window) == "20260522T120000Z--1h"
|
||||
|
||||
|
||||
def test_resolve_window_exact_range_id():
|
||||
since = datetime(2026, 5, 22, 10, 30, tzinfo=UTC)
|
||||
until = datetime(2026, 5, 22, 12, 0, tzinfo=UTC)
|
||||
window = ros.resolve_window("6h", since=since, until=until)
|
||||
|
||||
assert window.exact is True
|
||||
assert ros.report_id_for(window) == "20260522T103000Z--20260522T120000Z"
|
||||
|
||||
|
||||
def test_resolve_window_rejects_ambiguous_duration():
|
||||
with pytest.raises(ValueError):
|
||||
ros.resolve_window("hour")
|
||||
|
||||
|
||||
class TestRecentlyOnScopeRoutes:
|
||||
async def test_generate_list_and_read_digest(self, client, tmp_path, monkeypatch, fake_markitect):
|
||||
monkeypatch.setattr(ros.settings, "state_hub_report_dir", str(tmp_path))
|
||||
|
||||
await _create_domain(client)
|
||||
topic = await _create_topic(client)
|
||||
workstream = await _create_workstream(client, topic["id"])
|
||||
task = await _create_task(client, workstream["id"], title="Build digest source")
|
||||
await client.patch(
|
||||
f"/tasks/{task['id']}",
|
||||
json={"needs_human": True, "intervention_note": "Review the generated summary."},
|
||||
)
|
||||
progress = await client.post(
|
||||
"/progress/",
|
||||
json={
|
||||
"topic_id": topic["id"],
|
||||
"workstream_id": workstream["id"],
|
||||
"task_id": task["id"],
|
||||
"event_type": "note",
|
||||
"summary": "Built digest source",
|
||||
"author": "codex",
|
||||
},
|
||||
)
|
||||
assert progress.status_code == 201, progress.text
|
||||
|
||||
await _create_domain(client, slug="elsewhere", name="Elsewhere")
|
||||
other_topic = await _create_topic(client, domain_slug="elsewhere", slug="other-topic")
|
||||
other_progress = await client.post(
|
||||
"/progress/",
|
||||
json={"topic_id": other_topic["id"], "event_type": "note", "summary": "Do not include"},
|
||||
)
|
||||
assert other_progress.status_code == 201, other_progress.text
|
||||
|
||||
response = await client.post("/domains/digest/recently-on-scope/", json={"range": "1d"})
|
||||
assert response.status_code == 201, response.text
|
||||
body = response.json()
|
||||
|
||||
assert body["domain_slug"] == "digest"
|
||||
assert body["range"] == "1d"
|
||||
assert body["source_counts"]["progress_events"] == 1
|
||||
assert body["source_counts"]["attention_items"] == 1
|
||||
assert "Built digest source" in body["markdown"]
|
||||
|
||||
listed = await client.get("/domains/digest/recently-on-scope/")
|
||||
assert listed.status_code == 200
|
||||
reports = listed.json()
|
||||
assert len(reports) == 1
|
||||
assert reports[0]["id"] == body["id"]
|
||||
|
||||
markdown = await client.get(f"/domains/digest/recently-on-scope/{body['id']}")
|
||||
assert markdown.status_code == 200
|
||||
assert markdown.headers["content-type"].startswith("text/markdown")
|
||||
assert "RecentlyOnScope - Digest Domain" in markdown.text
|
||||
|
||||
async def test_generate_rejects_bad_range(self, client, tmp_path, monkeypatch, fake_markitect):
|
||||
monkeypatch.setattr(ros.settings, "state_hub_report_dir", str(tmp_path))
|
||||
await _create_domain(client)
|
||||
|
||||
response = await client.post("/domains/digest/recently-on-scope/", json={"range": "yesterday"})
|
||||
|
||||
assert response.status_code == 422
|
||||
|
||||
async def test_generate_reports_missing_markitect(self, client, tmp_path, monkeypatch):
|
||||
monkeypatch.setattr(ros.settings, "state_hub_report_dir", str(tmp_path))
|
||||
|
||||
def _missing_markitect(_template_path):
|
||||
raise MarkitectUnavailable("MarkiTect unavailable")
|
||||
|
||||
monkeypatch.setattr(ros, "inspect_markdown_template", _missing_markitect)
|
||||
await _create_domain(client)
|
||||
|
||||
response = await client.post("/domains/digest/recently-on-scope/", json={"range": "1h"})
|
||||
|
||||
assert response.status_code == 503
|
||||
|
||||
async def test_missing_report_returns_404(self, client, tmp_path, monkeypatch):
|
||||
monkeypatch.setattr(ros.settings, "state_hub_report_dir", str(tmp_path))
|
||||
|
||||
response = await client.get("/domains/digest/recently-on-scope/20260522T120000Z--1h")
|
||||
|
||||
assert response.status_code == 404
|
||||
Reference in New Issue
Block a user