"""FT for the gatekeeper invite via #id_bud_btn slide-out. Replaces the legacy inline `
` panel inside the gatekeeper modal. The bud-btn lives at the upper-right corner of the right sidebar (footer in landscape); slide-out hosts the email/ username field + OK btn. Submit fires async POST to epic:invite_gamer w. Accept: application/json — server returns {brief, recipient_display}, JS shows the slide-down Brief banner. """ from selenium.webdriver.common.by import By from apps.billboard.models import Brief from apps.epic.models import Room, RoomInvite from apps.lyric.models import User from .base import FunctionalTest class GatekeeperBudBtnPresenceTest(FunctionalTest): """The bud-btn renders for the room owner during gate phase, and is absent for non-owners (friend invites are owner-only).""" def setUp(self): super().setUp() self.owner = User.objects.create(email="owner@test.io", username="owner") self.gamer = User.objects.create(email="gamer@test.io", username="gamer") self.room = Room.objects.create(name="Bingobango", owner=self.owner) self.room_url = f"{self.live_server_url}/gameboard/room/{self.room.id}/gate/" def test_bud_btn_renders_for_owner(self): self.create_pre_authenticated_session("owner@test.io") self.browser.get(self.room_url) self.wait_for(lambda: self.browser.find_element(By.ID, "id_bud_btn")) def test_bud_btn_absent_for_non_owner(self): # A registered non-owner viewer doesn't see the invite affordance. self.create_pre_authenticated_session("gamer@test.io") self.browser.get(self.room_url) # Gatekeeper-specific element confirms page rendered self.wait_for(lambda: self.browser.find_element(By.CSS_SELECTOR, ".gate-modal")) self.assertFalse(self.browser.find_elements(By.ID, "id_bud_btn")) def test_legacy_invite_email_input_is_gone(self): """Sanity: the old inline form has been removed.""" self.create_pre_authenticated_session("owner@test.io") self.browser.get(self.room_url) self.wait_for(lambda: self.browser.find_element(By.CSS_SELECTOR, ".gate-modal")) self.assertFalse(self.browser.find_elements(By.ID, "id_invite_email")) class GatekeeperBudBtnAsyncInviteTest(FunctionalTest): """OK on the bud-btn slide-out fires the async invite — RoomInvite persisted, Brief w/ kind=GAME_INVITE created, slide-down banner shown.""" def setUp(self): super().setUp() self.owner = User.objects.create(email="owner@test.io", username="owner") self.alice = User.objects.create(email="alice@test.io", username="alice") self.room = Room.objects.create(name="Bingobango", owner=self.owner) self.room_url = f"{self.live_server_url}/gameboard/room/{self.room.id}/gate/" self.create_pre_authenticated_session("owner@test.io") self.browser.get(self.room_url) def _open_panel_and_invite(self, recipient): bud_btn = self.wait_for(lambda: self.browser.find_element(By.ID, "id_bud_btn")) bud_btn.click() recipient_input = self.wait_for( lambda: self.browser.find_element(By.ID, "id_recipient") ) recipient_input.send_keys(recipient) self.browser.find_element( By.CSS_SELECTOR, "#id_bud_panel .btn.btn-confirm" ).click() return bud_btn def test_invite_creates_room_invite(self): self._open_panel_and_invite("alice@test.io") self.wait_for(lambda: self.assertEqual( RoomInvite.objects.filter( room=self.room, invitee_email="alice@test.io" ).count(), 1, )) def test_invite_spawns_game_invite_brief(self): self._open_panel_and_invite("alice@test.io") self.wait_for(lambda: self.assertEqual( Brief.objects.filter( owner=self.owner, kind=Brief.KIND_GAME_INVITE, ).count(), 1, )) def test_invite_renders_slide_down_banner(self): self._open_panel_and_invite("alice@test.io") self.wait_for(lambda: self.browser.find_element(By.CSS_SELECTOR, ".note-banner")) def test_invite_closes_panel_after_success(self): bud_btn = self._open_panel_and_invite("alice@test.io") self.wait_for(lambda: self.assertNotIn("active", bud_btn.get_attribute("class"))) def test_invite_username_resolves_to_user_email(self): """Username-typed invite stores the resolved User's email.""" self._open_panel_and_invite("alice") self.wait_for(lambda: self.assertEqual( RoomInvite.objects.filter( room=self.room, invitee_email="alice@test.io" ).count(), 1, )) def test_invite_auto_adds_recipient_to_owner_buds(self): self._open_panel_and_invite("alice@test.io") self.wait_for(lambda: self.assertIn( self.alice, list(self.owner.buds.all()) ))