"""Functional tests for the PICK SEA overlay — Celtic Cross draw.""" from django.urls import reverse from selenium.webdriver.common.by import By from apps.applets.models import Applet from apps.epic.models import GateSlot, Room, TableSeat, TarotCard, DeckVariant from .base import ChannelsFunctionalTest def _make_sky_confirmed_room(live_server_url, user, earthman): """Create a SKY_SELECT room with one gamer seated and sig assigned. Returns (room, seat). The Character is NOT yet confirmed — call _confirm_sky() in the browser to trigger the async transition. """ room = Room.objects.create( name="Sea Test Room", table_status=Room.SKY_SELECT, owner=user ) slot = room.gate_slots.get(slot_number=1) slot.gamer = user slot.status = GateSlot.FILLED slot.save() room.gate_status = Room.OPEN room.save() sig_card = TarotCard.objects.filter(deck_variant=earthman, arcana="MAJOR").first() seat = TableSeat.objects.create( room=room, gamer=user, role="PC", slot_number=1, deck_variant=earthman, significator=sig_card, ) return room, seat class PickSeaAsyncTransitionTest(ChannelsFunctionalTest): """After sky confirm, PICK SEA overlay appears without a page refresh.""" def setUp(self): super().setUp() self.browser.set_window_size(800, 1200) 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"} ) from apps.lyric.models import User gamer, _ = User.objects.get_or_create(email="founder@test.io") earthman, _ = DeckVariant.objects.get_or_create( slug="earthman", defaults={"name": "Earthman Deck", "card_count": 108, "is_default": True}, ) gamer.unlocked_decks.add(earthman) gamer.equipped_deck = earthman gamer.save(update_fields=["equipped_deck"]) self.gamer = gamer self.room, self.seat = _make_sky_confirmed_room(self.live_server_url, gamer, earthman) self.room_url = self.live_server_url + reverse( "epic:room", kwargs={"room_id": self.room.id} ) self.natus_save_url = self.live_server_url + reverse( "epic:natus_save", kwargs={"room_id": self.room.id} ) def _confirm_sky(self): """POST to natus_save with action=confirm from browser JS (bypasses chart form).""" # Wait for the room WS connection to be ready before triggering confirm self.wait_for(lambda: self.browser.execute_script( "return !!(window._roomSocket && window._roomSocket.readyState === 1);" )) self.browser.execute_script(f""" const csrf = (document.cookie.match(/csrftoken=([^;]+)/) || ['',''])[1]; fetch('{self.natus_save_url}', {{ method: 'POST', credentials: 'same-origin', headers: {{'Content-Type': 'application/json', 'X-CSRFToken': csrf}}, body: JSON.stringify({{ birth_dt: '1990-06-15T09:00:00Z', birth_lat: 51.5, birth_lon: -0.1, birth_place: 'London', house_system: 'O', chart_data: {{}}, action: 'confirm', }}), }}); """) def test_sea_overlay_appears_without_page_refresh(self): """Confirming sky replaces the natus overlay with the sea overlay in-place.""" self.create_pre_authenticated_session("founder@test.io") self.browser.get(self.room_url) # Sky not yet confirmed — PICK SKY btn present, no sea overlay self.wait_for(lambda: self.browser.find_element(By.ID, "id_pick_sky_btn")) self.assertEqual(self.browser.find_elements(By.ID, "id_sea_overlay"), []) self._confirm_sky() # Sea overlay appears without page refresh sea_overlay = self.wait_for( lambda: self.browser.find_element(By.ID, "id_sea_overlay") ) self.assertTrue(sea_overlay.is_displayed()) def test_natus_overlay_not_visible_after_sky_confirm(self): """Natus overlay is removed from the DOM after sky confirm.""" self.create_pre_authenticated_session("founder@test.io") self.browser.get(self.room_url) self.wait_for(lambda: self.browser.find_element(By.ID, "id_pick_sky_btn")) self._confirm_sky() # Sea overlay must appear first (confirms transition happened) self.wait_for(lambda: self.browser.find_element(By.ID, "id_sea_overlay")) natus = self.browser.find_elements(By.ID, "id_natus_overlay") self.assertTrue(not natus or not natus[0].is_displayed()) def test_sea_open_class_on_html_after_confirm(self): """html.sea-open is set after sky confirm, giving the sea overlay its backdrop.""" self.create_pre_authenticated_session("founder@test.io") self.browser.get(self.room_url) self.wait_for(lambda: self.browser.find_element(By.ID, "id_pick_sky_btn")) self._confirm_sky() self.wait_for(lambda: self.browser.find_element(By.ID, "id_sea_overlay")) has_sea_open = self.browser.execute_script( "return document.documentElement.classList.contains('sea-open');" ) self.assertTrue(has_sea_open)