test: add admin routes tests
Made-with: Cursor
This commit is contained in:
140
tests/integration/admin.routes.test.ts
Normal file
140
tests/integration/admin.routes.test.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { buildAdminTestApp } from '../helpers/build-admin-test-app.js';
|
||||
import {
|
||||
createMockDb,
|
||||
selectChainOrderedLimitOffset,
|
||||
selectChainWhere,
|
||||
updateChainReturning,
|
||||
insertChain,
|
||||
} from '../test-utils.js';
|
||||
|
||||
describe('Admin routes integration', () => {
|
||||
let app: Awaited<ReturnType<typeof buildAdminTestApp>>;
|
||||
let mockDb: ReturnType<typeof createMockDb>;
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks();
|
||||
mockDb = createMockDb();
|
||||
app = await buildAdminTestApp(mockDb as never);
|
||||
});
|
||||
|
||||
describe('GET /admin/questions/pending', () => {
|
||||
it('returns pending questions list', async () => {
|
||||
const pendingQuestions = [
|
||||
{
|
||||
id: 'q-1',
|
||||
stack: 'js',
|
||||
level: 'beginner',
|
||||
type: 'single_choice',
|
||||
questionText: 'Test question?',
|
||||
options: [{ key: 'a', text: 'A' }],
|
||||
correctAnswer: 'a',
|
||||
explanation: 'Exp',
|
||||
source: 'manual',
|
||||
createdAt: new Date(),
|
||||
},
|
||||
];
|
||||
(mockDb.select as ReturnType<typeof vi.fn>)
|
||||
.mockReturnValueOnce(selectChainOrderedLimitOffset(pendingQuestions))
|
||||
.mockReturnValueOnce(selectChainWhere([{ count: 1 }]));
|
||||
|
||||
const res = await app.inject({
|
||||
method: 'GET',
|
||||
url: '/admin/questions/pending',
|
||||
headers: { authorization: 'Bearer any-token' },
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
const body = JSON.parse(res.body);
|
||||
expect(body.questions).toHaveLength(1);
|
||||
expect(body.questions[0].questionText).toBe('Test question?');
|
||||
expect(body.total).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /admin/questions/:questionId/approve', () => {
|
||||
it('returns 204 on success', async () => {
|
||||
(mockDb.update as ReturnType<typeof vi.fn>).mockReturnValueOnce(
|
||||
updateChainReturning([{ id: 'q-1' }])
|
||||
);
|
||||
(mockDb.insert as ReturnType<typeof vi.fn>).mockReturnValueOnce(
|
||||
insertChain([])
|
||||
);
|
||||
|
||||
const res = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/admin/questions/11111111-1111-1111-1111-111111111111/approve',
|
||||
headers: { authorization: 'Bearer any-token' },
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(204);
|
||||
});
|
||||
|
||||
it('returns 404 when question not found', async () => {
|
||||
(mockDb.update as ReturnType<typeof vi.fn>).mockReturnValueOnce(
|
||||
updateChainReturning([])
|
||||
);
|
||||
|
||||
const res = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/admin/questions/11111111-1111-1111-1111-111111111111/approve',
|
||||
headers: { authorization: 'Bearer any-token' },
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /admin/questions/:questionId/reject', () => {
|
||||
it('returns 204 on success', async () => {
|
||||
(mockDb.update as ReturnType<typeof vi.fn>).mockReturnValueOnce(
|
||||
updateChainReturning([{ id: 'q-1' }])
|
||||
);
|
||||
(mockDb.insert as ReturnType<typeof vi.fn>).mockReturnValueOnce(
|
||||
insertChain([])
|
||||
);
|
||||
|
||||
const res = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/admin/questions/11111111-1111-1111-1111-111111111111/reject',
|
||||
headers: { authorization: 'Bearer any-token' },
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(204);
|
||||
});
|
||||
});
|
||||
|
||||
describe('PATCH /admin/questions/:questionId', () => {
|
||||
it('returns updated question', async () => {
|
||||
const updatedQuestion = {
|
||||
id: 'q-1',
|
||||
stack: 'js',
|
||||
level: 'intermediate',
|
||||
type: 'single_choice',
|
||||
questionText: 'Updated?',
|
||||
options: [{ key: 'a', text: 'A' }],
|
||||
correctAnswer: 'a',
|
||||
explanation: 'Updated exp',
|
||||
source: 'manual',
|
||||
createdAt: new Date(),
|
||||
};
|
||||
(mockDb.update as ReturnType<typeof vi.fn>).mockReturnValueOnce(
|
||||
updateChainReturning([updatedQuestion])
|
||||
);
|
||||
(mockDb.insert as ReturnType<typeof vi.fn>).mockReturnValueOnce(
|
||||
insertChain([])
|
||||
);
|
||||
|
||||
const res = await app.inject({
|
||||
method: 'PATCH',
|
||||
url: '/admin/questions/11111111-1111-1111-1111-111111111111',
|
||||
headers: { authorization: 'Bearer any-token' },
|
||||
payload: { questionText: 'Updated?', explanation: 'Updated exp' },
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
const body = JSON.parse(res.body);
|
||||
expect(body.questionText).toBe('Updated?');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user