Peekaboo/tests/integration/invalid-format-integration.test.ts
Peter Steinberger ab882069b4 fix: Add defensive validation for invalid image formats with automatic PNG fallback
Implements robust handling for invalid image formats (like 'bmp', 'gif', 'webp') that bypass schema validation:

- Added defensive format validation in image tool handler
- Automatic path correction to ensure file extensions match actual format used
- Warning messages in response when format fallback occurs
- Comprehensive unit and integration test coverage for edge cases

This ensures invalid formats automatically fall back to PNG as requested, preventing
Swift CLI rejection and incorrect file extensions in output paths.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:44:17 +01:00

94 lines
No EOL
3.4 KiB
TypeScript

import { describe, it, expect, beforeEach } from "vitest";
import { imageToolHandler } from "../../src/tools/image";
import { initializeSwiftCliPath } from "../../src/utils/peekaboo-cli";
import { pino } from "pino";
import * as fs from "fs/promises";
import * as path from "path";
import * as os from "os";
// Initialize Swift CLI path (assuming 'peekaboo' binary is at project root)
const packageRootDir = path.resolve(__dirname, "..", ".."); // Adjust path from tests/integration to project root
initializeSwiftCliPath(packageRootDir);
const mockLogger = pino({ level: "silent" });
const mockContext = { logger: mockLogger };
// Conditionally skip Swift-dependent tests on non-macOS platforms
const describeSwiftTests = globalThis.shouldSkipSwiftTests ? describe.skip : describe;
describeSwiftTests("Invalid Format Integration Tests", () => {
let tempDir: string;
beforeEach(async () => {
// Create a temporary directory for test files
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "peekaboo-invalid-format-test-"));
});
it("should reject invalid format gracefully and not create files with wrong extensions", async () => {
const testPath = path.join(tempDir, "test_invalid_format.bmp");
// Test with invalid format 'bmp'
const result = await imageToolHandler(
{
format: "bmp",
path: testPath,
},
mockContext,
);
// Check what error we got
console.log("Result:", JSON.stringify(result, null, 2));
// The tool should succeed (format gets preprocessed to png)
expect(result.isError).toBeUndefined();
// Check if any files were created
if (result.saved_files && result.saved_files.length > 0) {
for (const savedFile of result.saved_files) {
// The actual saved file should have .png extension, not .bmp
expect(savedFile.path).not.toContain(".bmp");
expect(savedFile.path).toMatch(/\.png$/);
// Verify the file actually exists with the correct extension
const fileExists = await fs.access(savedFile.path).then(() => true).catch(() => false);
expect(fileExists).toBe(true);
// Verify no .bmp file was created
const bmpPath = savedFile.path.replace(/\.png$/, ".bmp");
const bmpExists = await fs.access(bmpPath).then(() => true).catch(() => false);
expect(bmpExists).toBe(false);
}
}
// The result content should not mention .bmp files
const resultText = result.content[0]?.text || "";
expect(resultText).not.toContain(".bmp");
});
it("should handle various invalid formats consistently", async () => {
const invalidFormats = ["gif", "webp", "tiff", "bmp", "xyz"];
for (const format of invalidFormats) {
const testPath = path.join(tempDir, `test_${format}.${format}`);
const result = await imageToolHandler(
{
format: format as any,
path: testPath,
},
mockContext,
);
// Should succeed with fallback
expect(result.isError).toBeUndefined();
if (result.saved_files && result.saved_files.length > 0) {
// All files should be saved as PNG regardless of input format
for (const savedFile of result.saved_files) {
expect(savedFile.path).toMatch(/\.png$/);
expect(savedFile.mime_type).toBe("image/png");
}
}
}
});
});