// Run with: // node_modules/.bin/tsx --test "editor/app/channels/[slug]/lib/stageOrder.test.ts" // // page.tsx builds its stage list from the registry rather than from a literal: // // ["configure", "playlist", // ...OPERATION_GROUP_ORDER.flatMap((g) => GROUP_STAGES[g]), // "cleanup", "diagnostics", "danger"] // // That array is what `?stage=` is resolved against and what the switcher renders // in order, so a change to it is a change to every stage link on the page. tsc // checks MEMBERSHIP (GROUP_STAGES is an exhaustive Record) // but not ORDER and not CARDINALITY — a group that gained a second stage, or an // OPERATION_GROUP_ORDER someone resorted, would compile and silently reorder the // page. This pins both against the literal list that shipped before the // derivation. import { test } from "node:test"; import assert from "node:assert/strict"; import { OPERATION_GROUP_ORDER } from "../../lib/operations"; import { GROUP_STAGES, type StageId } from "./stageStatus"; // The expression from page.tsx, verbatim. Duplicated rather than exported and // imported because page.tsx is a server component that reads the filesystem at // module scope; what is worth pinning is the SHAPE, and a copy that drifted from // the page would fail this test by construction on the next edit to either. function stageOrder(): StageId[] { return [ "configure", "playlist", ...OPERATION_GROUP_ORDER.flatMap((g) => GROUP_STAGES[g]), "cleanup", "diagnostics", "danger", ]; } test("the derived stage order is the list that shipped", () => { assert.deepEqual(stageOrder(), [ "configure", "playlist", "download", "transcribe", "digest", "speakers", "cleanup", "diagnostics", "danger", ]); }); test("every operation group names at least one stage, and none is orphaned", () => { // The exhaustiveness tsc gives is on the KEYS. This is the other half: a group // mapped to an empty array would compile and would mean an operation group // with nowhere to appear on the channel page. for (const group of OPERATION_GROUP_ORDER) { assert.ok( GROUP_STAGES[group].length > 0, `${group} names no stage, so its operations have no card`, ); } // And no stage is claimed by two groups, which would render it twice. const claimed = OPERATION_GROUP_ORDER.flatMap((g) => GROUP_STAGES[g]); assert.equal( claimed.length, new Set(claimed).size, `a stage is claimed by more than one group: ${claimed.join(",")}`, ); });