aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/test_layout_measured.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/tests/test_layout_measured.py')
-rw-r--r--packages/meshbay-hub/tests/test_layout_measured.py83
1 files changed, 81 insertions, 2 deletions
diff --git a/packages/meshbay-hub/tests/test_layout_measured.py b/packages/meshbay-hub/tests/test_layout_measured.py
index 57d325a..298a754 100644
--- a/packages/meshbay-hub/tests/test_layout_measured.py
+++ b/packages/meshbay-hub/tests/test_layout_measured.py
@@ -62,8 +62,12 @@ NAV = textwrap.dedent("""
</div>
</div>
</div>
+ <a class="nav-notif nav-search" href="#/search">
+ <svg class="icon" viewBox="0 0 24 24"></svg></a>
<a class="nav-notif" href="#/">&#128276;</a>
- <div class="user-menu"><button class="nav-btn">someone</button></div>
+ <div class="user-menu-wrap"><button class="user-menu-trigger">
+ <span class="user-menu-avatar">S</span><span class="user-menu-name">someone</span>
+ </button></div>
</div>
</nav>
""")
@@ -206,8 +210,12 @@ GROUPED = textwrap.dedent("""
</div>
</div>
</div>
+ <a class="nav-notif nav-search" href="#/search">
+ <svg class="icon" viewBox="0 0 24 24"></svg></a>
<a class="nav-notif" href="#/">&#128276;</a>
- <div class="user-menu"><button class="nav-btn">someone</button></div>
+ <div class="user-menu-wrap"><button class="user-menu-trigger">
+ <span class="user-menu-avatar">S</span><span class="user-menu-name">someone</span>
+ </button></div>
</div>
</nav>
""")
@@ -283,3 +291,74 @@ def test_the_waiting_bar_is_as_wide_as_a_progress_bar(grouped):
assert bar["width"] > 100, (
f"at {width} px the waiting bar is {bar['width']} px wide")
assert bar["height"] >= 3, "the waiting bar has no height"
+
+
+# ── The whole nav on a phone ────────────────────────────────────────────────
+#
+# Search moved from the sidebar to the nav, beside the bell. With the user's
+# name in the menu trigger, a 20-character handle already put the trigger 79 px
+# off a 320 px screen, and 159 px once search and a transfer were there too.
+# The fixture is the real markup of `Nav()` and `UserMenu()`, with the icons as
+# the 1em boxes `Icon()` draws.
+
+_ICON = '<svg class="icon" viewBox="0 0 24 24"></svg>'
+FULL_NAV = textwrap.dedent(f"""
+ <nav class="nav">
+ <div class="nav-left">
+ <button class="nav-hamburger">{_ICON}</button>
+ <a class="nav-brand" href="#/"><img class="nav-brand-m" alt="M">eshBay</a>
+ </div>
+ <div class="nav-right">
+ <div class="transfer-wrap">
+ <button class="nav-notif transfer-btn">{_ICON}<span class="notif-badge">2</span></button>
+ </div>
+ <a class="nav-notif nav-search" href="#/search">{_ICON}</a>
+ <a class="nav-notif" href="#/">{_ICON}<span class="notif-badge">3</span></a>
+ <div class="user-menu-wrap">
+ <button class="user-menu-trigger">
+ <span class="user-menu-avatar">A</span>
+ <span class="user-menu-name">a_rather_long_handle</span>
+ <svg class="icon user-menu-caret" viewBox="0 0 24 24"></svg>
+ </button>
+ </div>
+ </div>
+ </nav>
+""")
+FULL_NAV_WIDTHS = [320, 360, 412, 521, 768, 1024]
+
+
+@pytest.fixture(scope="module")
+def full_nav(tmp_path_factory):
+ fragment = tmp_path_factory.mktemp("fullnav") / "fragment.html"
+ fragment.write_text(FULL_NAV, encoding="utf-8")
+ proc = subprocess.run(
+ ["python3", str(HARNESS), ",".join(str(w) for w in FULL_NAV_WIDTHS),
+ str(fragment), ".nav-brand", ".nav-right", ".user-menu-trigger",
+ ".user-menu-name"],
+ capture_output=True, text=True, timeout=180)
+ assert proc.returncode == 0, f"probe failed: {proc.stdout}{proc.stderr}"
+ out = json.loads(proc.stdout)
+ assert "error" not in out, f"no measurement: {out}"
+ return out
+
+
+@pytest.mark.parametrize("width", FULL_NAV_WIDTHS)
+def test_the_user_menu_stays_inside_the_nav(full_nav, width):
+ """Off the right edge is where nobody can open it — and it holds sign-out."""
+ boxes = full_nav[str(width)]["boxes"]
+ trigger = boxes[".user-menu-trigger"]
+ assert trigger["right"] <= width - 16, (
+ f"at {width} px the user menu ends at {trigger['right']} px, past the "
+ "nav's own padding")
+ assert boxes[".nav-right"]["left"] >= boxes[".nav-brand"]["right"], (
+ f"at {width} px the nav's icons slide under the wordmark")
+
+
+@pytest.mark.parametrize("width", FULL_NAV_WIDTHS)
+def test_the_name_leaves_the_trigger_on_mobile_only(full_nav, width):
+ """Avatar alone up to the mobile breakpoint; the name beside it on a desktop."""
+ name = full_nav[str(width)]["boxes"][".user-menu-name"]
+ shown = bool(name and name["width"] > 0)
+ assert shown == (width > 768), (
+ f"at {width} px the name in the user menu is "
+ f"{'shown' if shown else 'hidden'}")