feat: recover interrupted Human Gate decisions (Closes #1446)
This commit is contained in:
1 parent
60f140d26a
commit
b303683ba1
21 files changed
+251
-58
No files matched your search
@@ -29,7 +29,7 @@ def test_release_artifact_reopens_human_gates_with_one_fresh_mobile_snapshot(
|
||||
current = {"gate": "g1"}
|
||||
evidence_url = {"value": "/evidence/manifest"}
|
||||
list_requests: list[str] = []
|
||||
decision_requests: list[str] = []
|
||||
decision_requests: list[dict] = []
|
||||
browser_errors: list[str] = []
|
||||
|
||||
def gate(gate_id: str) -> dict:
|
||||
@@ -62,7 +62,14 @@ def test_release_artifact_reopens_human_gates_with_one_fresh_mobile_snapshot(
|
||||
def human_gates_route(route):
|
||||
path = route.request.url.split("?", 1)[0]
|
||||
if route.request.method == "POST":
|
||||
decision_requests.append(path)
|
||||
decision_requests.append({
|
||||
"path": path,
|
||||
"key": route.request.headers.get("idempotency-key"),
|
||||
"body": route.request.post_data_json,
|
||||
})
|
||||
if len(decision_requests) == 1:
|
||||
route.abort("failed")
|
||||
return
|
||||
payload = {"receipt_id": "receipt-1", "state": "released"}
|
||||
elif path.endswith("/api/v1/human-gates"):
|
||||
list_requests.append(current["gate"])
|
||||
@@ -131,9 +138,28 @@ def test_release_artifact_reopens_human_gates_with_one_fresh_mobile_snapshot(
|
||||
assert progress_key and progress_key.endswith(":g1:1")
|
||||
assert page.evaluate("key => localStorage.getItem(key) !== null", progress_key)
|
||||
page.locator('[data-gate-decision="release"]').click()
|
||||
expect(page.locator("#human-gate-detail")).to_contain_text("Decision outcome unknown")
|
||||
expect(page.locator("[data-gate-recover]")).to_have_count(1)
|
||||
decision_key = page.evaluate(
|
||||
"Object.keys(localStorage).find(key => key.startsWith('stackchain.human-gate-decision.v1:'))"
|
||||
)
|
||||
assert decision_key
|
||||
assert len(decision_requests) == 1
|
||||
|
||||
page.reload(wait_until="networkidle")
|
||||
page.evaluate("document.querySelector('#open-human-gates').click()")
|
||||
expect(page.locator("#human-gate-detail")).to_contain_text("Decision outcome unknown")
|
||||
recover = page.locator("[data-gate-recover]")
|
||||
recover.scroll_into_view_if_needed()
|
||||
expect(recover).to_be_visible()
|
||||
recover_bounds = recover.bounding_box()
|
||||
assert recover_bounds and recover_bounds["height"] >= 44
|
||||
recover.click()
|
||||
expect(page.locator("#human-gates-status")).to_contain_text("Decision saved")
|
||||
expect(page.locator(".human-gate-decision-tray")).to_have_count(0)
|
||||
assert len(decision_requests) == 1
|
||||
assert len(decision_requests) == 2
|
||||
assert decision_requests[0] == decision_requests[1]
|
||||
assert not page.evaluate("key => localStorage.getItem(key) !== null", decision_key)
|
||||
assert not page.evaluate("key => localStorage.getItem(key) !== null", progress_key)
|
||||
|
||||
page.evaluate("document.querySelector('#close-human-gates').click()")
|
||||
|
||||
Reference in new issue
Block a user