test_hosted_dashboard_integration.py
file-level
1
files
1
commits
0
hotspots
0
🧊 dead
0
💥 blast risk
| 1 | """Integration tests for hosted governance dashboard (§HGD.12).""" |
| 2 | |
| 3 | from __future__ import annotations |
| 4 | |
| 5 | from tests.fixtures.hosted_dashboard import FixtureUpstream, start_test_hosted |
| 6 | from tools.hosted_dashboard.config import parse_hosted_dashboard_config |
| 7 | |
| 8 | |
| 9 | def test_health_body_unauthenticated() -> None: |
| 10 | handle, client, _ = start_test_hosted() |
| 11 | try: |
| 12 | status, payload = client.get("/api/health", auth=False) |
| 13 | assert status == 200 |
| 14 | assert payload["result"] == {"status": "ok", "mode": "hosted-read-only"} |
| 15 | finally: |
| 16 | handle.shutdown() |
| 17 | |
| 18 | |
| 19 | def test_org_summary_and_docs_envelope() -> None: |
| 20 | handle, client, _ = start_test_hosted() |
| 21 | try: |
| 22 | status, summary = client.get("/api/org/summary") |
| 23 | assert status == 200 |
| 24 | assert summary["ok"] is True |
| 25 | assert summary["meta"]["authoritative_workflow"] == "local" |
| 26 | repos = summary["result"]["repos"] |
| 27 | assert len(repos) == 1 |
| 28 | assert repos[0]["eligibility"] == "eligible" |
| 29 | |
| 30 | status, roadmap = client.get("/api/repos/acme/kit-demo/roadmap") |
| 31 | assert status == 200 |
| 32 | assert "Alpha" in roadmap["result"]["text"] |
| 33 | assert len(roadmap["result"]["sha256"]) == 64 |
| 34 | assert roadmap["result"]["path"] == "docs/ROADMAP.md" |
| 35 | |
| 36 | status, handover = client.get("/api/repos/acme/kit-demo/handover") |
| 37 | assert status == 200 |
| 38 | assert "Pending gates" in handover["result"]["text"] |
| 39 | |
| 40 | status, gates = client.get("/api/repos/acme/kit-demo/gates") |
| 41 | assert status == 200 |
| 42 | assert gates["result"]["document_derived"]["ok"] is True |
| 43 | assert gates["result"]["advisory_checks"] is None |
| 44 | finally: |
| 45 | handle.shutdown() |
| 46 | |
| 47 | |
| 48 | def test_missing_doc_not_found() -> None: |
| 49 | upstream = FixtureUpstream() |
| 50 | upstream.put_repo("acme", "empty") |
| 51 | upstream.put_file("acme", "empty", ".overseer/config.yaml", "docs: {}\n") |
| 52 | raw = { |
| 53 | "enabled": True, |
| 54 | "org_allowlist": ["acme/empty"], |
| 55 | "sources": { |
| 56 | "github_contents": True, |
| 57 | "github_meta": True, |
| 58 | "github_checks_advisory": False, |
| 59 | "musehub_read": False, |
| 60 | }, |
| 61 | } |
| 62 | handle, client, _ = start_test_hosted( |
| 63 | upstream=upstream, |
| 64 | config=parse_hosted_dashboard_config(raw), |
| 65 | ) |
| 66 | try: |
| 67 | status, payload = client.get("/api/repos/acme/empty/roadmap") |
| 68 | assert status == 404 |
| 69 | assert payload["error"] == "not_found" |
| 70 | finally: |
| 71 | handle.shutdown() |
| 72 | |
| 73 | |
| 74 | def test_write_scope_route_refuse() -> None: |
| 75 | handle, client, _ = start_test_hosted(write_scope_refused=True) |
| 76 | try: |
| 77 | status, payload = client.get("/api/org/summary") |
| 78 | assert status == 403 |
| 79 | assert payload["error"] == "write_scope_refused" |
| 80 | status, health = client.get("/api/health", auth=False) |
| 81 | assert status == 200 |
| 82 | finally: |
| 83 | handle.shutdown() |
| 84 | |
| 85 | |
| 86 | def test_cors_deny_non_allowlisted_origin() -> None: |
| 87 | handle, client, _ = start_test_hosted(cors_origins=("https://allowed.example",)) |
| 88 | try: |
| 89 | status, payload = client.get("/api/org/summary", origin="https://evil.example") |
| 90 | assert status == 403 |
| 91 | assert payload["error"] == "origin" |
| 92 | finally: |
| 93 | handle.shutdown() |
| 94 | |
| 95 | |
| 96 | def test_disallowed_upstream_host_refused() -> None: |
| 97 | from tools.hosted_dashboard.http_client import UpstreamClient, UpstreamError |
| 98 | |
| 99 | client = UpstreamClient(token=None) |
| 100 | try: |
| 101 | client.get_json("https://evil.example/repos/a/b") |
| 102 | assert False, "expected refuse" |
| 103 | except UpstreamError as exc: |
| 104 | assert exc.token == "upstream_host_refused" |
| 105 | |
| 106 | |
| 107 | def test_track_q_paths_not_registered() -> None: |
| 108 | handle, client, _ = start_test_hosted() |
| 109 | try: |
| 110 | for path in ( |
| 111 | "/api/review/freeze", |
| 112 | "/api/governance-sync", |
| 113 | "/api/ledger/append", |
| 114 | "/api/honesty-status", |
| 115 | ): |
| 116 | status, payload = client.get(path) |
| 117 | assert status == 404 |
| 118 | assert payload["error"] == "not_found" |
| 119 | finally: |
| 120 | handle.shutdown() |
| 121 | |
| 122 | |
| 123 | def test_empty_allowlist_zero_repos() -> None: |
| 124 | raw = { |
| 125 | "enabled": True, |
| 126 | "org_allowlist": [], |
| 127 | "sources": { |
| 128 | "github_contents": True, |
| 129 | "github_meta": True, |
| 130 | "github_checks_advisory": False, |
| 131 | "musehub_read": False, |
| 132 | }, |
| 133 | } |
| 134 | handle, client, _ = start_test_hosted(config=parse_hosted_dashboard_config(raw)) |
| 135 | try: |
| 136 | status, summary = client.get("/api/org/summary") |
| 137 | assert status == 200 |
| 138 | assert summary["result"]["repos"] == [] |
| 139 | finally: |
| 140 | handle.shutdown() |
| 141 | |
| 142 | |
| 143 | def test_unknown_query_400() -> None: |
| 144 | handle, client, _ = start_test_hosted() |
| 145 | try: |
| 146 | status, payload = client.get("/api/org/summary?path=secrets") |
| 147 | assert status == 400 |
| 148 | assert payload["error"] == "unknown_query" |
| 149 | finally: |
| 150 | handle.shutdown() |