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 { noteRelationshipRoutes } from './routes.js'; let app: FastifyInstance; beforeAll(async () => { app = await buildTestApp(noteRelationshipRoutes); }); beforeEach(() => { resetMemoryDatastore(); }); afterAll(async () => { await app.close(); }); const validRelationship = { id: 'rel-1', workspaceId: 'ws-1', fromNoteId: 'note-1', toNoteId: 'note-2', relationshipType: 'related', }; describe('note-relationships routes — integration', () => { it('POST /note-relationships creates a relationship and returns 201', async () => { const res = await app.inject({ method: 'POST', url: '/api/note-relationships', payload: validRelationship }); expect(res.statusCode).toBe(201); const body = res.json(); expect(body.id).toBe('rel-1'); expect(body.fromNoteId).toBe('note-1'); expect(body.toNoteId).toBe('note-2'); }); it('GET /note-relationships lists relationships by workspaceId', async () => { await app.inject({ method: 'POST', url: '/api/note-relationships', payload: validRelationship }); const res = await app.inject({ method: 'GET', url: '/api/note-relationships?workspaceId=ws-1' }); expect(res.statusCode).toBe(200); expect(res.json().items).toHaveLength(1); }); it('GET /note-relationships requires workspaceId', async () => { const res = await app.inject({ method: 'GET', url: '/api/note-relationships' }); expect(res.statusCode).toBe(400); }); it('POST /note-relationships rejects invalid body', async () => { const res = await app.inject({ method: 'POST', url: '/api/note-relationships', payload: { id: 'x' } }); expect(res.statusCode).toBe(400); }); });