diff --git a/src/functional_tests/room_page.py b/src/functional_tests/room_page.py new file mode 100644 index 0000000..1aafdd3 --- /dev/null +++ b/src/functional_tests/room_page.py @@ -0,0 +1,112 @@ +"""Room-page FT helpers — extracted from the per-page FT modules so the +helpers can be imported without coupling consumer FTs to a sibling test +file's lifecycle (renames, deletions). Mirrors the post_page.py pattern. + +Naming: underscored to signal "test infrastructure, not API surface", but +they're public within `functional_tests/` — direct imports are fine. + +Consumers: + test_room_role_select / test_room_sig_select — define-and-use + test_component_tray_tooltip — _equip_earthman_deck + test_room_tray / test_deck_contribution — both core helpers + test_game_invite / test_room_gatekeeper — _fill_room_via_orm +""" +from django.utils import timezone + +from apps.drama.models import Note +from apps.epic.models import ( + DeckVariant, GateSlot, Room, TableSeat, TarotCard, +) +from apps.lyric.models import User + + +SIG_SEAT_ORDER = ["PC", "NC", "EC", "SC", "AC", "BC"] + + +def _equip_earthman_deck(user): + # get_or_create: TransactionTestCase.flush() wipes migration-seeded + # DeckVariants between tests, so subsequent tests in the same run can't + # find it via filter(). + deck, _ = DeckVariant.objects.get_or_create( + slug="earthman", + defaults={"name": "Earthman", "card_count": 106, "is_default": True}, + ) + user.equipped_deck = deck + user.save(update_fields=["equipped_deck"]) + + +def _fill_room_via_orm(room, emails): + """Fill all 6 gate slots and set gate_status=OPEN. Returns list of gamers.""" + gamers = [] + for i, email in enumerate(emails, start=1): + gamer, _ = User.objects.get_or_create(email=email) + slot = room.gate_slots.get(slot_number=i) + slot.gamer = gamer + slot.status = GateSlot.FILLED + slot.save() + gamers.append(gamer) + room.gate_status = Room.OPEN + room.save() + return gamers + + +def _assign_all_roles(room, role_order=None): + """Assign roles to all slots, reveal them, and advance to SIG_SELECT. + Also ensures all gamers have an equipped_deck (required for sig_deck_cards).""" + if role_order is None: + role_order = SIG_SEAT_ORDER[:] + earthman, _ = DeckVariant.objects.get_or_create( + slug="earthman", + defaults={"name": "Earthman Deck", "card_count": 108, "is_default": True}, + ) + # Seed the 18 sig deck cards (migration data is flushed in TransactionTestCase FTs). + # _sig_unique_cards() filters arcana=MIDDLE, suits BRANDS/CROWNS/BLADES/GRAILS (Earthman). + _NAME = {11: "Maid", 12: "Jack", 13: "Queen", 14: "King"} + for suit in ("BRANDS", "CROWNS", "BLADES", "GRAILS"): + for number in (11, 12, 13, 14): + TarotCard.objects.get_or_create( + deck_variant=earthman, + slug=f"{_NAME[number].lower()}-of-{suit.lower()}-em", + defaults={"arcana": "MIDDLE", "suit": suit, "number": number, + "name": f"{_NAME[number]} of {suit.capitalize()}", + "levity_qualifier": "Elevated", + "gravity_qualifier": "Graven"}, + ) + # Numbers 0–1 are the sig deck's Major Arcana (unlocked via Note). + # Seed them with correct Earthman names and qualifiers, then unlock for all gamers. + for number, name, slug in [ + (0, "The Nomad", "the-nomad"), + (1, "The Schizo", "the-schizo"), + ]: + TarotCard.objects.get_or_create( + deck_variant=earthman, + slug=slug, + defaults={"arcana": "MAJOR", "number": number, "name": name, + "levity_qualifier": "Enlightened", + "gravity_qualifier": "Engraven"}, + ) + for slot in room.gate_slots.order_by("slot_number"): + if slot.gamer: + Note.objects.get_or_create( + user=slot.gamer, slug="super-nomad", + defaults={"earned_at": timezone.now()}, + ) + Note.objects.get_or_create( + user=slot.gamer, slug="super-schizo", + defaults={"earned_at": timezone.now()}, + ) + for slot in room.gate_slots.order_by("slot_number"): + if slot.gamer and not slot.gamer.equipped_deck: + slot.gamer.equipped_deck = earthman + slot.gamer.save(update_fields=["equipped_deck"]) + TableSeat.objects.update_or_create( + room=room, + slot_number=slot.slot_number, + defaults={ + "gamer": slot.gamer, + "role": role_order[slot.slot_number - 1], + "role_revealed": True, + }, + ) + room.table_status = Room.SIG_SELECT + room.save() diff --git a/src/functional_tests/test_component_tray_tooltip.py b/src/functional_tests/test_component_tray_tooltip.py index 7955a01..3eef3c7 100644 --- a/src/functional_tests/test_component_tray_tooltip.py +++ b/src/functional_tests/test_component_tray_tooltip.py @@ -14,28 +14,11 @@ from selenium.webdriver.common.by import By from .base import FunctionalTest from apps.applets.models import Applet -from apps.epic.models import DeckVariant, GateSlot, Room, TableSeat, TarotCard +from apps.epic.models import DeckVariant, Room, TableSeat, TarotCard from apps.lyric.models import User -def _equip_earthman_deck(user): - deck, _ = DeckVariant.objects.get_or_create( - slug="earthman", - defaults={"name": "Earthman", "card_count": 106, "is_default": True}, - ) - user.equipped_deck = deck - user.save(update_fields=["equipped_deck"]) - - -def _fill_room_via_orm(room, emails): - for i, email in enumerate(emails, start=1): - gamer, _ = User.objects.get_or_create(email=email) - slot = room.gate_slots.get(slot_number=i) - slot.gamer = gamer - slot.status = GateSlot.FILLED - slot.save() - room.gate_status = Room.OPEN - room.save() +from .room_page import _equip_earthman_deck, _fill_room_via_orm class TrayRoleCardTooltipTest(FunctionalTest): diff --git a/src/functional_tests/test_deck_contribution.py b/src/functional_tests/test_deck_contribution.py index 866a426..5b69225 100644 --- a/src/functional_tests/test_deck_contribution.py +++ b/src/functional_tests/test_deck_contribution.py @@ -22,8 +22,7 @@ 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 +from functional_tests.room_page import _fill_room_via_orm FOUNDER_EMAIL = "founder@test.io" GAMER_EMAIL = "gamer@test.io" diff --git a/src/functional_tests/test_game_invite.py b/src/functional_tests/test_game_invite.py index 2769c28..469cecf 100644 --- a/src/functional_tests/test_game_invite.py +++ b/src/functional_tests/test_game_invite.py @@ -47,7 +47,7 @@ except ImportError: _BILLPOST_READY = False 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.room_page import _fill_room_via_orm FOUNDER_EMAIL = "founder@test.io" INVITEE_EMAIL = "invitee@test.io" diff --git a/src/functional_tests/test_room_gatekeeper.py b/src/functional_tests/test_room_gatekeeper.py index 0f238fa..ab0dbd2 100644 --- a/src/functional_tests/test_room_gatekeeper.py +++ b/src/functional_tests/test_room_gatekeeper.py @@ -8,7 +8,7 @@ from .base import FunctionalTest from apps.applets.models import Applet from apps.epic.models import Room, GateSlot, select_token from apps.lyric.models import Token, User -from .test_room_role_select import _fill_room_via_orm +from .room_page import _fill_room_via_orm class GatekeeperTest(FunctionalTest): diff --git a/src/functional_tests/test_room_role_select.py b/src/functional_tests/test_room_role_select.py index 09c7bb9..0f021f1 100644 --- a/src/functional_tests/test_room_role_select.py +++ b/src/functional_tests/test_room_role_select.py @@ -8,37 +8,12 @@ from selenium.webdriver.common.by import By from .base import FunctionalTest, ChannelsFunctionalTest from .management.commands.create_session import create_pre_authenticated_session +from .room_page import _equip_earthman_deck, _fill_room_via_orm from apps.applets.models import Applet -from apps.epic.models import DeckVariant, Room, GateSlot, TableSeat +from apps.epic.models import Room, GateSlot, TableSeat from apps.lyric.models import User -def _equip_earthman_deck(user): - # get_or_create: TransactionTestCase.flush() wipes migration-seeded DeckVariants - # between tests, so subsequent tests in the same run can't find it via filter(). - deck, _ = DeckVariant.objects.get_or_create( - slug="earthman", - defaults={"name": "Earthman", "card_count": 106, "is_default": True}, - ) - user.equipped_deck = deck - user.save(update_fields=["equipped_deck"]) - - -def _fill_room_via_orm(room, emails): - """Fill all 6 gate slots and set gate_status=OPEN. Returns list of gamers.""" - gamers = [] - for i, email in enumerate(emails, start=1): - gamer, _ = User.objects.get_or_create(email=email) - slot = room.gate_slots.get(slot_number=i) - slot.gamer = gamer - slot.status = GateSlot.FILLED - slot.save() - gamers.append(gamer) - room.gate_status = Room.OPEN - room.save() - return gamers - - class RoleSelectTest(FunctionalTest): def setUp(self): diff --git a/src/functional_tests/test_room_sig_select.py b/src/functional_tests/test_room_sig_select.py index 86e743c..9ff8493 100644 --- a/src/functional_tests/test_room_sig_select.py +++ b/src/functional_tests/test_room_sig_select.py @@ -7,13 +7,13 @@ from selenium.webdriver.common.by import By from .base import FunctionalTest, ChannelsFunctionalTest from .management.commands.create_session import create_pre_authenticated_session +from .room_page import ( + SIG_SEAT_ORDER, _assign_all_roles, _fill_room_via_orm, +) from apps.applets.models import Applet -from apps.drama.models import Note -from apps.epic.models import DeckVariant, Room, TableSeat, TarotCard +from apps.epic.models import Room from apps.lyric.models import User -from .test_room_role_select import _fill_room_via_orm - # ── Significator Selection ──────────────────────────────────────────────────── # @@ -23,71 +23,6 @@ from .test_room_role_select import _fill_room_via_orm # # ───────────────────────────────────────────────────────────────────────────── -SIG_SEAT_ORDER = ["PC", "NC", "EC", "SC", "AC", "BC"] - - -def _assign_all_roles(room, role_order=None): - """Assign roles to all slots, reveal them, and advance to SIG_SELECT. - Also ensures all gamers have an equipped_deck (required for sig_deck_cards).""" - if role_order is None: - role_order = SIG_SEAT_ORDER[:] - earthman, _ = DeckVariant.objects.get_or_create( - slug="earthman", - defaults={"name": "Earthman Deck", "card_count": 108, "is_default": True}, - ) - # Seed the 18 sig deck cards (migration data is flushed in TransactionTestCase FTs). - # _sig_unique_cards() filters arcana=MIDDLE, suits BRANDS/CROWNS/BLADES/GRAILS (Earthman). - _NAME = {11: "Maid", 12: "Jack", 13: "Queen", 14: "King"} - for suit in ("BRANDS", "CROWNS", "BLADES", "GRAILS"): - for number in (11, 12, 13, 14): - TarotCard.objects.get_or_create( - deck_variant=earthman, - slug=f"{_NAME[number].lower()}-of-{suit.lower()}-em", - defaults={"arcana": "MIDDLE", "suit": suit, "number": number, - "name": f"{_NAME[number]} of {suit.capitalize()}", - "levity_qualifier": "Elevated", - "gravity_qualifier": "Graven"}, - ) - # Numbers 0–1 are the sig deck's Major Arcana (unlocked via Note). - # Seed them with correct Earthman names and qualifiers, then unlock for all gamers. - from django.utils import timezone - for number, name, slug in [ - (0, "The Nomad", "the-nomad"), - (1, "The Schizo", "the-schizo"), - ]: - TarotCard.objects.get_or_create( - deck_variant=earthman, - slug=slug, - defaults={"arcana": "MAJOR", "number": number, "name": name, - "levity_qualifier": "Enlightened", - "gravity_qualifier": "Engraven"}, - ) - for slot in room.gate_slots.order_by("slot_number"): - if slot.gamer: - Note.objects.get_or_create( - user=slot.gamer, slug="super-nomad", - defaults={"earned_at": timezone.now()}, - ) - Note.objects.get_or_create( - user=slot.gamer, slug="super-schizo", - defaults={"earned_at": timezone.now()}, - ) - for slot in room.gate_slots.order_by("slot_number"): - if slot.gamer and not slot.gamer.equipped_deck: - slot.gamer.equipped_deck = earthman - slot.gamer.save(update_fields=["equipped_deck"]) - TableSeat.objects.update_or_create( - room=room, - slot_number=slot.slot_number, - defaults={ - "gamer": slot.gamer, - "role": role_order[slot.slot_number - 1], - "role_revealed": True, - }, - ) - room.table_status = Room.SIG_SELECT - room.save() - class SigSelectTest(FunctionalTest): """Significator Selection — non-WebSocket tests.""" diff --git a/src/functional_tests/test_room_tray.py b/src/functional_tests/test_room_tray.py index f272c60..c15beb6 100644 --- a/src/functional_tests/test_room_tray.py +++ b/src/functional_tests/test_room_tray.py @@ -5,8 +5,7 @@ from django.test import tag from selenium.webdriver.common.by import By from .base import FunctionalTest -from .test_room_role_select import _fill_room_via_orm -from .test_room_sig_select import _assign_all_roles +from .room_page import _assign_all_roles, _fill_room_via_orm from apps.epic.models import Room from apps.lyric.models import User