Add sendImages E2E tests for DaemonClient
Add two E2E tests that verify image attachment support in sendMessage(): - "sends message with image attachment to Claude agent" - tests single image - "sends message with multiple image attachments" - tests multiple images Tests use minimal 1x1 PNG base64 and verify: - Server logs image attachments received - Agent processes message and completes turn - Assistant response is generated 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
8a614aac58
commit
7b8d032bbc
@@ -1504,4 +1504,134 @@ describe("daemon E2E", () => {
|
||||
60000 // 1 minute timeout
|
||||
);
|
||||
});
|
||||
|
||||
describe("sendImages", () => {
|
||||
// Minimal 1x1 red PNG image encoded in base64
|
||||
// This is a valid PNG that can be decoded by image processing libraries
|
||||
const MINIMAL_PNG_BASE64 =
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";
|
||||
|
||||
test(
|
||||
"sends message with image attachment to Claude agent",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
|
||||
// Create Claude agent
|
||||
const agent = await ctx.client.createAgent({
|
||||
provider: "claude",
|
||||
cwd,
|
||||
title: "Image Test Agent",
|
||||
});
|
||||
|
||||
expect(agent.id).toBeTruthy();
|
||||
expect(agent.provider).toBe("claude");
|
||||
|
||||
// Send message with image attachment
|
||||
await ctx.client.sendMessage(
|
||||
agent.id,
|
||||
"I'm sending you an image. Describe what information you received about the image attachment. Reply with a single short sentence.",
|
||||
{
|
||||
images: [
|
||||
{
|
||||
data: MINIMAL_PNG_BASE64,
|
||||
mimeType: "image/png",
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
// Wait for agent to complete
|
||||
const finalState = await ctx.client.waitForAgentIdle(agent.id, 120000);
|
||||
|
||||
expect(finalState.status).toBe("idle");
|
||||
expect(finalState.lastError).toBeUndefined();
|
||||
|
||||
// Verify stream events show the agent processed the message
|
||||
const queue = ctx.client.getMessageQueue();
|
||||
const streamEvents = queue.filter(
|
||||
(m) => m.type === "agent_stream" && m.payload.agentId === agent.id
|
||||
);
|
||||
|
||||
// Should have received stream events
|
||||
expect(streamEvents.length).toBeGreaterThan(0);
|
||||
|
||||
// Verify turn completed successfully
|
||||
const hasTurnCompleted = streamEvents.some(
|
||||
(m) =>
|
||||
m.type === "agent_stream" && m.payload.event.type === "turn_completed"
|
||||
);
|
||||
expect(hasTurnCompleted).toBe(true);
|
||||
|
||||
// Verify there was an assistant message in the timeline
|
||||
const hasAssistantMessage = streamEvents.some((m) => {
|
||||
if (m.type !== "agent_stream" || m.payload.event.type !== "timeline") {
|
||||
return false;
|
||||
}
|
||||
const item = m.payload.event.item;
|
||||
return item.type === "assistant_message" && item.text.length > 0;
|
||||
});
|
||||
expect(hasAssistantMessage).toBe(true);
|
||||
|
||||
// Cleanup
|
||||
await ctx.client.deleteAgent(agent.id);
|
||||
rmSync(cwd, { recursive: true, force: true });
|
||||
},
|
||||
180000 // 3 minute timeout for Claude API call
|
||||
);
|
||||
|
||||
test(
|
||||
"sends message with multiple image attachments",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
|
||||
// Create Claude agent
|
||||
const agent = await ctx.client.createAgent({
|
||||
provider: "claude",
|
||||
cwd,
|
||||
title: "Multi-Image Test Agent",
|
||||
});
|
||||
|
||||
expect(agent.id).toBeTruthy();
|
||||
|
||||
// Send message with two image attachments
|
||||
await ctx.client.sendMessage(
|
||||
agent.id,
|
||||
"I'm sending you two images. How many image attachments are mentioned in the context? Reply with just a number.",
|
||||
{
|
||||
images: [
|
||||
{
|
||||
data: MINIMAL_PNG_BASE64,
|
||||
mimeType: "image/png",
|
||||
},
|
||||
{
|
||||
data: MINIMAL_PNG_BASE64,
|
||||
mimeType: "image/jpeg",
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
// Wait for agent to complete
|
||||
const finalState = await ctx.client.waitForAgentIdle(agent.id, 120000);
|
||||
|
||||
expect(finalState.status).toBe("idle");
|
||||
expect(finalState.lastError).toBeUndefined();
|
||||
|
||||
// Verify turn completed
|
||||
const queue = ctx.client.getMessageQueue();
|
||||
const hasTurnCompleted = queue.some(
|
||||
(m) =>
|
||||
m.type === "agent_stream" &&
|
||||
m.payload.agentId === agent.id &&
|
||||
m.payload.event.type === "turn_completed"
|
||||
);
|
||||
expect(hasTurnCompleted).toBe(true);
|
||||
|
||||
// Cleanup
|
||||
await ctx.client.deleteAgent(agent.id);
|
||||
rmSync(cwd, { recursive: true, force: true });
|
||||
},
|
||||
180000 // 3 minute timeout for Claude API call
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user