fix: merge + lint fixes

This commit is contained in:
Gabriellvl 2025-04-01 18:38:36 +02:00
parent 7f189188e8
commit b556516359
12 changed files with 58 additions and 62 deletions

View file

@ -33,7 +33,7 @@ export async function getStudentHandler(req: Request, res: Response): Promise<vo
res.json({ student }); res.json({ student });
} }
export async function createStudentHandler(req: Request, res: Response) { export async function createStudentHandler(req: Request, res: Response): Promise<void> {
const username = req.body.username; const username = req.body.username;
const firstName = req.body.firstName; const firstName = req.body.firstName;
const lastName = req.body.lastName; const lastName = req.body.lastName;
@ -45,7 +45,7 @@ export async function createStudentHandler(req: Request, res: Response) {
res.json({ student }); res.json({ student });
} }
export async function deleteStudentHandler(req: Request, res: Response) { export async function deleteStudentHandler(req: Request, res: Response): Promise<void> {
const username = req.params.username; const username = req.params.username;
requireFields({ username }); requireFields({ username });
@ -125,7 +125,7 @@ export async function getStudentRequestsHandler(req: Request, res: Response): Pr
} }
export async function getStudentRequestHandler(req: Request, res: Response): Promise<void> { export async function getStudentRequestHandler(req: Request, res: Response): Promise<void> {
const username = req.params.username as string; const username = req.params.username;
const classId = req.params.classId; const classId = req.params.classId;
requireFields({ username, classId }); requireFields({ username, classId });
@ -133,8 +133,8 @@ export async function getStudentRequestHandler(req: Request, res: Response): Pro
res.json({ request }); res.json({ request });
} }
export async function deleteClassJoinRequestHandler(req: Request, res: Response) { export async function deleteClassJoinRequestHandler(req: Request, res: Response): Promise<void> {
const username = req.params.username as string; const username = req.params.username;
const classId = req.params.classId; const classId = req.params.classId;
requireFields({ username, classId }); requireFields({ username, classId });

View file

@ -33,7 +33,7 @@ export async function getTeacherHandler(req: Request, res: Response): Promise<vo
res.json({ teacher }); res.json({ teacher });
} }
export async function createTeacherHandler(req: Request, res: Response) { export async function createTeacherHandler(req: Request, res: Response): Promise<void> {
const username = req.body.username; const username = req.body.username;
const firstName = req.body.firstName; const firstName = req.body.firstName;
const lastName = req.body.lastName; const lastName = req.body.lastName;
@ -45,7 +45,7 @@ export async function createTeacherHandler(req: Request, res: Response) {
res.json({ teacher }); res.json({ teacher });
} }
export async function deleteTeacherHandler(req: Request, res: Response) { export async function deleteTeacherHandler(req: Request, res: Response): Promise<void> {
const username = req.params.username; const username = req.params.username;
requireFields({ username }); requireFields({ username });
@ -54,7 +54,7 @@ export async function deleteTeacherHandler(req: Request, res: Response) {
} }
export async function getTeacherClassHandler(req: Request, res: Response): Promise<void> { export async function getTeacherClassHandler(req: Request, res: Response): Promise<void> {
const username = req.params.username as string; const username = req.params.username;
const full = req.query.full === 'true'; const full = req.query.full === 'true';
requireFields({ username }); requireFields({ username });
@ -64,7 +64,7 @@ export async function getTeacherClassHandler(req: Request, res: Response): Promi
} }
export async function getTeacherStudentHandler(req: Request, res: Response): Promise<void> { export async function getTeacherStudentHandler(req: Request, res: Response): Promise<void> {
const username = req.params.username as string; const username = req.params.username;
const full = req.query.full === 'true'; const full = req.query.full === 'true';
requireFields({ username }); requireFields({ username });
@ -74,7 +74,7 @@ export async function getTeacherStudentHandler(req: Request, res: Response): Pro
} }
export async function getTeacherQuestionHandler(req: Request, res: Response): Promise<void> { export async function getTeacherQuestionHandler(req: Request, res: Response): Promise<void> {
const username = req.params.username as string; const username = req.params.username;
const full = req.query.full === 'true'; const full = req.query.full === 'true';
requireFields({ username }); requireFields({ username });
@ -83,7 +83,7 @@ export async function getTeacherQuestionHandler(req: Request, res: Response): Pr
res.json({ questions }); res.json({ questions });
} }
export async function getStudentJoinRequestHandler(req: Request, res: Response) { export async function getStudentJoinRequestHandler(req: Request, res: Response): Promise<void> {
const username = req.query.username as string; const username = req.query.username as string;
const classId = req.params.classId; const classId = req.params.classId;
requireFields({ username, classId }); requireFields({ username, classId });
@ -92,7 +92,7 @@ export async function getStudentJoinRequestHandler(req: Request, res: Response)
res.json({ joinRequests }); res.json({ joinRequests });
} }
export async function updateStudentJoinRequestHandler(req: Request, res: Response) { export async function updateStudentJoinRequestHandler(req: Request, res: Response): Promise<void> {
const studentUsername = req.query.studentUsername as string; const studentUsername = req.query.studentUsername as string;
const classId = req.params.classId; const classId = req.params.classId;
const accepted = req.body.accepted !== 'false'; // Default = true const accepted = req.body.accepted !== 'false'; // Default = true

View file

@ -55,7 +55,7 @@ export class QuestionRepository extends DwengoEntityRepository<Question> {
}); });
} }
public findAllByAuthor(author: Student): Promise<Question[]> { public async findAllByAuthor(author: Student): Promise<Question[]> {
return this.findAll({ return this.findAll({
where: { author }, where: { author },
orderBy: { timestamp: 'DESC' }, // New to old orderBy: { timestamp: 'DESC' }, // New to old

View file

@ -1,5 +1,5 @@
import { mapToUserDTO, UserDTO } from './user.js'; import { mapToUserDTO, UserDTO } from './user.js';
import { mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId } from './question.js'; import {mapToQuestionDTO, mapToQuestionDTOId, QuestionDTO, QuestionId} from './question.js';
import { Answer } from '../entities/questions/answer.entity.js'; import { Answer } from '../entities/questions/answer.entity.js';
export interface AnswerDTO { export interface AnswerDTO {
@ -29,10 +29,10 @@ export interface AnswerId {
sequenceNumber: number; sequenceNumber: number;
} }
export function mapToAnswerId(answer: AnswerDTO): AnswerId { export function mapToAnswerDTOId(answer: Answer): AnswerId {
return { return {
author: answer.author.username, author: answer.author.username,
toQuestion: mapToQuestionId(answer.toQuestion), toQuestion: mapToQuestionDTOId(answer.toQuestion),
sequenceNumber: answer.sequenceNumber, sequenceNumber: answer.sequenceNumber!,
}; };
} }

View file

@ -18,7 +18,7 @@ export function mapToStudentRequestDTO(request: ClassJoinRequest): StudentReques
}; };
} }
export function mapToStudentRequest(student: Student, cls: Class) { export function mapToStudentRequest(student: Student, cls: Class): ClassJoinRequest {
return getClassJoinRequestRepository().create({ return getClassJoinRequestRepository().create({
requester: student, requester: student,
class: cls, class: cls,

View file

@ -1,8 +1,8 @@
import { getAnswerRepository, getQuestionRepository } from '../data/repositories.js'; import { getAnswerRepository, getQuestionRepository } from '../data/repositories.js';
import { mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId } from '../interfaces/question.js'; import {mapToQuestionDTO, mapToQuestionDTOId, QuestionDTO, QuestionId} from '../interfaces/question.js';
import { Question } from '../entities/questions/question.entity.js'; import { Question } from '../entities/questions/question.entity.js';
import { Answer } from '../entities/questions/answer.entity.js'; import { Answer } from '../entities/questions/answer.entity.js';
import { AnswerDTO, AnswerId, mapToAnswerDTO, mapToAnswerId } from '../interfaces/answer.js'; import { AnswerDTO, AnswerId, mapToAnswerDTO, mapToAnswerDTOId } from '../interfaces/answer.js';
import { QuestionRepository } from '../data/questions/question-repository.js'; import { QuestionRepository } from '../data/questions/question-repository.js';
import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js';
import { mapToStudent } from '../interfaces/student.js'; import { mapToStudent } from '../interfaces/student.js';
@ -15,13 +15,11 @@ export async function getAllQuestions(id: LearningObjectIdentifier, full: boolea
return []; return [];
} }
const questionsDTO: QuestionDTO[] = questions.map(mapToQuestionDTO);
if (full) { if (full) {
return questionsDTO; return questions.map(mapToQuestionDTO);
} }
return questionsDTO.map(mapToQuestionId); return questions.map(mapToQuestionDTOId);
} }
async function fetchQuestion(questionId: QuestionId): Promise<Question | null> { async function fetchQuestion(questionId: QuestionId): Promise<Question | null> {
@ -59,13 +57,11 @@ export async function getAnswersByQuestion(questionId: QuestionId, full: boolean
return []; return [];
} }
const answersDTO = answers.map(mapToAnswerDTO);
if (full) { if (full) {
return answersDTO; return answers.map(mapToAnswerDTO);
} }
return answersDTO.map(mapToAnswerId); return answers.map(mapToAnswerDTOId);
} }
export async function createQuestion(questionDTO: QuestionDTO): Promise<QuestionDTO | null> { export async function createQuestion(questionDTO: QuestionDTO): Promise<QuestionDTO | null> {

View file

@ -12,8 +12,13 @@ import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js
import { mapToStudent, mapToStudentDTO, StudentDTO } from '../interfaces/student.js'; import { mapToStudent, mapToStudentDTO, StudentDTO } from '../interfaces/student.js';
import { mapToSubmissionDTO, mapToSubmissionDTOId, SubmissionDTO, SubmissionDTOId } from '../interfaces/submission.js'; import { mapToSubmissionDTO, mapToSubmissionDTOId, SubmissionDTO, SubmissionDTOId } from '../interfaces/submission.js';
import { getAllAssignments } from './assignments.js'; import { getAllAssignments } from './assignments.js';
import { mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId } from '../interfaces/question.js'; import {
import { mapToStudentRequest, mapToStudentRequestDTO } from '../interfaces/student-request.js'; mapToQuestionDTO,
mapToQuestionDTOId,
QuestionDTO,
QuestionId
} from '../interfaces/question.js';
import {mapToStudentRequest, mapToStudentRequestDTO, StudentRequestDTO} from '../interfaces/student-request.js';
import { Student } from '../entities/users/student.entity.js'; import { Student } from '../entities/users/student.entity.js';
import { NotFoundException } from '../exceptions/not-found-exception.js'; import { NotFoundException } from '../exceptions/not-found-exception.js';
import { fetchClass } from './classes.js'; import { fetchClass } from './classes.js';
@ -116,16 +121,14 @@ export async function getStudentQuestions(username: string, full: boolean): Prom
const questionRepository = getQuestionRepository(); const questionRepository = getQuestionRepository();
const questions = await questionRepository.findAllByAuthor(student); const questions = await questionRepository.findAllByAuthor(student);
const questionsDTO = questions.map(mapToQuestionDTO);
if (full) { if (full) {
return questionsDTO; return questions.map(mapToQuestionDTO);
} }
return questionsDTO.map(mapToQuestionId); return questions.map(mapToQuestionDTOId);
} }
export async function createClassJoinRequest(username: string, classId: string) { export async function createClassJoinRequest(username: string, classId: string): Promise<StudentRequestDTO> {
const requestRepo = getClassJoinRequestRepository(); const requestRepo = getClassJoinRequestRepository();
const student = await fetchStudent(username); // Throws error if student not found const student = await fetchStudent(username); // Throws error if student not found
@ -136,7 +139,7 @@ export async function createClassJoinRequest(username: string, classId: string)
return mapToStudentRequestDTO(request); return mapToStudentRequestDTO(request);
} }
export async function getJoinRequestsByStudent(username: string) { export async function getJoinRequestsByStudent(username: string): Promise<StudentRequestDTO[]> {
const requestRepo = getClassJoinRequestRepository(); const requestRepo = getClassJoinRequestRepository();
const student = await fetchStudent(username); const student = await fetchStudent(username);
@ -145,7 +148,7 @@ export async function getJoinRequestsByStudent(username: string) {
return requests.map(mapToStudentRequestDTO); return requests.map(mapToStudentRequestDTO);
} }
export async function getJoinRequestByStudentClass(username: string, classId: string){ export async function getJoinRequestByStudentClass(username: string, classId: string): Promise<StudentRequestDTO>{
const requestRepo = getClassJoinRequestRepository(); const requestRepo = getClassJoinRequestRepository();
const student = await fetchStudent(username); const student = await fetchStudent(username);
@ -159,7 +162,7 @@ export async function getJoinRequestByStudentClass(username: string, classId: st
return mapToStudentRequestDTO(request); return mapToStudentRequestDTO(request);
} }
export async function deleteClassJoinRequest(username: string, classId: string) { export async function deleteClassJoinRequest(username: string, classId: string): Promise<StudentRequestDTO> {
const requestRepo = getClassJoinRequestRepository(); const requestRepo = getClassJoinRequestRepository();
const student = await fetchStudent(username); const student = await fetchStudent(username);

View file

@ -90,7 +90,7 @@ export async function getClassesByTeacher(username: string, full: boolean): Prom
return classes.map((cls) => cls.id); return classes.map((cls) => cls.id);
} }
export async function getStudentsByTeacher(username: string, full: boolean) { export async function getStudentsByTeacher(username: string, full: boolean): Promise<StudentDTO[] | string[]> {
const classes: ClassDTO[] = await fetchClassesByTeacher(username); const classes: ClassDTO[] = await fetchClassesByTeacher(username);
if (!classes || classes.length === 0) { if (!classes || classes.length === 0) {
@ -141,7 +141,7 @@ export async function getJoinRequestsByClass(classId: string): Promise<StudentRe
return requests.map(mapToStudentRequestDTO); return requests.map(mapToStudentRequestDTO);
} }
export async function updateClassJoinRequestStatus(studentUsername: string, classId: string, accepted: boolean = true): Promise<StudentRequestDTO> { export async function updateClassJoinRequestStatus(studentUsername: string, classId: string, accepted = true): Promise<StudentRequestDTO> {
const requestRepo: ClassJoinRequestRepository = getClassJoinRequestRepository(); const requestRepo: ClassJoinRequestRepository = getClassJoinRequestRepository();
const classRepo: ClassRepository = getClassRepository(); const classRepo: ClassRepository = getClassRepository();

View file

@ -49,14 +49,14 @@ describe('Student controllers', () => {
it('Student not found', async () => { it('Student not found', async () => {
req = { params: { username: 'doesnotexist' } }; req = { params: { username: 'doesnotexist' } };
await expect(() => getStudentHandler(req as Request, res as Response)) await expect(async () => getStudentHandler(req as Request, res as Response))
.rejects.toThrow(NotFoundException); .rejects.toThrow(NotFoundException);
}); });
it('No username', async () => { it('No username', async () => {
req = { params: {} }; req = { params: {} };
await expect(() => getStudentHandler(req as Request, res as Response)) await expect(async () => getStudentHandler(req as Request, res as Response))
.rejects.toThrowError(BadRequestException); .rejects.toThrowError(BadRequestException);
}); });
@ -75,8 +75,6 @@ describe('Student controllers', () => {
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ student: expect.objectContaining(student) })); expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ student: expect.objectContaining(student) }));
console.log(jsonMock)
req = { params: { username: 'coolstudent' } }; req = { params: { username: 'coolstudent' } };
await deleteStudentHandler(req as Request, res as Response); await deleteStudentHandler(req as Request, res as Response);
@ -93,14 +91,14 @@ describe('Student controllers', () => {
}, },
}; };
await expect(() => createStudentHandler(req as Request, res as Response)) await expect(async () => createStudentHandler(req as Request, res as Response))
.rejects.toThrowError(EntityAlreadyExistsException); .rejects.toThrowError(EntityAlreadyExistsException);
}); });
it('Create student no body', async () => { it('Create student no body', async () => {
req = { body: {} }; req = { body: {} };
await expect(() => createStudentHandler(req as Request, res as Response)) await expect(async () => createStudentHandler(req as Request, res as Response))
.rejects.toThrowError(BadRequestException); .rejects.toThrowError(BadRequestException);
}); });
@ -168,7 +166,7 @@ describe('Student controllers', () => {
it('Deleting non-existent student', async () => { it('Deleting non-existent student', async () => {
req = { params: { username: 'doesnotexist' } }; req = { params: { username: 'doesnotexist' } };
await expect(() => deleteStudentHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException); await expect(async () => deleteStudentHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException);
}); });
it('Get join requests by student', async () => { it('Get join requests by student', async () => {
@ -220,7 +218,7 @@ describe('Student controllers', () => {
body: { classId: 'id02' }, body: { classId: 'id02' },
}; };
await expect(() => createStudentRequestHandler(req as Request, res as Response)) await expect(async () => createStudentRequestHandler(req as Request, res as Response))
.rejects.toThrow(ConflictException); .rejects.toThrow(ConflictException);
}); });
@ -233,7 +231,7 @@ describe('Student controllers', () => {
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ request: expect.anything() })); expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ request: expect.anything() }));
await expect(() => deleteClassJoinRequestHandler(req as Request, res as Response)) await expect(async () => deleteClassJoinRequestHandler(req as Request, res as Response))
.rejects.toThrow(NotFoundException); .rejects.toThrow(NotFoundException);
}); });
}); });

