From 44bf4e626c06ebcefb32334ddf617c1f2b6a4d9a Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Fri, 5 Jun 2026 14:54:26 -0400 Subject: [PATCH] =?UTF-8?q?Sig=20Select:=20regression=20spec=20=E2=80=94?= =?UTF-8?q?=20re-ready=20restarts=20the=20visual=20countdown=20(client=20b?= =?UTF-8?q?isection)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A diagnostic that replays the reported "cancel → re-ready doesn't restart the flashing numeral" sequence purely through the client handlers (countdown_start → countdown_cancel → countdown_start). It passes: _showCountdown re-renders the numeral every time the event is received, so the client logic is sound. This bisects the live bug to WS *delivery* (the re-ready countdown_start not reaching the browser), not client state — consistent with a dropped room socket that never reconnected (every subsequent live event lost until a refresh, which matches the symptom exactly). The auto-reconnect added in a6ce207 is the relevant mitigation; kept as a permanent guard on the client restart path. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/static/tests/SigSelectSpec.js | 19 +++++++++++++++++++ src/static_src/tests/SigSelectSpec.js | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/static/tests/SigSelectSpec.js b/src/static/tests/SigSelectSpec.js index a467eaa..2e6d519 100644 --- a/src/static/tests/SigSelectSpec.js +++ b/src/static/tests/SigSelectSpec.js @@ -919,6 +919,25 @@ describe("SigSelect", () => { takeSigBtn = document.getElementById("id_take_sig_btn"); expect(takeSigBtn.textContent).toBe("WAIT NVM"); }); + + it("re-renders the numeral when countdown_start arrives again after a cancel", () => { + // Diagnostic for the re-ready bug: cancel → re-ready must restart the + // visual countdown. This exercises the CLIENT handler chain only; if + // it passes, the live failure is WS delivery (socket / broadcast), not + // client logic. + makeFixture({ reservations: '{"42":"PC"}', ready: true, countdownRemaining: 9 }); + takeSigBtn = document.getElementById("id_take_sig_btn"); + expect(takeSigBtn.textContent).toBe("9"); // counting + window.dispatchEvent(new CustomEvent("room:countdown_cancel", { + detail: { polarity: "levity", seconds_remaining: 7 }, + })); + expect(takeSigBtn.textContent).toBe("WAIT NVM"); // cancelled + window.dispatchEvent(new CustomEvent("room:countdown_start", { + detail: { polarity: "levity", seconds: 7 }, + })); + expect(takeSigBtn.textContent).toBe("7"); // restarted + expect(takeSigBtn.classList.contains("sig-take-sig-btn--counting")).toBe(true); + }); }); // ── polarity_room_done → tray sequence ─────────────────────────────────── // diff --git a/src/static_src/tests/SigSelectSpec.js b/src/static_src/tests/SigSelectSpec.js index a467eaa..2e6d519 100644 --- a/src/static_src/tests/SigSelectSpec.js +++ b/src/static_src/tests/SigSelectSpec.js @@ -919,6 +919,25 @@ describe("SigSelect", () => { takeSigBtn = document.getElementById("id_take_sig_btn"); expect(takeSigBtn.textContent).toBe("WAIT NVM"); }); + + it("re-renders the numeral when countdown_start arrives again after a cancel", () => { + // Diagnostic for the re-ready bug: cancel → re-ready must restart the + // visual countdown. This exercises the CLIENT handler chain only; if + // it passes, the live failure is WS delivery (socket / broadcast), not + // client logic. + makeFixture({ reservations: '{"42":"PC"}', ready: true, countdownRemaining: 9 }); + takeSigBtn = document.getElementById("id_take_sig_btn"); + expect(takeSigBtn.textContent).toBe("9"); // counting + window.dispatchEvent(new CustomEvent("room:countdown_cancel", { + detail: { polarity: "levity", seconds_remaining: 7 }, + })); + expect(takeSigBtn.textContent).toBe("WAIT NVM"); // cancelled + window.dispatchEvent(new CustomEvent("room:countdown_start", { + detail: { polarity: "levity", seconds: 7 }, + })); + expect(takeSigBtn.textContent).toBe("7"); // restarted + expect(takeSigBtn.classList.contains("sig-take-sig-btn--counting")).toBe(true); + }); }); // ── polarity_room_done → tray sequence ─────────────────────────────────── //