DRAW SEA async-transition FT: reload fallback for non-felt-save sky confirm — TDD
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful

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) <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-06-07 18:36:05 -04:00
parent d5e4fc53f0
commit ce4cb03af7
2 changed files with 28 additions and 13 deletions

View File

@@ -92,19 +92,29 @@ class PickSeaAsyncTransitionTest(ChannelsFunctionalTest):
""") """)
def test_pick_sea_btn_visible_after_sky_confirm(self): def test_pick_sea_btn_visible_after_sky_confirm(self):
"""Confirming sky reloads the room to the hex w. DRAW SEA replacing """Confirming sky lands the room on the hex w. DRAW SEA in place of CAST
CAST SKY; the sea overlay is NOT auto-opened.""" 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.create_pre_authenticated_session("founder@test.io")
self.browser.get(self.room_url) 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.wait_for(lambda: self.browser.find_element(By.ID, "id_pick_sky_btn"))
self._confirm_sky() self._confirm_sky()
# Page reloads → hex shows DRAW SEA in place of CAST SKY. # DRAW SEA becomes the live phase btn; CAST SKY stays in the phase-stack
self.wait_for(lambda: self.browser.find_element(By.ID, "id_pick_sea_btn")) # but goes --out (the buttons cross-fade in one grid cell now, so the
self.assertEqual(self.browser.find_elements(By.ID, "id_pick_sky_btn"), []) # 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 # Sea overlay is NOT auto-opened — it only appears once the gamer
# clicks DRAW SEA. # clicks DRAW SEA.

View File

@@ -542,14 +542,19 @@
} }
// ── Sky confirmed (self-targeted WS) ────────────────────────────────────── // ── Sky confirmed (self-targeted WS) ──────────────────────────────────────
// The acting gamer's own SAVE .then() already revealed the wheel; the WS // Two cases:
// event just re-asserts the saved state (idempotent). No reload — the gamer // • This browser captured the chart (the gamer saved via the felt) → the
// lingers on the saved wheel; the gear NVM does the navigation back to the // save .then() already ran the cascade; this WS re-fire is idempotent
// hex (now DRAW SEA). A second browser of the same seat with no captured // (re-asserts the saved state, no second cascade, no reload).
// chart no-ops here (rare) and reconciles on its next load. // • 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() { function _onSkyConfirmed() {
_activateSavedState(); if (_lastChartData) {
_activateSavedState();
} else {
window.location.reload();
}
} }
// ── DEL btn — JS-injected after the wheel paints; absent on a blank modal // ── DEL btn — JS-injected after the wheel paints; absent on a blank modal