test: 引入 Vitest 测试骨架并抽出颜色/比例纯函数模块

This commit is contained in:
2026-06-15 13:39:02 +08:00
parent 307537a7ce
commit 45e6534ee1
12 changed files with 3773 additions and 199 deletions
@@ -0,0 +1,90 @@
import { describe, it, expect } from "vitest";
import {
validateEcommerceImageFiles,
summarizeRejectedImages,
normalizeEcommerceImageMime,
ECOMMERCE_MAX_IMAGE_BYTES,
} from "./ecommerceImageValidation";
function makeFile(name: string, type: string, size: number): File {
return new File([new Uint8Array(size)], name, { type });
}
describe("validateEcommerceImageFiles", () => {
it("accepts supported types under the size limit", () => {
const result = validateEcommerceImageFiles([
makeFile("a.png", "image/png", 1024),
makeFile("b.jpg", "image/jpeg", 1024),
makeFile("c.webp", "image/webp", 1024),
makeFile("d.gif", "image/gif", 1024),
]);
expect(result.accepted).toHaveLength(4);
expect(result.rejected).toHaveLength(0);
});
it("rejects unsupported mime types", () => {
const result = validateEcommerceImageFiles([makeFile("x.bmp", "image/bmp", 1024)]);
expect(result.accepted).toHaveLength(0);
expect(result.rejected[0]).toMatchObject({ name: "x.bmp", reason: "不支持的图片格式" });
});
it("rejects files over 10MB", () => {
const result = validateEcommerceImageFiles([
makeFile("big.png", "image/png", ECOMMERCE_MAX_IMAGE_BYTES + 1),
]);
expect(result.accepted).toHaveLength(0);
expect(result.rejected[0]).toMatchObject({ name: "big.png", reason: "图片超过 10MB" });
});
it("accepts exactly 10MB (boundary)", () => {
const result = validateEcommerceImageFiles([
makeFile("edge.png", "image/png", ECOMMERCE_MAX_IMAGE_BYTES),
]);
expect(result.accepted).toHaveLength(1);
});
it("partitions a mixed batch", () => {
const result = validateEcommerceImageFiles([
makeFile("ok.png", "image/png", 100),
makeFile("bad.bmp", "image/bmp", 100),
makeFile("huge.jpg", "image/jpeg", ECOMMERCE_MAX_IMAGE_BYTES + 1),
]);
expect(result.accepted).toHaveLength(1);
expect(result.rejected).toHaveLength(2);
});
});
describe("summarizeRejectedImages", () => {
it("returns empty string for no rejections", () => {
expect(summarizeRejectedImages([])).toBe("");
});
it("summarizes a single rejection", () => {
expect(summarizeRejectedImages([{ name: "a.bmp", reason: "不支持的图片格式" }])).toBe(
"a.bmp 已跳过:不支持的图片格式",
);
});
it("appends count suffix for multiple rejections", () => {
const summary = summarizeRejectedImages([
{ name: "a.bmp", reason: "不支持的图片格式" },
{ name: "b.bmp", reason: "不支持的图片格式" },
]);
expect(summary).toBe("a.bmp 等 2 个文件 已跳过:不支持的图片格式");
});
});
describe("normalizeEcommerceImageMime", () => {
it("passes through supported types", () => {
expect(normalizeEcommerceImageMime("image/png")).toBe("image/png");
expect(normalizeEcommerceImageMime("image/jpeg")).toBe("image/jpeg");
expect(normalizeEcommerceImageMime("image/webp")).toBe("image/webp");
expect(normalizeEcommerceImageMime("image/gif")).toBe("image/gif");
});
it("falls back to image/png for unsupported or empty types", () => {
expect(normalizeEcommerceImageMime("image/bmp")).toBe("image/png");
expect(normalizeEcommerceImageMime("")).toBe("image/png");
expect(normalizeEcommerceImageMime("application/octet-stream")).toBe("image/png");
});
});