From 7ad944c77d24a6744e5cbd93a9b76a29661304aa Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Mon, 24 Mar 2025 15:20:51 +0100 Subject: [PATCH] feat: test service student --- backend/src/controllers/students.ts | 4 +- backend/src/interfaces/student.ts | 8 +-- backend/src/services/students.ts | 9 ++- backend/tests/services/students.test.ts | 96 +++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 14 deletions(-) create mode 100644 backend/tests/services/students.test.ts diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index 8dbf3da9..b472358f 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -1,7 +1,7 @@ import { Request, Response } from 'express'; import { createStudent, - deleteStudent, getAllStudentIds, + deleteStudent, getAllStudents, getStudent, getStudentAssignments, @@ -16,7 +16,7 @@ import { StudentDTO } from '../interfaces/student.js'; export async function getAllStudentsHandler(req: Request, res: Response): Promise { const full = req.query.full === 'true'; - const students: StudentDTO[] | string[] = full ? await getAllStudents() : await getAllStudentIds(); + const students: StudentDTO[] | string[] = await getAllStudents(full); if (!students) { res.status(404).json({ error: `Students not found.` }); diff --git a/backend/src/interfaces/student.ts b/backend/src/interfaces/student.ts index 079b355b..82a06a1e 100644 --- a/backend/src/interfaces/student.ts +++ b/backend/src/interfaces/student.ts @@ -1,16 +1,10 @@ import { Student } from '../entities/users/student.entity.js'; export interface StudentDTO { - id: string; + id?: string; username: string; firstName: string; lastName: string; - endpoints?: { - classes: string; - questions: string; - invitations: string; - groups: string; - }; } export function mapToStudentDTO(student: Student): StudentDTO { diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index 63339874..88242cdc 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -13,14 +13,13 @@ import { mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; import { getAllAssignments } from './assignments.js'; import {mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId} from "../interfaces/question"; -export async function getAllStudents(): Promise { +export async function getAllStudents(full: boolean): Promise { const studentRepository = getStudentRepository(); const users = await studentRepository.findAll(); - return users.map(mapToStudentDTO); -} -export async function getAllStudentIds(): Promise { - const users = await getAllStudents(); + if (full) + return users.map(mapToStudentDTO); + return users.map((user) => user.username); } diff --git a/backend/tests/services/students.test.ts b/backend/tests/services/students.test.ts new file mode 100644 index 00000000..cf6870a3 --- /dev/null +++ b/backend/tests/services/students.test.ts @@ -0,0 +1,96 @@ +import {describe, it, expect, vi, beforeEach, beforeAll} from 'vitest'; +import {Student} from "../../src/entities/users/student.entity"; +import {StudentDTO} from "../../src/interfaces/student"; +import {setupTestApp} from "../setup-tests"; +import {createStudent, deleteStudent, getAllStudents, getStudent} from "../../src/services/students"; + +const mockStudentRepo = { + findAll: vi.fn(), + findByUsername: vi.fn(), + create: vi.fn(), + save: vi.fn(), + deleteByUsername: vi.fn(), +}; + +describe('StudentService', () => { + + beforeAll(async () => { + await setupTestApp(); + }); + + beforeEach(() => { + vi.clearAllMocks(); + vi.mock('../../src/data/repositories', () => ({ + getStudentRepository: () => mockStudentRepo, + })); + }); + + it('Student list full', async () => { + mockStudentRepo.findAll.mockResolvedValue([ + new Student('DireStraits', 'Mark', 'Knopfler'), + ]); + + const result = await getAllStudents(true); + + expect(mockStudentRepo.findAll).toHaveBeenCalled(); + expect(result[0]).toHaveProperty('username', 'DireStraits'); + }); + + it('Student list ids', async () => { + mockStudentRepo.findAll.mockResolvedValue([ + new Student('Tool', 'Maynard', 'Keenan'), + ]); + + const result = await getAllStudents(false); + + expect(mockStudentRepo.findAll).toHaveBeenCalled(); + expect(result).toContain('Tool'); + expect(typeof result[0]).toBe('string'); + }); + + it('Student not found', async () => { + mockStudentRepo.findByUsername.mockResolvedValue(null); + + const result = await getStudent('doesnotexist'); + expect(result).toBeNull(); + }); + + it('Create + get student', async () => { + const dto: StudentDTO = { + username: 'SmashingPumpkins', + firstName: 'Billy', + lastName: 'Corgan', + }; + + const studentEntity = new Student(dto.username, dto.firstName, dto.lastName); + + mockStudentRepo.create.mockReturnValue(studentEntity); + mockStudentRepo.save.mockResolvedValue(undefined); + mockStudentRepo.findByUsername.mockResolvedValue(studentEntity); + + const created = await createStudent(dto); + const found = await getStudent(dto.username); + + expect(created).not.toBeNull(); + expect(found).not.toBeNull(); + expect(found?.username).toBe(dto.username); + }); + + it('Delete non existing student', async () => { + mockStudentRepo.findByUsername.mockResolvedValue(null); + + const result = await deleteStudent('ghost'); + expect(result).toBeNull(); + }); + + it('Delete student', async () => { + const student = new Student('TheDoors', 'Jim', 'Morisson'); + mockStudentRepo.findByUsername.mockResolvedValue(student); + mockStudentRepo.deleteByUsername.mockResolvedValue(undefined); + + const result = await deleteStudent('TheDoors'); + + expect(mockStudentRepo.deleteByUsername).toHaveBeenCalledWith('TheDoors'); + expect(result?.username).toBe('TheDoors'); + }); +});