Paging clicks only visible controls: First/Prev are mobile-only
Munchkin Big Box and Tang Garden hung 30s each on a "First Page" anchor that exists but is invisible: BGG renders every paging control twice, and the First/Prev pair lives only in the mobile set (<li class="visible-xs-inline">). A desktop viewport can never click it. Paging now selects the first VISIBLE match, and returning to page 1 closes and reopens the sub-view (which always opens on page 1) instead of reaching for a control that isn't there. A test proves no hidden control is ever clicked — the fake picker raises if one is. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016jXZFSTZQKzAC8fqpWSz9g
This commit is contained in:
co-authored by
Claude Fable 5
parent
ba55863cef
commit
9283a3e980
+34
-6
@@ -559,26 +559,35 @@ class _FakePicker:
|
||||
self.page = 0
|
||||
self.clicked = None
|
||||
self.cancelled = False
|
||||
self.reopened = 0
|
||||
|
||||
# -- locator plumbing the uploader uses ---------------------------
|
||||
def locator(self, selector):
|
||||
picker = self
|
||||
|
||||
class _Loc:
|
||||
def __init__(self, texts=None):
|
||||
self.texts = texts
|
||||
def __init__(self, index=0):
|
||||
self.index = index
|
||||
|
||||
def all_text_contents(self):
|
||||
return picker.pages[picker.page]
|
||||
|
||||
def count(self):
|
||||
if "pagination" in selector:
|
||||
return 1
|
||||
return 2 # BGG renders a mobile AND a desktop control
|
||||
return len(picker.pages[picker.page])
|
||||
|
||||
def nth(self, i):
|
||||
return _Loc(i)
|
||||
|
||||
def is_visible(self):
|
||||
# among PAGING controls, index 0 is the mobile
|
||||
# (visible-xs-*) duplicate — present but not clickable
|
||||
return "pagination" not in selector or self.index != 0
|
||||
|
||||
@property
|
||||
def first(self):
|
||||
return self
|
||||
return _Loc(0)
|
||||
|
||||
def wait_for(self, **kw):
|
||||
return None
|
||||
@@ -588,10 +597,10 @@ class _FakePicker:
|
||||
return "ng-scope disabled" if last else "ng-scope"
|
||||
|
||||
def click(self):
|
||||
if "pagination" in selector and not self.is_visible():
|
||||
raise AssertionError("clicked a HIDDEN paging control")
|
||||
if "Next Page" in selector:
|
||||
picker.page += 1
|
||||
elif "First Page" in selector:
|
||||
picker.page = 0
|
||||
|
||||
def filter(self, has_text=None):
|
||||
picker.clicked = has_text.pattern if has_text else None
|
||||
@@ -610,6 +619,9 @@ class _FakePicker:
|
||||
def click(self):
|
||||
if name == "Cancel":
|
||||
picker.cancelled = True
|
||||
elif name == "Set version/edition":
|
||||
picker.page = 0 # the sub-view reopens on page 1
|
||||
picker.reopened += 1
|
||||
|
||||
return _Btn()
|
||||
|
||||
@@ -667,3 +679,19 @@ def test_absent_version_reports_pages_scanned():
|
||||
picked, why = up._select_version(dialog, "English edition")
|
||||
assert picked is False
|
||||
assert "not offered" in why and "1 page(s)" in why
|
||||
|
||||
|
||||
def test_paging_never_clicks_a_hidden_mobile_control():
|
||||
"""BGG renders First/Prev/Next twice — a desktop set and a mobile set
|
||||
that is invisible on a desktop viewport. Clicking the hidden one hangs
|
||||
until timeout (it did, on Munchkin Big Box and Tang Garden)."""
|
||||
up, dialog = _picker_uploader(
|
||||
[
|
||||
["Munchkin (German edition) (2010)"],
|
||||
["Munchkin (English edition) (2009)"],
|
||||
]
|
||||
)
|
||||
picked, _ = up._select_version(dialog, "English edition 2009")
|
||||
assert picked is True # no AssertionError from the fake = no hidden click
|
||||
# the initial open plus ONE reopen — never a "First Page" click
|
||||
assert dialog.reopened == 2
|
||||
|
||||
Reference in New Issue
Block a user