fix: Trim whitespace from app_target parameter

- Add .trim() to app_target when passing to Swift CLI
- Handles cases like "   Spotify   " correctly matching "Spotify"
- Applies to all app name formats including window specifiers

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Peter Steinberger 2025-06-08 06:47:56 +01:00
parent 979ae84f6b
commit 0301df2608
2 changed files with 91 additions and 4 deletions

View file

@ -96,7 +96,7 @@ export function buildSwiftCliArgs(
const specifierType = parts[1];
const specifierValue = parts.slice(2).join(":"); // Handle colons in window titles
args.push("--app", appName);
args.push("--app", appName.trim());
args.push("--mode", "window");
if (specifierType === "WINDOW_TITLE") {
@ -115,12 +115,12 @@ export function buildSwiftCliArgs(
{ app_target: input.app_target },
"Malformed window specifier, treating as app name",
);
args.push("--app", input.app_target);
args.push("--app", input.app_target.trim());
args.push("--mode", "multi");
}
} else {
// 'AppName': All windows of that app
args.push("--app", input.app_target);
args.push("--app", input.app_target.trim());
args.push("--mode", "multi");
}

View file

@ -317,6 +317,64 @@ describe("Image Tool", () => {
);
});
it("should handle case-insensitive format values", async () => {
// Import schema to test preprocessing
const { imageToolSchema } = await import("../../../src/types/index.js");
// Mock resolveImagePath for minimal case
mockResolveImagePath.mockResolvedValue({
effectivePath: "/tmp/test.png",
tempDirUsed: undefined,
});
const mockResponse = mockSwiftCli.captureImage("screen", {
path: "/tmp/test.png",
format: "png",
});
mockExecuteSwiftCli.mockResolvedValue(mockResponse);
// Test uppercase PNG - parse through schema first
const parsedInput = imageToolSchema.parse({ format: "PNG", path: "/tmp/test.png" });
await imageToolHandler(
parsedInput,
mockContext,
);
expect(mockExecuteSwiftCli).toHaveBeenCalledWith(
expect.arrayContaining(["--format", "png"]),
mockLogger,
);
});
it("should handle jpeg alias for jpg format", async () => {
// Import schema to test preprocessing
const { imageToolSchema } = await import("../../../src/types/index.js");
// Mock resolveImagePath for minimal case
mockResolveImagePath.mockResolvedValue({
effectivePath: "/tmp/test.jpg",
tempDirUsed: undefined,
});
const mockResponse = mockSwiftCli.captureImage("screen", {
path: "/tmp/test.jpg",
format: "jpg",
});
mockExecuteSwiftCli.mockResolvedValue(mockResponse);
// Test jpeg alias - parse through schema first
const parsedInput = imageToolSchema.parse({ format: "jpeg", path: "/tmp/test.jpg" });
await imageToolHandler(
parsedInput,
mockContext,
);
expect(mockExecuteSwiftCli).toHaveBeenCalledWith(
expect.arrayContaining(["--format", "jpg"]),
mockLogger,
);
});
it("should handle app_target: 'frontmost' with warning", async () => {
// Mock resolveImagePath for minimal case
mockResolveImagePath.mockResolvedValue({
@ -1116,6 +1174,9 @@ describe("Image Tool", () => {
});
it("should fall back to PNG when format is an invalid value", async () => {
// Import schema to test preprocessing
const { imageToolSchema } = await import("../../../src/types/index.js");
// Mock resolveImagePath
mockResolveImagePath.mockResolvedValue({
effectivePath: MOCK_TEMP_IMAGE_DIR,
@ -1129,8 +1190,9 @@ describe("Image Tool", () => {
mockExecuteSwiftCli.mockResolvedValue(mockResponse);
// Test with invalid format - schema should preprocess to 'png'
const parsedInput = imageToolSchema.parse({ format: "invalid" });
const result = await imageToolHandler(
{ format: "invalid" as any },
parsedInput,
mockContext,
);
@ -1200,4 +1262,29 @@ describe("Image Tool", () => {
expect(result.content[0].text).toBe("Image capture failed: Application not found");
});
});
describe("imageToolHandler - Whitespace trimming", () => {
it("should trim leading and trailing whitespace from app_target", async () => {
mockResolveImagePath.mockResolvedValue({
effectivePath: MOCK_TEMP_IMAGE_DIR,
tempDirUsed: MOCK_TEMP_IMAGE_DIR,
});
const mockResponse = mockSwiftCli.captureImage("Spotify", {
path: MOCK_SAVED_FILE_PATH,
format: "png",
});
mockExecuteSwiftCli.mockResolvedValue(mockResponse);
await imageToolHandler(
{ app_target: " Spotify " },
mockContext,
);
// Check that the Swift CLI was called with trimmed app name
const callArgs = mockExecuteSwiftCli.mock.calls[0][0];
const appIndex = callArgs.indexOf("--app");
expect(callArgs[appIndex + 1]).toBe("Spotify"); // Should be trimmed
});
});
});