aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/test_sidebar_legal_measured.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-14 11:17:42 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-14 11:17:42 +0200
commit2fb66c5baecdd8b49be904f6244f66ba04f68061 (patch)
tree3b80940e1819a811f6ec2c04831e3616a74a8eae /packages/meshbay-hub/tests/test_sidebar_legal_measured.py
parenta294c1d338ba4c20d66873d593d1c101e69c5a40 (diff)
downloadmeshbay-2fb66c5baecdd8b49be904f6244f66ba04f68061.tar.gz
feat(ui): an indexing dock above the music bar, on every page
Adding a large directory left the operator nothing to look at once they left the Settings panel that started it, and nothing at all when it was added from another machine. A band now sits above the music bar on every page: one row per group with indexing under way, naming the root being walked, percent, bytes and files, and the roots waiting their turn; "indexing finished" for a few seconds at the end. A click opens the group's Settings, and × hides the row until that group is idle. Two sources feed it. On the node's own machine the desktop client polls the loopback `GET /api/index-status` for every group, whatever the route. An operator's group page forwards MNP `index_progress` pushes, resolving the root from the roots table it opened; an ordinary member keeps the sidebar dot only, and a page clears its row when it lets go of the group. Where both describe a group, loopback wins. Reconcile passes and watchdog bursts show only past 1 GB or 5 s, so a single dropped file does not flash a bar. The logic lives in index-dock-model.js, which has no imports and is tested under node. The dock publishes `--index-dock-h` and the sidebar stops above it and the music bar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T6jPTeocXA1BePekdsgPya
Diffstat (limited to 'packages/meshbay-hub/tests/test_sidebar_legal_measured.py')
-rw-r--r--packages/meshbay-hub/tests/test_sidebar_legal_measured.py43
1 files changed, 38 insertions, 5 deletions
diff --git a/packages/meshbay-hub/tests/test_sidebar_legal_measured.py b/packages/meshbay-hub/tests/test_sidebar_legal_measured.py
index faaaec7..3c44d83 100644
--- a/packages/meshbay-hub/tests/test_sidebar_legal_measured.py
+++ b/packages/meshbay-hub/tests/test_sidebar_legal_measured.py
@@ -29,16 +29,26 @@ pytestmark = pytest.mark.skipif(
# The probe's frames are this tall.
WINDOW_H = 740
MUSIC_BAR_H = 64
+INDEX_DOCK_H = 52
WIDTHS = [390, 1024, 1440]
-def _page(music: bool) -> str:
+def _page(music: bool, dock: bool = False) -> 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 ""
+ # Rendered right before the music bar, as app.js does.
+ if dock:
+ bar = (f'<div class="index-dock" style="height:{INDEX_DOCK_H}px;'
+ f'box-sizing:border-box">indexing</div>') + bar
+ props = []
+ if music:
+ props.append(f"--music-bar-h:{MUSIC_BAR_H}px")
+ if dock:
+ props.append(f"--index-dock-h:{INDEX_DOCK_H}px")
+ style = f' style="{";".join(props)}"' if props else ""
return textwrap.dedent(f"""
<div id="app"{style}>
<nav class="nav"><div class="nav-left"><a class="nav-brand" href="#/">MeshBay</a></div>
@@ -55,12 +65,12 @@ def _page(music: bool) -> str:
""")
-def _measure(tmp_path_factory, music: bool) -> dict:
+def _measure(tmp_path_factory, music: bool, dock: bool = False) -> dict:
fragment = tmp_path_factory.mktemp("sidebar") / "fragment.html"
- fragment.write_text(_page(music), encoding="utf-8")
+ fragment.write_text(_page(music, dock), encoding="utf-8")
proc = subprocess.run(
["python3", str(HARNESS), ",".join(str(w) for w in WIDTHS),
- str(fragment), ".sidebar-legal", ".sidebar", ".music-player-bar"],
+ str(fragment), ".sidebar-legal", ".sidebar", ".music-player-bar", ".index-dock"],
capture_output=True, text=True, timeout=180)
assert proc.returncode == 0, f"probe failed: {proc.stdout}{proc.stderr}"
out = json.loads(proc.stdout)
@@ -78,6 +88,11 @@ def playing(tmp_path_factory):
return _measure(tmp_path_factory, music=True)
+@pytest.fixture(scope="module")
+def indexing(tmp_path_factory):
+ return _measure(tmp_path_factory, music=True, dock=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."""
@@ -99,3 +114,21 @@ def test_the_music_bar_does_not_cover_it(playing, width):
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")
+
+
+@pytest.mark.parametrize("width", WIDTHS)
+def test_the_indexing_dock_stacks_on_the_music_bar_and_covers_nothing(indexing, width):
+ """The dock (index-dock.js) pins right above the music bar, off
+ `--music-bar-h`, and the sidebar stops above both."""
+ link = indexing[str(width)]["boxes"][".sidebar-legal"]
+ dock = indexing[str(width)]["boxes"][".index-dock"]
+ bar = indexing[str(width)]["boxes"][".music-player-bar"]
+ assert link is not None and dock is not None and bar is not None
+ assert abs(bar["top"] + bar["height"] - WINDOW_H) <= 1, (
+ f"at {width} px the music bar ends at {bar['top'] + bar['height']}")
+ assert abs(dock["top"] + dock["height"] - bar["top"]) <= 1, (
+ f"at {width} px the dock ends at {dock['top'] + dock['height']} "
+ f"and the music bar starts at {bar['top']}")
+ bottom = link["top"] + link["height"]
+ assert dock["top"] - 8 <= bottom <= dock["top"] + 1, (
+ f"at {width} px the link ends at {bottom} and the dock starts at {dock['top']}")