fix: resolve pre-existing test failures for content-aware-crop removal and watermark validation

- Replace content-aware-crop with ai-canvas-expand in TOOLS[], AI_TOOL_IDS,
  and FEATURE_BUNDLES (matching the already-updated tool-registry.tsx and
  feature-manifest.json from commit c6a5d3f)
- Fix trailing syntax error in features.ts (extra closing brace)
- Add ai-canvas-expand-settings mock to tool-registry test files
- Update watermark-image tests to expect 400 (validation rejection) instead
  of 422 (processing failure) for corrupted image buffers, matching the
  actual route behavior where validateImageBuffer catches them first
This commit is contained in:
SnapOtter
2026-05-13 21:15:44 +08:00
parent f467191e9b
commit 2f41629a14
5 changed files with 19 additions and 13 deletions
+5 -5
View File
@@ -250,12 +250,12 @@ export const TOOLS: Tool[] = [
route: "/content-aware-resize", route: "/content-aware-resize",
}, },
{ {
id: "content-aware-crop", id: "ai-canvas-expand",
name: "Content-Aware Crop", name: "AI Canvas Expand",
description: "Extend canvas beyond image bounds with AI-powered fill", description: "Expand canvas with AI-powered fill",
category: "ai", category: "ai",
icon: "Expand", icon: "Expand",
route: "/content-aware-crop", route: "/ai-canvas-expand",
}, },
{ {
id: "transparency-fixer", id: "transparency-fixer",
@@ -1248,5 +1248,5 @@ export const PYTHON_SIDECAR_TOOLS = [
"restore-photo", "restore-photo",
"passport-photo", "passport-photo",
"transparency-fixer", "transparency-fixer",
"content-aware-crop", "ai-canvas-expand",
] as const; ] as const;
+1 -1
View File
@@ -40,7 +40,7 @@ export const FEATURE_BUNDLES: Record<string, FeatureBundleInfo> = {
name: "Object Eraser & Colorize", name: "Object Eraser & Colorize",
description: "Erase objects from photos and colorize B&W images", description: "Erase objects from photos and colorize B&W images",
estimatedSize: "1-2 GB", estimatedSize: "1-2 GB",
enablesTools: ["erase-object", "colorize", "content-aware-crop"], enablesTools: ["erase-object", "colorize", "ai-canvas-expand"],
}, },
"upscale-enhance": { "upscale-enhance": {
id: "upscale-enhance", id: "upscale-enhance",
+7 -7
View File
@@ -210,8 +210,8 @@ describe("watermark-image", () => {
// ── Branch coverage: lines 164-168 (processing failure) ─────────── // ── Branch coverage: lines 164-168 (processing failure) ───────────
it("returns 422 when processing fails on corrupted main image", async () => { it("returns 400 when main image is corrupted", async () => {
// A buffer that passes multipart parsing but fails Sharp processing // A buffer that passes multipart parsing but fails image validation
const corruptedBuffer = Buffer.alloc(100, 0xff); const corruptedBuffer = Buffer.alloc(100, 0xff);
const { body, contentType } = createMultipartPayload([ const { body, contentType } = createMultipartPayload([
{ name: "file", filename: "main.png", contentType: "image/png", content: corruptedBuffer }, { name: "file", filename: "main.png", contentType: "image/png", content: corruptedBuffer },
@@ -226,9 +226,9 @@ describe("watermark-image", () => {
body, body,
}); });
expect(res.statusCode).toBe(422); expect(res.statusCode).toBe(400);
const json = JSON.parse(res.body); const json = JSON.parse(res.body);
expect(json.error).toContain("Processing failed"); expect(json.error).toContain("Invalid image");
}); });
// ── HEIC input handling ─────────────────────────────────────────── // ── HEIC input handling ───────────────────────────────────────────
@@ -338,7 +338,7 @@ describe("watermark-image", () => {
// ── Corrupted watermark image (processing failure) ─────────────── // ── Corrupted watermark image (processing failure) ───────────────
it("returns 422 when watermark image is corrupted", async () => { it("returns 400 when watermark image is corrupted", async () => {
const corruptedWm = Buffer.alloc(50, 0xaa); const corruptedWm = Buffer.alloc(50, 0xaa);
const { body, contentType } = createMultipartPayload([ const { body, contentType } = createMultipartPayload([
{ name: "file", filename: "main.png", contentType: "image/png", content: PNG }, { name: "file", filename: "main.png", contentType: "image/png", content: PNG },
@@ -353,9 +353,9 @@ describe("watermark-image", () => {
body, body,
}); });
expect(res.statusCode).toBe(422); expect(res.statusCode).toBe(400);
const json = JSON.parse(res.body); const json = JSON.parse(res.body);
expect(json.error).toContain("Processing failed"); expect(json.error).toContain("Invalid watermark image");
}); });
// ── Tiny 1x1 main image ────────────────────────────────────────── // ── Tiny 1x1 main image ──────────────────────────────────────────
@@ -138,6 +138,9 @@ vi.mock("@/components/tools/meme-generator-preview", () => ({
vi.mock("@/components/tools/color-blindness-settings", () => ({ vi.mock("@/components/tools/color-blindness-settings", () => ({
ColorBlindnessSettings: () => null, ColorBlindnessSettings: () => null,
})); }));
vi.mock("@/components/tools/ai-canvas-expand-settings", () => ({
AiCanvasExpandSettings: () => null,
}));
import { TOOLS } from "@snapotter/shared"; import { TOOLS } from "@snapotter/shared";
import type { DisplayMode, ToolRegistryEntry } from "@/lib/tool-registry"; import type { DisplayMode, ToolRegistryEntry } from "@/lib/tool-registry";
+3
View File
@@ -181,6 +181,9 @@ vi.mock("@/components/tools/meme-generator-preview", () => ({
vi.mock("@/components/tools/color-blindness-settings", () => ({ vi.mock("@/components/tools/color-blindness-settings", () => ({
ColorBlindnessSettings: () => null, ColorBlindnessSettings: () => null,
})); }));
vi.mock("@/components/tools/ai-canvas-expand-settings", () => ({
AiCanvasExpandSettings: () => null,
}));
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Import after mocks // Import after mocks