fix CI FT regressions: deck contribution, ROLE SELECT no-deck guard, sig qualifiers, Carte Blanche multi-slot
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful

- test_deck_contribution: get_or_create _equip_earthman + unlocked_decks.add; slot_number=2 on
  _setup_in_use_deck seat; navigate to /gameboard/ (not gate — game-kit panel absent there);
  drop #id_kit_card_deck click ({% empty %} placeholder; deck renders in loop when present);
  use textContent for CSS-hidden tooltip; drop stale .deck-micro-status assertion (now mini-portal)
- ROLE SELECT FTs (RoleSelectTest + RoleSelectTrayTest): equip Earthman deck for active-slot
  user in each test that opens the fan — fixes no-deck JS guard blocking #id_role_select
- test_room_sig_select: seed The Nomad/Schizo w. correct Earthman slugs/names + Enlightened/
  Engraven qualifiers; grant super-nomad + super-schizo Notes to all gamers so Major Arcana
  appear in overlay; seed Middle Arcana w. Elevated/Graven qualifiers; rename test methods
- test_game_kit: drop stale assertIn("active", text) — availability moved to In-Use mini-portal
- Carte Blanche: CB stays equipped after multi-slot deposit (revert drop_token unequip);
  select_role existing-seat query gains order_by("slot_number") for deterministic primary seat;
  multi-slot FT: kit bag shows placeholder after first deposit (CB unequipped); cold-feet
  verifies DON via hover→portal; re-equip via portal DON before re-deposit; new
  test_carte_in_use_game_kit_shows_room_attribution checks Game Kit tooltip after deposit

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-04-28 16:29:51 -04:00
parent 9eb1c1523e
commit 759ce8d3e4
6 changed files with 158 additions and 89 deletions

View File

