learning_ai_notes/backend/src/server.test.ts
saravanakumardb1 bdbf387f88 feat(backend): add batch review endpoint + saved-views module
- note-agent-actions: added POST /batch-review for bulk approve/reject (up to 50 items)
- note-agent-actions: PATCH now auto-sets reviewedBy/reviewedAt on approve/reject
- saved-views: new module with full CRUD (types, repository, routes)
  - Cosmos container: saved_views, partition: /userId
  - Supports scope filtering (workspace, search, review)
- Registered saved-views routes in server.ts (7 modules total)
- Updated route count tests

Verification: backend typecheck + 18/18 tests pass.
2026-03-10 19:33:33 -07:00

63 lines
2.4 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
const createServiceAppMock = vi.fn();
const registerOptionalJwtContextMock = vi.fn(async () => undefined);
const startServiceMock = vi.fn(async () => undefined);
const initCosmosIfNeededMock = vi.fn(async () => undefined);
const initDatastoreMock = vi.fn(() => undefined);
const appMock = {
register: vi.fn(async () => undefined),
};
vi.mock('@bytelyst/fastify-core', () => ({
createServiceApp: createServiceAppMock,
registerOptionalJwtContext: registerOptionalJwtContextMock,
startService: startServiceMock,
}));
vi.mock('jose', () => ({
jwtVerify: vi.fn(async () => ({ payload: { sub: 'user_1', productId: 'notelett' } })),
}));
vi.mock('./modules/note-agent-actions/routes.js', () => ({ noteAgentActionRoutes: vi.fn() }));
vi.mock('./modules/note-artifacts/routes.js', () => ({ noteArtifactRoutes: vi.fn() }));
vi.mock('./modules/notes/routes.js', () => ({ noteRoutes: vi.fn() }));
vi.mock('./modules/note-relationships/routes.js', () => ({ noteRelationshipRoutes: vi.fn() }));
vi.mock('./modules/note-tasks/routes.js', () => ({ noteTaskRoutes: vi.fn() }));
vi.mock('./modules/saved-views/routes.js', () => ({ savedViewRoutes: vi.fn() }));
vi.mock('./modules/workspaces/routes.js', () => ({ workspaceRoutes: vi.fn() }));
vi.mock('./lib/cosmos-init.js', () => ({ initCosmosIfNeeded: initCosmosIfNeededMock }));
vi.mock('./lib/datastore.js', () => ({ initDatastore: initDatastoreMock }));
vi.mock('./lib/config.js', () => ({
config: {
SERVICE_NAME: 'notelett-backend',
CORS_ORIGIN: '*',
PORT: 4016,
HOST: '0.0.0.0',
JWT_SECRET: 'test-secret',
},
}));
vi.mock('./lib/product-config.js', () => ({ DISPLAY_NAME: 'NoteLett' }));
describe('server bootstrap', () => {
beforeEach(() => {
vi.resetModules();
vi.clearAllMocks();
createServiceAppMock.mockResolvedValue(appMock);
appMock.register.mockReset();
appMock.register.mockResolvedValue(undefined);
});
it('initializes app, routes, and starts service', async () => {
await import('./server.js');
expect(initCosmosIfNeededMock).toHaveBeenCalledOnce();
expect(initDatastoreMock).toHaveBeenCalledOnce();
expect(createServiceAppMock).toHaveBeenCalledOnce();
expect(registerOptionalJwtContextMock).toHaveBeenCalledOnce();
expect(appMock.register).toHaveBeenCalledTimes(7);
expect(startServiceMock).toHaveBeenCalledWith(appMock, { port: 4016, host: '0.0.0.0' });
});
});