aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/tests')
-rw-r--r--packages/meshbay-hub/tests/test_sidebar_legal_measured.py101
1 files changed, 101 insertions, 0 deletions
diff --git a/packages/meshbay-hub/tests/test_sidebar_legal_measured.py b/packages/meshbay-hub/tests/test_sidebar_legal_measured.py
new file mode 100644
index 0000000..faaaec7
--- /dev/null
+++ b/packages/meshbay-hub/tests/test_sidebar_legal_measured.py
@@ -0,0 +1,101 @@
+"""
+The legal link at the foot of the sidebar, measured in a browser.
+
+It is pinned to the bottom of the window, not of the page: the sidebar sticks
+under the navigation bar at the window's height, so on a long file list the
+link is still on screen. And the music bar, pinned to the bottom of the window
+as well, must not cover it — the bar publishes its height as `--music-bar-h`
+(sticky.js, as the toolbars do), and the sidebar stops above it. That value
+is set by hand here; what is under test is the stylesheet's arithmetic.
+
+On a phone the sidebar is the slide-out panel, measured open.
+"""
+
+import json
+import shutil
+import subprocess
+import textwrap
+from pathlib import Path
+
+import pytest
+
+HARNESS = Path(__file__).parent / "harness" / "layout_probe.py"
+STATIC = Path(__file__).resolve().parents[1] / "src" / "meshbay_hub" / "static"
+
+pytestmark = pytest.mark.skipif(
+ shutil.which("google-chrome") is None or not (STATIC / "style.css").exists(),
+ reason="Chrome or the SPA stylesheet is not available")
+
+# The probe's frames are this tall.
+WINDOW_H = 740
+MUSIC_BAR_H = 64
+WIDTHS = [390, 1024, 1440]
+
+
+def _page(music: bool) -> str:
+ groups = "".join(
+ f'<a class="sidebar-item sidebar-group" href="#/"><span class="si-head">'
+ f'<span class="sidebar-item-name">Some group {i}</span></span></a>' for i in range(4))
+ bar = (f'<div class="music-player-bar" style="height:{MUSIC_BAR_H}px;'
+ f'box-sizing:border-box">a track</div>') if music else ""
+ style = f' style="--music-bar-h:{MUSIC_BAR_H}px"' if music else ""
+ return textwrap.dedent(f"""
+ <div id="app"{style}>
+ <nav class="nav"><div class="nav-left"><a class="nav-brand" href="#/">MeshBay</a></div>
+ <div class="nav-right"><button class="nav-btn">someone</button></div></nav>
+ <div class="layout">
+ <aside class="sidebar open">
+ <div class="sidebar-section"><div class="sidebar-heading">My groups</div>{groups}</div>
+ <a class="sidebar-legal" href="/legal/">Legal information</a>
+ </aside>
+ <main class="main"><h2>A long list</h2><div style="height:3000px"></div></main>
+ </div>
+ {bar}
+ </div>
+ """)
+
+
+def _measure(tmp_path_factory, music: bool) -> dict:
+ fragment = tmp_path_factory.mktemp("sidebar") / "fragment.html"
+ fragment.write_text(_page(music), encoding="utf-8")
+ proc = subprocess.run(
+ ["python3", str(HARNESS), ",".join(str(w) for w in WIDTHS),
+ str(fragment), ".sidebar-legal", ".sidebar", ".music-player-bar"],
+ 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.fixture(scope="module")
+def plain(tmp_path_factory):
+ return _measure(tmp_path_factory, music=False)
+
+
+@pytest.fixture(scope="module")
+def playing(tmp_path_factory):
+ return _measure(tmp_path_factory, music=True)
+
+
+@pytest.mark.parametrize("width", WIDTHS)
+def test_the_link_is_at_the_bottom_of_the_window(plain, width):
+ """Not at the bottom of a 3000px page, where nobody would find it."""
+ link = plain[str(width)]["boxes"][".sidebar-legal"]
+ assert link is not None, "no legal link"
+ bottom = link["top"] + link["height"]
+ assert WINDOW_H - 8 <= bottom <= WINDOW_H, (
+ f"at {width} px the link ends at {bottom}, the window at {WINDOW_H}")
+ assert link["offLeft"] == 0 and link["offRight"] == 0
+
+
+@pytest.mark.parametrize("width", WIDTHS)
+def test_the_music_bar_does_not_cover_it(playing, width):
+ link = playing[str(width)]["boxes"][".sidebar-legal"]
+ bar = playing[str(width)]["boxes"][".music-player-bar"]
+ assert link is not None and bar is not None
+ bottom = link["top"] + link["height"]
+ assert bottom <= bar["top"] + 1, (
+ f"at {width} px the link ends at {bottom} and the music bar starts at {bar['top']}")
+ assert bottom >= bar["top"] - 8, (
+ f"at {width} px the link floats {bar['top'] - bottom} px above the music bar")