Files
vfxreview/lib/render-pipeline/deliveries.test.ts
T
twotalesanimation a073f92da3
Deploy / deploy (push) Successful in 7m31s
fix(delivery): number same-day packages per episode, not per project
Numbering was scoped to the project, so the day's first delivery of
episode 102 was named _02 purely because episode 101 had already gone out
that morning. The count is meant to distinguish repeat deliveries of the
same content, and packageDir already separates episodes — three episodes
delivering today each land in their own folder and each are that folder's
first delivery. Adding `episode` to the lookup makes the suffix mean what
the folder layout already implies: only a second delivery of the *same*
episode becomes _02. The [projectId, episode] index already exists, so
the extra filter costs nothing.

packageNameTemplate also moves from {yymmdd} to {yyyymmdd}. The AE panel
has always built its local delivery folders with a four-digit year, so
this is the server matching the connector rather than a new convention.
The {yymmdd} token stays in TokenValues: a project carrying its own
template in deliveryConfig is unaffected either way.

Existing packages are untouched — buildDeliveryJobManifest reads rootPath
off the record. On the day of the changeover an episode that already
delivered as 260903_Delivery starts again at the bare 20260903_Delivery,
which is a different name and a different folder, so nothing merges.

Producer reviews keep their per-project numbering: a review can span
several episodes and stores episode as "", so scoping it the same way
would put every such review in one bucket.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 10:07:52 +02:00

99 lines
3.4 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { DELIVERY_CONFIG_DEFAULT, applyTokens, dateTokens, nextPackageName, tidyPath } from "./deliveries";
const BASE = "20260901_Delivery";
describe("nextPackageName", () => {
it("uses the bare base for the first package of the day", () => {
expect(nextPackageName(BASE, [])).toBe(BASE);
});
it("suffixes later packages sharing the base", () => {
expect(nextPackageName(BASE, [BASE])).toBe(`${BASE}_02`);
expect(nextPackageName(BASE, [BASE, `${BASE}_02`])).toBe(`${BASE}_03`);
});
it("never reuses a number after a gap", () => {
expect(nextPackageName(BASE, [BASE, `${BASE}_02`, `${BASE}_04`])).toBe(`${BASE}_05`);
});
it("ignores names that only share a prefix", () => {
expect(nextPackageName(BASE, [`${BASE}_final`, "20260902_Delivery"])).toBe(BASE);
});
});
describe("delivery layout", () => {
const tokens = {
deliveryRoot: "//SAN/DELIVERY",
showId: "ACME",
episode: "101",
packageName: BASE,
};
it("separates shows so two shows' episode 101 cannot collide", () => {
const acme = applyTokens(DELIVERY_CONFIG_DEFAULT.layout.packageDir, tokens);
const other = applyTokens(DELIVERY_CONFIG_DEFAULT.layout.packageDir, { ...tokens, showId: "BRAVO" });
expect(acme).toBe("//SAN/DELIVERY/ACME/101/20260901_Delivery");
expect(other).not.toBe(acme);
});
it("puts producer reviews under the show too", () => {
expect(applyTokens(DELIVERY_CONFIG_DEFAULT.layout.reviewDir, tokens)).toBe(
"//SAN/DELIVERY/ACME/PRODUCER_REVIEWS/20260901_Delivery"
);
});
});
describe("tidyPath", () => {
it("drops the empty segment a non-episodic show leaves behind", () => {
const raw = applyTokens(DELIVERY_CONFIG_DEFAULT.layout.packageDir, {
deliveryRoot: "//SAN/DELIVERY",
showId: "ACME",
episode: "",
packageName: BASE,
});
expect(tidyPath(raw)).toBe("//SAN/DELIVERY/ACME/20260901_Delivery");
});
it("keeps the UNC root intact", () => {
expect(tidyPath("//SAN/DELIVERY/ACME")).toBe("//SAN/DELIVERY/ACME");
});
it("leaves a well-formed path alone", () => {
expect(tidyPath("V:/DELIVERY/ACME/101/x")).toBe("V:/DELIVERY/ACME/101/x");
});
});
describe("per-episode numbering", () => {
// The scoping itself lives in createDeliveryPackage's query, which passes
// only the names already used by *this* episode. These pin the contract that
// depends on: another episode's delivery must not push this one to _02.
it("gives each episode's first delivery of the day the bare name", () => {
const ep101 = nextPackageName(BASE, [BASE]);
const ep102 = nextPackageName(BASE, []);
expect(ep101).toBe(`${BASE}_02`);
expect(ep102).toBe(BASE);
});
it("keeps two episodes' same-named packages in separate folders", () => {
const dirFor = (episode: string, packageName: string) =>
tidyPath(
applyTokens(DELIVERY_CONFIG_DEFAULT.layout.packageDir, {
deliveryRoot: "//SAN/DELIVERY",
showId: "ACME",
episode,
packageName,
})
);
expect(dirFor("101", BASE)).toBe("//SAN/DELIVERY/ACME/101/20260901_Delivery");
expect(dirFor("102", BASE)).toBe("//SAN/DELIVERY/ACME/102/20260901_Delivery");
});
});
describe("package name template", () => {
it("names the day with a four-digit year", () => {
const name = applyTokens(DELIVERY_CONFIG_DEFAULT.packageNameTemplate, dateTokens(new Date(2026, 8, 1)));
expect(name).toBe("20260901_Delivery");
});
});