View file

@ -9,7 +9,6 @@ import {
getStudentJoinRequestHandler, getStudentJoinRequestHandler,
getTeacherClassHandler, getTeacherClassHandler,
getTeacherHandler, getTeacherHandler,
getTeacherQuestionHandler,
getTeacherStudentHandler, getTeacherStudentHandler,
updateStudentJoinRequestHandler, updateStudentJoinRequestHandler,
} from '../../src/controllers/teachers.js'; } from '../../src/controllers/teachers.js';
@ -46,14 +45,14 @@ describe('Teacher controllers', () => {
it('Teacher not found', async () => { it('Teacher not found', async () => {
req = { params: { username: 'doesnotexist' } }; req = { params: { username: 'doesnotexist' } };
await expect(() => getTeacherHandler(req as Request, res as Response)) await expect(async () => getTeacherHandler(req as Request, res as Response))
.rejects.toThrow(NotFoundException); .rejects.toThrow(NotFoundException);
}); });
it('No username', async () => { it('No username', async () => {
req = { params: {} }; req = { params: {} };
await expect(() => getTeacherHandler(req as Request, res as Response)) await expect(async () => getTeacherHandler(req as Request, res as Response))
.rejects.toThrowError(BadRequestException); .rejects.toThrowError(BadRequestException);
}); });
@ -88,14 +87,14 @@ describe('Teacher controllers', () => {
}, },
}; };
await expect(() => createTeacherHandler(req as Request, res as Response)) await expect(async () => createTeacherHandler(req as Request, res as Response))
.rejects.toThrowError(EntityAlreadyExistsException); .rejects.toThrowError(EntityAlreadyExistsException);
}); });
it('Create teacher no body', async () => { it('Create teacher no body', async () => {
req = { body: {} }; req = { body: {} };
await expect(() => createTeacherHandler(req as Request, res as Response)) await expect(async () => createTeacherHandler(req as Request, res as Response))
.rejects.toThrowError(BadRequestException); .rejects.toThrowError(BadRequestException);
}); });
@ -117,7 +116,7 @@ describe('Teacher controllers', () => {
it('Deleting non-existent student', async () => { it('Deleting non-existent student', async () => {
req = { params: { username: 'doesnotexist' } }; req = { params: { username: 'doesnotexist' } };
await expect(() => deleteTeacherHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException); await expect(async () => deleteTeacherHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException);
}); });
it('Get teacher classes', async () => { it('Get teacher classes', async () => {
@ -193,9 +192,9 @@ describe('Teacher controllers', () => {
body: { accepted: 'true' }, body: { accepted: 'true' },
}; };
const teacher = await updateStudentJoinRequestHandler(req as Request, res as Response); await updateStudentJoinRequestHandler(req as Request, res as Response);
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ teacher: expect.objectContaining(teacher) })); expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ request: expect.anything() }));
req = { req = {
params: { username: 'PinkFloyd' }, params: { username: 'PinkFloyd' },
@ -204,6 +203,6 @@ describe('Teacher controllers', () => {
await getStudentRequestsHandler(req as Request, res as Response); await getStudentRequestsHandler(req as Request, res as Response);
const status: boolean = jsonMock.mock.lastCall?.[0].requests[0].status; const status: boolean = jsonMock.mock.lastCall?.[0].requests[0].status;
expect(status).toBeTruthy; expect(status).toBeTruthy();
}); });
}); });

