196 lines
5.5 KiB
TypeScript
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' },
|
|
);
|
|
});
|
|
});
|