""" Functional tests: deck-to-seat contribution mechanics. Sprint 1 (DeckContributionTest): Confirming a role in ROLE SELECT assigns the gamer's equipped deck to the TableSeat. The Game Kit immediately reflects the in-use state: the deck card gains the game name in its tooltip and the micro-status reads "In-Use". Sprint 2 (DeckInUseGameKitTest): With a deck already assigned to an active seat the Game Kit DON button is btn-disabled and no DOFF toggle is shown (unlike the normal equipped state where DOFF is visible). Clicking the card shows a tooltip naming the game. A second deck that is NOT assigned to any active seat has normal DON/DOFF behaviour. """ import time from django.test import tag from selenium.webdriver.common.by import By from apps.applets.models import Applet from apps.epic.models import DeckVariant, GateSlot, Room, TableSeat from apps.lyric.models import User from functional_tests.base import FunctionalTest from functional_tests.test_room_role_select import _fill_room_via_orm from functional_tests.test_room_sig_select import _assign_all_roles FOUNDER_EMAIL = "founder@test.io" GAMER_EMAIL = "gamer@test.io" def _equip_earthman(user): earthman = DeckVariant.objects.get(slug="earthman") user.equipped_deck = earthman user.save(update_fields=["equipped_deck"]) return earthman def _room_at_role_select(name="Wildfire"): """Create a room filled to 6 and at ROLE_SELECT table status.""" founder, _ = User.objects.get_or_create(email=FOUNDER_EMAIL) room = Room.objects.create(name=name, owner=founder) emails = [FOUNDER_EMAIL, GAMER_EMAIL, "b@test.io", "c@test.io", "d@test.io", "e@test.io"] _fill_room_via_orm(room, emails) for slot in room.gate_slots.all(): if slot.gamer: _equip_earthman(slot.gamer) room.table_status = Room.ROLE_SELECT room.save() return room, founder # ── Sprint 1 ───────────────────────────────────────────────────────────────── class DeckContributionTest(FunctionalTest): """Sprint 1: role confirmation → TableSeat.deck_variant set; Game Kit shows In-Use.""" def setUp(self): super().setUp() self.browser.set_window_size(800, 1200) for slug, name, ctx in [ ("game-kit", "Game Kit", "gameboard"), ("gk-decks", "Card Decks","game-kit"), ]: Applet.objects.get_or_create(slug=slug, defaults={"name": name, "context": ctx}) def test_confirming_role_assigns_equipped_deck_to_seat(self): """After the gamer confirms a role, Game Kit shows the Earthman deck as 'In-Use' with the game name in the deck tooltip, and the micro-status changes from 'Equipped' to 'In-Use'. """ room, founder = _room_at_role_select() gamer = User.objects.get(email=GAMER_EMAIL) # Gamer logs in and navigates to the role-select room session_key = self.create_pre_authenticated_session(GAMER_EMAIL) self.browser.get(self.live_server_url) self.browser.add_cookie({"name": "sessionid", "value": session_key}) self.browser.get(self.live_server_url + f"/gameboard/room/{room.pk}/") # Gamer confirms a role (NC — slot 2 is theirs) role_btn = self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, ".role-card[data-role='NC'] .btn-confirm") ) role_btn.click() # Deck is now assigned to the seat in the DB self.wait_for(lambda: self.assertTrue( TableSeat.objects.filter( gamer=gamer, room=room, deck_variant=gamer.equipped_deck, ).exists(), "TableSeat.deck_variant was not set after role confirmation", )) # Navigate to Game Kit → Card Decks to verify UI state self.browser.get(self.live_server_url + "/gameboard/") decks_btn = self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_kit_card_deck") ) decks_btn.click() earthman_card = self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_kit_earthman_deck") ) earthman_card.click() # open tooltip # Tooltip shows the game name tooltip = self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, ".tt-deck-game-name") ) self.assertIn(room.name.upper(), tooltip.text.upper()) # Micro-status reads "In-Use", not "Equipped" micro_status = self.wait_for( lambda: self.browser.find_element( By.CSS_SELECTOR, "#id_kit_earthman_deck .deck-micro-status" ) ) self.assertIn("IN-USE", micro_status.text.upper()) self.assertNotIn("EQUIPPED", micro_status.text.upper()) # ── Sprint 2 ───────────────────────────────────────────────────────────────── class DeckInUseGameKitTest(FunctionalTest): """Sprint 2: DON disabled + no DOFF toggle for in-use deck; second deck unaffected.""" def setUp(self): super().setUp() self.browser.set_window_size(800, 1200) for slug, name, ctx in [ ("game-kit", "Game Kit", "gameboard"), ("gk-decks", "Card Decks","game-kit"), ]: Applet.objects.get_or_create(slug=slug, defaults={"name": name, "context": ctx}) def _setup_in_use_deck(self): """Create a seated gamer whose Earthman deck is already assigned to a seat.""" room, founder = _room_at_role_select() gamer = User.objects.get(email=GAMER_EMAIL) earthman = _equip_earthman(gamer) # Assign deck directly (Sprint 1 must be green first) seat = TableSeat.objects.create(gamer=gamer, room=room, role="NC", deck_variant=earthman) return gamer, earthman, room, seat def test_don_is_disabled_and_doff_absent_for_in_use_deck(self): """DON button carries btn-disabled; DOFF is not rendered at all (not just disabled).""" gamer, earthman, room, seat = self._setup_in_use_deck() session_key = self.create_pre_authenticated_session(GAMER_EMAIL) self.browser.get(self.live_server_url) self.browser.add_cookie({"name": "sessionid", "value": session_key}) self.browser.get(self.live_server_url + "/gameboard/") self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_kit_card_deck") ).click() self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_kit_earthman_deck") ).click() # DON is disabled don_btn = self.wait_for( lambda: self.browser.find_element( By.CSS_SELECTOR, f"#id_kit_earthman_deck .btn-equip" ) ) self.assertIn("btn-disabled", don_btn.get_attribute("class")) # DOFF button is not present (not just disabled — entirely absent) doff_btns = self.browser.find_elements( By.CSS_SELECTOR, f"#id_kit_earthman_deck .btn-unequip:not(.btn-disabled)" ) self.assertEqual(len(doff_btns), 0, "DOFF button should not be shown for an in-use deck") def test_tooltip_names_the_game_for_in_use_deck(self): """Opening an in-use deck's tooltip shows the room name it is contributing to.""" gamer, earthman, room, seat = self._setup_in_use_deck() session_key = self.create_pre_authenticated_session(GAMER_EMAIL) self.browser.get(self.live_server_url) self.browser.add_cookie({"name": "sessionid", "value": session_key}) self.browser.get(self.live_server_url + "/gameboard/") self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_kit_card_deck") ).click() self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_kit_earthman_deck") ).click() game_label = self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, ".tt-deck-game-name") ) self.assertIn(room.name.upper(), game_label.text.upper()) def test_non_contributing_deck_has_normal_don_doff(self): """A deck not assigned to any active seat shows the normal DON/DOFF apparatus.""" gamer, earthman, room, seat = self._setup_in_use_deck() # Unlock Fiorentine for the gamer so it appears in Game Kit fiorentine = DeckVariant.objects.get(slug="fiorentine-minchiate") gamer.unlocked_decks.add(fiorentine) session_key = self.create_pre_authenticated_session(GAMER_EMAIL) self.browser.get(self.live_server_url) self.browser.add_cookie({"name": "sessionid", "value": session_key}) self.browser.get(self.live_server_url + "/gameboard/") self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_kit_card_deck") ).click() self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_kit_fiorentine_deck") ).click() don_btn = self.wait_for( lambda: self.browser.find_element( By.CSS_SELECTOR, "#id_kit_fiorentine_deck .btn-equip" ) ) self.assertNotIn("btn-disabled", don_btn.get_attribute("class"))