From ce4cb03af742e1ddbe7bece69c064611ec3ef74a Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Sun, 7 Jun 2026 18:36:05 -0400 Subject: [PATCH] =?UTF-8?q?DRAW=20SEA=20async-transition=20FT:=20reload=20?= =?UTF-8?q?fallback=20for=20non-felt-save=20sky=20confirm=20=E2=80=94=20TD?= =?UTF-8?q?D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Running the corequisite channels FTs surfaced a real gap the cascade introduced: a sky confirm that did NOT come through the felt's own save (a direct POST, or another browser of the same seat) left _lastChartData null, so _onSkyConfirmed's _activateSavedState returned early → no transition at all (the old code reloaded). - _sky_overlay.html: _onSkyConfirmed now reloads when _lastChartData is absent (the pre-cascade behaviour, preserved for non-felt-save confirm paths); the felt-save path still eases to DRAW SEA via the cascade (no reload). - test_game_room_select_sea.py: the async-transition assertion updated for the phase-stack — CAST SKY is now present-but-`--out` (hidden in the shared grid cell), not removed from the DOM, so assert the `hex-phase-btn--out` class on CAST SKY + its ABSENCE on DRAW SEA rather than `find_elements(...) == []`. Corequisite FTs run green: select_sea async-transition (3) + deal (9) channels; dash my_sky async-save + aperture-snap (3) — the shared body.sky-saved apparatus is untouched by the room-scoped felt SCSS. select_sky FTs already green. The sig SRG7 reveal FT is unaffected (it waits for the SIG_SELECT hidden CAST SKY, which that branch still renders; it never clicks, so the _reload change isn't reached). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../test_game_room_select_sea.py | 22 ++++++++++++++----- .../gameboard/_partials/_sky_overlay.html | 19 ++++++++++------ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/functional_tests/test_game_room_select_sea.py b/src/functional_tests/test_game_room_select_sea.py index f4fa907..0455c99 100644 --- a/src/functional_tests/test_game_room_select_sea.py +++ b/src/functional_tests/test_game_room_select_sea.py @@ -92,19 +92,29 @@ class PickSeaAsyncTransitionTest(ChannelsFunctionalTest): """) def test_pick_sea_btn_visible_after_sky_confirm(self): - """Confirming sky reloads the room to the hex w. DRAW SEA replacing - CAST SKY; the sea overlay is NOT auto-opened.""" + """Confirming sky lands the room on the hex w. DRAW SEA in place of CAST + SKY; the sea overlay is NOT auto-opened. (A direct-POST confirm has no + captured chart on this browser, so _onSkyConfirmed reloads to the server- + rendered DRAW SEA hex; the felt-save path eases there via the cascade.)""" self.create_pre_authenticated_session("founder@test.io") self.browser.get(self.room_url) - # Sky not yet confirmed — CAST SKY btn present. + # Sky not yet confirmed — CAST SKY is the live (non --out) phase btn. self.wait_for(lambda: self.browser.find_element(By.ID, "id_pick_sky_btn")) self._confirm_sky() - # Page reloads → hex shows DRAW SEA in place of CAST SKY. - self.wait_for(lambda: self.browser.find_element(By.ID, "id_pick_sea_btn")) - self.assertEqual(self.browser.find_elements(By.ID, "id_pick_sky_btn"), []) + # DRAW SEA becomes the live phase btn; CAST SKY stays in the phase-stack + # but goes --out (the buttons cross-fade in one grid cell now, so the + # stale CAST SKY is hidden via the class, not removed from the DOM). + self.wait_for(lambda: self.assertNotIn( + "hex-phase-btn--out", + self.browser.find_element(By.ID, "id_pick_sea_btn").get_attribute("class"), + )) + self.assertIn( + "hex-phase-btn--out", + self.browser.find_element(By.ID, "id_pick_sky_btn").get_attribute("class"), + ) # Sea overlay is NOT auto-opened — it only appears once the gamer # clicks DRAW SEA. diff --git a/src/templates/apps/gameboard/_partials/_sky_overlay.html b/src/templates/apps/gameboard/_partials/_sky_overlay.html index e6bf4a5..2c538e4 100644 --- a/src/templates/apps/gameboard/_partials/_sky_overlay.html +++ b/src/templates/apps/gameboard/_partials/_sky_overlay.html @@ -542,14 +542,19 @@ } // ── Sky confirmed (self-targeted WS) ────────────────────────────────────── - // The acting gamer's own SAVE .then() already revealed the wheel; the WS - // event just re-asserts the saved state (idempotent). No reload — the gamer - // lingers on the saved wheel; the gear NVM does the navigation back to the - // hex (now DRAW SEA). A second browser of the same seat with no captured - // chart no-ops here (rare) and reconciles on its next load. - + // Two cases: + // • This browser captured the chart (the gamer saved via the felt) → the + // save .then() already ran the cascade; this WS re-fire is idempotent + // (re-asserts the saved state, no second cascade, no reload). + // • No captured chart (a direct POST confirm, or another browser of the same + // seat) → the cascade can't run, so reload to land on the server-rendered + // DRAW SEA hex (the pre-cascade behaviour, preserved for these paths). function _onSkyConfirmed() { - _activateSavedState(); + if (_lastChartData) { + _activateSavedState(); + } else { + window.location.reload(); + } } // ── DEL btn — JS-injected after the wheel paints; absent on a blank modal