fix: manual my-sea draws persist on refresh + reloaded slots stay clickable — root cause was SeaDeal stamping slot.dataset.posKey w. selector form (".sea-pos-cover") while my-sea's inline _collectHandFromDom + template's _my_sea_slot.html use raw names ("cover"). Key mismatch silently dropped manual draws from the lock POST → server rejected empty hand → no row → refresh showed empty state. AUTO DRAW worked only because it assembled fullHand w. raw posNames directly, bypassing the broken collector. TDD — 2 new FTs pin the contract:
- test_manual_draw_persists_on_refresh - test_reloaded_slot_can_reopen_stage_modal_on_click Changes: - sea.js: stamp `dataset.posKey` w. raw name (strip `.sea-pos-` prefix); `_seaHand` keyed by raw; `_viewingPos` is raw too (`_hideStage` prefixes when querySelector'ing); new `SeaDeal.seedHand(handByPosName)` public method for init-time DOM-walk seeding. - my_sea.html inline init: walk server-rendered filled slots, look up each card by `data-card-id` from the embedded deck JSON, reconstruct per-instance `reversed` + polarity from the slot's classes, hand the map to `SeaDeal.seedHand`. Without this, reloaded slots short-circuit the overlay click handler on `if (!_seaHand[pos]) return;`. The gameroom-side SeaDeal callers in `_sea_overlay.html` continue to pass selector form (SeaDeal accepts either — `_posName` helper strips prefix tolerantly). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -902,6 +902,63 @@ class MySeaCardDrawTest(FunctionalTest):
|
||||
)
|
||||
self.wait_for(lambda: self.assertTrue(stage.is_displayed()))
|
||||
|
||||
# ── Test 5c — manual draw survives refresh ──────────────────────────────
|
||||
|
||||
def test_manual_draw_persists_on_refresh(self):
|
||||
"""User-reported 2026-05-21: manually-drawn cards disappeared
|
||||
after a refresh. Root cause: SeaDeal's `_fillSlot` stamps
|
||||
`slot.dataset.posKey` w. the selector form (".sea-pos-cover"),
|
||||
but the inline `_collectHandFromDom` looks up by raw name from
|
||||
`_currentOrder()` ("cover"). The key mismatch means manual
|
||||
draws are dropped from the POST body — server stores nothing
|
||||
→ refresh shows empty state.
|
||||
|
||||
Fix: standardize on raw position names for `dataset.posKey`."""
|
||||
from apps.gameboard.models import MySeaDraw
|
||||
picker = self._enter_picker_phase()
|
||||
self._draw_one(picker, "levity")
|
||||
# POST is async — wait for server commit by polling the DB.
|
||||
self.wait_for(
|
||||
lambda: self.assertEqual(
|
||||
len(MySeaDraw.objects.get(user=self.gamer).hand), 1,
|
||||
)
|
||||
)
|
||||
self.browser.refresh()
|
||||
picker = self.wait_for(
|
||||
lambda: self.browser.find_element(
|
||||
By.CSS_SELECTOR, ".my-sea-page[data-phase='picker']"
|
||||
)
|
||||
)
|
||||
self.assertEqual(_count_filled_slots(picker), 1)
|
||||
|
||||
# ── Test 5d — reloaded slot re-opens stage modal on click ───────────────
|
||||
|
||||
def test_reloaded_slot_can_reopen_stage_modal_on_click(self):
|
||||
"""After refresh, server-rendered filled slots must remain
|
||||
clickable to re-open the stage modal. Requires SeaDeal's init
|
||||
to seed `_seaHand` from the embedded deck JSON + the saved
|
||||
slots in the DOM. User-reported 2026-05-21."""
|
||||
from apps.gameboard.models import MySeaDraw
|
||||
picker = self._enter_picker_phase()
|
||||
self._draw_one(picker, "levity")
|
||||
self.wait_for(
|
||||
lambda: self.assertEqual(
|
||||
len(MySeaDraw.objects.get(user=self.gamer).hand), 1,
|
||||
)
|
||||
)
|
||||
self.browser.refresh()
|
||||
slot = self.wait_for(
|
||||
lambda: self.browser.find_element(
|
||||
By.CSS_SELECTOR, ".sea-pos-lay .sea-card-slot--filled"
|
||||
)
|
||||
)
|
||||
slot.click() # first tap — focus
|
||||
slot.click() # second tap — open modal
|
||||
stage = self.wait_for(
|
||||
lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_sea_stage")
|
||||
)
|
||||
self.wait_for(lambda: self.assertTrue(stage.is_displayed()))
|
||||
|
||||
# ── Test 6 ───────────────────────────────────────────────────────────────
|
||||
|
||||
def test_del_btn_is_disabled_until_hand_complete(self):
|
||||
|
||||
Reference in New Issue
Block a user