import { readFileSync } from "node:fs"; import { expect, it } from "vitest"; // One invariant, two languages, no shared wire format — so a test is the only thing that can hold // them together. // // The backend finishes an item when a progress checkpoint lands within `_FINISH_MARGIN_S` of the // duration: watched, position cleared, scrobbled to Plex. The player's refused-finish rollback must // therefore never post a position inside that window, or the branch named "take the finish back" // performs, through the backend, the very write that was just refused (rounds 6 and 7 both landed // on this). The frontend mirrors the number so it knows where the window starts. // // Both were 30 and exactly complementary, but nothing related them, so a backend-only change would // have re-opened the defect silently — a rule stated in a comment and not enforced in code, the one // thing this repo's house rules single out. The direction matters: the frontend's margin must be at // LEAST the backend's. Larger is merely conservative (a rollback skipped where it could have run); // smaller is the bug. // // Both values are read from source rather than imported: `plexPlayerHooks` pulls in the i18n module // (and with it `localStorage`), and booting half the app to read one integer would make this test // about the module graph instead of about the two numbers. function constantIn(path: string, pattern: RegExp): number { const source = readFileSync(new URL(path, import.meta.url), "utf8"); const m = pattern.exec(source); // If this fails the constant was renamed or moved — find it and re-point this test, because the // invariant it guards did not go away. expect(m, `${pattern} not found in ${path}`).not.toBeNull(); return Number(m![1]); } it("never lets the player's finish margin fall below the backend's", () => { const backend = constantIn( "../../../backend/app/routes/plex/playback.py", /^_FINISH_MARGIN_S\s*=\s*(\d+)/m, ); const frontend = constantIn("./plexPlayerHooks.ts", /^const FINISH_MARGIN_S\s*=\s*(\d+)/m); expect(backend).toBeGreaterThan(0); expect(frontend).toBeGreaterThanOrEqual(backend); });