import { describe, it, expect } from "vitest"; import { nextReviewName, reviewMovName } from "./reviews"; /** * Review folders are named by date, and several reviews a day are normal — * a morning pass and an afternoon one land in the same studio's inbox, so the * numbering has to be unambiguous about which came first. */ describe("nextReviewName", () => { const BASE = "20260828_Producer_review"; it("leaves the first review of the day unnumbered", () => { expect(nextReviewName(BASE, [])).toBe(BASE); }); it("numbers from _02 once the plain name is taken", () => { expect(nextReviewName(BASE, [BASE])).toBe(`${BASE}_02`); expect(nextReviewName(BASE, [BASE, `${BASE}_02`])).toBe(`${BASE}_03`); }); it("counts from the highest number, not the count", () => { // A cancelled _02 still holds its number: reusing it would give two // different folders the same name in the delivery history. expect(nextReviewName(BASE, [BASE, `${BASE}_02`, `${BASE}_04`])).toBe(`${BASE}_05`); }); it("picks up numbering even when the plain name was never used", () => { expect(nextReviewName(BASE, [`${BASE}_02`])).toBe(`${BASE}_03`); }); it("ignores names that merely start with the base", () => { // A hand-named "…_review_final" is somebody's own folder, not part of // this sequence, and must not push the number along. expect(nextReviewName(BASE, [`${BASE}_final`, `${BASE}_02x`])).toBe(BASE); }); it("does not confuse another day's reviews", () => { expect(nextReviewName(BASE, ["20260827_Producer_review_03"])).toBe(BASE); }); it("treats the base as a literal, not a pattern", () => { const dotted = "2026.08.28_review"; expect(nextReviewName(dotted, ["2026x08x28_review"])).toBe(dotted); }); }); describe("reviewMovName", () => { const SOURCE = "//SAN/renders/UNG_106_010_020/v004/UNG_106_010_020_cmp_TT_v004.mov"; it("uses the client's own naming when the production supplies it", () => { expect(reviewMovName({ shotCode: "UNG_106_010_020", clientCode: "EP6_VFX_012" }, "v004", SOURCE)).toBe( "EP6_VFX_012_v004.mov" ); }); it("falls back to the studio convention", () => { expect(reviewMovName({ shotCode: "UNG_106_010_020", clientCode: null }, "v004", SOURCE)).toBe( "UNG_106_010_020_cmp_TT_v004.mov" ); }); it("ignores a whitespace-only client code", () => { expect(reviewMovName({ shotCode: "UNG_106_010_020", clientCode: " " }, "v004", SOURCE)).toBe( "UNG_106_010_020_cmp_TT_v004.mov" ); }); it("keeps whatever extension the source actually has", () => { expect( reviewMovName({ shotCode: "UNG_106_010_020", clientCode: null }, "v004", "//SAN/a/b_v004.mxf") ).toBe("UNG_106_010_020_cmp_TT_v004.mxf"); }); it("does not mistake a dot in a folder name for an extension", () => { expect( reviewMovName({ shotCode: "UNG_106_010_020", clientCode: null }, "v004", "//SAN/v1.2/rendered_mov") ).toBe("UNG_106_010_020_cmp_TT_v004.mov"); }); });