import { describe, expect, it, vi } from 'vitest'; import { configureDataService, getCodingPlugins, parseCodingPluginProject, setCodingPluginEnabled, } from '@/lib/coding-plugins'; const PROJECT_ID = 'local-project'; function projection() { return { schemaVersion: 1, project: { localProjectId: PROJECT_ID, durableProjectId: null }, policyStatus: 'current', unknownPluginIds: [], items: [{ id: 'makelore.data-service', version: '1.0.0', contractVersion: 1, requiresBackend: true, displayName: '开发数据服务', description: '项目数据', enabled: false, state: 'disabled', backend: { status: 'unconfigured' }, skills: [{ id: 'data-service', assignedAgentIds: [] }], capabilities: [{ id: 'data-service.control', operations: [{ id: 'inspect', billing: { mode: 'included', availability: 'available', notice: 'Fixed quotas apply' }, tool: { name: 'data_service_inspect', label: 'Inspect', description: 'Inspect data', mutation: 'read', permissions: ['project.data.read'], }, }], }], settingsSurface: 'data-service', }], }; } describe('coding plugins Renderer client', () => { it('strictly parses the bounded Main projection', () => { expect(parseCodingPluginProject(projection())).toEqual(projection()); expect(() => parseCodingPluginProject({ ...projection(), owner: 'secret' })).toThrow(); expect(() => parseCodingPluginProject({ ...projection(), items: [{ ...projection().items[0], state: 'installed' }] })).toThrow(); }); it('uses the local project handle exactly once and enable does not configure', async () => { const fetcher = vi.fn() .mockResolvedValueOnce(projection()) .mockResolvedValueOnce({ ...projection(), items: [{ ...projection().items[0], enabled: true, state: 'configuration_required' }] }); await getCodingPlugins(PROJECT_ID, fetcher); await setCodingPluginEnabled(PROJECT_ID, 'makelore.data-service', true, fetcher); expect(fetcher).toHaveBeenNthCalledWith(1, '/api/coding/plugins?projectId=local-project'); expect(fetcher).toHaveBeenNthCalledWith(2, '/api/coding/plugins/makelore.data-service', { method: 'PUT', body: JSON.stringify({ projectId: PROJECT_ID, enabled: true }), }); expect(fetcher.mock.calls.flat().join(' ')).not.toContain('/api/works/data-service/project'); }); it('configures Data Service only through its existing typed route', async () => { const response = { success: true, status: 200, code: null, error: null, retryable: false, data: { instance_id: 'instance-1', project_id: '11111111-1111-4111-8111-111111111111', collections: [], usage: { document_count: 0, total_bytes: 0 }, limits: { max_collections: 20, max_documents: 1000, max_total_bytes: 20971520, max_document_bytes: 65536, list_default_limit: 50, list_max_limit: 100, list_max_data_bytes: 1048576, mutations_per_minute: 120, }, created_at: '2026-08-27T00:00:00Z', updated_at: '2026-08-27T00:00:00Z', }, }; const fetcher = vi.fn().mockResolvedValue(response); await expect(configureDataService(['todos'], fetcher)).resolves.toEqual(response); expect(fetcher).toHaveBeenCalledWith('/api/works/data-service/project', { method: 'PUT', body: JSON.stringify({ collections: ['todos'] }), }); }); });