import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import Database from 'better-sqlite3'; import { mkdtempSync, rmSync } from 'fs'; import { tmpdir } from 'os'; import { join } from 'path'; import { runMigrations } from '../../db/migrate.js'; import { NotesRepository } from '../../notes/notes-repository.js'; import { NotesService } from '../../notes/notes-service.js'; import { executeNotesTools, TOOL_DEFS } from './notes.js'; describe('notes tools', () => { let tmpRoot: string; let db: Database.Database; let service: NotesService; let ctx: { notesService: NotesService; user: Express.User }; beforeEach(() => { tmpRoot = mkdtempSync(join(tmpdir(), 'notes-tools-test-')); db = new Database(join(tmpRoot, 'test.db')); runMigrations(db); db.prepare(`INSERT INTO users (id, email, name) VALUES ('alice','a@x.com','Alice')`).run(); const repo = new NotesRepository(db); service = new NotesService({ db, repo, userFolderRoot: tmpRoot, getUserOrgIds: () => [] }); ctx = { notesService: service, user: { id: 'alice', role: 'user', orgIds: [], email: 'a@x.com', name: 'Alice', avatarUrl: null, status: 'active', defaultVisibility: 'private', defaultVisibilityOrgId: null, }, }; }); afterEach(() => { db.close(); rmSync(tmpRoot, { recursive: true, force: true }); }); it('exposes 3 TOOL_DEFS', () => { expect(Object.keys(TOOL_DEFS).sort()).toEqual(['ReadNote', 'SearchNotes', 'WriteNote']); }); it('WriteNote writes a note and returns path', async () => { const result = await executeNotesTools('WriteNote', { folder: 'cve', file_name: 'foo.md', content: '---\nvisibility: public\n---\nbody', }, ctx); expect(result?.isError).toBeFalsy(); expect(result?.output).toContain('cve/foo.md'); }); it('SearchNotes finds a written note via FTS', async () => { await executeNotesTools('WriteNote', { folder: 'cve', file_name: 'foo.md', content: '---\ntitle: kubernetes pod crash\nvisibility: public\n---\nbody', }, ctx); const result = await executeNotesTools('SearchNotes', { query: 'kubernetes' }, ctx); expect(result?.isError).toBeFalsy(); expect(result?.output).toContain('foo.md'); }); it('ReadNote returns full body and FM', async () => { await executeNotesTools('WriteNote', { folder: 'cve', file_name: 'foo.md', content: '---\nvisibility: public\n---\nbody content', }, ctx); const result = await executeNotesTools('ReadNote', { owner_id: 'alice', folder: 'cve', file_name: 'foo.md', }, ctx); expect(result?.isError).toBeFalsy(); expect(result?.output).toContain('body content'); }); });