103 lines
4.1 KiB
TypeScript
103 lines
4.1 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const hostApiFetch = vi.hoisted(() => vi.fn());
|
|
|
|
vi.mock('@/lib/host-api', () => ({ hostApiFetch }));
|
|
|
|
describe('coding project Host facade', () => {
|
|
beforeEach(() => vi.clearAllMocks());
|
|
|
|
it('uses only the vendor-neutral project metadata routes', async () => {
|
|
hostApiFetch
|
|
.mockResolvedValueOnce({ projects: [], activeProjectId: null })
|
|
.mockResolvedValueOnce({ snapshot: { project: { id: 'project/a' }, config: {} } })
|
|
.mockResolvedValueOnce({ conversations: [] })
|
|
.mockResolvedValueOnce({ conversation: { id: 'conversation-1' } })
|
|
.mockResolvedValueOnce({ conversation: { id: 'conversation-1', title: 'Renamed' } })
|
|
.mockResolvedValueOnce({});
|
|
const {
|
|
createCodingProjectConversation,
|
|
getCodingProjectConfig,
|
|
listCodingProjectConversations,
|
|
listCodingProjects,
|
|
patchCodingProjectConversation,
|
|
deleteCodingProjectConversation,
|
|
} = await import('@/lib/coding-projects');
|
|
|
|
await listCodingProjects();
|
|
await getCodingProjectConfig('project/a');
|
|
await listCodingProjectConversations('project/a');
|
|
await createCodingProjectConversation({
|
|
projectId: 'project/a',
|
|
agentId: 'agent-1',
|
|
title: '新对话',
|
|
});
|
|
await patchCodingProjectConversation('conversation/1', { title: 'Renamed', unread: true });
|
|
await deleteCodingProjectConversation('conversation/1');
|
|
|
|
expect(hostApiFetch.mock.calls).toEqual([
|
|
['/api/coding/projects'],
|
|
['/api/coding/projects/config?projectId=project%2Fa'],
|
|
['/api/coding/projects/conversations?projectId=project%2Fa'],
|
|
['/api/coding/projects/conversations', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ projectId: 'project/a', agentId: 'agent-1', title: '新对话' }),
|
|
}],
|
|
['/api/coding/conversations/conversation%2F1', {
|
|
method: 'PATCH',
|
|
body: JSON.stringify({ title: 'Renamed', unread: true }),
|
|
}],
|
|
['/api/coding/conversations/conversation%2F1', { method: 'DELETE' }],
|
|
]);
|
|
});
|
|
|
|
it('sends explicit identity choices and a literal independent-copy confirmation', async () => {
|
|
hostApiFetch
|
|
.mockResolvedValueOnce({ snapshot: { project: { id: 'local-1' }, config: { projectId: 'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa' }, knowledgeFiles: [] } })
|
|
.mockResolvedValueOnce({ snapshot: { project: { id: 'local-1' }, config: { projectId: 'bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb' }, knowledgeFiles: [] } })
|
|
.mockResolvedValueOnce({ snapshot: { project: { id: 'local-1' }, config: { projectId: 'cccccccc-cccc-4ccc-8ccc-cccccccccccc' }, knowledgeFiles: [] } });
|
|
const {
|
|
createCodingProject,
|
|
isCanonicalCodingProjectId,
|
|
makeCodingProjectIndependentCopy,
|
|
resolveCodingProjectIdentity,
|
|
} = await import('@/lib/coding-projects');
|
|
|
|
await createCodingProject({
|
|
projectPath: 'C:/projects/new',
|
|
projectType: 'custom',
|
|
identity: { kind: 'create' },
|
|
});
|
|
await resolveCodingProjectIdentity('local-1', {
|
|
kind: 'bind',
|
|
projectId: 'bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb',
|
|
});
|
|
await makeCodingProjectIndependentCopy('local-1');
|
|
|
|
expect(isCanonicalCodingProjectId('bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb')).toBe(true);
|
|
expect(isCanonicalCodingProjectId('BBBBBBBB-BBBB-4BBB-8BBB-BBBBBBBBBBBB')).toBe(false);
|
|
expect(isCanonicalCodingProjectId('not-a-project-id')).toBe(false);
|
|
expect(hostApiFetch.mock.calls).toEqual([
|
|
['/api/coding/projects/create', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
projectPath: 'C:/projects/new',
|
|
projectType: 'custom',
|
|
identity: { kind: 'create' },
|
|
}),
|
|
}],
|
|
['/api/coding/projects/identity', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
localProjectId: 'local-1',
|
|
identity: { kind: 'bind', projectId: 'bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb' },
|
|
}),
|
|
}],
|
|
['/api/coding/projects/identity/independent-copy', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ localProjectId: 'local-1', confirmed: true }),
|
|
}],
|
|
]);
|
|
});
|
|
});
|