aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/test_menu_scroll.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/tests/test_menu_scroll.py')
-rw-r--r--packages/meshbay-hub/tests/test_menu_scroll.py68
1 files changed, 67 insertions, 1 deletions
diff --git a/packages/meshbay-hub/tests/test_menu_scroll.py b/packages/meshbay-hub/tests/test_menu_scroll.py
index 5b680a4..b56a053 100644
--- a/packages/meshbay-hub/tests/test_menu_scroll.py
+++ b/packages/meshbay-hub/tests/test_menu_scroll.py
@@ -1,5 +1,8 @@
"""
-A pop-up menu taller than the window can be scrolled without dismissing itself.
+A pop-up menu taller than the window can be scrolled, and scrolled all the way.
+
+Two defects, one symptom — "the last track cannot be reached" — and they had to
+be fixed in that order, because the first hides the second.
`.ctx-menu` is `overflow-y: auto` under a `max-height`, and a playlist's
tracklist expands *inside* it — sixty tracks is three times the panel's height,
@@ -16,6 +19,14 @@ this: it reaches every row with `.click()`, which scrolls nothing at all.
The last two cases are the ones that must keep closing the menu, and they are
why the fix is a filter on the event's origin rather than a removed listener.
+
+The second defect is where the panel ends. `max-height: calc(100vh - 16px)`
+says how tall it may be and nothing about where its bottom lands, so a panel
+opened 300px down the window ran 300px past the bottom of it. It scrolled — but
+its last rows scrolled into a part of itself that is off the screen, which no
+further scrolling brings back. `menu.js` measures the room left below where it
+put the panel. The flip case is measured too, because the condition deciding it
+was rewritten in the same breath.
"""
import json
@@ -74,3 +85,58 @@ def test_scrolling_the_page_still_closes_it(cases):
# under a sticky toolbar, so a menu that survives leaves itself pointing at
# an album that has moved.
assert cases["scrolled the page underneath"]["closed"]
+
+
+def test_a_long_menu_ends_inside_the_window(cases):
+ c = cases["a long menu opened partway down the window"]
+ assert c["overflows"], f"the fixture measures nothing: {c}"
+ assert c["panelBottom"] <= c["viewport"], (
+ f"the panel runs {c['panelBottom'] - c['viewport']}px past the bottom "
+ f"of the window: {c}")
+
+
+def test_the_last_row_of_a_long_menu_can_be_reached(cases):
+ # Scrolled to the end, the last row has to be *visible*. This is the
+ # user-facing sentence, and the one that fails while the panel overruns the
+ # window: the rows are there, scrolled into a region nothing can show.
+ c = cases["a long menu opened partway down the window"]
+ assert c["lastRowLabel"].startswith("Track 60"), c
+ assert c["lastRowBottom"] <= c["viewport"], (
+ f"the last row sits {c['lastRowBottom'] - c['viewport']}px below the "
+ f"window after scrolling to the end: {c}")
+
+
+def test_it_still_opens_at_the_pointer_when_the_room_is_below(cases):
+ # The cure must not be a menu that jumps somewhere else: a list too tall
+ # for any placement stays where it was asked for and scrolls.
+ c = cases["a long menu opened partway down the window"]
+ assert c["panelTop"] == c["openedAt"], c
+
+
+def test_an_expanded_submenu_stays_inside_the_window(cases):
+ c = cases["a submenu expanded inside it"]
+ assert c["panelBottom"] > c["collapsedBottom"], (
+ f"the submenu did not actually expand: {c}")
+ assert c["panelBottom"] <= c["viewport"], c
+ assert c["lastRowLabel"].startswith("Track 60"), c
+ assert c["lastRowBottom"] <= c["viewport"], c
+
+
+def test_an_expanded_submenu_is_re_placed_rather_than_left_in_its_slot(cases):
+ # The size change happens in `MenuItems`' own state, which the placement
+ # effect cannot see on its own — this is what the report upward is for.
+ # Without it the panel keeps the height measured for its collapsed self:
+ # the menu stays inside the window, and a sixty-track list is threaded
+ # through the 192px that were free below where it was opened.
+ c = cases["a submenu expanded inside it"]
+ assert c["panelHeight"] > c["viewport"] - c["openedAt"], (
+ f"the panel is still the size the collapsed menu was given: {c}")
+
+
+def test_a_short_menu_at_the_bottom_edge_still_flips(cases):
+ # No regression on the placement that already worked: a menu that fits
+ # above the pointer is drawn there whole, not pinned to the edge and
+ # squeezed into the few pixels left below it.
+ c = cases["a short menu opened at the bottom edge"]
+ assert c["panelBottom"] <= c["openedAt"], c
+ assert not c["overflows"], f"a four-item menu should not need scrolling: {c}"