import { readdirSync, readFileSync } from "node:fs"; import { describe, expect, it } from "vitest"; // E28 S3d4 (E18.5's `h-screen` → `dvh`). `100vh` is the viewport with a mobile browser's toolbars // RETRACTED: on a tablet with the toolbar showing, an `h-screen` shell runs its bottom edge (the // last rows, a dialog's footer) under the toolbar. `dvh` follows the toolbar. A static `vh` size is // the same trap at a smaller scale, so the app sizes by `dvh` everywhere. function sources(): Array<[string, string]> { const walk = (u: URL, prefix: string): Array<[string, string]> => readdirSync(u, { withFileTypes: true }).flatMap((e) => { if (e.isDirectory()) return walk(new URL(`${e.name}/`, u), `${prefix}${e.name}/`); if (!/\.tsx?$/.test(e.name) || e.name.includes(".test.")) return []; return [ [`${prefix}${e.name}`, readFileSync(new URL(e.name, u), "utf-8")] as [string, string], ]; }); return walk(new URL("../", import.meta.url), ""); } // The Plex player's stage is sized with the 80vh × 1.25 zoom trick. It changes in S3f, where the // players are re-fitted for touch and verified by playing them on the tablet. const PENDING_S3F = new Set(["components/PlexPlayer.tsx"]); describe("viewport units", () => { it("are dynamic: no h-screen / min-h-screen, no static vh", () => { const hits = sources() .filter(([name]) => !PENDING_S3F.has(name)) .filter(([, src]) => /\b(?:min-|max-)?h-screen\b|\d(?:\.\d+)?vh\b/.test(src)) .map(([name]) => name); expect(hits).toEqual([]); }); });