Tray follows the ?seat-selected seat, not the canonical PC seat
A multi-seat (CARTE) gamer clicking a pos-circle switched the sig overlay (via the ?seat=N override) but the tray stayed pinned to the role-canonical PC seat — my_tray_role read assigned_seats[0] (role-sorted, always PC) and my_tray_sig read _canonical_user_seat. So every circle put the PC icon in the tray regardless of which one was clicked. Re-point both tray keys to the seat occupying current_slot (the acting seat). Single-seat gamers are unaffected — their lone slot IS current_slot, so selected_seat == their canonical seat. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -810,6 +810,81 @@ class PositionTooltipCarteRenderTest(TestCase):
|
||||
self.assertNotIn("drop-token-btn", content)
|
||||
|
||||
|
||||
class CarteTrayFollowsSelectedSeatTest(TestCase):
|
||||
"""A multi-seat (CARTE) gamer's tray must mirror the seat at the
|
||||
?seat-selected pos-circle (current_slot), not the canonical PC seat.
|
||||
|
||||
Regression: my_tray_role / my_tray_sig were pinned to the role-sorted
|
||||
assigned_seats[0] (always PC) and _canonical_user_seat, so clicking ANY
|
||||
pos-circle put the PC icon in the tray. The seat-switch (?seat=N) only
|
||||
re-pointed the sig OVERLAY; the tray ignored it entirely."""
|
||||
|
||||
# Reverse canonical pick order: select_role fills the lowest open slot
|
||||
# each turn, so picking BC,AC,SC,EC,NC,PC seats them at slots 1..6.
|
||||
SLOT_ROLES = {1: "BC", 2: "AC", 3: "SC", 4: "EC", 5: "NC", 6: "PC"}
|
||||
|
||||
def setUp(self):
|
||||
self.viewer = User.objects.create(email="disco@test.io", username="disco")
|
||||
self.deck, _ = DeckVariant.objects.get_or_create(
|
||||
slug="earthman",
|
||||
defaults={"name": "Earthman", "card_count": 106, "is_default": True},
|
||||
)
|
||||
self.room = Room.objects.create(name="Carte Room", owner=self.viewer)
|
||||
self.room.gate_slots.update(
|
||||
gamer=self.viewer, status=GateSlot.FILLED,
|
||||
filled_at=timezone.now(), debited_token_type=Token.CARTE,
|
||||
)
|
||||
Token.objects.create(
|
||||
user=self.viewer, token_type=Token.CARTE,
|
||||
current_room=self.room, slots_claimed=6,
|
||||
)
|
||||
self.room.gate_status = Room.OPEN
|
||||
self.room.table_status = Room.ROLE_SELECT
|
||||
self.room.save()
|
||||
for n, role in self.SLOT_ROLES.items():
|
||||
TableSeat.objects.create(
|
||||
room=self.room, gamer=self.viewer, slot_number=n,
|
||||
role=role, deck_variant=self.deck,
|
||||
)
|
||||
self.client.force_login(self.viewer)
|
||||
self.room_url = reverse("epic:room", kwargs={"room_id": self.room.id})
|
||||
|
||||
def test_seat_param_points_tray_role_at_that_seat(self):
|
||||
# ?seat=4 → pos-circle 4 holds EC, so the tray role card is EC, not PC.
|
||||
response = self.client.get(self.room_url + "?seat=4")
|
||||
self.assertEqual(response.context["my_tray_role"], "EC")
|
||||
|
||||
def test_each_owned_circle_yields_its_own_seat_role(self):
|
||||
for n, role in self.SLOT_ROLES.items():
|
||||
response = self.client.get(self.room_url + f"?seat={n}")
|
||||
self.assertEqual(
|
||||
response.context["my_tray_role"], role,
|
||||
f"pos-circle {n} should put role {role} in the tray",
|
||||
)
|
||||
|
||||
def test_default_no_seat_tray_follows_lowest_owned_circle(self):
|
||||
# No ?seat → current_slot is the lowest owned pos-circle (1 = BC),
|
||||
# NOT the role-canonical PC seat (slot 6).
|
||||
response = self.client.get(self.room_url)
|
||||
self.assertEqual(response.context["my_tray_role"], "BC")
|
||||
|
||||
def test_seat_param_points_tray_sig_at_that_seat(self):
|
||||
sig = TarotCard.objects.create(
|
||||
deck_variant=self.deck, slug="ec-sig",
|
||||
arcana="MIDDLE", suit="BRANDS", number=13, name="Queen of Brands",
|
||||
)
|
||||
ec_seat = TableSeat.objects.get(room=self.room, slot_number=4)
|
||||
ec_seat.significator = sig
|
||||
ec_seat.save(update_fields=["significator"])
|
||||
# Switch to EC's circle → its sig rides the tray.
|
||||
response = self.client.get(self.room_url + "?seat=4")
|
||||
self.assertEqual(response.context["my_tray_sig"], sig)
|
||||
# The PC circle (slot 6) has no sig → switching there shows none
|
||||
# (proving the tray no longer falls back to a single canonical seat).
|
||||
response = self.client.get(self.room_url + "?seat=6")
|
||||
self.assertIsNone(response.context["my_tray_sig"])
|
||||
|
||||
|
||||
class PickRolesViewTest(TestCase):
|
||||
def setUp(self):
|
||||
self.founder = User.objects.create(email="founder@test.io")
|
||||
|
||||
Reference in New Issue
Block a user