- Add test-helpers.ts with buildTestApp() + resetMemoryDatastore() - notes: 11 tests (CRUD, archive, filter, search, validation) - workspaces: 7 tests (CRUD, summaries with noteCount, validation) - note-tasks: 6 tests (CRUD, filter by workspaceId, validation) - note-artifacts: 7 tests (CRUD, filter by noteId, validation) - note-relationships: 4 tests (create, list, validation) - note-agent-actions: 8 tests (CRUD, pending, batch-review, validation) - saved-views: 8 tests (CRUD, filter by scope, delete, validation) - Fix listPendingActions to avoid unsupported $in operator in memory provider - Total: 75 backend tests (was 24)
98 lines
3.4 KiB
TypeScript
98 lines
3.4 KiB
TypeScript
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import type { FastifyInstance } from 'fastify';
|
|
|
|
const { extractAuthMock } = vi.hoisted(() => ({
|
|
extractAuthMock: vi.fn(async () => ({ sub: 'user_1', type: 'access' })),
|
|
}));
|
|
|
|
vi.mock('../../lib/auth.js', () => ({ extractAuth: extractAuthMock }));
|
|
vi.mock('../../lib/product-config.js', () => ({ PRODUCT_ID: 'notelett' }));
|
|
|
|
import { buildTestApp, resetMemoryDatastore } from '../../test-helpers.js';
|
|
import { noteArtifactRoutes } from './routes.js';
|
|
|
|
let app: FastifyInstance;
|
|
|
|
beforeAll(async () => {
|
|
app = await buildTestApp(noteArtifactRoutes);
|
|
});
|
|
|
|
beforeEach(() => {
|
|
resetMemoryDatastore();
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await app.close();
|
|
});
|
|
|
|
const validArtifact = {
|
|
id: 'artifact-1',
|
|
workspaceId: 'ws-1',
|
|
noteId: 'note-1',
|
|
artifactType: 'file',
|
|
title: 'Launch brief.pdf',
|
|
description: 'Ready for review',
|
|
blobPath: 'notelett/user-1/launch-brief.pdf',
|
|
contentType: 'application/pdf',
|
|
sizeBytes: 2048,
|
|
};
|
|
|
|
describe('note-artifacts routes — integration', () => {
|
|
it('POST /note-artifacts creates an artifact and returns 201', async () => {
|
|
const res = await app.inject({ method: 'POST', url: '/api/note-artifacts', payload: validArtifact });
|
|
expect(res.statusCode).toBe(201);
|
|
const body = res.json();
|
|
expect(body.id).toBe('artifact-1');
|
|
expect(body.title).toBe('Launch brief.pdf');
|
|
expect(body.blobPath).toBe('notelett/user-1/launch-brief.pdf');
|
|
});
|
|
|
|
it('GET /note-artifacts lists artifacts by workspaceId', async () => {
|
|
await app.inject({ method: 'POST', url: '/api/note-artifacts', payload: validArtifact });
|
|
const res = await app.inject({ method: 'GET', url: '/api/note-artifacts?workspaceId=ws-1' });
|
|
expect(res.statusCode).toBe(200);
|
|
expect(res.json().items).toHaveLength(1);
|
|
});
|
|
|
|
it('GET /note-artifacts requires workspaceId', async () => {
|
|
const res = await app.inject({ method: 'GET', url: '/api/note-artifacts' });
|
|
expect(res.statusCode).toBe(400);
|
|
});
|
|
|
|
it('GET /note-artifacts filters by noteId', async () => {
|
|
await app.inject({ method: 'POST', url: '/api/note-artifacts', payload: validArtifact });
|
|
await app.inject({
|
|
method: 'POST',
|
|
url: '/api/note-artifacts',
|
|
payload: { ...validArtifact, id: 'artifact-2', noteId: 'note-2' },
|
|
});
|
|
const res = await app.inject({ method: 'GET', url: '/api/note-artifacts?workspaceId=ws-1¬eId=note-1' });
|
|
expect(res.json().items).toHaveLength(1);
|
|
});
|
|
|
|
it('PATCH /note-artifacts/:id updates an artifact', async () => {
|
|
await app.inject({ method: 'POST', url: '/api/note-artifacts', payload: validArtifact });
|
|
const res = await app.inject({
|
|
method: 'PATCH',
|
|
url: '/api/note-artifacts/artifact-1?workspaceId=ws-1',
|
|
payload: { title: 'Updated title' },
|
|
});
|
|
expect(res.statusCode).toBe(200);
|
|
expect(res.json().title).toBe('Updated title');
|
|
});
|
|
|
|
it('PATCH /note-artifacts/:id returns 404 for missing artifact', async () => {
|
|
const res = await app.inject({
|
|
method: 'PATCH',
|
|
url: '/api/note-artifacts/missing?workspaceId=ws-1',
|
|
payload: { title: 'X' },
|
|
});
|
|
expect(res.statusCode).toBe(404);
|
|
});
|
|
|
|
it('POST /note-artifacts rejects invalid body', async () => {
|
|
const res = await app.inject({ method: 'POST', url: '/api/note-artifacts', payload: { id: 'x' } });
|
|
expect(res.statusCode).toBe(400);
|
|
});
|
|
});
|