58 lines
1.8 KiB
TypeScript
58 lines
1.8 KiB
TypeScript
import { mkdtemp, readdir } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import path from "node:path";
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const getUploadRootFromEnvMock = vi.fn();
|
|
let uploadRoot: string | null = null;
|
|
|
|
vi.mock("../../lib/server/uploads/uploadRoot", async () => {
|
|
const actual = await vi.importActual<
|
|
typeof import("../../lib/server/uploads/uploadRoot")
|
|
>("../../lib/server/uploads/uploadRoot");
|
|
return {
|
|
...actual,
|
|
getUploadRootFromEnv: () => getUploadRootFromEnvMock(),
|
|
};
|
|
});
|
|
|
|
import { saveCreateFlowUpload } from "../../lib/server/uploads/saveCreateFlowUpload";
|
|
|
|
const PNG_1X1 = Buffer.from(
|
|
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==",
|
|
"base64",
|
|
);
|
|
|
|
describe("saveCreateFlowUpload", () => {
|
|
beforeEach(async () => {
|
|
uploadRoot = await mkdtemp(path.join(tmpdir(), "cr-upload-save-"));
|
|
getUploadRootFromEnvMock.mockReset();
|
|
getUploadRootFromEnvMock.mockImplementation(() => uploadRoot);
|
|
});
|
|
|
|
afterEach(() => {
|
|
uploadRoot = null;
|
|
});
|
|
|
|
it("writes a sniffed PNG even when the client declared the wrong MIME", async () => {
|
|
const saved = await saveCreateFlowUpload({
|
|
purpose: "communityAvatar",
|
|
buffer: PNG_1X1,
|
|
});
|
|
expect("error" in saved).toBe(false);
|
|
if ("error" in saved) return;
|
|
expect(saved.mimeType).toBe("image/png");
|
|
const files = await readdir(uploadRoot!);
|
|
expect(files).toEqual([`${saved.id}.png`]);
|
|
});
|
|
|
|
it("rejects spoofed bytes without writing", async () => {
|
|
const saved = await saveCreateFlowUpload({
|
|
purpose: "communityAvatar",
|
|
buffer: Buffer.from("not an image"),
|
|
});
|
|
expect(saved).toEqual({ error: "validation", reason: "invalidType" });
|
|
expect(await readdir(uploadRoot!)).toEqual([]);
|
|
});
|
|
});
|