View file

@ -1,4 +1,4 @@
import { Connection, EntityManager, IDatabaseDriver } from '@mikro-orm/core'; import { EntityManager} from '@mikro-orm/core';
import { Student } from '../../../src/entities/users/student.entity'; import { Student } from '../../../src/entities/users/student.entity';
// 🔓 Ruwe testdata array — herbruikbaar in assertions // 🔓 Ruwe testdata array — herbruikbaar in assertions
@ -14,6 +14,6 @@ export const TEST_STUDENTS = [
]; ];
// 🏗️ Functie die ORM entities maakt uit de data array // 🏗️ Functie die ORM entities maakt uit de data array
export function makeTestStudents(em: EntityManager<IDatabaseDriver<Connection>>): Student[] { export function makeTestStudents(em: EntityManager): Student[] {
return TEST_STUDENTS.map((data) => em.create(Student, data)); return TEST_STUDENTS.map((data) => em.create(Student, data));
} }

View file

@ -4,7 +4,7 @@ import { ThemeController } from "@/controllers/themes.ts";
const themeController = new ThemeController(); const themeController = new ThemeController();
export function useThemeQuery(language: MaybeRefOrGetter<string | undefined>){ export function useThemeQuery(language: MaybeRefOrGetter<string | undefined>) {
return useQuery({ return useQuery({
queryKey: ["themes", language], queryKey: ["themes", language],
queryFn: () => { queryFn: () => {
@ -15,7 +15,7 @@ export function useThemeQuery(language: MaybeRefOrGetter<string | undefined>){
}); });
} }
export function useThemeHruidsQuery(themeKey: MaybeRefOrGetter<string | undefined>){ export function useThemeHruidsQuery(themeKey: MaybeRefOrGetter<string | undefined>) {
return useQuery({ return useQuery({
queryKey: ["theme-hruids", themeKey], queryKey: ["theme-hruids", themeKey],
queryFn: () => themeController.getHruidsByKey(toValue(themeKey)!), queryFn: () => themeController.getHruidsByKey(toValue(themeKey)!),