import { existsSync } from "node:fs"; import path from "node:path"; // WHAT THE SONG PROJECT'S BULK DATA OFFERS THIS MACHINE — one rule, two // readers. // // The 39 GB (`wav48/`, `asr/`, `media/`) is re-derivable from the archive and // deliberately not in the repo. `SONG_DIR`'s default // (`~/reports/quartering-uh-song/data`, song/paths.mjs) is empty or absent on // most machines, so // `make-fixture.mjs` builds an empty fixture and every spec that judges a clip // used to fail — LOUDLY, as a red suite, over a machine that never had the data // rather than over anything a change broke. Red that means "you are on a // different laptop" is red people learn to ignore. // // WHY THIS IS A SHARED MODULE AND NOT THE FIXTURE'S WRITTEN JSON ALONE. // `make-fixture.mjs` writes `fixture-capabilities.json` as the RECORD — it is // what an operator reads in a CI log — but a spec cannot depend on that file // existing when it is collected: Playwright loads the spec modules to build its // test list, and the fixture is built by a `webServer` command. On a fresh // checkout the file is simply not there yet, and a helper that failed closed on // that would skip the whole song suite on a machine that HAS the data. So both // sides answer from the same directories, here. export function songCapabilities(songData) { const has = (d) => existsSync(path.join(songData, d)); const caps = { songData: existsSync(songData), // The candidate files — the population every clip list is built from. cand2: has("cand2"), // The audio. `make-fixture` copies a candidate only when its wav is // present, so without this the queues are empty whatever cand2 holds. wav48: has("wav48"), asr: has("asr"), media: has("media"), songDir: songData, }; // THE COMPOUND THE CLIP SPECS READ. A queue with no candidates and a bench // with no audio are the same failure from two directions, so one flag names // it. caps.song = caps.cand2 && caps.wav48; return caps; }