From 5b2b234c5486b096e8dc11928eb9254f8092a8a8 Mon Sep 17 00:00:00 2001 From: funman300 Date: Mon, 22 Jun 2026 12:46:12 -0700 Subject: [PATCH] fix(web-e2e): expose serialize() on classic bridge; use real clock API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two latent test bugs surfaced once the e2e suite actually ran (it had been red on the webServer startup timeout, so these never executed): 14 passed, 4 failed. - game.js `__FERROUS_DEBUG__` was missing `serialize()` — play.html's bridge has it but the /play-classic bridge (which the resume/move-history tests use) drifted. Added it (the wasm SolitaireGame already exposes serialize()). - game_behaviors.spec.js called `page.clock.tick()`, which is the sinon name; Playwright's Clock API method is `page.clock.runFor()`. Replaced all 6 calls. Co-Authored-By: Claude Opus 4.8 (1M context) --- solitaire_server/e2e/tests/game_behaviors.spec.js | 14 +++++++------- solitaire_server/web/game.js | 3 +++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/solitaire_server/e2e/tests/game_behaviors.spec.js b/solitaire_server/e2e/tests/game_behaviors.spec.js index af1bc9e..425379f 100644 --- a/solitaire_server/e2e/tests/game_behaviors.spec.js +++ b/solitaire_server/e2e/tests/game_behaviors.spec.js @@ -136,7 +136,7 @@ test("new game button resets move history and score", async ({ page }) => { test("timer stops accumulating while tab is hidden", async ({ page }) => { // Install the fake clock before navigation so the game's setInterval is - // controlled by page.clock.tick() and won't fire on real wall-clock time. + // controlled by page.clock.runFor() and won't fire on real wall-clock time. await page.clock.install(); await page.goto("/play-classic?seed=42"); @@ -144,7 +144,7 @@ test("timer stops accumulating while tab is hidden", async ({ page }) => { await waitForBridge(page); // Advance 3 fake seconds to get a non-zero timer reading. - await page.clock.tick(3_000); + await page.clock.runFor(3_000); const timerAfter3s = await page.locator("#hud-timer").textContent(); expect(timerAfter3s).toBe("0:03"); @@ -152,7 +152,7 @@ test("timer stops accumulating while tab is hidden", async ({ page }) => { await setTabHidden(page, true); // Advance 10 fake seconds while hidden. - await page.clock.tick(10_000); + await page.clock.runFor(10_000); const timerWhileHidden = await page.locator("#hud-timer").textContent(); expect(timerWhileHidden).toBe("0:03"); // must not have advanced @@ -160,7 +160,7 @@ test("timer stops accumulating while tab is hidden", async ({ page }) => { await setTabHidden(page, false); // Advance 2 more fake seconds. - await page.clock.tick(2_000); + await page.clock.runFor(2_000); const timerAfterResume = await page.locator("#hud-timer").textContent(); expect(timerAfterResume).toBe("0:05"); // only 3 + 2 visible seconds counted }); @@ -182,11 +182,11 @@ test("timer does not restart while tab is visible during an auto-complete or won // the snap state correctly gates the restart. // // Advance 2 s, then hide+show — timer should continue normally. - await page.clock.tick(2_000); + await page.clock.runFor(2_000); await setTabHidden(page, true); - await page.clock.tick(5_000); + await page.clock.runFor(5_000); await setTabHidden(page, false); - await page.clock.tick(2_000); + await page.clock.runFor(2_000); const timerText = await page.locator("#hud-timer").textContent(); // 2 visible + 0 hidden + 2 visible = 4 total diff --git a/solitaire_server/web/game.js b/solitaire_server/web/game.js index f8978f9..dec4e95 100644 --- a/solitaire_server/web/game.js +++ b/solitaire_server/web/game.js @@ -986,6 +986,9 @@ window.__FERROUS_DEBUG__ = { snapshot() { return game ? game.debug_snapshot() : null; }, + serialize() { + return game ? game.serialize() : null; + }, applyLegalMove(index) { if (!game) return { ok: false, error: "game_not_ready" }; const result = game.debug_apply_legal_move(index);