from selenium.webdriver.common.by import By from .base import FunctionalTest from apps.applets.models import Applet from apps.epic.models import Room, GateSlot from apps.lyric.models import User class GatekeeperTest(FunctionalTest): def setUp(self): super().setUp() Applet.objects.get_or_create( slug="new-game", defaults={"name": "New Game", "context": "gameboard"} ) Applet.objects.get_or_create( slug="my-games", defaults={"name": "My Games", "context": "gameboard"} ) def test_founder_creates_room_and_sees_gatekeeper(self): # 1. Log in, navigate to gameboard self.create_pre_authenticated_session("founder@test.io") self.browser.get(self.live_server_url + "/gameboard/") # 2. New Game applet has room name input, create button self.wait_for( lambda: self.browser.find_element(By.ID, "id_applet_new_game") ) self.browser.find_element(By.ID, "id_new_game_name").send_keys("Test Room") self.browser.find_element(By.ID, "id_create_game_btn").click() # 3. User is redirected to Gatekeeper page for new room self.wait_for( lambda: self.assertIn("/gameboard/room/", self.browser.current_url) ) self.wait_for( lambda: self.assertIn("/gate/", self.browser.current_url) ) # 4. Page shows room name, GATHERING status body = self.browser.find_element(By.TAG_NAME, "body") self.assertIn("Test Room", body.text) self.assertIn("GATHERING", body.text) # 5. Six token slots are visible slots = self.browser.find_elements(By.CSS_SELECTOR, ".gate-slot") self.assertEqual(len(slots), 6) # 6. Slot 1 has Drop Token btn; slots 2–6 show as empty slot_1 = slots[0] slot_1.find_element(By.CSS_SELECTOR, ".drop-token-btn") for slot in slots[1:]: self.assertIn("empty", slot.get_attribute("class")) def test_founder_drops_token_and_slot_fills(self): # 1. Set up: log in, create room, arrive at gatekeeper self.create_pre_authenticated_session("founder@test.io") self.browser.get(self.live_server_url + "/gameboard/") self.wait_for( lambda: self.browser.find_element(By.ID, "id_new_game_name") ) self.browser.find_element(By.ID, "id_new_game_name").send_keys("Dragon's Den") self.browser.find_element(By.ID, "id_create_game_btn").click() self.wait_for( lambda: self.assertIn("/gate/", self.browser.current_url) ) # 2. Founder clicks Drop Token on slot 1 drop_btn = self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, ".drop-token-btn") ) drop_btn.click() # 3. Slot 1 now filled; drop btn gone self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, ".gate-slot.filled") ) slots = self.browser.find_elements(By.CSS_SELECTOR, ".gate-slot") self.assertIn("filled", slots[0].get_attribute("class")) self.assertEqual( len(self.browser.find_elements(By.CSS_SELECTOR, ".drop-token-btn")), 0 ) def test_room_appears_in_my_games_after_creation(self): # 1. Set up founder, game room, name self.create_pre_authenticated_session("founder@test.io") self.browser.get(self.live_server_url + "/gameboard/") self.wait_for( lambda: self.browser.find_element(By.ID, "id_new_game_name") ) self.browser.find_element(By.ID, "id_new_game_name").send_keys("Dragon's Den") self.browser.find_element(By.ID, "id_create_game_btn").click() self.wait_for( lambda: self.assertIn("/gate/", self.browser.current_url) ) # 2. Navigate back to gameboard self.browser.get(self.live_server_url + "/gameboard/") my_games = self.wait_for( lambda: self.browser.find_element(By.ID, "id_applet_my_games") ) self.assertIn("Dragon's Den", my_games.text) def test_second_gamer_drops_token_into_open_slot(self): # 1. Founder creates room, fills slot 1 self.create_pre_authenticated_session("founder@test.io") self.browser.get(self.live_server_url +"/gameboard/") self.wait_for( lambda: self.browser.find_element(By.ID, "id_new_game_name") ) self.browser.find_element(By.ID, "id_new_game_name").send_keys("Dragon's Den") self.browser.find_element(By.ID, "id_create_game_btn").click() self.wait_for( lambda: self.assertIn("/gate/", self.browser.current_url) ) room_url = self.browser.current_url self.browser.find_element(By.CSS_SELECTOR, ".drop-token-btn").click() self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, ".gate-slot.filled") ) # 2. Founder invites friend via email (duplicate invite logic from My Notes applet) invite_input = self.wait_for( lambda: self.browser.find_element(By.ID, "id_invite_email") ) invite_input.send_keys("friend@test.io") self.browser.find_element(By.ID, "id_invite_btn").click() # 3. Friend logs in, sees invitation in My Games self.create_pre_authenticated_session("friend@test.io") self.browser.get(self.live_server_url + "/gameboard/") my_games = self.wait_for( lambda: self.browser.find_element(By.ID, "id_applet_my_games") ) self.assertIn("Dragon's Den", my_games.text) # 3. Friend follows link to gatekeeper self.browser.find_element(By.LINK_TEXT, "Dragon's Den").click() # 4. Friend sees drop btn on open slot drop_btn = self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, ".drop-token-btn") ) drop_btn.click() # 5. Now two slots filled self.wait_for( lambda: self.assertEqual( len(self.browser.find_elements(By.CSS_SELECTOR, ".gate-slot.filled")), 2 ) ) def test_gate_opens_when_all_slots_filled(self): # 1. Founder creates room self.create_pre_authenticated_session("founder@test.io") self.browser.get(self.live_server_url + "/gameboard/") self.wait_for( lambda: self.browser.find_element(By.ID, "id_new_game_name") ) self.browser.find_element(By.ID, "id_new_game_name").send_keys("Dragon's Den") self.browser.find_element(By.ID, "id_create_game_btn").click() self.wait_for( lambda: self.assertIn("/gate/", self.browser.current_url) ) room_url = self.browser.current_url # 2. Fill all 6 slots directly via ORM (founder + 5 extras) self.browser.find_element(By.CSS_SELECTOR, ".drop-token-btn").click() self.wait_for( lambda: self.browser.find_element(By.CSS_SELECTOR, ".gate-slot.filled") ) room = Room.objects.get(name="Dragon's Den") for i, email in enumerate([ "g2@test.io", "g3@test.io", "g4@test.io", "g5@test.io", "g6@test.io" ], start=2): gamer = User.objects.create(email=email) slot = room.gate_slots.get(slot_number=i) slot.gamer = gamer slot.status = GateSlot.FILLED slot.save() room.refresh_from_db() room.gate_status = Room.OPEN room.save() # 3. Gatekeeper disappears via htmx self.wait_for( lambda: self.assertEqual( len(self.browser.find_elements(By.CSS_SELECTOR, ".gate-modal")), 0 ) ) # Restore the following once room built # body = self.browser.find_element(By.TAG_NAME, "body") # self.assertIn("OPEN", body.text)