@@ -168,6 +168,7 @@ class CarteBlancheTest(FunctionalTest):
self.wait_for(
lambda: self.assertIn("/gate/", self.browser.current_url)
)
gate_url = self.browser.current_url
self.wait_for(
lambda: self.browser.find_element(By.CSS_SELECTOR, ".gate-overlay")
)
@@ -217,24 +218,13 @@ class CarteBlancheTest(FunctionalTest):
)
self.wait_for(lambda: get_circle(1).find_element(By.CSS_SELECTOR, ".drop-token-btn"))
# 12. Carte tooltip in kit bag shows room name (lease info)
# 12. Kit bag trinket section is now empty — Carte Blanche unequipped on deposit
self.browser.find_element(By.ID, "id_kit_btn").click()
self.wait_for(
lambda: self.browser.find_element(
By.CSS_SELECTOR,
f'#id_kit_bag_dialog [data-token-type="{Token.CARTE}"]',
By.CSS_SELECTOR, "#id_kit_bag_dialog .kit-bag-placeholder"
)
)
carte_in_bag = self.browser.find_element(
By.CSS_SELECTOR, f'#id_kit_bag_dialog [data-token-type="{Token.CARTE}"]'
)
# Kit bag tooltips are CSS-hidden; read textContent (not .text) to avoid
# relying on hover visibility in headless Firefox.
self.assertIn(
"The Long Room",
carte_in_bag.find_element(By.CSS_SELECTOR, ".tt").get_attribute("textContent"),
)
# Close kit bag
self.browser.find_element(By.ID, "id_kit_btn").click()
self.wait_for(
lambda: self.assertFalse(
@@ -249,26 +239,35 @@ class CarteBlancheTest(FunctionalTest):
len(self.browser.find_elements(By.CSS_SELECTOR, ".token-slot.claimed")), 0
)
)
# Lease info cleared from kit bag tooltip
self.browser.find_element(By.ID, "id_kit_btn").click()
self.wait_for(
lambda: self.browser.find_element(
By.CSS_SELECTOR,
f'#id_kit_bag_dialog [data-token-type="{Token.CARTE}"]',
)
# Carte reappears in Game Kit with DON available — not re-equipped automatically.
# Game Kit is only in the /gameboard/ context, not the gatekeeper page.
self.browser.get(self.live_server_url + "/gameboard/")
carte_el = self.browser.find_element(By.ID, "id_kit_carte_blanche")
self.browser.execute_script(
"arguments[0].scrollIntoView({block:'center'})", carte_el
)
carte_in_bag = self.browser.find_element(
By.CSS_SELECTOR, f'#id_kit_bag_dialog [data-token-type="{Token.CARTE}"]'
ActionChains(self.browser).move_to_element(carte_el).perform()
portal = self.wait_for(
lambda: self.browser.find_element(By.ID, "id_tooltip_portal")
)
self.assertNotIn(
"The Long Room",
carte_in_bag.find_element(By.CSS_SELECTOR, ".tt").get_attribute("textContent"),
self.wait_for(lambda: self.assertTrue(portal.is_displayed()))
don = self.wait_for(
lambda: portal.find_element(By.CSS_SELECTOR, ".btn-equip")
)
self.browser.find_element(By.ID, "id_kit_btn").click()
self.assertNotIn("btn-disabled", don.get_attribute("class"))
# ── COLD FEET RESOLVED: full six-slot run ────────────────────────────
# 14. Re-deposit Carte
# 14. Re-equip Carte via portal DON, navigate back to gate
don.click()
self.wait_for(
lambda: self.assertIn(
"btn-disabled",
portal.find_element(By.CSS_SELECTOR, ".btn-equip").get_attribute("class"),
)
)
self.browser.get(gate_url)
self.wait_for(lambda: self.browser.find_element(By.CSS_SELECTOR, ".gate-overlay"))
open_kit_and_select_carte()
deposit_carte()
@@ -331,3 +330,56 @@ class CarteBlancheTest(FunctionalTest):
self.wait_for(
lambda: self.browser.find_element(By.CSS_SELECTOR, ".launch-game-btn")
)
def test_carte_in_use_game_kit_shows_room_attribution(self):
"""While Carte Blanche is deposited in a room, its Game Kit tooltip
shows 'In game: <room name>' so the gamer knows where it's committed."""
self.create_pre_authenticated_session("blanche@test.io")
self.browser.get(self.live_server_url + "/gameboard/")
self.wait_for(lambda: self.browser.find_element(By.ID, "id_game_kit"))
# DON the Carte Blanche via tooltip portal
carte_el = self.browser.find_element(By.ID, "id_kit_carte_blanche")
self.browser.execute_script(
"arguments[0].scrollIntoView({block:'center'})", carte_el
)
ActionChains(self.browser).move_to_element(carte_el).perform()
portal = self.wait_for(
lambda: self.browser.find_element(By.ID, "id_tooltip_portal")
)
self.wait_for(lambda: self.assertTrue(portal.is_displayed()))
don = self.wait_for(lambda: portal.find_element(By.CSS_SELECTOR, ".btn-equip"))
don.click()
self.wait_for(
lambda: self.assertIn(
"btn-disabled",
portal.find_element(By.CSS_SELECTOR, ".btn-equip").get_attribute("class"),
)
)
# Create a room and deposit the Carte Blanche
self.browser.find_element(By.ID, "id_new_game_name").send_keys("Commitment Room")
self.browser.find_element(By.ID, "id_create_game_btn").click()
self.wait_for(lambda: self.assertIn("/gate/", self.browser.current_url))
self.browser.find_element(By.ID, "id_kit_btn").click()
self.wait_for(
lambda: self.browser.find_element(
By.CSS_SELECTOR,
f'#id_kit_bag_dialog [data-token-type="{Token.CARTE}"]',
)
).click()
self.browser.find_element(By.CSS_SELECTOR, "button.token-rails").click()
self.wait_for(
lambda: self.browser.find_element(By.CSS_SELECTOR, ".token-slot.claimed")
)
# Game Kit panel is on /gameboard/, not the gate page — navigate back to check tooltip
self.browser.get(self.live_server_url + "/gameboard/")
carte_tt = self.wait_for(
lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_kit_carte_blanche .tt")
)
self.assertIn(
"Commitment Room",
carte_tt.get_attribute("textContent"),
)