import { describe, expect, it } from "vitest"; import { MAX_SAFE_NAME_BYTES, safeFileName } from "./names.js"; describe("safeFileName", () => { it("keeps ordinary names", () => { expect(safeFileName("Meeting notes.pdf")).toBe("Meeting notes.pdf"); }); it("strips directories and traversal", () => { expect(safeFileName("../../etc/passwd")).toBe("passwd"); expect(safeFileName("C:\\Users\\x\\evil.exe")).toBe("evil.exe"); expect(safeFileName("..")).toBe("attachment"); }); it("removes control/bidi characters and reserved punctuation", () => { expect(safeFileName("a\u0000b\u202ecod.exe")).toBe("abcod.exe"); expect(safeFileName('wed:"na|me?*.txt')).toBe("we_ir_d_na_me_.txt"); expect(safeFileName(" .hidden ")).toBe("hidden"); }); it("NFKC-normalises and collapses whitespace", () => { expect(safeFileName("full \t width.PNG")).toBe("full width.png"); }); it("guards Windows device names", () => { expect(safeFileName("CON.txt")).toBe("_CON.txt"); }); it("appends the sniffed extension only when none exists", () => { expect(safeFileName("photo", "jpg")).toBe("photo.jpg"); expect(safeFileName("photo.jpeg", "jpg")).toBe("photo.jpeg"); expect(safeFileName("", "pdf")).toBe("attachment.pdf"); }); it("bounds length in UTF-8 bytes while preserving the extension", () => { const name = safeFileName(`${"ü".repeat(200)}.pdf`); expect(Buffer.byteLength(name, "utf8")).toBeLessThanOrEqual(MAX_SAFE_NAME_BYTES); expect(name.endsWith(".pdf")).toBe(true); }); });