Files
Genarrative/src/services/image-editor/editorAgentClient.test.ts
T

196 lines
5.5 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from 'vitest';
import {
cancelEditorAgentToolCall,
confirmEditorAgentToolCall,
createEditorAgentConversation,
deleteEditorAgentConversation,
getEditorAgentConversation,
listEditorAgentConversations,
sendEditorAgentMessage,
} from './editorAgentClient';
const requestJsonMock = vi.hoisted(() => vi.fn());
vi.mock('../apiClient', () => ({
requestJson: requestJsonMock,
}));
describe('editorAgentClient', () => {
afterEach(() => {
requestJsonMock.mockReset();
});
it('uses the planned editor agent conversation CRUD routes', async () => {
requestJsonMock
.mockResolvedValueOnce({
conversations: [
{
conversationId: 'conversation-1',
projectId: 'project-1',
title: '角色参考',
createdAt: '2026-07-03T00:00:00.000Z',
updatedAt: '2026-07-03T00:00:00.000Z',
},
],
})
.mockResolvedValueOnce({
conversation: {
conversationId: 'conversation-2',
projectId: 'project-1',
title: '新对话',
messages: [],
createdAt: '2026-07-03T00:00:00.000Z',
updatedAt: '2026-07-03T00:01:00.000Z',
},
})
.mockResolvedValueOnce({
conversation: {
conversationId: 'conversation-1',
projectId: 'project-1',
title: '角色参考',
messages: [],
createdAt: '2026-07-03T00:00:00.000Z',
updatedAt: '2026-07-03T00:02:00.000Z',
},
})
.mockResolvedValueOnce({
conversation: {
conversationId: 'conversation-1',
projectId: 'project-1',
title: '角色参考',
messages: [],
createdAt: '2026-07-03T00:00:00.000Z',
updatedAt: '2026-07-03T00:02:00.000Z',
},
});
await listEditorAgentConversations('project-1');
await createEditorAgentConversation('project-1', { title: '新对话' });
await getEditorAgentConversation('conversation-1');
await deleteEditorAgentConversation('conversation-1');
expect(requestJsonMock).toHaveBeenNthCalledWith(
1,
'/api/editor/projects/project-1/agent-conversations',
{ method: 'GET' },
'读取画布 Agent 会话列表失败',
);
expect(requestJsonMock).toHaveBeenNthCalledWith(
2,
'/api/editor/projects/project-1/agent-conversations',
expect.objectContaining({
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: '新对话' }),
}),
'创建画布 Agent 会话失败',
);
expect(requestJsonMock).toHaveBeenNthCalledWith(
3,
'/api/editor/agent-conversations/conversation-1',
{ method: 'GET' },
'读取画布 Agent 会话失败',
);
expect(requestJsonMock).toHaveBeenNthCalledWith(
4,
'/api/editor/agent-conversations/conversation-1',
{ method: 'DELETE' },
'删除画布 Agent 会话失败',
);
});
it('sends an editor agent message and returns delta messages', async () => {
const responseBody = {
deltaMessages: [
{
id: 1,
role: 'assistant',
text: '我来处理',
attachments: [],
toolCall: null,
createdAt: '2026-07-03T00:00:00.000Z',
},
],
errorMessage: null,
};
requestJsonMock.mockResolvedValueOnce(responseBody);
const result = await sendEditorAgentMessage('conversation-1', {
text: '帮我把角色改成像素风',
attachments: [],
});
expect(result).toEqual(responseBody);
expect(requestJsonMock).toHaveBeenCalledWith(
'/api/editor/agent-conversations/conversation-1/messages',
expect.objectContaining({
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: '帮我把角色改成像素风',
attachments: [],
}),
}),
'发送画布 Agent 消息失败',
expect.objectContaining({
timeoutMs: 1_200_000,
authImpact: 'local',
}),
);
});
it('confirms and cancels a pending tool call by numeric message id', async () => {
const completedMessage = {
id: 7,
role: 'system',
text: 'internal completed tool output',
attachments: [],
toolCall: {
toolName: 'edit-image',
summary: '',
status: 'completed',
args: {},
images: [],
error: null,
},
createdAt: '2026-07-10T00:00:00.000Z',
};
const cancelledMessage = {
...completedMessage,
toolCall: {
...completedMessage.toolCall,
status: 'cancelled',
},
};
requestJsonMock
.mockResolvedValueOnce(completedMessage)
.mockResolvedValueOnce(cancelledMessage);
await expect(confirmEditorAgentToolCall('conversation/1', 7)).resolves.toBe(
completedMessage,
);
await expect(cancelEditorAgentToolCall('conversation/1', 7)).resolves.toBe(
cancelledMessage,
);
expect(requestJsonMock).toHaveBeenNthCalledWith(
1,
'/api/editor/agent-conversations/conversation%2F1/messages/7/confirm',
{ method: 'POST' },
'确认画布 Agent 操作失败',
{
timeoutMs: 1_200_000,
authImpact: 'local',
},
);
expect(requestJsonMock).toHaveBeenNthCalledWith(
2,
'/api/editor/agent-conversations/conversation%2F1/messages/7/cancel',
{ method: 'POST' },
'取消画布 Agent 操作失败',
{ authImpact: 'local' },
);
});
});