132 lines
5.3 KiB
Python
132 lines
5.3 KiB
Python
|
|
"""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)
|