"""Video side shell: the Music ↔ Video toggle + video sidebar (experimental branch). This is the first slice of the video side. It must be ADDITIVE and ISOLATED: the music sidebar/nav is untouched, the toggle + video nav are wired purely via data-attributes (no inline onclick — which would also break the script-split integrity contract), and the controller is a self-contained IIFE that adds no globals. These pin all of that so a regression can't silently couple the two sides or break the music shell. """ from __future__ import annotations import re from pathlib import Path _ROOT = Path(__file__).resolve().parent.parent _INDEX = (_ROOT / "webui" / "index.html").read_text(encoding="utf-8", errors="replace") _JS = (_ROOT / "webui" / "static" / "video" / "video-side.js").read_text(encoding="utf-8") _CSS_PATH = _ROOT / "webui" / "static" / "video" / "video-side.css" EXPECTED_VIDEO_PAGES = { "video-dashboard", "video-search", "video-discover", "video-library", "video-watchlist", "video-wishlist", "video-downloads", "video-calendar", "video-import", "video-settings", "video-issues", "video-help", } def _block(html: str, open_tag_re: str, close_tag: str) -> str: """Return the substring from the first match of open_tag_re to the next close_tag.""" m = re.search(open_tag_re, html) assert m, f"could not find {open_tag_re!r}" end = html.index(close_tag, m.end()) return html[m.start():end + len(close_tag)] # --- the toggle ------------------------------------------------------------ def test_side_toggle_has_music_and_video(): block = _block(_INDEX, r'
") assert 'data-side-target="music"' in block assert 'data-side-target="video"' in block # Wired by JS, not inline handlers (isolation + integrity contract). assert "onclick" not in block # --- the video nav --------------------------------------------------------- def test_video_nav_has_all_expected_pages(): block = _block(_INDEX, r'