Files
SnapOtter/tests/unit/web/icon-map.test.ts
T
SnapOtter 7f62bc32db test: expand coverage to 3,382 tests across all layers
- Unit: 1,353 tests (42 files) — +256 new tests covering AI bridge
  modules, image-engine sharpen/optimize-for-web, Zustand stores, and
  icon-map validation
- Integration: 1,640 tests (57 files) — +826 new tests across all
  tool routes, pipeline/progress/batch infrastructure, user-files,
  edit-metadata, and a 321-test cross-format matrix
- E2E-Docker: 389 passing (20 spec files) — 6 new spec files for
  batch processing, format conversion, layout, optimization,
  watermark/overlay, and pipeline chains. Tests verified against fresh
  Docker container with all 6 AI bundles installed.

Bug fixes discovered during testing:
- fix(compress): SVG/BMP/exotic formats crashed Sharp encoder — added
  format-safety fallback to PNG
- fix(rate-limit): increase default login attempt limit from 10 to 500
  per minute — previous value caused false test failures and is too
  restrictive for a self-hosted app
- fix(auth.setup): wait for consent button visibility before clicking
  to prevent flaky E2E-Docker auth setup
2026-04-24 22:43:14 +08:00

102 lines
2.4 KiB
TypeScript

// @vitest-environment jsdom
import { describe, expect, it } from "vitest";
import { ICON_MAP } from "@/lib/icon-map";
describe("ICON_MAP", () => {
it("is a non-empty object", () => {
expect(Object.keys(ICON_MAP).length).toBeGreaterThan(0);
});
it("every value is a valid React component", () => {
for (const [key, value] of Object.entries(ICON_MAP)) {
const isComponent =
typeof value === "function" ||
(typeof value === "object" && value !== null && "$$typeof" in value);
expect(isComponent).toBe(true);
}
});
it("contains all category icons referenced by shared constants", () => {
const categoryIcons = [
"Layers",
"Zap",
"SlidersHorizontal",
"Stamp",
"Wrench",
"LayoutGrid",
"FileType",
"Sparkles",
];
for (const icon of categoryIcons) {
expect(ICON_MAP[icon]).toBeDefined();
}
});
it("contains all tool icons referenced by shared constants", () => {
const toolIcons = [
"Maximize2",
"Crop",
"RotateCw",
"FileOutput",
"Minimize2",
"Globe",
"ShieldOff",
"PenLine",
"FileEdit",
"FileText",
"Focus",
"Pipette",
"Eraser",
"ZoomIn",
"Wand2",
"ScanText",
"EyeOff",
"ScanFace",
"Palette",
"Eye",
"Undo2",
"UserCheck",
"Type",
"Image",
"TextCursorInput",
"Info",
"Columns2",
"Copy",
"QrCode",
"ScanLine",
"Code",
"Columns",
"Grid3x3",
"Frame",
"FileImage",
"PenTool",
"Film",
];
for (const icon of toolIcons) {
expect(ICON_MAP[icon]).toBeDefined();
}
});
it("does not contain undefined or null values", () => {
for (const [key, value] of Object.entries(ICON_MAP)) {
expect(value).not.toBeNull();
expect(value).not.toBeUndefined();
}
});
it("keys are PascalCase (Lucide icon naming convention)", () => {
for (const key of Object.keys(ICON_MAP)) {
expect(key[0]).toBe(key[0].toUpperCase());
}
});
it("specific commonly used icons exist", () => {
expect(ICON_MAP.Crop).toBeDefined();
expect(ICON_MAP.Maximize2).toBeDefined();
expect(ICON_MAP.RotateCw).toBeDefined();
expect(ICON_MAP.Sparkles).toBeDefined();
expect(ICON_MAP.CheckCircle2).toBeDefined();
expect(ICON_MAP.Star).toBeDefined();
});
});