test_q4b_ui_e2e.py python
124 lines 3.8 KB
Raw
sha256:0e9549ec7b463911bc08b7d586dc320b1ac9b1f5c943ee7e3865dcc6cb0f6f83 chore(governance): sync handover+roadmap to 84db8c8 (drift:… Human 1 day ago
1 """End-to-end tests for Track Q / Q4b Path B UI redesign (§Q4A.15)."""
2
3 from __future__ import annotations
4
5 import os
6 import signal
7 import subprocess
8 import sys
9 import time
10 import urllib.request
11 from pathlib import Path
12
13 from cli.kit_root import kit_root
14 from tests.fixtures.app import free_port, seed_app_e2e_repo, seed_app_repo, start_test_app
15 from tests.support import FIXTURES, make_runner, ok, pass_provider_factory
16
17 DIAGRAMS = (
18 "/assets/diagrams/lanes.svg",
19 "/assets/diagrams/regimes.svg",
20 "/assets/diagrams/layers.svg",
21 "/assets/diagrams/kit-consumer.svg",
22 )
23
24
25 def _governance_runner(tmp_path: Path):
26 return make_runner(
27 {
28 "git rev-parse --abbrev-ref HEAD": ok("main"),
29 "git status --porcelain": ok(""),
30 "git rev-parse origin/main": ok("cafebabe"),
31 "gh pr list --state merged --limit 5 --json number,title,mergeCommit,mergedAt": ok("[]"),
32 "git remote get-url origin": ok("[email protected]:owner/repo.git"),
33 "git merge-base --is-ancestor": ok(""),
34 }
35 )
36
37
38 def test_overview_structure_status_roadmap_actions(tmp_path: Path) -> None:
39 artifact = seed_app_e2e_repo(tmp_path)
40 rel = artifact.relative_to(tmp_path).as_posix()
41 docs = tmp_path / "docs"
42 (docs / "OVERSEER-HANDOVER.md").write_text(
43 (FIXTURES / "governance-handover-drift.md").read_text(encoding="utf-8"),
44 encoding="utf-8",
45 )
46 (docs / "ROADMAP.md").write_text(
47 (FIXTURES / "governance-roadmap-drift.md").read_text(encoding="utf-8"),
48 encoding="utf-8",
49 )
50
51 handle, client = start_test_app(
52 tmp_path,
53 runner=_governance_runner(tmp_path),
54 review_provider_factory=pass_provider_factory(),
55 )
56 try:
57 status, health = client.get("/api/health")
58 assert status == 200
59 assert health["ok"] is True
60
61 request = urllib.request.Request(
62 f"{client.base_url}/",
63 headers={"Authorization": f"Bearer {client.session}"},
64 )
65 with urllib.request.urlopen(request, timeout=5) as response:
66 html = response.read().decode("utf-8")
67 assert 'id="tab-overview"' in html
68 assert 'id="tab-structure"' in html
69 for path in DIAGRAMS:
70 assert path in html
71 svg_req = urllib.request.Request(
72 f"{client.base_url}{path}",
73 headers={"Authorization": f"Bearer {client.session}"},
74 )
75 with urllib.request.urlopen(svg_req, timeout=5) as response:
76 assert response.status == 200
77
78 _s, status_payload = client.get("/api/status")
79 assert status_payload["result"]["initialized"] is True
80
81 _s, roadmap = client.get("/api/docs/roadmap")
82 assert roadmap["ok"] is True
83
84 _s, freeze = client.post("/api/review/freeze", {"path": rel, "dry_run": True})
85 assert freeze["exit_code"] == 0
86
87 _s, sync = client.post("/api/governance-sync", {"write": False})
88 assert sync["exit_code"] == 0
89 finally:
90 handle.shutdown()
91
92
93 def test_ok_app_sigint_exit_zero(tmp_path: Path) -> None:
94 seed_app_repo(tmp_path)
95 port = free_port()
96 env = os.environ.copy()
97 env["PYTHONPATH"] = str(kit_root())
98 proc = subprocess.Popen(
99 [
100 sys.executable,
101 "-m",
102 "cli.main",
103 "app",
104 "--port",
105 str(port),
106 "--bind",
107 "127.0.0.1",
108 "--repo",
109 str(tmp_path),
110 ],
111 cwd=str(tmp_path),
112 env=env,
113 stdout=subprocess.PIPE,
114 stderr=subprocess.PIPE,
115 )
116 try:
117 time.sleep(0.8)
118 proc.send_signal(signal.SIGINT)
119 code = proc.wait(timeout=5)
120 assert code in {0, -2, 130}
121 finally:
122 if proc.poll() is None:
123 proc.kill()
124 proc.wait(timeout=3)
File History 1 commit
sha256:6abcf1fa82a7a621ccbc945f19acdba5bc0db54569599404a1452fb4a096a199 fix(ISR): default require_independent_second_reviewer to require Human minor 1 day ago