"""AP0.9 — Operating Model Extension II tests.""" from __future__ import annotations from datetime import datetime, timedelta, timezone from tests.factories import provision_user_in_tenant from tests.test_initiatives_actions import ( _auth, _create_action, _create_initiative, _login, ) def _create_evidence(client, token, initiative_id, **kwargs): body = {"title": "Evidence Test", **kwargs} return client.post( f"/api/initiatives/{initiative_id}/evidence", json=body, headers=_auth(token), ) def _create_decision(client, token, initiative_id, **kwargs): body = {"title": "Decision Test", **kwargs} return client.post( f"/api/initiatives/{initiative_id}/decisions", json=body, headers=_auth(token), ) def _create_review(client, token, initiative_id, **kwargs): body = {"title": "Review Test", **kwargs} return client.post( f"/api/initiatives/{initiative_id}/reviews", json=body, headers=_auth(token), ) def _create_recurring(client, token, initiative_id, **kwargs): body = {"title": "Recurring Test", **kwargs} return client.post( f"/api/initiatives/{initiative_id}/recurring", json=body, headers=_auth(token), ) def test_action_ready_status_and_due_at(client): user = provision_user_in_tenant(tenant_role="member") token = _login(client, user) initiative_id = _create_initiative(client, token).json()["id"] due = (datetime.now(timezone.utc) - timedelta(days=1)).isoformat() created = client.post( f"/api/initiatives/{initiative_id}/actions", json={"title": "Due Action", "status": "ready", "due_at": due}, headers=_auth(token), ) assert created.status_code == 201 action = created.json() assert action["status"] == "ready" assert action["due_at"] is not None def test_attention_overdue_action(client): user = provision_user_in_tenant(tenant_role="member") token = _login(client, user) initiative_id = _create_initiative(client, token).json()["id"] action = _create_action(client, token, initiative_id, title="Overdue").json() past = (datetime.now(timezone.utc) - timedelta(hours=2)).isoformat() client.patch( f"/api/actions/{action['id']}", json={"due_at": past}, headers=_auth(token), ) res = client.get("/api/workspace/attention", headers=_auth(token)) assert res.status_code == 200 assert any(i["kind"] == "overdue_action" for i in res.json()) def test_attention_review_due(client): user = provision_user_in_tenant(tenant_role="member") token = _login(client, user) initiative_id = _create_initiative(client, token).json()["id"] past = (datetime.now(timezone.utc) - timedelta(hours=1)).isoformat() created = _create_review( client, token, initiative_id, status="planned", due_at=past ) assert created.status_code == 201 res = client.get("/api/workspace/attention", headers=_auth(token)) assert res.status_code == 200 assert any(i["kind"] == "review_due" for i in res.json()) def test_attention_recurring_due(client): user = provision_user_in_tenant(tenant_role="member") token = _login(client, user) initiative_id = _create_initiative(client, token).json()["id"] past = (datetime.now(timezone.utc) - timedelta(hours=1)).isoformat() created = _create_recurring( client, token, initiative_id, status="active", next_due_at=past ) assert created.status_code == 201 res = client.get("/api/workspace/attention", headers=_auth(token)) assert res.status_code == 200 assert any(i["kind"] == "recurring_due" for i in res.json()) def test_evidence_crud(client): user = provision_user_in_tenant(tenant_role="member") token = _login(client, user) initiative_id = _create_initiative(client, token).json()["id"] created = _create_evidence(client, token, initiative_id) assert created.status_code == 201 ev_id = created.json()["id"] listed = client.get( f"/api/initiatives/{initiative_id}/evidence", headers=_auth(token) ) assert listed.status_code == 200 assert len(listed.json()) == 1 deleted = client.delete(f"/api/evidence/{ev_id}", headers=_auth(token)) assert deleted.status_code == 204 def test_decision_crud(client): user = provision_user_in_tenant(tenant_role="member") token = _login(client, user) initiative_id = _create_initiative(client, token).json()["id"] created = _create_decision(client, token, initiative_id, status="proposed") assert created.status_code == 201 dec_id = created.json()["id"] patched = client.patch( f"/api/decisions/{dec_id}", json={"status": "decided", "outcome": "Ja"}, headers=_auth(token), ) assert patched.status_code == 200 assert patched.json()["status"] == "decided" def test_member_has_ap09_capabilities(client): member = provision_user_in_tenant(tenant_role="member") token = _login(client, member) ctx = client.get("/api/me/context", headers=_auth(token)).json() caps = ctx["capabilities"] for key in ( "kairo.evidence.read", "kairo.evidence.manage", "kairo.decision.read", "kairo.decision.manage", "kairo.review.read", "kairo.review.manage", "kairo.recurring.read", "kairo.recurring.manage", ): assert key in caps