Sig select: caution tooltip, FLIP/FYI stat block, keyword display

- TarotCard.cautions JSONField + cautions_json property; migrations
  0027–0029 seed The Schizo (number=1) with 4 rival-interaction cautions
  (Roman-numeral card refs: I. The Pervert / II. The Occultist, etc.)
- Sig-select overlay: FLIP (stat-block toggle) + FYI (caution tooltip)
  buttons; nav PRV/NXT portaled outside tooltip at bottom corners (z-70);
  caution tooltip covers stat block (inset:0, z-60, Gaussian blur);
  tooltip click dismisses; FLIP/FYI fully dead while btn-disabled;
  nav wraps circularly (4/4 → 1/4, 1/4 → 4/4)
- SCSS: btn-disabled specificity fix (!important); btn-nav-left/right
  classes; sig-caution-* layout; stat-face keyword lists
- Jasmine suite expanded: stat block + FLIP (5 specs), caution tooltip
  (16 specs) including wrap-around and disabled-button behaviour
- IT tests: TarotCardCautionsTest (5), SigSelectRenderingTest (8)
- Role-card SVG icons added to static/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-04-07 00:22:04 -04:00
parent e2cc38686f
commit 520fdf7862
24 changed files with 1936 additions and 54 deletions

View File

@@ -926,7 +926,7 @@ def _full_sig_setUp(test_case, role_order=None):
room.table_status = Room.SIG_SELECT
room.save()
card_in_deck = TarotCard.objects.get(
deck_variant=earthman, arcana="MIDDLE", suit="WANDS", number=11
deck_variant=earthman, arcana="MIDDLE", suit="BRANDS", number=11
)
test_case.client.force_login(founder)
return room, gamers, earthman, card_in_deck
@@ -963,6 +963,32 @@ class SigSelectRenderingTest(TestCase):
response = self.client.get(self.url)
self.assertNotContains(response, "id_sig_deck")
def test_sig_cards_render_keyword_data_attributes(self):
response = self.client.get(self.url)
content = response.content.decode()
self.assertIn("data-keywords-upright=", content)
self.assertIn("data-keywords-reversed=", content)
def test_sig_stat_block_structure_rendered(self):
response = self.client.get(self.url)
self.assertContains(response, "sig-stat-block")
self.assertContains(response, "sig-flip-btn")
self.assertContains(response, "stat-face--upright")
self.assertContains(response, "stat-face--reversed")
def test_sig_cards_render_cautions_data_attribute(self):
response = self.client.get(self.url)
self.assertContains(response, "data-cautions=")
def test_sig_caution_tooltip_structure_rendered(self):
response = self.client.get(self.url)
self.assertContains(response, "sig-caution-tooltip")
self.assertContains(response, "sig-caution-btn")
self.assertContains(response, "sig-caution-effect")
self.assertContains(response, "sig-caution-index")
self.assertContains(response, "sig-caution-prev")
self.assertContains(response, "sig-caution-next")
class SelectSigCardViewTest(TestCase):
"""select_sig view — records choice, enforces turn order, rejects bad input."""
@@ -1000,8 +1026,8 @@ class SelectSigCardViewTest(TestCase):
def test_select_sig_card_not_in_deck_returns_400(self):
# Create a pip card (number=5) — not in the sig deck (only court 1114 + major 01)
other = TarotCard.objects.create(
deck_variant=self.earthman, arcana="MINOR", suit="WANDS", number=5,
name="Five of Wands Test", slug="five-of-wands-test",
deck_variant=self.earthman, arcana="MINOR", suit="BRANDS", number=5,
name="Five of Brands Test", slug="five-of-brands-test",
keywords_upright=[], keywords_reversed=[],
)
response = self._post(card_id=other.id)
@@ -1188,7 +1214,7 @@ class SigReserveViewTest(TestCase):
def test_reserve_different_card_while_holding_returns_409(self):
"""Cannot OK a different card while holding one — must NVM first."""
card_b = TarotCard.objects.filter(
deck_variant=self.earthman, arcana="MIDDLE", suit="WANDS", number=12
deck_variant=self.earthman, arcana="MIDDLE", suit="BRANDS", number=12
).first()
self._reserve() # PC grabs card A → 200
response = self._reserve(card_id=card_b.id) # tries card B → 409
@@ -1210,7 +1236,7 @@ class SigReserveViewTest(TestCase):
def test_reserve_blocked_then_unblocked_after_release(self):
"""After NVM, a new card can be OK'd."""
card_b = TarotCard.objects.filter(
deck_variant=self.earthman, arcana="MIDDLE", suit="WANDS", number=12
deck_variant=self.earthman, arcana="MIDDLE", suit="BRANDS", number=12
).first()
self._reserve() # hold card A
self._reserve(action="release") # NVM