Files
zen-kanji/server/tests/services/controllers.test.js
Rene Kievits 6438660b03 init
2025-12-18 01:30:52 +01:00

143 lines
5.2 KiB
JavaScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import * as AuthController from '../../src/controllers/auth.controller.js';
import * as ReviewController from '../../src/controllers/review.controller.js';
import * as SyncController from '../../src/controllers/sync.controller.js';
import * as CollectionController from '../../src/controllers/collection.controller.js';
import * as AuthService from '../../src/services/auth.service.js';
import * as ReviewService from '../../src/services/review.service.js';
import * as SyncService from '../../src/services/sync.service.js';
import * as StatsService from '../../src/services/stats.service.js';
import { StudyItem } from '../../src/models/StudyItem.js';
vi.mock('../../src/services/auth.service.js');
vi.mock('../../src/services/review.service.js');
vi.mock('../../src/services/sync.service.js');
vi.mock('../../src/services/stats.service.js');
vi.mock('../../src/models/StudyItem.js');
const mockReq = (body = {}, user = {}, query = {}) => ({ body, user, query });
const mockReply = () => {
const res = {};
res.code = vi.fn().mockReturnValue(res);
res.send = vi.fn().mockReturnValue(res);
res.jwtSign = vi.fn().mockResolvedValue('token');
return res;
};
describe('Controllers', () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe('Auth Controller', () => {
it('login should fail without apiKey', async () => {
const reply = mockReply();
await AuthController.login(mockReq({}), reply);
expect(reply.code).toHaveBeenCalledWith(400);
});
it('login should succeed', async () => {
const reply = mockReply();
AuthService.loginUser.mockResolvedValue({ _id: 1, tokenVersion: 1 });
await AuthController.login(mockReq({ apiKey: 'key' }), reply);
expect(reply.jwtSign).toHaveBeenCalled();
expect(reply.code).not.toHaveBeenCalledWith(401);
});
it('login should catch errors', async () => {
const reply = mockReply();
AuthService.loginUser.mockRejectedValue(new Error('fail'));
await AuthController.login(mockReq({ apiKey: 'k' }), reply);
expect(reply.code).toHaveBeenCalledWith(401);
});
it('logout should succeed', async () => {
const reply = mockReply();
await AuthController.logout(mockReq({}, { _id: 1 }), reply);
expect(AuthService.logoutUser).toHaveBeenCalled();
});
});
describe('Review Controller', () => {
it('submitReview should succeed', async () => {
const reply = mockReply();
ReviewService.processReview.mockResolvedValue({});
await ReviewController.submitReview(mockReq({}), reply);
expect(reply.send).toHaveBeenCalled();
});
it('submitReview should handle error', async () => {
const reply = mockReply();
ReviewService.processReview.mockRejectedValue(new Error('err'));
await ReviewController.submitReview(mockReq({}), reply);
expect(reply.code).toHaveBeenCalledWith(404);
});
});
describe('Sync Controller', () => {
it('sync should succeed', async () => {
const reply = mockReply();
SyncService.syncWithWaniKani.mockResolvedValue({});
await SyncController.sync(mockReq({}, {}), reply);
expect(reply.send).toHaveBeenCalled();
});
it('sync should handle error', async () => {
const reply = mockReply();
SyncService.syncWithWaniKani.mockRejectedValue(new Error('err'));
await SyncController.sync(mockReq({}, {}), reply);
expect(reply.code).toHaveBeenCalledWith(500);
});
});
describe('Collection Controller', () => {
it('getCollection should return items', async () => {
const reply = mockReply();
StudyItem.find.mockResolvedValue([]);
await CollectionController.getCollection(mockReq({}, { _id: 1 }), reply);
expect(reply.send).toHaveBeenCalledWith([]);
});
it('getQueue should call service with default limit', async () => {
const reply = mockReply();
ReviewService.getQueue.mockResolvedValue([]);
await CollectionController.getQueue(mockReq({}, {}, {}), reply);
expect(ReviewService.getQueue).toHaveBeenCalledWith(expect.anything(), 20, undefined);
});
it('getQueue should call service with provided limit', async () => {
const reply = mockReply();
ReviewService.getQueue.mockResolvedValue([]);
await CollectionController.getQueue(mockReq({}, {}, { limit: '50' }), reply);
expect(ReviewService.getQueue).toHaveBeenCalledWith(expect.anything(), 50, undefined);
});
it('getStats should call service', async () => {
const reply = mockReply();
StatsService.getUserStats.mockResolvedValue({});
await CollectionController.getStats(mockReq({}, {}), reply);
expect(StatsService.getUserStats).toHaveBeenCalled();
});
it('updateSettings should initialize settings if missing', async () => {
const reply = mockReply();
const save = vi.fn();
const user = { save };
await CollectionController.updateSettings(mockReq({ batchSize: 50 }, user), reply);
expect(user.settings).toBeDefined();
expect(user.settings.batchSize).toBe(50);
expect(save).toHaveBeenCalled();
});
it('updateSettings should update drawingAccuracy', async () => {
const reply = mockReply();
const save = vi.fn();
const user = { settings: {}, save };
await CollectionController.updateSettings(mockReq({ drawingAccuracy: 5 }, user), reply);
expect(user.settings.drawingAccuracy).toBe(5);
expect(save).toHaveBeenCalled();
});
});
});