From 299a8068628d5229d35c39226b8fcd4f9af9338b Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Sun, 29 Mar 2026 23:46:23 -0400 Subject: [PATCH] fixed open #id_tray obscuring role select FTs --- src/apps/epic/static/apps/epic/role-select.js | 10 ++++++- src/functional_tests/test_room_role_select.py | 28 ++++++++----------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/apps/epic/static/apps/epic/role-select.js b/src/apps/epic/static/apps/epic/role-select.js index 4eb42fd..519c50f 100644 --- a/src/apps/epic/static/apps/epic/role-select.js +++ b/src/apps/epic/static/apps/epic/role-select.js @@ -1,4 +1,8 @@ var RoleSelect = (function () { + // Set to true by handleTurnChanged so that a WS turn_changed that races + // ahead of the fetch response doesn't get overridden by Tray.open(). + var _turnChangedBeforeFetch = false; + var ROLES = [ { code: "PC", name: "Player", element: "Fire" }, { code: "BC", name: "Builder", element: "Stone" }, @@ -24,6 +28,7 @@ var RoleSelect = (function () { } function selectRole(roleCode, cardEl) { + _turnChangedBeforeFetch = false; // fresh selection, reset the race flag var invCard = cardEl.cloneNode(true); invCard.classList.add("flipped"); // strip old event listeners from the clone by replacing with a clean copy @@ -70,7 +75,8 @@ var RoleSelect = (function () { trayCard.dataset.role = roleCode; grid.insertBefore(trayCard, grid.firstChild); } - if (typeof Tray !== "undefined") { + // Only open if turn_changed hasn't already arrived and closed it. + if (typeof Tray !== "undefined" && !_turnChangedBeforeFetch) { Tray.open(); } } @@ -164,6 +170,8 @@ var RoleSelect = (function () { if (invSlot) invSlot.innerHTML = ""; // Force-close tray instantly so it never obscures the next player's card-stack. + // Also set the race flag so the fetch .then() doesn't re-open if it arrives late. + _turnChangedBeforeFetch = true; if (typeof Tray !== "undefined") Tray.forceClose(); var stack = document.querySelector(".card-stack[data-user-slots]"); diff --git a/src/functional_tests/test_room_role_select.py b/src/functional_tests/test_room_role_select.py index 61acbd3..196e9b5 100644 --- a/src/functional_tests/test_room_role_select.py +++ b/src/functional_tests/test_room_role_select.py @@ -772,35 +772,32 @@ class RoleSelectChannelsTest(ChannelsFunctionalTest): By.CSS_SELECTOR, ".card-stack[data-state='eligible']" )) - # Select a role — tray opens and card lands in topmost square. + # Select a role — card lands in topmost grid square. self.browser.find_element(By.CSS_SELECTOR, ".card-stack").click() self.wait_for(lambda: self.browser.find_element(By.ID, "id_role_select")) self.browser.find_element(By.CSS_SELECTOR, "#id_role_select .card").click() self.confirm_guard() - self.wait_for(lambda: self.assertTrue( - self.browser.execute_script("return Tray.isOpen()") - )) - is_first = self.browser.execute_script(""" + # Wait for fetch .then() — card must be first child of grid. + self.wait_for(lambda: self.assertTrue(self.browser.execute_script(""" var card = document.querySelector('#id_tray_grid .tray-role-card'); return card !== null && card === card.parentElement.firstElementChild; - """) - self.assertTrue(is_first, "Role card should be first child (topmost) of grid") + """))) # Turn advances via WS — seat 2 becomes active. self.wait_for(lambda: self.browser.find_element( By.CSS_SELECTOR, ".table-seat.active[data-slot='2']" )) - # Tray must be closed after turn_changed. + # Tray must be closed: forceClose() fires in handleTurnChanged. self.assertFalse( self.browser.execute_script("return Tray.isOpen()"), "Tray should be closed after turn advances" ) def test_landscape_tray_closes_on_turn_advance(self): - """Landscape: same sequence — role card at leftmost grid square; tray - closes when turn_changed arrives.""" + """Landscape: role card at leftmost grid square; tray closes when + turn_changed arrives via WS.""" self.browser.set_window_size(844, 390) room_url = self._make_turn_test_room() self.create_pre_authenticated_session("founder@test.io") @@ -814,21 +811,18 @@ class RoleSelectChannelsTest(ChannelsFunctionalTest): self.browser.find_element(By.CSS_SELECTOR, "#id_role_select .card").click() self.confirm_guard() - self.wait_for(lambda: self.assertTrue( - self.browser.execute_script("return Tray.isOpen()") - )) - is_first = self.browser.execute_script(""" + # Wait for fetch .then() — card must be first child of grid. + self.wait_for(lambda: self.assertTrue(self.browser.execute_script(""" var card = document.querySelector('#id_tray_grid .tray-role-card'); return card !== null && card === card.parentElement.firstElementChild; - """) - self.assertTrue(is_first, "Role card should be first child (leftmost) of grid") + """))) # Turn advances via WS — seat 2 becomes active. self.wait_for(lambda: self.browser.find_element( By.CSS_SELECTOR, ".table-seat.active[data-slot='2']" )) - # Tray must be closed after turn_changed. + # Tray must be closed. self.assertFalse( self.browser.execute_script("return Tray.isOpen()"), "Tray should be closed after turn advances"