Files
siftlode/frontend/src/lib/clipLimits.contract.test.ts
T
peter b4bf71ea64 fix(clip): a clip is held to its owner's storage cap, and its limits and failures say the server's truth
- The cut file is measured against what its owner has left, for a YouTube range (whose fetch never
  reads yt-dlp's size ceiling) and for a Plex clip (which fetches nothing), before the fetch and
  again before it is placed; a refusal leaves the asset pending for a Retry.
- A silent Plex file is cut silent; a file the probe cannot read says so.
- A second job on a failed or renamed clip gets the same YouTube diagnosis and the fetched title.
- The "too long" refusal names the server's cap; a contract test holds the client's copies of the
  clip limits to clip.py; the shipped player clients are pinned against the installed yt-dlp.
- One HDR transfer set and one rating_key lookup; job status words from JobStatus; the display-name
  guard sees subscript writes and the clip route; stale comments and types follow the clip job.
2026-10-10 15:35:12 +02:00

36 lines
1.5 KiB
TypeScript

import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
// The limits a clip is marked to, held in two languages: the clip panel's handles, fields and keys
// keep a range the server takes, and a crop frame no smaller than it cuts. Neither side can see the
// other's copy, so the gate reads both (as `api/downloads.contract.test.ts` does for the name bound).
// A cap moved on one side alone makes the panel offer what the server refuses — or clamp below
// what it would take — with every other test green.
//
// Read as TEXT: the modules are plain constants, but reading the source is what makes a renamed or
// moved constant fail here instead of comparing two undefineds.
const src = (u: string) => readFileSync(new URL(u, import.meta.url), "utf-8");
const backend = src("../../../backend/app/downloads/clip.py");
function pyConst(name: string): number {
const m = backend.match(new RegExp(`^${name}\\s*=\\s*([\\d.]+)`, "m"));
expect(m, `backend/app/downloads/clip.py no longer defines ${name}`).toBeTruthy();
return Number(m![1]);
}
function tsConst(file: string, name: string): number {
const m = src(file).match(new RegExp(`^(?:export )?const ${name} = ([\\d.]+);`, "m"));
expect(m, `${file} no longer defines ${name}`).toBeTruthy();
return Number(m![1]);
}
describe("clip limits", () => {
it.each([
["./clipRange.ts", "MIN_CLIP_S"],
["./clipRange.ts", "MAX_CLIP_S"],
["./cropGeometry.ts", "MIN_CROP"],
])("%s %s is the server's", (file, name) => {
expect(tsConst(file, name)).toBe(pyConst(name));
});
});