From 32428736255e0eb78b043c529bf7daeabb5b0e2e Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Mon, 18 May 2026 00:25:10 -0400 Subject: [PATCH] =?UTF-8?q?btn-primary=20label=20renames=20+=20stage-card?= =?UTF-8?q?=20polarity=20color=20refinements=20=E2=80=94=20two=20interleav?= =?UTF-8?q?ed=20threads=20from=20one=20session,=20committing=20together=20?= =?UTF-8?q?since=20both=20touch=20sig=20+=20sea=20stage=20cards=20;=20LABE?= =?UTF-8?q?L=20RENAMES:=20PICK=20SIGS=20=E2=86=92=20SCAN=20SIGS=20(room.ht?= =?UTF-8?q?ml=20#id=5Fpick=5Fsigs=5Fbtn),=20PICK=20SKY=20=E2=86=92=20CAST?= =?UTF-8?q?=20SKY=20(room.html=20#id=5Fpick=5Fsky=5Fbtn=20=C3=97=202),=20P?= =?UTF-8?q?ICK=20SEA=20=E2=86=92=20DRAW=20SEA=20(room.html=20#id=5Fpick=5F?= =?UTF-8?q?sea=5Fbtn),=20TAKE=20SIG=20=E2=86=92=20SAVE=20SIG=20(sig-select?= =?UTF-8?q?.js=20=5FtakeSigBtn.textContent=20=C3=97=202=20callsites=20+=20?= =?UTF-8?q?section=20comment)=20=E2=80=94=20Element=20IDs=20(id=5Fpick=5Fs?= =?UTF-8?q?ky=5Fbtn=20etc.),=20URL=20names=20(epic:pick=5Fsigs,=20epic:pic?= =?UTF-8?q?k=5Fsky),=20and=20Python=20state=20enums=20(TableStatus.PICK=5F?= =?UTF-8?q?SKY,=20PICK=5FSEA,=20SIG=5FSELECT)=20intentionally=20retained?= =?UTF-8?q?=20as=20stable=20identifiers;=20the=20renamed=20text=20is=20pur?= =?UTF-8?q?ely=20the=20.btn-primary=20user-facing=20label=20;=20FT=20+=20I?= =?UTF-8?q?T=20mentions=20of=20the=20old=20labels=20swept=20in=20test=5Fga?= =?UTF-8?q?me=5Froom=5Fselect=5F{sig,sky,sea,role}.py,=20test=5Fbillboard.?= =?UTF-8?q?py,=20setup=5Fsea=5Fsession.py=20mgmt=20cmd,=20apps/epic/{views?= =?UTF-8?q?,utils,models,tasks,tests/integrated/test=5Fviews}.py,=20SigSel?= =?UTF-8?q?ectSpec.js,=20sky=5Foverlay/sea=5Foverlay/dashboard/sky.html,?= =?UTF-8?q?=20=5Fcard-deck.scss,=20=5Fsky.scss=20=E2=80=94=20all=20docstri?= =?UTF-8?q?ng/comment=20references=20updated=20for=20cascade-grep=20cleanl?= =?UTF-8?q?iness=20;=20STAGE-CARD=20COLOR=20+=20CLASS=20REFINEMENTS=20(ear?= =?UTF-8?q?lier=20in=20session):=20sig-stage=20card=20text=20colour=20spli?= =?UTF-8?q?t=20per=20polarity=20=E2=80=94=20gravity=20gets=20--terUser=20o?= =?UTF-8?q?n=20.fan-card-name=20+=20.fan-card-reversal-{name,qualifier}=20?= =?UTF-8?q?+=20.sig-qualifier-{above,below},=20levity=20gets=20--quiUser?= =?UTF-8?q?=20on=20the=20same=20five=20slots;=20all=20selectors=20prefixed?= =?UTF-8?q?=20w.=20.sig-stage-card=20to=20match=20the=200,4,0=20specificit?= =?UTF-8?q?y=20of=20the=20default=20`.sig-stage=20.sig-stage-card=20.fan-c?= =?UTF-8?q?ard-face=20.sig-qualifier-*`=20rule=20(without=20the=20prefix?= =?UTF-8?q?=20the=20polarity=20overrides=20lose=20the=20cascade=20?= =?UTF-8?q?=E2=80=94=20.sig-qualifier-below=20was=20visibly=20stuck=20on?= =?UTF-8?q?=20the=20default=20--quiUser)=20;=20.stat-face-label=20gets=20p?= =?UTF-8?q?olarity-inverse=20colours=20=E2=80=94=20gravity=20stat-block=20?= =?UTF-8?q?bg=20is=20--secUser=20(opposite=20of=20card's=20--priUser)=20so?= =?UTF-8?q?=20the=20label=20takes=20--quiUser=20to=20stay=20legible;=20lev?= =?UTF-8?q?ity=20is=20the=20symmetric=20flip=20(label=20=3D=20--terUser=20?= =?UTF-8?q?on=20--priUser=20stat-block=20bg)=20;=20levity=20card=20title/q?= =?UTF-8?q?ualifier=20drop-shadow=20swapped=20from=20rgba(0,0,0,=E2=80=A6)?= =?UTF-8?q?=20=E2=86=92=20rgba(255,255,255,=E2=80=A6)=20=E2=80=94=20dark?= =?UTF-8?q?=20drop=20reads=20as=20harsh=20smudge=20against=20the=20inverte?= =?UTF-8?q?d-frame=20levity=20--secUser=20bg;=20applied=20to=20both=20sig-?= =?UTF-8?q?overlay[data-polarity=3D"levity"]=20stage=20card=20AND=20sea-st?= =?UTF-8?q?age--levity=20via=20$=5Fsea-title-shadow-levity=20(former=20sha?= =?UTF-8?q?red=20$=5Fsea-title-shadow=20split=20into=20per-polarity=20{lev?= =?UTF-8?q?ity,gravity}=20variants)=20;=20reversal-face=20class/content=20?= =?UTF-8?q?alignment=20so=20each=20`.fan-card-reversal-*`=20class=20always?= =?UTF-8?q?=20carries=20its=20semantic=20content=20=E2=80=94=20DOM=20order?= =?UTF-8?q?=20per=20arcana=20type=20controls=20visual=20layout=20after=20t?= =?UTF-8?q?he=20180=C2=B0=20SPIN=20(DOM-second=20appears=20visually=20on?= =?UTF-8?q?=20top):=20Major=20=E2=86=92=20title=20in=20.fan-card-reversal-?= =?UTF-8?q?name=20@=20DOM-second=20(visually=20top=20after=20spin),=20qual?= =?UTF-8?q?ifier=20in=20.fan-card-reversal-qualifier=20@=20DOM-first;=20No?= =?UTF-8?q?n-major=20=E2=86=92=20title=20in=20.fan-card-reversal-name=20@?= =?UTF-8?q?=20DOM-first=20(visually=20bottom=20after=20spin),=20qualifier?= =?UTF-8?q?=20in=20.fan-card-reversal-qualifier=20@=20DOM-second=20(preser?= =?UTF-8?q?ves=20the=20original=20"qualifier=20word=20reads=20first=20afte?= =?UTF-8?q?r=20spin"=20layout=20for=20Middle/Minor=20arcana=20=E2=80=94=20?= =?UTF-8?q?e.g.=20"Relieving=20/=20Eight=20of=20Crowns"=20not=20"Eight=20o?= =?UTF-8?q?f=20Crowns=20/=20Relieving")=20;=20=5Ftarot=5Ffan.html=20render?= =?UTF-8?q?s=20per-arcana=20DOM=20order=20directly=20(Django=20template=20?= =?UTF-8?q?branches=20handle=20both=20layouts);=20sig=20+=20sea=20overlays?= =?UTF-8?q?=20render=20a=20fixed=20two-`

`=20skeleton=20(one=20DOM=20ord?= =?UTF-8?q?er)=20so=20stage-card.js's=20populator=20dynamically=20rewrites?= =?UTF-8?q?=20the=20two=20`

`s'=20className=20per=20arcana=20=E2=80=94?= =?UTF-8?q?=20Major/override=20branch=20flips=20DOM-second=20to=20.fan-car?= =?UTF-8?q?d-reversal-name=20+=20content,=20DOM-first=20to=20.fan-card-rev?= =?UTF-8?q?ersal-qualifier;=20non-major=20branch=20keeps=20DOM-first=20as?= =?UTF-8?q?=20.fan-card-reversal-name=20+=20title,=20DOM-second=20as=20.fa?= =?UTF-8?q?n-card-reversal-qualifier=20+=20reversalQualifier-or-polarity-f?= =?UTF-8?q?allback=20;=20SigSelectSpec.js=20+=20SeaDealSpec.js=20fixtures?= =?UTF-8?q?=20+=20Major=20reversed-face=20assertion=20updated=20for=20the?= =?UTF-8?q?=20new=20semantic=20=E2=80=94=20TDD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code architected by Disco DeDisco Git commit message Co-Authored-By: Claude Sonnet 4.6 --- src/apps/epic/models.py | 6 +-- src/apps/epic/static/apps/epic/sig-select.js | 12 ++--- src/apps/epic/static/apps/epic/stage-card.js | 50 ++++++++++++------- src/apps/epic/tasks.py | 2 +- src/apps/epic/tests/integrated/test_views.py | 8 +-- src/apps/epic/utils.py | 2 +- src/apps/epic/views.py | 6 +-- .../management/commands/setup_sea_session.py | 6 +-- src/functional_tests/test_billboard.py | 2 +- .../test_game_room_select_role.py | 6 +-- .../test_game_room_select_sea.py | 24 ++++----- .../test_game_room_select_sig.py | 42 ++++++++-------- .../test_game_room_select_sky.py | 8 +-- src/static/tests/SigSelectSpec.js | 12 ++--- src/static_src/scss/_card-deck.scss | 50 ++++++++++++++----- src/static_src/scss/_sky.scss | 6 +-- src/static_src/tests/SigSelectSpec.js | 12 ++--- src/templates/apps/dashboard/sky.html | 2 +- .../gameboard/_partials/_sea_overlay.html | 7 ++- .../_partials/_sig_select_overlay.html | 4 ++ .../gameboard/_partials/_sky_overlay.html | 14 +++--- .../apps/gameboard/_partials/_tarot_fan.html | 18 ++++--- src/templates/apps/gameboard/room.html | 8 +-- 23 files changed, 179 insertions(+), 128 deletions(-) diff --git a/src/apps/epic/models.py b/src/apps/epic/models.py index 169db4d..6a450ab 100644 --- a/src/apps/epic/models.py +++ b/src/apps/epic/models.py @@ -624,7 +624,7 @@ class Character(models.Model): """A gamer's player-character for one seat in one game session. Lifecycle: - - Created (draft) when gamer opens PICK SKY overlay. + - Created (draft) when gamer opens CAST SKY overlay. - confirmed_at set on confirm → locked. - retired_at set on retirement → archived (seat may hold a new Character). @@ -647,7 +647,7 @@ class Character(models.Model): TableSeat, on_delete=models.CASCADE, related_name='characters', ) - # ── significator (set at PICK SKY) ──────────────────────────────────── + # ── significator (set at CAST SKY) ──────────────────────────────────── significator = models.ForeignKey( TarotCard, null=True, blank=True, on_delete=models.SET_NULL, related_name='character_significators', @@ -665,7 +665,7 @@ class Character(models.Model): # ── computed sky snapshot (full PySwiss response) ─────────────────── chart_data = models.JSONField(null=True, blank=True) - # ── celtic cross spread (added at PICK SEA) ─────────────────────────── + # ── celtic cross spread (added at DRAW SEA) ─────────────────────────── celtic_cross = models.JSONField(null=True, blank=True) # ── lifecycle ───────────────────────────────────────────────────────── diff --git a/src/apps/epic/static/apps/epic/sig-select.js b/src/apps/epic/static/apps/epic/sig-select.js index 2d5490d..94d222e 100644 --- a/src/apps/epic/static/apps/epic/sig-select.js +++ b/src/apps/epic/static/apps/epic/sig-select.js @@ -317,7 +317,7 @@ var SigSelect = (function () { }); } - // ── TAKE SIG / WAIT NVM button ───────────────────────────────────────── + // ── SAVE SIG / WAIT NVM button ───────────────────────────────────────── function _onTakeSigClick() { if (_isReady) { @@ -337,7 +337,7 @@ var SigSelect = (function () { _countdownTimer = null; if (_takeSigBtn) _takeSigBtn.style.fontSize = ''; } - if (_takeSigBtn) _takeSigBtn.textContent = 'TAKE SIG'; + if (_takeSigBtn) _takeSigBtn.textContent = 'SAVE SIG'; _stopWaitNoGlow(); _stopCountdownGlow(); } @@ -367,7 +367,7 @@ var SigSelect = (function () { _takeSigBtn.id = 'id_take_sig_btn'; _takeSigBtn.className = 'btn btn-primary sig-take-sig-btn'; _takeSigBtn.type = 'button'; - _takeSigBtn.textContent = 'TAKE SIG'; + _takeSigBtn.textContent = 'SAVE SIG'; _takeSigBtn.addEventListener('click', _onTakeSigClick); stage.appendChild(_takeSigBtn); } @@ -495,7 +495,7 @@ var SigSelect = (function () { function _showWaitingMsg(pendingPolarity) { if (document.getElementById('id_hex_waiting_msg')) return; // If the OTHER polarity finished before our tray sequence completed, - // pick_sky_available will already have fired and revealed PICK SKY. + // pick_sky_available will already have fired and revealed CAST SKY. // In that case skip the waiting msg so the two don't co-exist. var pickSkyBtn = document.getElementById('id_pick_sky_btn'); if (pickSkyBtn && pickSkyBtn.style.display !== 'none') return; @@ -539,7 +539,7 @@ var SigSelect = (function () { // the overlay vanishes; overlay dismissal + waiting msg run last. // User sees: stage card → tray slides in → sig fades into the tray // cell → tray slides out → 2s pause → overlay dismisses → table hex - // w. waiting msg (or PICK SKY btn if both polarities are done). + // w. waiting msg (or CAST SKY btn if both polarities are done). function _settle() { _dismissSigOverlay(); _showWaitingMsg(pendingPolarity); @@ -625,7 +625,7 @@ var SigSelect = (function () { userRole = overlay.dataset.userRole; userPolarity= overlay.dataset.polarity; - // PICK SKY btn is rendered hidden during SIG_SELECT; reveal on pick_sky_available + // CAST SKY btn is rendered hidden during SIG_SELECT; reveal on pick_sky_available var pickSkyBtn = document.getElementById('id_pick_sky_btn'); if (pickSkyBtn) { pickSkyBtn.addEventListener('click', function () { diff --git a/src/apps/epic/static/apps/epic/stage-card.js b/src/apps/epic/static/apps/epic/stage-card.js index a3b5ca8..682928d 100644 --- a/src/apps/epic/static/apps/epic/stage-card.js +++ b/src/apps/epic/static/apps/epic/stage-card.js @@ -143,26 +143,42 @@ var StageCard = (function () { if (qBelow) qBelow.textContent = isMajor ? qualifier : ''; } - // Reversal face — four cases: - // Polarity-split: full reversal title in qualifier slot (top-after-spin), name slot empty - // Major: title (with comma) in qualifier slot, qualifier in name slot - // Non-major + reversal_qual: reversal_qualifier in qualifier slot, title in name slot - // Non-major no reversal_qual: fall back to current polarity's qualifier - var rQual = stageCard.querySelector('.fan-card-reversal-qualifier'); - var rName = stageCard.querySelector('.fan-card-reversal-name'); - if (rQual && rName) { + // Reversal face — class always matches semantic content: + // .fan-card-reversal-name → title-like text + // .fan-card-reversal-qualifier → qualifier-like text + // DOM order controls visual layout after the 180° SPIN (DOM-second appears + // visually on top). Sig + sea skeletons render a fixed slot pair so we + // assign classes per-arcana here so each branch lands in the right slot: + // Major / polarity-split — title on top → .name carried by DOM-second + // Non-major — qualifier on top → .qualifier carried by DOM-second + var slots = stageCard.querySelectorAll('.fan-card-face-reversal > p'); + if (slots.length === 2) { + var bottomEl = slots[0]; // DOM-first → visually bottom after spin + var topEl = slots[1]; // DOM-second → visually top after spin + // Wipe any squeeze-class artifacts from a prior populate call before + // re-stamping the base class — keeps the slot's CSS predictable. + bottomEl.className = ''; + topEl.className = ''; + if (reversalOverride) { - _setTitle(rQual, reversalOverride, card); - rName.textContent = ''; + // Polarity-split: single-line title on TOP; qualifier slot empty. + topEl.className = 'fan-card-reversal-name'; + _setTitle(topEl, reversalOverride, card); + bottomEl.className = 'fan-card-reversal-qualifier'; + bottomEl.textContent = ''; } else if (isMajor) { - _setTitle(rQual, title + ',', card); - rName.textContent = qualifier; - } else if (reversalQualifier) { - rQual.textContent = reversalQualifier; - _setTitle(rName, title, card); + // Major: title-with-comma on TOP, qualifier on BOTTOM. + topEl.className = 'fan-card-reversal-name'; + _setTitle(topEl, title + ',', card); + bottomEl.className = 'fan-card-reversal-qualifier'; + bottomEl.textContent = qualifier; } else { - rQual.textContent = qualifier; - _setTitle(rName, title, card); + // Non-major: qualifier on TOP, title on BOTTOM (inverted from + // upright order by design — qualifier word reads first after spin). + topEl.className = 'fan-card-reversal-qualifier'; + topEl.textContent = reversalQualifier || qualifier; + bottomEl.className = 'fan-card-reversal-name'; + _setTitle(bottomEl, title, card); } } } diff --git a/src/apps/epic/tasks.py b/src/apps/epic/tasks.py index 9281ec7..8268f37 100644 --- a/src/apps/epic/tasks.py +++ b/src/apps/epic/tasks.py @@ -1,5 +1,5 @@ """ -Countdown scheduler for the polarity-room TAKE SIG gate. +Countdown scheduler for the polarity-room SAVE SIG gate. Uses threading.Timer so no separate Celery worker is needed in development. Single-process only — swap for a Celery task if production uses multiple diff --git a/src/apps/epic/tests/integrated/test_views.py b/src/apps/epic/tests/integrated/test_views.py index 5af5660..d41a46e 100644 --- a/src/apps/epic/tests/integrated/test_views.py +++ b/src/apps/epic/tests/integrated/test_views.py @@ -879,7 +879,7 @@ class SelectRoleMultiSeatTest(TestCase): class RoomViewAllRolesFilledTest(TestCase): - """Room view in ROLE_SELECT with all seats assigned shows PICK SIGS button.""" + """Room view in ROLE_SELECT with all seats assigned shows SCAN SIGS button.""" def setUp(self): import lxml.html self.lxml = lxml.html @@ -1785,7 +1785,7 @@ class SigConfirmViewTest(TestCase): # ── SKY_SELECT rendering ────────────────────────────────────────────────────── class PickSkyRenderingTest(TestCase): - """Room page at SKY_SELECT renders PICK SKY btn and sig card in tray cell 2.""" + """Room page at SKY_SELECT renders CAST SKY btn and sig card in tray cell 2.""" def setUp(self): self.room, self.gamers, self.earthman, _ = _full_sig_setUp(self) @@ -1865,7 +1865,7 @@ class PickSkyRenderingTest(TestCase): self.assertEqual(founder.sky_birth_tz, "America/New_York") def test_no_sky_delete_btn_in_blank_sky_select_modal(self): - """A fresh PICK SKY modal (no preview wheel rendered yet) must not + """A fresh CAST SKY modal (no preview wheel rendered yet) must not carry the DEL btn — it would otherwise float in the empty wheel area suggesting there's something to delete when the user has only seen the form. The JS schedulePreview success handler is the contract that @@ -1881,7 +1881,7 @@ class PickSkyRenderingTest(TestCase): # ── SEA_SELECT rendering ────────────────────────────────────────────────────── class PickSeaRenderingTest(TestCase): - """At SKY_SELECT, a confirmed Character swaps PICK SKY → PICK SEA + sea overlay.""" + """At SKY_SELECT, a confirmed Character swaps CAST SKY → DRAW SEA + sea overlay.""" def setUp(self): self.room, self.gamers, self.earthman, _ = _full_sig_setUp(self) diff --git a/src/apps/epic/utils.py b/src/apps/epic/utils.py index aa92979..1f9c279 100644 --- a/src/apps/epic/utils.py +++ b/src/apps/epic/utils.py @@ -5,7 +5,7 @@ from apps.epic.models import Room, RoomInvite # ── Game-wide constants ──────────────────────────────────────────────────── # Reversal probability applied to any card pulled from a stack, anywhere in -# the game (PICK SEA initially; future phases — gameplay draws etc. — will +# the game (DRAW SEA initially; future phases — gameplay draws etc. — will # share this single source of truth). Stub for a future per-user profile # override: callers MUST go through stack_reversal_probability(user, room) # rather than referencing the constant directly so the user-config hookup is diff --git a/src/apps/epic/views.py b/src/apps/epic/views.py index 652b2d4..337f015 100644 --- a/src/apps/epic/views.py +++ b/src/apps/epic/views.py @@ -413,7 +413,7 @@ def room_view(request, room_id): ctx = _role_select_context(room, request.user) ctx["room"] = room ctx["page_class"] = "page-gameboard" - # Reversal-rate hint label under PICK SEA's SPREAD select — same helper as + # Reversal-rate hint label under DRAW SEA's SPREAD select — same helper as # sea_partial so the value tracks any future per-user override automatically. ctx["stack_reversal_pct"] = int(round(stack_reversal_probability(request.user, room) * 100)) return render(request, "apps/gameboard/room.html", ctx) @@ -1223,7 +1223,7 @@ def sky_save(request, room_id): @login_required def sky_delete(request, room_id): """Purge the requesting gamer's Character on this seat — both unconfirmed - drafts AND confirmed rows. The in-room PICK SKY DEL targets this so SAVE + drafts AND confirmed rows. The in-room CAST SKY DEL targets this so SAVE SKY → DEL → refresh truly drops the saved sky for the seat. The User model's sky_chart_data is intentionally untouched (Dashsky / My Sky applet's DEL handles that separately).""" @@ -1239,7 +1239,7 @@ def sky_delete(request, room_id): @login_required def sea_deck(request, room_id): - """Shuffled deck lists (levity + gravity halves) for PICK SEA draw. + """Shuffled deck lists (levity + gravity halves) for DRAW SEA draw. Excludes all Significators already claimed by seated gamers. Returns {levity: [{id, name, arcana, suit, number, levity_qualifier, diff --git a/src/functional_tests/management/commands/setup_sea_session.py b/src/functional_tests/management/commands/setup_sea_session.py index ed1bf08..87168db 100644 --- a/src/functional_tests/management/commands/setup_sea_session.py +++ b/src/functional_tests/management/commands/setup_sea_session.py @@ -1,8 +1,8 @@ """ -Management command for manual single-gamer PICK SEA testing. +Management command for manual single-gamer DRAW SEA testing. Creates a room at SKY_SELECT with one seated gamer whose sky is already -confirmed, so the PICK SEA overlay is immediately visible on page load. +confirmed, so the DRAW SEA overlay is immediately visible on page load. Usage: python src/manage.py setup_sea_session @@ -32,7 +32,7 @@ def _make_session(user): class Command(BaseCommand): - help = "Set up a SKY_SELECT room with sky confirmed and print a PICK SEA URL" + help = "Set up a SKY_SELECT room with sky confirmed and print a DRAW SEA URL" def add_arguments(self, parser): parser.add_argument("--base-url", default="http://localhost:8000") diff --git a/src/functional_tests/test_billboard.py b/src/functional_tests/test_billboard.py index a93b98e..dc55353 100644 --- a/src/functional_tests/test_billboard.py +++ b/src/functional_tests/test_billboard.py @@ -453,7 +453,7 @@ class BillscrollGearMenuTest(FunctionalTest): FT: the billscroll page has a gear menu that filters events by label. Frame = all regular (non-struck) drama entries. - Redact = struck-through (retracted) entries, e.g. a WAIT NVM after TAKE SIG. + Redact = struck-through (retracted) entries, e.g. a WAIT NVM after SAVE SIG. Scenario (one gamer, Role + Sig events): 1. Both labels checked by default — all events visible. diff --git a/src/functional_tests/test_game_room_select_role.py b/src/functional_tests/test_game_room_select_role.py index 0f021f1..3d4c329 100644 --- a/src/functional_tests/test_game_room_select_role.py +++ b/src/functional_tests/test_game_room_select_role.py @@ -843,12 +843,12 @@ class RoleSelectChannelsTest(ChannelsFunctionalTest): )) # ------------------------------------------------------------------ # - # Test 7 — PICK SIGS appears + card stack removed on last role # + # Test 7 — SCAN SIGS appears + card stack removed on last role # # ------------------------------------------------------------------ # def test_pick_sigs_appears_and_card_stack_removed_on_last_role(self): """When the sixth and final role is confirmed, the all_roles_filled - WS event makes the PICK SIGS button visible and removes the card + WS event makes the SCAN SIGS button visible and removes the card stack from the DOM entirely.""" emails = [ "founder@test.io", "amigo@test.io", "bud@test.io", @@ -883,7 +883,7 @@ class RoleSelectChannelsTest(ChannelsFunctionalTest): self.browser.find_element(By.CSS_SELECTOR, "#id_role_select .card").click() self.confirm_guard() - # PICK SIGS wrap must become visible via the all_roles_filled WS event. + # SCAN SIGS wrap must become visible via the all_roles_filled WS event. self.wait_for(lambda: self.assertFalse( self.browser.find_element(By.ID, "id_pick_sigs_wrap").get_attribute("style"), )) diff --git a/src/functional_tests/test_game_room_select_sea.py b/src/functional_tests/test_game_room_select_sea.py index f3ef437..f4fa907 100644 --- a/src/functional_tests/test_game_room_select_sea.py +++ b/src/functional_tests/test_game_room_select_sea.py @@ -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 # `