diff --git a/backend/src/controllers/error-helper.ts b/backend/src/controllers/error-helper.ts index da627d72..dd4091c8 100644 --- a/backend/src/controllers/error-helper.ts +++ b/backend/src/controllers/error-helper.ts @@ -1,4 +1,4 @@ -import {BadRequestException} from "../exceptions/bad-request-exception"; +import { BadRequestException } from '../exceptions/bad-request-exception'; /** * Checks for the presence of required fields and throws a BadRequestException diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index 46faef1d..aa3fd9ba 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -1,17 +1,20 @@ import { Request, Response } from 'express'; import { createClassJoinRequest, - createStudent, deleteClassJoinRequest, + createStudent, + deleteClassJoinRequest, deleteStudent, - getAllStudents, getJoinRequestsByStudent, + getAllStudents, + getJoinRequestsByStudent, getStudent, getStudentAssignments, getStudentClasses, - getStudentGroups, getStudentQuestions, + getStudentGroups, + getStudentQuestions, getStudentSubmissions, } from '../services/students.js'; import { StudentDTO } from '../interfaces/student.js'; -import {requireFields} from "./error-helper.js"; +import { requireFields } from './error-helper.js'; export async function getAllStudentsHandler(req: Request, res: Response): Promise { const full = req.query.full === 'true'; @@ -128,7 +131,7 @@ export async function getStudentRequestHandler(req: Request, res: Response): Pro requireFields({ username }); const requests = await getJoinRequestsByStudent(username); - res.status(201).json({ requests }) + res.status(201).json({ requests }); } export async function deleteClassJoinRequestHandler(req: Request, res: Response) { @@ -139,5 +142,3 @@ export async function deleteClassJoinRequestHandler(req: Request, res: Response) await deleteClassJoinRequest(username, classId); res.sendStatus(204); } - - diff --git a/backend/src/controllers/teachers.ts b/backend/src/controllers/teachers.ts index 5c5a7324..ce328dac 100644 --- a/backend/src/controllers/teachers.ts +++ b/backend/src/controllers/teachers.ts @@ -3,16 +3,18 @@ import { createTeacher, deleteTeacher, getAllTeachers, - getClassesByTeacher, getJoinRequestsByClass, + getClassesByTeacher, + getJoinRequestsByClass, getStudentsByTeacher, getTeacher, - getTeacherQuestions, updateClassJoinRequestStatus + getTeacherQuestions, + updateClassJoinRequestStatus, } from '../services/teachers.js'; import { ClassDTO } from '../interfaces/class.js'; import { StudentDTO } from '../interfaces/student.js'; import { QuestionDTO, QuestionId } from '../interfaces/question.js'; import { TeacherDTO } from '../interfaces/teacher.js'; -import {requireFields} from "./error-helper.js"; +import { requireFields } from './error-helper.js'; export async function getAllTeachersHandler(req: Request, res: Response): Promise { const full = req.query.full === 'true'; diff --git a/backend/src/data/classes/class-join-request-repository.ts b/backend/src/data/classes/class-join-request-repository.ts index b2d699ee..ce1dcec5 100644 --- a/backend/src/data/classes/class-join-request-repository.ts +++ b/backend/src/data/classes/class-join-request-repository.ts @@ -1,6 +1,6 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { Class } from '../../entities/classes/class.entity.js'; -import {ClassJoinRequest, ClassJoinRequestStatus} from '../../entities/classes/class-join-request.entity.js'; +import { ClassJoinRequest, ClassJoinRequestStatus } from '../../entities/classes/class-join-request.entity.js'; import { Student } from '../../entities/users/student.entity.js'; export class ClassJoinRequestRepository extends DwengoEntityRepository { @@ -8,7 +8,7 @@ export class ClassJoinRequestRepository extends DwengoEntityRepository { - return this.findAll({ where: { class: clazz, status: ClassJoinRequestStatus.Open, } }); // TODO check if works like this + return this.findAll({ where: { class: clazz, status: ClassJoinRequestStatus.Open } }); // TODO check if works like this } public findByStudentAndClass(requester: Student, clazz: Class): Promise { return this.findOne({ requester, class: clazz }); diff --git a/backend/src/interfaces/student-request.ts b/backend/src/interfaces/student-request.ts index 6ced158d..bde840c9 100644 --- a/backend/src/interfaces/student-request.ts +++ b/backend/src/interfaces/student-request.ts @@ -1,13 +1,13 @@ -import {mapToStudentDTO, StudentDTO} from "./student"; -import {ClassJoinRequest, ClassJoinRequestStatus} from "../entities/classes/class-join-request.entity"; -import {getClassJoinRequestRepository} from "../data/repositories"; -import {Student} from "../entities/users/student.entity"; -import {Class} from "../entities/classes/class.entity"; +import { mapToStudentDTO, StudentDTO } from './student'; +import { ClassJoinRequest, ClassJoinRequestStatus } from '../entities/classes/class-join-request.entity'; +import { getClassJoinRequestRepository } from '../data/repositories'; +import { Student } from '../entities/users/student.entity'; +import { Class } from '../entities/classes/class.entity'; export interface StudentRequestDTO { requester: StudentDTO; class: string; - status: ClassJoinRequestStatus + status: ClassJoinRequestStatus; } export function mapToStudentRequestDTO(request: ClassJoinRequest): StudentRequestDTO { diff --git a/backend/src/routes/student-join-requests.ts b/backend/src/routes/student-join-requests.ts index 73532347..de2d522b 100644 --- a/backend/src/routes/student-join-requests.ts +++ b/backend/src/routes/student-join-requests.ts @@ -1,8 +1,5 @@ -import express from "express"; -import { - createStudentRequestHandler, deleteClassJoinRequestHandler, - getStudentRequestHandler, -} from "../controllers/students"; +import express from 'express'; +import { createStudentRequestHandler, deleteClassJoinRequestHandler, getStudentRequestHandler } from '../controllers/students'; const router = express.Router({ mergeParams: true }); diff --git a/backend/src/routes/students.ts b/backend/src/routes/students.ts index b2d0fc93..0f5d5349 100644 --- a/backend/src/routes/students.ts +++ b/backend/src/routes/students.ts @@ -10,7 +10,7 @@ import { getStudentQuestionsHandler, getStudentSubmissionsHandler, } from '../controllers/students.js'; -import joinRequestRouter from './student-join-requests.js' +import joinRequestRouter from './student-join-requests.js'; const router = express.Router(); @@ -39,6 +39,6 @@ router.get('/:username/groups', getStudentGroupsHandler); // A list of questions a user has created router.get('/:username/questions', getStudentQuestionsHandler); -router.use('/:username/joinRequests', joinRequestRouter) +router.use('/:username/joinRequests', joinRequestRouter); export default router; diff --git a/backend/src/routes/teachers.ts b/backend/src/routes/teachers.ts index 058bc0a3..746e0d16 100644 --- a/backend/src/routes/teachers.ts +++ b/backend/src/routes/teachers.ts @@ -2,11 +2,13 @@ import express from 'express'; import { createTeacherHandler, deleteTeacherHandler, - getAllTeachersHandler, getStudentJoinRequestHandler, + getAllTeachersHandler, + getStudentJoinRequestHandler, getTeacherClassHandler, getTeacherHandler, getTeacherQuestionHandler, - getTeacherStudentHandler, updateStudentJoinRequestHandler, + getTeacherStudentHandler, + updateStudentJoinRequestHandler, } from '../controllers/teachers.js'; const router = express.Router(); diff --git a/backend/src/services/classes.ts b/backend/src/services/classes.ts index 6581cb93..f14a3cb5 100644 --- a/backend/src/services/classes.ts +++ b/backend/src/services/classes.ts @@ -3,8 +3,8 @@ import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; import { mapToStudentDTO, StudentDTO } from '../interfaces/student.js'; import { mapToTeacherInvitationDTO, mapToTeacherInvitationDTOIds, TeacherInvitationDTO } from '../interfaces/teacher-invitation.js'; import { getLogger } from '../logging/initalize.js'; -import {NotFoundException} from "../exceptions/not-found-exception"; -import {Class} from "../entities/classes/class.entity"; +import { NotFoundException } from '../exceptions/not-found-exception'; +import { Class } from '../entities/classes/class.entity'; const logger = getLogger(); @@ -13,7 +13,7 @@ export async function fetchClass(classId: string): Promise { const cls = await classRepository.findById(classId); if (!cls) { - throw new NotFoundException("Class with id not found"); + throw new NotFoundException('Class with id not found'); } return cls; diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index 37f54d78..e043ceee 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -4,7 +4,7 @@ import { getGroupRepository, getQuestionRepository, getStudentRepository, - getSubmissionRepository + getSubmissionRepository, } from '../data/repositories.js'; import { AssignmentDTO } from '../interfaces/assignment.js'; import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; @@ -13,17 +13,18 @@ import { mapToStudent, mapToStudentDTO, StudentDTO } from '../interfaces/student import { mapToSubmissionDTO, mapToSubmissionDTOId, SubmissionDTO, SubmissionDTOId } from '../interfaces/submission.js'; import { getAllAssignments } from './assignments.js'; import { mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId } from '../interfaces/question.js'; -import {mapToStudentRequest, mapToStudentRequestDTO} from "../interfaces/student-request.js"; -import {Student} from "../entities/users/student.entity.js"; -import {NotFoundException} from "../exceptions/not-found-exception.js"; -import {fetchClass} from "./classes.js"; +import { mapToStudentRequest, mapToStudentRequestDTO } from '../interfaces/student-request.js'; +import { Student } from '../entities/users/student.entity.js'; +import { NotFoundException } from '../exceptions/not-found-exception.js'; +import { fetchClass } from './classes.js'; export async function getAllStudents(full: boolean): Promise { const studentRepository = getStudentRepository(); const users = await studentRepository.findAll(); - if (full) - {return users.map(mapToStudentDTO);} + if (full) { + return users.map(mapToStudentDTO); + } return users.map((user) => user.username); } @@ -33,7 +34,7 @@ export async function fetchStudent(username: string): Promise { const user = await studentRepository.findByUsername(username); if (!user) { - throw new NotFoundException("Student with username not found"); + throw new NotFoundException('Student with username not found'); } return user; @@ -115,8 +116,9 @@ export async function getStudentQuestions(username: string, full: boolean): Prom const questionsDTO = questions.map(mapToQuestionDTO); - if (full) - {return questionsDTO;} + if (full) { + return questionsDTO; + } return questionsDTO.map(mapToQuestionId); } @@ -146,7 +148,6 @@ export async function deleteClassJoinRequest(studentUsername: string, classId: s const student = await fetchStudent(studentUsername); const cls = await fetchClass(classId); - const request = await requestRepo.findByStudentAndClass(student, cls); if (!request) { diff --git a/backend/src/services/teachers.ts b/backend/src/services/teachers.ts index f32a7a56..11b27b70 100644 --- a/backend/src/services/teachers.ts +++ b/backend/src/services/teachers.ts @@ -6,24 +6,24 @@ import { getTeacherRepository, } from '../data/repositories.js'; import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; -import {mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId} from '../interfaces/question.js'; +import { mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId } from '../interfaces/question.js'; import { mapToTeacher, mapToTeacherDTO, TeacherDTO } from '../interfaces/teacher.js'; -import {Teacher} from "../entities/users/teacher.entity.js"; -import {fetchStudent} from "./students.js"; -import {ClassJoinRequest, ClassJoinRequestStatus} from "../entities/classes/class-join-request.entity.js"; -import {mapToStudentRequestDTO, StudentRequestDTO} from "../interfaces/student-request.js"; -import {TeacherRepository} from "../data/users/teacher-repository.js"; -import {ClassRepository} from "../data/classes/class-repository.js"; -import {Class} from "../entities/classes/class.entity.js"; -import {StudentDTO} from "../interfaces/student.js"; -import {LearningObjectRepository} from "../data/content/learning-object-repository.js"; -import {LearningObject} from "../entities/content/learning-object.entity.js"; -import {QuestionRepository} from "../data/questions/question-repository.js"; -import {Question} from "../entities/questions/question.entity.js"; -import {ClassJoinRequestRepository} from "../data/classes/class-join-request-repository.js"; -import {Student} from "../entities/users/student.entity.js"; -import {NotFoundException} from "../exceptions/not-found-exception.js"; -import {getClassStudents} from "./classes.js"; +import { Teacher } from '../entities/users/teacher.entity.js'; +import { fetchStudent } from './students.js'; +import { ClassJoinRequest, ClassJoinRequestStatus } from '../entities/classes/class-join-request.entity.js'; +import { mapToStudentRequestDTO, StudentRequestDTO } from '../interfaces/student-request.js'; +import { TeacherRepository } from '../data/users/teacher-repository.js'; +import { ClassRepository } from '../data/classes/class-repository.js'; +import { Class } from '../entities/classes/class.entity.js'; +import { StudentDTO } from '../interfaces/student.js'; +import { LearningObjectRepository } from '../data/content/learning-object-repository.js'; +import { LearningObject } from '../entities/content/learning-object.entity.js'; +import { QuestionRepository } from '../data/questions/question-repository.js'; +import { Question } from '../entities/questions/question.entity.js'; +import { ClassJoinRequestRepository } from '../data/classes/class-join-request-repository.js'; +import { Student } from '../entities/users/student.entity.js'; +import { NotFoundException } from '../exceptions/not-found-exception.js'; +import { getClassStudents } from './classes.js'; export async function getAllTeachers(full: boolean): Promise { const teacherRepository: TeacherRepository = getTeacherRepository(); @@ -40,7 +40,7 @@ export async function fetchTeacher(username: string): Promise { const user: Teacher | null = await teacherRepository.findByUsername(username); if (!user) { - throw new NotFoundException("Teacher with username not found"); + throw new NotFoundException('Teacher with username not found'); } return user; @@ -86,7 +86,7 @@ export async function getClassesByTeacher(username: string, full: boolean): Prom export async function getStudentsByTeacher(username: string, full: boolean) { const classes: ClassDTO[] = await fetchClassesByTeacher(username); - if (!classes || classes.length === 0){ + if (!classes || classes.length === 0) { return []; } @@ -109,7 +109,7 @@ export async function getTeacherQuestions(username: string, full: boolean): Prom // Console.log(learningObjects) // TODO returns empty - if (!learningObjects || learningObjects.length === 0){ + if (!learningObjects || learningObjects.length === 0) { return []; } @@ -125,12 +125,12 @@ export async function getTeacherQuestions(username: string, full: boolean): Prom return questionsDTO.map(mapToQuestionId); } -export async function getJoinRequestsByClass( classId: string ): Promise { +export async function getJoinRequestsByClass(classId: string): Promise { const classRepository: ClassRepository = getClassRepository(); const cls: Class | null = await classRepository.findById(classId); if (!cls) { - throw new NotFoundException("Class with id not found"); + throw new NotFoundException('Class with id not found'); } const requestRepo: ClassJoinRequestRepository = getClassJoinRequestRepository(); @@ -138,7 +138,7 @@ export async function getJoinRequestsByClass( classId: string ): Promise { +export async function updateClassJoinRequestStatus(studentUsername: string, classId: string, accepted: boolean = true): Promise { const requestRepo: ClassJoinRequestRepository = getClassJoinRequestRepository(); const classRepo: ClassRepository = getClassRepository(); diff --git a/backend/tests/controllers/students.test.ts b/backend/tests/controllers/students.test.ts index 57c5da96..fae8a479 100644 --- a/backend/tests/controllers/students.test.ts +++ b/backend/tests/controllers/students.test.ts @@ -12,14 +12,14 @@ import { getStudentQuestionsHandler, createStudentRequestHandler, getStudentRequestHandler, - deleteClassJoinRequestHandler + deleteClassJoinRequestHandler, } from '../../src/controllers/students.js'; -import {TEST_STUDENTS} from "../test_assets/users/students.testdata.js"; -import {NotFoundException} from "../../src/exceptions/not-found-exception.js"; -import {BadRequestException} from "../../src/exceptions/bad-request-exception.js"; -import {ConflictException} from "../../src/exceptions/conflict-exception.js"; -import {EntityAlreadyExistsException} from "../../src/exceptions/entity-already-exists-exception.js"; -import {StudentDTO} from "../../src/interfaces/student.js"; +import { TEST_STUDENTS } from '../test_assets/users/students.testdata.js'; +import { NotFoundException } from '../../src/exceptions/not-found-exception.js'; +import { BadRequestException } from '../../src/exceptions/bad-request-exception.js'; +import { ConflictException } from '../../src/exceptions/conflict-exception.js'; +import { EntityAlreadyExistsException } from '../../src/exceptions/entity-already-exists-exception.js'; +import { StudentDTO } from '../../src/interfaces/student.js'; describe('Student controllers', () => { let req: Partial; @@ -45,7 +45,7 @@ describe('Student controllers', () => { }); it('Get student', async () => { - req = { params: { username: 'DireStraits' }}; + req = { params: { username: 'DireStraits' } }; await getStudentHandler(req as Request, res as Response); @@ -55,17 +55,13 @@ describe('Student controllers', () => { it('Student not found', async () => { req = { params: { username: 'doesnotexist' } }; - await expect(() => getStudentHandler(req as Request, res as Response)) - .rejects - .toThrow(NotFoundException); + await expect(() => getStudentHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException); }); it('No username', async () => { req = { params: {} }; - await expect(() => getStudentHandler(req as Request, res as Response)) - .rejects - .toThrowError(BadRequestException); + await expect(() => getStudentHandler(req as Request, res as Response)).rejects.toThrowError(BadRequestException); }); it('Create and delete student', async () => { @@ -73,8 +69,8 @@ describe('Student controllers', () => { body: { username: 'coolstudent', firstName: 'New', - lastName: 'Student' - } + lastName: 'Student', + }, }; await createStudentHandler(req as Request, res as Response); @@ -88,27 +84,22 @@ describe('Student controllers', () => { expect(sendStatusMock).toHaveBeenCalledWith(200); }); - it('Create duplicate student', async () => { req = { body: { username: 'DireStraits', firstName: 'dupe', - lastName: 'dupe' - } + lastName: 'dupe', + }, }; - await expect(() => createStudentHandler(req as Request, res as Response)) - .rejects - .toThrowError(EntityAlreadyExistsException); + await expect(() => createStudentHandler(req as Request, res as Response)).rejects.toThrowError(EntityAlreadyExistsException); }); it('Create student no body', async () => { req = { body: {} }; - await expect(() => createStudentHandler(req as Request, res as Response)) - .rejects - .toThrowError(BadRequestException); + await expect(() => createStudentHandler(req as Request, res as Response)).rejects.toThrowError(BadRequestException); }); it('Student list', async () => { @@ -133,7 +124,6 @@ describe('Student controllers', () => { await getStudentClassesHandler(req as Request, res as Response); - expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ classes: expect.anything() })); const result = jsonMock.mock.lastCall?.[0]; @@ -176,9 +166,7 @@ describe('Student controllers', () => { it('Deleting non-existent student', async () => { req = { params: { username: 'doesnotexist' } }; - await expect(() => deleteStudentHandler(req as Request, res as Response)) - .rejects - .toThrow(NotFoundException); + await expect(() => deleteStudentHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException); }); it('Get join requests by student', async () => { @@ -203,7 +191,7 @@ describe('Student controllers', () => { it('Create join request', async () => { req = { params: { username: 'Noordkaap' }, - body: { classId: 'id02' } + body: { classId: 'id02' }, }; await createStudentRequestHandler(req as Request, res as Response); @@ -214,15 +202,12 @@ describe('Student controllers', () => { it('Create join request duplicate', async () => { req = { params: { username: 'Tool' }, - body: { classId: 'id02' } + body: { classId: 'id02' }, }; - await expect(() => createStudentRequestHandler(req as Request, res as Response)) - .rejects - .toThrow(ConflictException); + await expect(() => createStudentRequestHandler(req as Request, res as Response)).rejects.toThrow(ConflictException); }); - it('Delete join request', async () => { req = { params: { username: 'Noordkaap', classId: 'id02' }, @@ -232,9 +217,6 @@ describe('Student controllers', () => { expect(sendStatusMock).toHaveBeenCalledWith(204); - await expect(() => deleteClassJoinRequestHandler(req as Request, res as Response)) - .rejects - .toThrow(NotFoundException); + await expect(() => deleteClassJoinRequestHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException); }); - }); diff --git a/backend/tests/controllers/teachers.test.ts b/backend/tests/controllers/teachers.test.ts index 78d67318..9fa3e501 100644 --- a/backend/tests/controllers/teachers.test.ts +++ b/backend/tests/controllers/teachers.test.ts @@ -1,17 +1,22 @@ -import {beforeAll, beforeEach, describe, expect, it, Mock, vi} from "vitest"; -import {Request, Response} from "express"; -import {setupTestApp} from "../setup-tests.js"; -import {NotFoundException} from "../../src/exceptions/not-found-exception.js"; +import { beforeAll, beforeEach, describe, expect, it, Mock, vi } from 'vitest'; +import { Request, Response } from 'express'; +import { setupTestApp } from '../setup-tests.js'; +import { NotFoundException } from '../../src/exceptions/not-found-exception.js'; import { createTeacherHandler, deleteTeacherHandler, - getAllTeachersHandler, getStudentJoinRequestHandler, getTeacherClassHandler, - getTeacherHandler, getTeacherQuestionHandler, getTeacherStudentHandler, updateStudentJoinRequestHandler -} from "../../src/controllers/teachers.js"; -import {BadRequestException} from "../../src/exceptions/bad-request-exception.js"; -import {EntityAlreadyExistsException} from "../../src/exceptions/entity-already-exists-exception.js"; -import {getStudentRequestHandler} from "../../src/controllers/students.js"; -import {TeacherDTO} from "../../src/interfaces/teacher.js"; + getAllTeachersHandler, + getStudentJoinRequestHandler, + getTeacherClassHandler, + getTeacherHandler, + getTeacherQuestionHandler, + getTeacherStudentHandler, + updateStudentJoinRequestHandler, +} from '../../src/controllers/teachers.js'; +import { BadRequestException } from '../../src/exceptions/bad-request-exception.js'; +import { EntityAlreadyExistsException } from '../../src/exceptions/entity-already-exists-exception.js'; +import { getStudentRequestHandler } from '../../src/controllers/students.js'; +import { TeacherDTO } from '../../src/interfaces/teacher.js'; describe('Teacher controllers', () => { let req: Partial; @@ -37,7 +42,7 @@ describe('Teacher controllers', () => { }); it('Get teacher', async () => { - req = { params: { username: 'FooFighters' }}; + req = { params: { username: 'FooFighters' } }; await getTeacherHandler(req as Request, res as Response); @@ -45,19 +50,15 @@ describe('Teacher controllers', () => { }); it('Teacher not found', async () => { - req = {params: {username: 'doesnotexist'}}; + req = { params: { username: 'doesnotexist' } }; - await expect(() => getTeacherHandler(req as Request, res as Response)) - .rejects - .toThrow(NotFoundException); + await expect(() => getTeacherHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException); }); it('No username', async () => { req = { params: {} }; - await expect(() => getTeacherHandler(req as Request, res as Response)) - .rejects - .toThrowError(BadRequestException); + await expect(() => getTeacherHandler(req as Request, res as Response)).rejects.toThrowError(BadRequestException); }); it('Create and delete teacher', async () => { @@ -65,8 +66,8 @@ describe('Teacher controllers', () => { body: { username: 'coolteacher', firstName: 'New', - lastName: 'Teacher' - } + lastName: 'Teacher', + }, }; await createTeacherHandler(req as Request, res as Response); @@ -86,20 +87,16 @@ describe('Teacher controllers', () => { username: 'FooFighters', firstName: 'Dave', lastName: 'Grohl', - } + }, }; - await expect(() => createTeacherHandler(req as Request, res as Response)) - .rejects - .toThrowError(EntityAlreadyExistsException); + await expect(() => createTeacherHandler(req as Request, res as Response)).rejects.toThrowError(EntityAlreadyExistsException); }); it('Create teacher no body', async () => { req = { body: {} }; - await expect(() => createTeacherHandler(req as Request, res as Response)) - .rejects - .toThrowError(BadRequestException); + await expect(() => createTeacherHandler(req as Request, res as Response)).rejects.toThrowError(BadRequestException); }); it('Teacher list', async () => { @@ -120,12 +117,9 @@ describe('Teacher controllers', () => { it('Deleting non-existent student', async () => { req = { params: { username: 'doesnotexist' } }; - await expect(() => deleteTeacherHandler(req as Request, res as Response)) - .rejects - .toThrow(NotFoundException); + await expect(() => deleteTeacherHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException); }); - it('Get teacher classes', async () => { req = { params: { username: 'FooFighters' }, @@ -196,7 +190,7 @@ describe('Teacher controllers', () => { req = { query: { username: 'LimpBizkit', studentUsername: 'PinkFloyd' }, params: { classId: 'id02' }, - body: { accepted: 'true' } + body: { accepted: 'true' }, }; await updateStudentJoinRequestHandler(req as Request, res as Response); @@ -209,11 +203,7 @@ describe('Teacher controllers', () => { await getStudentRequestHandler(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; }); - - - - }); diff --git a/backend/tests/test_assets/users/students.testdata.ts b/backend/tests/test_assets/users/students.testdata.ts index b86ef0d0..8bb3213b 100644 --- a/backend/tests/test_assets/users/students.testdata.ts +++ b/backend/tests/test_assets/users/students.testdata.ts @@ -15,6 +15,5 @@ export const TEST_STUDENTS = [ // 🏗️ Functie die ORM entities maakt uit de data array export function makeTestStudents(em: EntityManager>): Student[] { - return TEST_STUDENTS.map(data => em.create(Student, data)); + return TEST_STUDENTS.map((data) => em.create(Student, data)); } - diff --git a/frontend/src/controllers/teachers.ts b/frontend/src/controllers/teachers.ts index 23b1968b..cdbacae7 100644 --- a/frontend/src/controllers/teachers.ts +++ b/frontend/src/controllers/teachers.ts @@ -33,12 +33,12 @@ export class TeacherController extends BaseController { return this.get<{ questions: any[] }>(`/${username}/questions`, { full }); } - getStudentJoinRequests(username: string, classId: string){ + getStudentJoinRequests(username: string, classId: string) { return this.get<{ joinRequests: any[] }>(`/${username}/joinRequests/${classId}`); } - updateStudentJoinRequest(teacherUsername: string, classId: string, studentUsername: string, accepted: boolean){ - return this.put(`/${teacherUsername}/joinRequests/${classId}/${studentUsername}`, accepted) + updateStudentJoinRequest(teacherUsername: string, classId: string, studentUsername: string, accepted: boolean) { + return this.put(`/${teacherUsername}/joinRequests/${classId}/${studentUsername}`, accepted); } // GetInvitations(id: string) {return this.get<{ invitations: string[] }>(`/${id}/invitations`);} diff --git a/frontend/src/queries/students.ts b/frontend/src/queries/students.ts index aaf05544..f94d85ed 100644 --- a/frontend/src/queries/students.ts +++ b/frontend/src/queries/students.ts @@ -1,21 +1,20 @@ import { computed, toValue } from "vue"; import type { MaybeRefOrGetter } from "vue"; -import {useMutation, useQuery, useQueryClient} from "@tanstack/vue-query"; -import {StudentController} from "@/controllers/students.ts"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/vue-query"; +import { StudentController } from "@/controllers/students.ts"; const studentController = new StudentController(); /** 🔑 Query keys */ -const STUDENTS_QUERY_KEY = (full: boolean) => ['students', full]; -const STUDENT_QUERY_KEY = (username: string) => ['student', username]; -const STUDENT_CLASSES_QUERY_KEY = (username: string, full: boolean) => ['student-classes', username, full]; -const STUDENT_ASSIGNMENTS_QUERY_KEY = (username: string, full: boolean) => ['student-assignments', username, full]; -const STUDENT_GROUPS_QUERY_KEY = (username: string, full: boolean) => ['student-groups', username, full]; -const STUDENT_SUBMISSIONS_QUERY_KEY = (username: string) => ['student-submissions', username]; -const STUDENT_QUESTIONS_QUERY_KEY = (username: string, full: boolean) => ['student-questions', username, full]; +const STUDENTS_QUERY_KEY = (full: boolean) => ["students", full]; +const STUDENT_QUERY_KEY = (username: string) => ["student", username]; +const STUDENT_CLASSES_QUERY_KEY = (username: string, full: boolean) => ["student-classes", username, full]; +const STUDENT_ASSIGNMENTS_QUERY_KEY = (username: string, full: boolean) => ["student-assignments", username, full]; +const STUDENT_GROUPS_QUERY_KEY = (username: string, full: boolean) => ["student-groups", username, full]; +const STUDENT_SUBMISSIONS_QUERY_KEY = (username: string) => ["student-submissions", username]; +const STUDENT_QUESTIONS_QUERY_KEY = (username: string, full: boolean) => ["student-questions", username, full]; const STUDENT_JOIN_REQUESTS_QUERY_KEY = (username: string) => ["student-join-requests", username]; - export function useStudentsQuery(full: MaybeRefOrGetter = true) { return useQuery({ queryKey: computed(() => STUDENTS_QUERY_KEY(toValue(full))), @@ -31,7 +30,10 @@ export function useStudentQuery(username: MaybeRefOrGetter) }); } -export function useStudentClassesQuery(username: MaybeRefOrGetter, full: MaybeRefOrGetter = true) { +export function useStudentClassesQuery( + username: MaybeRefOrGetter, + full: MaybeRefOrGetter = true, +) { return useQuery({ queryKey: computed(() => STUDENT_CLASSES_QUERY_KEY(toValue(username)!, toValue(full))), queryFn: () => studentController.getClasses(toValue(username)!, toValue(full)), @@ -39,7 +41,10 @@ export function useStudentClassesQuery(username: MaybeRefOrGetter, full: MaybeRefOrGetter = true) { +export function useStudentAssignmentsQuery( + username: MaybeRefOrGetter, + full: MaybeRefOrGetter = true, +) { return useQuery({ queryKey: computed(() => STUDENT_ASSIGNMENTS_QUERY_KEY(toValue(username)!, toValue(full))), queryFn: () => studentController.getAssignments(toValue(username)!, toValue(full)), @@ -47,7 +52,10 @@ export function useStudentAssignmentsQuery(username: MaybeRefOrGetter, full: MaybeRefOrGetter = true) { +export function useStudentGroupsQuery( + username: MaybeRefOrGetter, + full: MaybeRefOrGetter = true, +) { return useQuery({ queryKey: computed(() => STUDENT_GROUPS_QUERY_KEY(toValue(username)!, toValue(full))), queryFn: () => studentController.getGroups(toValue(username)!, toValue(full)), @@ -63,7 +71,10 @@ export function useStudentSubmissionsQuery(username: MaybeRefOrGetter, full: MaybeRefOrGetter = true) { +export function useStudentQuestionsQuery( + username: MaybeRefOrGetter, + full: MaybeRefOrGetter = true, +) { return useQuery({ queryKey: computed(() => STUDENT_QUESTIONS_QUERY_KEY(toValue(username)!, toValue(full))), queryFn: () => studentController.getQuestions(toValue(username)!, toValue(full)), @@ -77,7 +88,7 @@ export function useCreateStudentMutation() { return useMutation({ mutationFn: (data: any) => studentController.createStudent(data), onSuccess: () => { - await queryClient.invalidateQueries({ queryKey: ['students'] }); + await queryClient.invalidateQueries({ queryKey: ["students"] }); }, onError: (err) => { alert("Create student failed:", err); @@ -94,7 +105,7 @@ export function useDeleteStudentMutation() { return useMutation({ mutationFn: (username: string) => studentController.deleteStudent(username), onSuccess: () => { - await queryClient.invalidateQueries({ queryKey: ['students'] }); + await queryClient.invalidateQueries({ queryKey: ["students"] }); }, onError: (err) => { alert("Delete student failed:", err); @@ -145,7 +156,3 @@ export function useDeleteJoinRequestMutation() { }, }); } - - - - diff --git a/frontend/src/queries/teachers.ts b/frontend/src/queries/teachers.ts index 2df0eeec..f8ba0f6a 100644 --- a/frontend/src/queries/teachers.ts +++ b/frontend/src/queries/teachers.ts @@ -1,7 +1,7 @@ import { computed, toValue } from "vue"; import type { MaybeRefOrGetter } from "vue"; import { useQuery, useMutation, useQueryClient } from "@tanstack/vue-query"; -import {TeacherController} from "@/controllers/teachers.ts"; +import { TeacherController } from "@/controllers/teachers.ts"; const teacherController = new TeacherController(); @@ -28,7 +28,10 @@ export function useTeacherQuery(username: MaybeRefOrGetter) }); } -export function useTeacherClassesQuery(username: MaybeRefOrGetter, full: MaybeRefOrGetter = false) { +export function useTeacherClassesQuery( + username: MaybeRefOrGetter, + full: MaybeRefOrGetter = false, +) { return useQuery({ queryKey: computed(() => TEACHER_CLASSES_QUERY_KEY(toValue(username)!, toValue(full))), queryFn: () => teacherController.getClasses(toValue(username)!, toValue(full)), @@ -36,7 +39,10 @@ export function useTeacherClassesQuery(username: MaybeRefOrGetter, full: MaybeRefOrGetter = false) { +export function useTeacherStudentsQuery( + username: MaybeRefOrGetter, + full: MaybeRefOrGetter = false, +) { return useQuery({ queryKey: computed(() => TEACHER_STUDENTS_QUERY_KEY(toValue(username)!, toValue(full))), queryFn: () => teacherController.getStudents(toValue(username)!, toValue(full)), @@ -44,7 +50,10 @@ export function useTeacherStudentsQuery(username: MaybeRefOrGetter, full: MaybeRefOrGetter = false) { +export function useTeacherQuestionsQuery( + username: MaybeRefOrGetter, + full: MaybeRefOrGetter = false, +) { return useQuery({ queryKey: computed(() => TEACHER_QUESTIONS_QUERY_KEY(toValue(username)!, toValue(full))), queryFn: () => teacherController.getQuestions(toValue(username)!, toValue(full)), @@ -52,7 +61,10 @@ export function useTeacherQuestionsQuery(username: MaybeRefOrGetter, classId: MaybeRefOrGetter) { +export function useTeacherJoinRequestsQuery( + username: MaybeRefOrGetter, + classId: MaybeRefOrGetter, +) { return useQuery({ queryKey: computed(() => JOIN_REQUESTS_QUERY_KEY(toValue(username)!, toValue(classId)!)), queryFn: () => teacherController.getStudentJoinRequests(toValue(username)!, toValue(classId)!), @@ -66,7 +78,7 @@ export function useCreateTeacherMutation() { return useMutation({ mutationFn: (data: any) => teacherController.createTeacher(data), onSuccess: () => { - await queryClient.invalidateQueries({ queryKey: ['teachers'] }); + await queryClient.invalidateQueries({ queryKey: ["teachers"] }); }, onError: (err) => { alert("Create teacher failed:", err); @@ -80,7 +92,7 @@ export function useDeleteTeacherMutation() { return useMutation({ mutationFn: (username: string) => teacherController.deleteTeacher(username), onSuccess: () => { - await queryClient.invalidateQueries({ queryKey: ['teachers'] }); + await queryClient.invalidateQueries({ queryKey: ["teachers"] }); }, onError: (err) => { alert("Delete teacher failed:", err); @@ -92,7 +104,12 @@ export function useUpdateJoinRequestMutation() { const queryClient = useQueryClient(); return useMutation({ - mutationFn: ({ teacherUsername, classId, studentUsername, accepted }: { + mutationFn: ({ + teacherUsername, + classId, + studentUsername, + accepted, + }: { teacherUsername: string; classId: string; studentUsername: string; diff --git a/frontend/src/queries/themes.ts b/frontend/src/queries/themes.ts index 391771c0..71e3f679 100644 --- a/frontend/src/queries/themes.ts +++ b/frontend/src/queries/themes.ts @@ -1,6 +1,6 @@ import { useQuery } from "@tanstack/vue-query"; import { type MaybeRefOrGetter, toValue } from "vue"; -import {ThemeController} from "@/controllers/themes.ts"; +import { ThemeController } from "@/controllers/themes.ts"; const themeController = new ThemeController(); diff --git a/frontend/tests/controllers/student.test.ts b/frontend/tests/controllers/student.test.ts index 4a911410..3f9b7db5 100644 --- a/frontend/tests/controllers/student.test.ts +++ b/frontend/tests/controllers/student.test.ts @@ -1,20 +1,20 @@ -import { describe, it, expect, beforeAll } from 'vitest'; -import {StudentController} from "../../src/controllers/students"; +import { describe, it, expect, beforeAll } from "vitest"; +import { StudentController } from "../../src/controllers/students"; const controller = new StudentController(); -describe('StudentController', () => { +describe("StudentController", () => { const newStudent = { - username: 'teststudent1', - firstName: 'Testy', - lastName: 'McTestface', + username: "teststudent1", + firstName: "Testy", + lastName: "McTestface", }; beforeAll(() => { // Start backend }); - it('creates a student and fetches it by username', async () => { + it("creates a student and fetches it by username", async () => { // Create student await controller.createStudent(newStudent); @@ -29,7 +29,6 @@ describe('StudentController', () => { expect(student.firstName).toBe(newStudent.firstName); expect(student.lastName).toBe(newStudent.lastName); - await controller.deleteStudent(newStudent.username); }); }); diff --git a/frontend/tests/controllers/teacher.test.ts b/frontend/tests/controllers/teacher.test.ts index 0a1de683..44c615d5 100644 --- a/frontend/tests/controllers/teacher.test.ts +++ b/frontend/tests/controllers/teacher.test.ts @@ -1,20 +1,20 @@ -import { describe, it, expect, beforeAll } from 'vitest'; -import {TeacherController} from "../../src/controllers/teachers"; +import { describe, it, expect, beforeAll } from "vitest"; +import { TeacherController } from "../../src/controllers/teachers"; const controller = new TeacherController(); -describe('TeacherController', () => { +describe("TeacherController", () => { const newTeacher = { - username: 'testteacher3', - firstName: 'Testy', - lastName: 'McTestface', + username: "testteacher3", + firstName: "Testy", + lastName: "McTestface", }; beforeAll(() => { // Start backend }); - it('creates a student and fetches it by username', async () => { + it("creates a student and fetches it by username", async () => { // Create student await controller.createTeacher(newTeacher); @@ -29,7 +29,6 @@ describe('TeacherController', () => { expect(teacher.firstName).toBe(newTeacher.firstName); expect(teacher.lastName).toBe(newTeacher.lastName); - await controller.deleteTeacher(newTeacher.username); }); });