btn-primary label renames + stage-card polarity color refinements — two interleaved threads from one session, committing together since both touch sig + sea stage cards ; LABEL RENAMES: PICK SIGS → SCAN SIGS (room.html #id_pick_sigs_btn), PICK SKY → CAST SKY (room.html #id_pick_sky_btn × 2), PICK SEA → DRAW SEA (room.html #id_pick_sea_btn), TAKE SIG → SAVE SIG (sig-select.js _takeSigBtn.textContent × 2 callsites + section comment) — Element IDs (id_pick_sky_btn etc.), URL names (epic:pick_sigs, epic:pick_sky), and Python state enums (TableStatus.PICK_SKY, PICK_SEA, SIG_SELECT) intentionally retained as stable identifiers; the renamed text is purely the .btn-primary user-facing label ; FT + IT mentions of the old labels swept in test_game_room_select_{sig,sky,sea,role}.py, test_billboard.py, setup_sea_session.py mgmt cmd, apps/epic/{views,utils,models,tasks,tests/integrated/test_views}.py, SigSelectSpec.js, sky_overlay/sea_overlay/dashboard/sky.html, _card-deck.scss, _sky.scss — all docstring/comment references updated for cascade-grep cleanliness ; STAGE-CARD COLOR + CLASS REFINEMENTS (earlier in session): sig-stage card text colour split per polarity — gravity gets --terUser on .fan-card-name + .fan-card-reversal-{name,qualifier} + .sig-qualifier-{above,below}, levity gets --quiUser on the same five slots; all selectors prefixed w. .sig-stage-card to match the 0,4,0 specificity of the default .sig-stage .sig-stage-card .fan-card-face .sig-qualifier-* rule (without the prefix the polarity overrides lose the cascade — .sig-qualifier-below was visibly stuck on the default --quiUser) ; .stat-face-label gets polarity-inverse colours — gravity stat-block bg is --secUser (opposite of card's --priUser) so the label takes --quiUser to stay legible; levity is the symmetric flip (label = --terUser on --priUser stat-block bg) ; levity card title/qualifier drop-shadow swapped from rgba(0,0,0,…) → rgba(255,255,255,…) — dark drop reads as harsh smudge against the inverted-frame levity --secUser bg; applied to both sig-overlay[data-polarity="levity"] stage card AND sea-stage--levity via $_sea-title-shadow-levity (former shared $_sea-title-shadow split into per-polarity {levity,gravity} variants) ; reversal-face class/content alignment so each .fan-card-reversal-* class always carries its semantic content — DOM order per arcana type controls visual layout after the 180° SPIN (DOM-second appears visually on top): Major → title in .fan-card-reversal-name @ DOM-second (visually top after spin), qualifier in .fan-card-reversal-qualifier @ DOM-first; Non-major → title in .fan-card-reversal-name @ DOM-first (visually bottom after spin), qualifier in .fan-card-reversal-qualifier @ DOM-second (preserves the original "qualifier word reads first after spin" layout for Middle/Minor arcana — e.g. "Relieving / Eight of Crowns" not "Eight of Crowns / Relieving") ; _tarot_fan.html renders per-arcana DOM order directly (Django template branches handle both layouts); sig + sea overlays render a fixed two-<p> skeleton (one DOM order) so stage-card.js's populator dynamically rewrites the two <p>s' className per arcana — Major/override branch flips DOM-second to .fan-card-reversal-name + content, DOM-first to .fan-card-reversal-qualifier; non-major branch keeps DOM-first as .fan-card-reversal-name + title, DOM-second as .fan-card-reversal-qualifier + reversalQualifier-or-polarity-fallback ; SigSelectSpec.js + SeaDealSpec.js fixtures + Major reversed-face assertion updated for the new semantic — TDD

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-05-18 00:25:10 -04:00
parent ace8612099
commit 3242873625
23 changed files with 179 additions and 128 deletions

View File

@@ -1,4 +1,4 @@
"""Functional tests for the PICK SEA overlay — Celtic Cross draw."""
"""Functional tests for the DRAW SEA overlay — Celtic Cross draw."""
from django.test import tag
from django.urls import reverse
@@ -39,7 +39,7 @@ def _make_sky_confirmed_room(live_server_url, user, earthman):
@tag("channels")
class PickSeaAsyncTransitionTest(ChannelsFunctionalTest):
"""After sky confirm, the sky overlay closes and the room reloads to the
table hex w. the PICK SEA btn visible — the gamer must opt into the sea
table hex w. the DRAW SEA btn visible — the gamer must opt into the sea
overlay rather than be auto-launched into it."""
def setUp(self):
@@ -92,22 +92,22 @@ class PickSeaAsyncTransitionTest(ChannelsFunctionalTest):
""")
def test_pick_sea_btn_visible_after_sky_confirm(self):
"""Confirming sky reloads the room to the hex w. PICK SEA replacing
PICK SKY; the sea overlay is NOT auto-opened."""
"""Confirming sky reloads the room to the hex w. DRAW SEA replacing
CAST SKY; the sea overlay is NOT auto-opened."""
self.create_pre_authenticated_session("founder@test.io")
self.browser.get(self.room_url)
# Sky not yet confirmed — PICK SKY btn present.
# Sky not yet confirmed — CAST SKY btn present.
self.wait_for(lambda: self.browser.find_element(By.ID, "id_pick_sky_btn"))
self._confirm_sky()
# Page reloads → hex shows PICK SEA in place of PICK 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"), [])
# Sea overlay is NOT auto-opened — it only appears once the gamer
# clicks PICK SEA.
# clicks DRAW SEA.
has_sea_open = self.browser.execute_script(
"return document.documentElement.classList.contains('sea-open');"
)
@@ -126,7 +126,7 @@ class PickSeaAsyncTransitionTest(ChannelsFunctionalTest):
self.assertTrue(not sky or not sky[0].is_displayed())
def test_clicking_pick_sea_btn_opens_sea_overlay(self):
"""The gamer's explicit click on PICK SEA is what opens the sea overlay."""
"""The gamer's explicit click on DRAW SEA is what opens the sea overlay."""
self.create_pre_authenticated_session("founder@test.io")
self.browser.get(self.room_url)
self.wait_for(lambda: self.browser.find_element(By.ID, "id_pick_sky_btn"))
@@ -134,7 +134,7 @@ class PickSeaAsyncTransitionTest(ChannelsFunctionalTest):
self._confirm_sky()
self.wait_for(lambda: self.browser.find_element(By.ID, "id_pick_sea_btn"))
# On slow CI, the PICK SEA btn parses into the DOM before the inline
# On slow CI, the DRAW SEA btn parses into the DOM before the inline
# `<script>` at the bottom of _sea_overlay.html has bound `openSea` to
# it; a one-shot click can land before the handler exists. Retry click
# + assert together via wait_for so the race resolves naturally.
@@ -150,7 +150,7 @@ class PickSeaAsyncTransitionTest(ChannelsFunctionalTest):
self.assertTrue(sea_overlay.is_displayed())
# ── Helpers for PICK SEA deal tests ──────────────────────────────────────────
# ── Helpers for DRAW SEA deal tests ──────────────────────────────────────────
def _seed_earthman_cards(earthman, count=20):
"""Seed enough Middle Arcana cards for the deck piles."""
@@ -167,7 +167,7 @@ def _seed_earthman_cards(earthman, count=20):
def _make_sea_ready_room(earthman):
"""Create a SKY_SELECT room with a confirmed Character ready for PICK SEA.
"""Create a SKY_SELECT room with a confirmed Character ready for DRAW SEA.
Returns (room, gamer, seat, char, room_url).
"""
@@ -199,7 +199,7 @@ def _make_sea_ready_room(earthman):
@tag("channels")
class PickSeaDealTest(ChannelsFunctionalTest):
"""PICK SEA deck stacks, OK btn interaction, card draw, and LOCK HAND."""
"""DRAW SEA deck stacks, OK btn interaction, card draw, and LOCK HAND."""
def setUp(self):
super().setUp()