From 191dad53650322d805534a21ebc3c4bce0bc8752 Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Wed, 20 May 2026 11:56:09 -0400 Subject: [PATCH] =?UTF-8?q?my-sea=20hex-btn=20state-machine=20FT=20pin:=20?= =?UTF-8?q?extend=20`test=5Flanding=5Frenders=5Fhex=5Fwith=5Ffree=5Fdraw?= =?UTF-8?q?=5Fbtn`=20to=20assert=20PAID=20DRAW=20+=20GATE=20VIEW=20are=20a?= =?UTF-8?q?bsent=20for=20fresh=20users=20=E2=80=94=20closes=20the=20mutual?= =?UTF-8?q?-exclusion=20gap=20(the=20other=20two=20states=20already=20pin?= =?UTF-8?q?=20the=20same=20invariant=20from=20their=20own=20directions;=20?= =?UTF-8?q?this=20adds=20the=20FREE-DRAW=20side).=20Docstring=20spells=20o?= =?UTF-8?q?ut=20the=203-way=20state=20machine=20for=20future=20readers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 (1M context) --- src/functional_tests/test_game_my_sea.py | 27 ++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/functional_tests/test_game_my_sea.py b/src/functional_tests/test_game_my_sea.py index 16ca995..fbca23b 100644 --- a/src/functional_tests/test_game_my_sea.py +++ b/src/functional_tests/test_game_my_sea.py @@ -205,8 +205,20 @@ class MySeaDrawSeaLandingTest(FunctionalTest): """User w. sig → /gameboard/my-sea/ shows the DRY table hex (re- used from my-sign / the room shell) w. a central FREE DRAW btn. Element ID `id_draw_sea_btn` describes intent (the draw entry - point) — a future sprint will conditionally swap the label to - DRAW SEA once the daily free has been used.""" + point); the hex-center btn is a 3-way state machine: + - FREE DRAW (`#id_draw_sea_btn`) — fresh user (no active row, no + deposit). Pinned here. + - PAID DRAW (`#id_my_sea_paid_draw_btn`) — deposit reserved. + Pinned by `MySeaLandingPaidDrawTest`. + - GATE VIEW (`#id_my_sea_gate_view_btn`) — quota spent, no + deposit (post-DEL). Pinned by + `MySeaDeleteDrawAndGuardPortalTest` (the DEL-confirm flow). + + The three IDs are mutually exclusive — only one renders at a + time. This test pins the fresh-user side of that exclusion + (FREE DRAW present, the other two absent); the deposit + post- + DEL sides have their own dedicated FTs that pin the same + invariant from the other directions.""" self.create_pre_authenticated_session(self.email) self.browser.get(self.live_server_url + "/gameboard/my-sea/") # data-phase=landing on the page wrapper @@ -221,6 +233,17 @@ class MySeaDrawSeaLandingTest(FunctionalTest): self.assertIn("FREE", btn.text.upper()) self.assertIn("DRAW", btn.text.upper()) self.assertIn("btn-primary", btn.get_attribute("class")) + # Mutual exclusion: PAID DRAW + GATE VIEW must NOT also render. + self.assertEqual( + len(page.find_elements(By.CSS_SELECTOR, "#id_my_sea_paid_draw_btn")), + 0, + "PAID DRAW btn must not render when no deposit is reserved", + ) + self.assertEqual( + len(page.find_elements(By.CSS_SELECTOR, "#id_my_sea_gate_view_btn")), + 0, + "GATE VIEW btn must not render when no active draw row exists", + ) # ── Test 2 ───────────────────────────────────────────────────────────────