learning_ai_notes/backend/src/modules/notes/routes.test.ts
Saravana Achu Mac a697752d15 feat: implement WEB_AI_FAST_ROADMAP (web + backend + docs)
Phase 1: Command palette (⌘K), editor autosave with quiet auto-saves, dashboard
saved views from API + quick links + onboarding seed CTA, explicit task scan panel.

Phase 2: Context pack formatter with YAML frontmatter, copy on note + workspace .md export.

Phase 3: ADR for hybrid search without embeddings; POST /notes/search (lexical +
ranked hybrid); search UI mode toggle.

Phase 4: POST copilot + suggest-title; in-editor copilot actions; /chat retrieval
answers with citations (backend chat.rag_enabled).

Phase 5: Settings MCP snippet, offline queue note, API token deferral; DEEP_LINKS.md.

Phase 6: Note shares + public GET; share page; POST onboarding-seed.

Phase 7: note_versions on PATCH; version panel; create-note templates; PWA manifest.

Flags: search.hybrid_enabled, copilot.enabled, chat.rag_enabled, onboarding.seed_enabled.
Made-with: Cursor
2026-03-31 13:00:36 -07:00

65 lines
2.1 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
import { noteRoutes } from './routes.js';
const {
extractAuthMock,
listNotesMock,
getNoteMock,
createNoteMock,
updateNoteMock,
} = vi.hoisted(() => ({
extractAuthMock: vi.fn(async () => ({ sub: 'user_1' })),
listNotesMock: vi.fn(async () => ({ items: [], total: 0 })),
getNoteMock: vi.fn(async () => null),
createNoteMock: vi.fn(async (doc: unknown) => doc),
updateNoteMock: vi.fn(async () => null),
}));
vi.mock('../../lib/auth.js', () => ({ extractAuth: extractAuthMock, requireWriter: extractAuthMock }));
vi.mock('../../lib/product-config.js', () => ({ PRODUCT_ID: 'notelett' }));
vi.mock('../../lib/feature-flags.js', () => ({
isFeatureEnabled: vi.fn(() => true),
}));
vi.mock('../../lib/telemetry.js', () => ({ trackEvent: vi.fn() }));
vi.mock('../../lib/extraction-client.js', () => ({ extractFromText: vi.fn(async () => ({ summary: 'test' })) }));
vi.mock('../../lib/copilot-transform.js', () => ({
runCopilotTransform: vi.fn(async () => 'transformed'),
suggestTitleFromBody: vi.fn(async () => 'Suggested title'),
}));
vi.mock('../note-artifacts/repository.js', () => ({ createNoteArtifact: vi.fn(async (doc: unknown) => doc) }));
vi.mock('./repository.js', () => ({
listNotes: listNotesMock,
getNote: getNoteMock,
createNote: createNoteMock,
updateNote: updateNoteMock,
}));
vi.mock('../note-versions/repository.js', () => ({
appendNoteVersion: vi.fn(async () => ({})),
listNoteVersions: vi.fn(async () => ({ items: [], total: 0 })),
}));
vi.mock('../note-shares/repository.js', () => ({
createNoteShare: vi.fn(async () => ({})),
}));
describe('noteRoutes', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('registers route handlers', async () => {
const app = {
get: vi.fn(),
post: vi.fn(),
patch: vi.fn(),
delete: vi.fn(),
};
await noteRoutes(app as never);
expect(app.get).toHaveBeenCalledTimes(5);
expect(app.post).toHaveBeenCalledTimes(9);
expect(app.patch).toHaveBeenCalledTimes(1);
expect(app.delete).toHaveBeenCalledTimes(1);
});
});