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)); }); });