test: model worker transport outage deterministically
All checks were successful
CI / lint (pull_request) Successful in 2m40s
CI / build-release (pull_request) Successful in 6s
CI / browser-journey (pull_request) Successful in 2m3s
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy 2026-08-17 02:46:42 +00:00
parent 0fc152f623
commit cf76bc3636
2 changed files with 14 additions and 0 deletions

View File

@ -4,6 +4,7 @@ from __future__ import annotations
import json
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from threading import Event
from urllib.parse import parse_qs, urlsplit
@ -51,6 +52,7 @@ class FakeGiteaServer(ThreadingHTTPServer):
super().__init__(address, FakeGiteaHandler)
self.created_issues: list[dict] = []
self.issue_creation_enabled = False
self.issue_creation_ready = Event()
self.assigned_issue_numbers = [issue["number"] for issue in AVAILABLE_ISSUES]
self.comments: list[tuple[int, str]] = []
self.requests: list[tuple[str, str]] = []
@ -147,6 +149,8 @@ class FakeGiteaHandler(BaseHTTPRequestHandler):
if path != "/api/v1/repos/acme/mobile/issues":
self._json(404, {"message": "not found"})
return
if not self.server.issue_creation_enabled:
self.server.issue_creation_ready.wait(timeout=45)
if not self.server.issue_creation_enabled:
self._json(503, {"message": "release journey is still offline"})
return

View File

@ -232,6 +232,10 @@ def test_release_artifact_files_one_mobile_issue_exactly_once_after_offline_relo
page.locator("#create-issue-repository").select_option("acme/mobile")
expect(page.locator("#submit-new-issue")).to_be_enabled()
# Page offline emulation can leave service-worker requests connected.
# Abort the mutation at the browser boundary too, matching a real
# transport outage without poisoning server-side idempotency state.
context.route("**/api/v1/repos/acme/mobile/issues", lambda route: route.abort())
context.set_offline(True)
page.locator("#submit-new-issue").click()
expect(page.locator("#issue-filing-review")).to_be_visible()
@ -267,6 +271,8 @@ def test_release_artifact_files_one_mobile_issue_exactly_once_after_offline_relo
browser_errors.clear() # Chromium reports expected network errors while the context is offline.
failed_responses.clear()
fake.issue_creation_enabled = True
fake.issue_creation_ready.set()
context.unroute("**/api/v1/repos/acme/mobile/issues")
context.set_offline(False)
page.evaluate("window.dispatchEvent(new Event('online'))")
# Containerized Actions runners can take longer than a local browser to wake the
@ -275,12 +281,15 @@ def test_release_artifact_files_one_mobile_issue_exactly_once_after_offline_relo
if fake.created_issues:
break
page.wait_for_timeout(250)
local_debug = page.evaluate("localStorage.getItem('stackchain.issue-outbox.v1')")
durable_debug = indexed_issue_records(page)
assert fake.created_issues == [
{"title": TITLE, "body": BODY, "assignee": "timmy"}
], (
f"url={page.url} ready={page.evaluate('document.readyState')} "
f"status={page.locator('#my-work-action-status').inner_text()!r} "
f"errors={browser_errors[-5:]!r} responses={failed_responses[-10:]!r} "
f"local={local_debug!r} durable={durable_debug!r} "
f"requests={fake.requests[-20:]!r}"
)
# Deferred workspace startup can report its already-issued offline request
@ -310,6 +319,7 @@ def test_release_artifact_files_one_mobile_issue_exactly_once_after_offline_relo
assert page.evaluate("document.documentElement.scrollWidth <= window.innerWidth")
browser.close()
finally:
fake.issue_creation_ready.set()
fake.shutdown()
fake.server_close()
fake_thread.join(timeout=5)