fix(display): Stage 0 display continuity, revocation, and kiosk recovery #92

Open
ekklesia-bot wants to merge 7 commits from stage0/display-runtime-continuity into main
Showing only changes of commit bae4ff3c6a - Show all commits
+27 -1
View File
@@ -14,7 +14,7 @@
// stream-failure the first realtime connection is refused: is realtime re-established? // stream-failure the first realtime connection is refused: is realtime re-established?
// caching-probe can a display on the API origin store storage-origin images in Cache Storage? // caching-probe can a display on the API origin store storage-origin images in Cache Storage?
// stream-recycle one page past the five-minute realtime recycle, with a timestamped timeline // stream-recycle one page past the five-minute realtime recycle, with a timestamped timeline
// revoke revoke the paired kiosk while its display is open // revoke revoke the paired kiosk while its display is open, then pair it again
// //
// Every DevTools command and every page-side request has its own deadline, and a step has an overall // Every DevTools command and every page-side request has its own deadline, and a step has an overall
// budget. A call that never answers fails the step with a line naming that exact call, because a call // budget. A call that never answers fails the step with a line naming that exact call, because a call
@@ -976,6 +976,32 @@ async function run() {
result.stopped, result.stopped,
`a revoked display returns to the pairing screen without a reload (within ${watchMs / 1000}s)`, `a revoked display returns to the pairing screen without a reload (within ${watchMs / 1000}s)`,
); );
// Revocation is recoverable: the same screen pairs again and resumes, keeping its place in the
// module's roster. It also leaves the kiosk paired for the steps that run after this one.
const rosterBefore = moduleId === "signage" ? (await signageViewers(owner.page)).length : 0;
if (await page.waitFor(find("display-pairing-code"), "a fresh pairing code after revocation")) {
const code = (
await page.evaluate(`${find("display-pairing-code")}.textContent`, "reading the code")
).replace(/\D/gu, "");
const approved = await owner.page.api("POST", "/api/v1/device-pairing/approvals", {
code,
deviceName: "Repro kiosk",
});
check(approved.status === 200, "the owner approves the revoked screen's new code");
check(
await waitLive(page, "the re-paired display to go live"),
"a revoked screen is paired again and resumes without a reload",
);
if (moduleId === "signage") {
const rosterAfter = (await signageViewers(owner.page)).length;
check(
rosterAfter === rosterBefore,
`re-pairing keeps the screen's existing roster entry (${rosterBefore} before, ${rosterAfter} after)`,
);
}
} else {
check(false, "a revoked screen shows a fresh pairing code");
}
await page.close(); await page.close();
kiosk.close(); kiosk.close();
await finishOwner(owner); await finishOwner(owner);