- Refactored types in `Knowledge/types.ts` to introduce new interfaces for document handling. - Added `KnowledgeDocItem`, `KnowledgeDocsListResponse`, `KnowledgeDocsUploadInput`, `KnowledgeDocsUploadResponse`, and `KnowledgeDocsDeleteResponse` for better structure and clarity. - Updated `KnowledgeDocsApiClient` interface to include methods for listing, uploading, and deleting documents. fix: replace deprecated icons in AccountSettingsPanel and SettingMenu - Replaced `CheckCircleIcon` with `CheckCircle` from `lucide-react` in `AccountSettingsPanel.tsx`. - Updated `SettingMenu.tsx` to use `Settings` and `User` from `lucide-react` instead of custom icons. test: add tests for knowledge docs routes and KnowledgePage - Created `knowledge-docs-routes.test.ts` to test API routes for listing, uploading, and deleting knowledge documents. - Added `knowledge-page.test.tsx` to test the rendering and functionality of the KnowledgePage component, including document loading and deletion.
113 lines
3.0 KiB
TypeScript
113 lines
3.0 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const mocks = vi.hoisted(() => ({
|
|
listKnowledgeDocs: vi.fn(),
|
|
uploadKnowledgeDoc: vi.fn(),
|
|
deleteKnowledgeDoc: vi.fn(),
|
|
isSafeKnowledgeDocName: vi.fn(),
|
|
}));
|
|
|
|
vi.mock('../electron/utils/knowledge-docs', () => ({
|
|
listKnowledgeDocs: mocks.listKnowledgeDocs,
|
|
uploadKnowledgeDoc: mocks.uploadKnowledgeDoc,
|
|
deleteKnowledgeDoc: mocks.deleteKnowledgeDoc,
|
|
isSafeKnowledgeDocName: mocks.isSafeKnowledgeDocName,
|
|
}));
|
|
|
|
import { normalizeRequest } from '../electron/api/route-utils';
|
|
import { handleKnowledgeRoutes } from '../electron/api/routes/knowledge';
|
|
|
|
const ctx = {
|
|
gatewayManager: null,
|
|
providerApiService: null,
|
|
mainWindow: null,
|
|
} as any;
|
|
|
|
describe('knowledge docs routes', () => {
|
|
beforeEach(() => {
|
|
mocks.listKnowledgeDocs.mockReset();
|
|
mocks.uploadKnowledgeDoc.mockReset();
|
|
mocks.deleteKnowledgeDoc.mockReset();
|
|
mocks.isSafeKnowledgeDocName.mockReset();
|
|
mocks.isSafeKnowledgeDocName.mockReturnValue(true);
|
|
});
|
|
|
|
it('returns listed knowledge docs from the local route', async () => {
|
|
mocks.listKnowledgeDocs.mockResolvedValue([
|
|
{
|
|
name: 'guide.md',
|
|
size: 128,
|
|
modifiedAt: '2026-04-18T10:00:00.000Z',
|
|
type: 'md',
|
|
},
|
|
]);
|
|
|
|
const response = await handleKnowledgeRoutes(normalizeRequest({
|
|
path: '/api/knowledge/docs',
|
|
method: 'GET',
|
|
}), ctx);
|
|
|
|
expect(response?.ok).toBe(true);
|
|
expect(response?.json).toMatchObject({
|
|
success: true,
|
|
files: [
|
|
expect.objectContaining({
|
|
name: 'guide.md',
|
|
type: 'md',
|
|
}),
|
|
],
|
|
});
|
|
});
|
|
|
|
it('uploads and deletes docs through the route contract', async () => {
|
|
mocks.uploadKnowledgeDoc.mockResolvedValue({
|
|
name: 'guide.md',
|
|
size: 128,
|
|
modifiedAt: '2026-04-18T10:00:00.000Z',
|
|
type: 'md',
|
|
});
|
|
|
|
const upload = await handleKnowledgeRoutes(normalizeRequest({
|
|
path: '/api/knowledge/docs',
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
fileName: 'guide.md',
|
|
base64: Buffer.from('hello').toString('base64'),
|
|
}),
|
|
}), ctx);
|
|
|
|
expect(upload?.ok).toBe(true);
|
|
expect(upload?.json).toMatchObject({
|
|
success: true,
|
|
file: expect.objectContaining({
|
|
name: 'guide.md',
|
|
}),
|
|
});
|
|
|
|
const remove = await handleKnowledgeRoutes(normalizeRequest({
|
|
path: '/api/knowledge/docs/guide.md',
|
|
method: 'DELETE',
|
|
}), ctx);
|
|
|
|
expect(remove?.ok).toBe(true);
|
|
expect(remove?.json).toMatchObject({ success: true });
|
|
expect(mocks.deleteKnowledgeDoc).toHaveBeenCalledWith('guide.md');
|
|
});
|
|
|
|
it('rejects unsafe file names', async () => {
|
|
mocks.isSafeKnowledgeDocName.mockReturnValue(false);
|
|
|
|
const response = await handleKnowledgeRoutes(normalizeRequest({
|
|
path: '/api/knowledge/docs',
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
fileName: '../escape.md',
|
|
base64: Buffer.from('bad').toString('base64'),
|
|
}),
|
|
}), ctx);
|
|
|
|
expect(response?.ok).toBe(false);
|
|
expect(response?.status).toBe(400);
|
|
});
|
|
});
|