diff --git a/backend/.env.test b/backend/.env.test index 2d928db0..b4cdca4f 100644 --- a/backend/.env.test +++ b/backend/.env.test @@ -4,6 +4,8 @@ # Should not need to be modified. # See .env.example for more information. # +### Advanced configuration ### + ### Dwengo ### @@ -21,3 +23,7 @@ DWENGO_AUTH_TEACHER_CLIENT_ID=dwengo DWENGO_AUTH_TEACHER_JWKS_ENDPOINT=http://localhost:7080/realms/teacher/protocol/openid-connect/certs DWENGO_CORS_ALLOWED_ORIGINS=http://localhost:5173,http://localhost:3000,http://localhost:9876,* + +### Advanced configuration ### + +DWENGO_LOGGING_LEVEL=debug diff --git a/backend/src/orm.ts b/backend/src/orm.ts index 76cd0ee9..424ec15d 100644 --- a/backend/src/orm.ts +++ b/backend/src/orm.ts @@ -7,12 +7,17 @@ let orm: MikroORM | undefined; export async function initORM(testingMode = false): Promise> { const logger: Logger = getLogger(); - logger.info('Initializing ORM'); - logger.debug('MikroORM config is', config); + const options = config(testingMode); + + logger.info('MikroORM config is', options); + + logger.info('Initializing ORM'); + orm = await MikroORM.init(options); + logger.info('MikroORM initialized'); - orm = await MikroORM.init(config(testingMode)); // Update the database scheme if necessary and enabled. if (getEnvVar(envVars.DbUpdate)) { + logger.info('MikroORM: Updating database schema'); await orm.schema.updateSchema(); } else { const diff = await orm.schema.getUpdateSchemaSQL(); diff --git a/backend/tests/controllers/answers.test.ts b/backend/tests/controllers/answers.test.ts index 2bc8ed16..bf7b1456 100644 --- a/backend/tests/controllers/answers.test.ts +++ b/backend/tests/controllers/answers.test.ts @@ -5,6 +5,7 @@ import { Language } from '@dwengo-1/common/util/language'; import { getAllAnswersHandler, getAnswerHandler, updateAnswerHandler } from '../../src/controllers/answers'; import { BadRequestException } from '../../src/exceptions/bad-request-exception'; import { NotFoundException } from '../../src/exceptions/not-found-exception'; +import { getAnswer02 } from '../test_assets/questions/answers.testdata'; describe('Questions controllers', () => { let req: Partial; @@ -24,9 +25,14 @@ describe('Questions controllers', () => { }); it('Get answers list', async () => { + const a = getAnswer02(); req = { - params: { hruid: 'id05', version: '1', seq: '2' }, - query: { lang: Language.English, full: 'true' }, + params: { + hruid: a.toQuestion.learningObjectHruid, + version: a.toQuestion.learningObjectVersion.toString(), + seq: a.toQuestion.sequenceNumber!.toString(), + }, + query: { lang: a.toQuestion.learningObjectLanguage, full: 'true' }, }; await getAllAnswersHandler(req as Request, res as Response); @@ -38,9 +44,15 @@ describe('Questions controllers', () => { }); it('Get answer', async () => { + const a = getAnswer02(); req = { - params: { hruid: 'id05', version: '1', seq: '2', seqAnswer: '2' }, - query: { lang: Language.English, full: 'true' }, + params: { + hruid: a.toQuestion.learningObjectHruid, + version: a.toQuestion.learningObjectVersion.toString(), + seq: a.toQuestion.sequenceNumber!.toString(), + seqAnswer: a.sequenceNumber!.toString(), + }, + query: { lang: a.toQuestion.learningObjectLanguage, full: 'true' }, }; await getAnswerHandler(req as Request, res as Response); @@ -68,11 +80,19 @@ describe('Questions controllers', () => { await expect(async () => getAnswerHandler(req as Request, res as Response)).rejects.toThrow(BadRequestException); }); - it('Update question', async () => { - const newContent = 'updated question'; + it('Update answer', async () => { + const a = getAnswer02(); + const q = a.toQuestion; + + const newContent = 'updated answer'; req = { - params: { hruid: 'id05', version: '1', seq: '2', seqAnswer: '2' }, - query: { lang: Language.English }, + params: { + hruid: q.learningObjectHruid, + version: q.learningObjectVersion.toString(), + seq: q.sequenceNumber!.toString(), + seqAnswer: a.sequenceNumber!.toString(), + }, + query: { lang: q.learningObjectLanguage }, body: { content: newContent }, }; diff --git a/backend/tests/controllers/questions.test.ts b/backend/tests/controllers/questions.test.ts index f2612fc7..ece00823 100644 --- a/backend/tests/controllers/questions.test.ts +++ b/backend/tests/controllers/questions.test.ts @@ -5,6 +5,7 @@ import { getAllQuestionsHandler, getQuestionHandler, updateQuestionHandler } fro import { Language } from '@dwengo-1/common/util/language'; import { NotFoundException } from '../../src/exceptions/not-found-exception'; import { BadRequestException } from '../../src/exceptions/bad-request-exception'; +import { getQuestion01 } from '../test_assets/questions/questions.testdata'; describe('Questions controllers', () => { let req: Partial; @@ -24,9 +25,10 @@ describe('Questions controllers', () => { }); it('Get question list', async () => { + const q = getQuestion01(); req = { - params: { hruid: 'id05', version: '1' }, - query: { lang: Language.English, full: 'true' }, + params: { hruid: q.learningObjectHruid, version: q.learningObjectVersion.toString() }, + query: { lang: q.learningObjectLanguage, full: 'true' }, }; await getAllQuestionsHandler(req as Request, res as Response); @@ -38,9 +40,10 @@ describe('Questions controllers', () => { }); it('Get question', async () => { + const q = getQuestion01(); req = { - params: { hruid: 'id05', version: '1', seq: '1' }, - query: { lang: Language.English, full: 'true' }, + params: { hruid: q.learningObjectHruid, version: q.learningObjectVersion.toString(), seq: q.sequenceNumber!.toString() }, + query: { lang: q.learningObjectLanguage, full: 'true' }, }; await getQuestionHandler(req as Request, res as Response); @@ -51,8 +54,9 @@ describe('Questions controllers', () => { }); it('Get question with fallback sequence number and version', async () => { + const q = getQuestion01(); req = { - params: { hruid: 'id05' }, + params: { hruid: q.learningObjectHruid }, query: { lang: Language.English, full: 'true' }, }; @@ -99,10 +103,11 @@ describe('Questions controllers', () => { */ it('Update question', async () => { + const q = getQuestion01(); const newContent = 'updated question'; req = { - params: { hruid: 'id05', version: '1', seq: '1' }, - query: { lang: Language.English }, + params: { hruid: q.learningObjectHruid, version: q.learningObjectVersion.toString(), seq: q.sequenceNumber!.toString() }, + query: { lang: q.learningObjectLanguage }, body: { content: newContent }, }; diff --git a/backend/tests/controllers/students.test.ts b/backend/tests/controllers/students.test.ts index dbd22d46..b5ac1e0d 100644 --- a/backend/tests/controllers/students.test.ts +++ b/backend/tests/controllers/students.test.ts @@ -15,13 +15,17 @@ import { deleteClassJoinRequestHandler, getStudentRequestHandler, } from '../../src/controllers/students.js'; -import { TEST_STUDENTS } from '../test_assets/users/students.testdata.js'; +import { getDireStraits, getNoordkaap, getTheDoors, 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 '@dwengo-1/common/interfaces/student'; -import { getClass02 } from '../test_assets/classes/classes.testdata'; +import { getClass02 } from '../test_assets/classes/classes.testdata.js'; +import { getClassJoinRequest02 } from '../test_assets/classes/class-join-requests.testdata.js'; +import { getTestGroup01 } from '../test_assets/assignments/groups.testdata.js'; +import { getSubmission01 } from '../test_assets/assignments/submission.testdata.js'; +import { getQuestion01 } from '../test_assets/questions/questions.testdata.js'; describe('Student controllers', () => { let req: Partial; @@ -41,7 +45,8 @@ describe('Student controllers', () => { }); it('Get student', async () => { - req = { params: { username: 'DireStraits' } }; + const student = getDireStraits(); + req = { params: { username: student.username } }; await getStudentHandler(req as Request, res as Response); @@ -83,11 +88,12 @@ describe('Student controllers', () => { }); it('Create duplicate student', async () => { + const student = getDireStraits(); req = { body: { - username: 'DireStraits', - firstName: 'dupe', - lastName: 'dupe', + username: student.username, + firstName: student.firstName, + lastName: student.lastName, }, }; @@ -111,14 +117,17 @@ describe('Student controllers', () => { // Check is DireStraits is part of the student list const studentUsernames = result.students.map((s: StudentDTO) => s.username); - expect(studentUsernames).toContain('DireStraits'); + + expect(studentUsernames).toContain(TEST_STUDENTS[0].username); // Check length, +1 because of create expect(result.students).toHaveLength(TEST_STUDENTS.length); }); it('Student classes', async () => { - req = { params: { username: 'DireStraits' }, query: {} }; + const class_ = getClass02(); + const member = class_.students[0]; + req = { params: { username: member.username }, query: {} }; await getStudentClassesHandler(req as Request, res as Response); @@ -129,7 +138,9 @@ describe('Student controllers', () => { }); it('Student groups', async () => { - req = { params: { username: 'DireStraits' }, query: {} }; + const group = getTestGroup01(); + const member = group.members[0]; + req = { params: { username: member.username }, query: {} }; await getStudentGroupsHandler(req as Request, res as Response); @@ -140,7 +151,8 @@ describe('Student controllers', () => { }); it('Student submissions', async () => { - req = { params: { username: 'DireStraits' }, query: { full: 'true' } }; + const submission = getSubmission01(); + req = { params: { username: submission.submitter.username }, query: { full: 'true' } }; await getStudentSubmissionsHandler(req as Request, res as Response); @@ -151,7 +163,8 @@ describe('Student controllers', () => { }); it('Student questions', async () => { - req = { params: { username: 'DireStraits' }, query: { full: 'true' } }; + const question = getQuestion01(); + req = { params: { username: question.author.username }, query: { full: 'true' } }; await getStudentQuestionsHandler(req as Request, res as Response); @@ -168,8 +181,9 @@ describe('Student controllers', () => { }); it('Get join requests by student', async () => { + const jr = getClassJoinRequest02(); req = { - params: { username: 'PinkFloyd' }, + params: { username: jr.requester.username }, }; await getStudentRequestsHandler(req as Request, res as Response); @@ -186,8 +200,9 @@ describe('Student controllers', () => { }); it('Get join request by student and class', async () => { + const jr = getClassJoinRequest02(); req = { - params: { username: 'PinkFloyd', classId: getClass02().classId }, + params: { username: jr.requester.username, classId: jr.class.classId! }, }; await getStudentRequestHandler(req as Request, res as Response); @@ -200,9 +215,11 @@ describe('Student controllers', () => { }); it('Create and delete join request', async () => { + const student = getTheDoors(); + const class_ = getClass02(); req = { - params: { username: 'TheDoors' }, - body: { classId: getClass02().classId }, + params: { username: student.username }, + body: { classId: class_.classId! }, }; await createStudentRequestHandler(req as Request, res as Response); @@ -210,7 +227,7 @@ describe('Student controllers', () => { expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ request: expect.anything() })); req = { - params: { username: 'TheDoors', classId: getClass02().classId }, + params: { username: student.username, classId: class_.classId! }, }; await deleteClassJoinRequestHandler(req as Request, res as Response); @@ -221,18 +238,21 @@ describe('Student controllers', () => { }); it('Create join request student already in class error', async () => { + const student = getNoordkaap(); + const class_ = getClass02(); req = { - params: { username: 'Noordkaap' }, - body: { classId: getClass02().classId }, + params: { username: student.username }, + body: { classId: class_.classId! }, }; await expect(async () => createStudentRequestHandler(req as Request, res as Response)).rejects.toThrow(ConflictException); }); it('Create join request duplicate', async () => { + const jr = getClassJoinRequest02(); req = { - params: { username: 'Tool' }, - body: { classId: getClass02().classId }, + params: { username: jr.requester.username }, + body: { classId: jr.class.classId! }, }; await expect(async () => createStudentRequestHandler(req as Request, res as Response)).rejects.toThrow(ConflictException); diff --git a/backend/tests/controllers/teacher-invitations.test.ts b/backend/tests/controllers/teacher-invitations.test.ts index 675efea1..289d384a 100644 --- a/backend/tests/controllers/teacher-invitations.test.ts +++ b/backend/tests/controllers/teacher-invitations.test.ts @@ -12,7 +12,9 @@ import { TeacherInvitationData } from '@dwengo-1/common/interfaces/teacher-invit import { getClassHandler } from '../../src/controllers/classes'; import { BadRequestException } from '../../src/exceptions/bad-request-exception'; import { ClassStatus } from '@dwengo-1/common/util/class-join-request'; -import { getClass02 } from '../test_assets/classes/classes.testdata'; +import { getTeacherInvitation01 } from '../test_assets/classes/teacher-invitations.testdata.js'; +import { getLimpBizkit, getTestleerkracht1 } from '../test_assets/users/teachers.testdata.js'; +import { getClass02 } from '../test_assets/classes/classes.testdata.js'; describe('Teacher controllers', () => { let req: Partial; @@ -32,7 +34,8 @@ describe('Teacher controllers', () => { }); it('Get teacher invitations by', async () => { - req = { params: { username: 'LimpBizkit' }, query: { sent: 'true' } }; + const ti = getTeacherInvitation01(); + req = { params: { username: ti.sender.username }, query: { sent: 'true' } }; await getAllInvitationsHandler(req as Request, res as Response); @@ -44,7 +47,8 @@ describe('Teacher controllers', () => { }); it('Get teacher invitations for', async () => { - req = { params: { username: 'FooFighters' }, query: { by: 'false' } }; + const ti = getTeacherInvitation01(); + req = { params: { username: ti.receiver.username }, query: { by: 'false' } }; await getAllInvitationsHandler(req as Request, res as Response); @@ -55,10 +59,13 @@ describe('Teacher controllers', () => { }); it('Create and delete invitation', async () => { + const sender = getLimpBizkit(); + const receiver = getTestleerkracht1(); + const class_ = getClass02(); const body = { - sender: 'LimpBizkit', - receiver: 'testleerkracht1', - class: getClass02().classId, + sender: sender.username, + receiver: receiver.username, + class: class_.classId, } as TeacherInvitationData; req = { body }; @@ -66,9 +73,9 @@ describe('Teacher controllers', () => { req = { params: { - sender: 'LimpBizkit', - receiver: 'testleerkracht1', - classId: getClass02().classId, + sender: sender.username, + receiver: receiver.username, + classId: class_.classId!, }, body: { accepted: 'false' }, }; @@ -77,11 +84,12 @@ describe('Teacher controllers', () => { }); it('Get invitation', async () => { + const ti = getTeacherInvitation01(); req = { params: { - sender: 'LimpBizkit', - receiver: 'FooFighters', - classId: getClass02().classId, + sender: ti.sender.username, + receiver: ti.receiver.username, + classId: ti.class.classId!, }, }; await getInvitationHandler(req as Request, res as Response); @@ -98,10 +106,11 @@ describe('Teacher controllers', () => { }); it('Accept invitation', async () => { + const ti = getTeacherInvitation01(); const body = { - sender: 'LimpBizkit', - receiver: 'FooFighters', - class: getClass02().classId, + sender: ti.sender.username, + receiver: ti.receiver.username, + class: ti.class.classId, } as TeacherInvitationData; req = { body }; @@ -112,13 +121,13 @@ describe('Teacher controllers', () => { req = { params: { - id: getClass02().classId, + id: ti.class.classId!, }, }; await getClassHandler(req as Request, res as Response); const result = jsonMock.mock.lastCall?.[0]; - expect(result.class.teachers).toContain('FooFighters'); + expect(result.class.teachers).toContain(ti.receiver.username); }); }); diff --git a/backend/tests/controllers/teachers.test.ts b/backend/tests/controllers/teachers.test.ts index fcf80d90..fe36e99b 100644 --- a/backend/tests/controllers/teachers.test.ts +++ b/backend/tests/controllers/teachers.test.ts @@ -16,7 +16,9 @@ import { BadRequestException } from '../../src/exceptions/bad-request-exception. import { EntityAlreadyExistsException } from '../../src/exceptions/entity-already-exists-exception.js'; import { getStudentRequestsHandler } from '../../src/controllers/students.js'; import { getClassHandler } from '../../src/controllers/classes'; -import { getClass02 } from '../test_assets/classes/classes.testdata'; +import { getFooFighters, getTestleerkracht1 } from '../test_assets/users/teachers.testdata.js'; +import { getClass02 } from '../test_assets/classes/classes.testdata.js'; +import { getClassJoinRequest01 } from '../test_assets/classes/class-join-requests.testdata.js'; describe('Teacher controllers', () => { let req: Partial; @@ -36,7 +38,8 @@ describe('Teacher controllers', () => { }); it('Get teacher', async () => { - req = { params: { username: 'FooFighters' } }; + const teacher = getFooFighters(); + req = { params: { username: teacher.username } }; await getTeacherHandler(req as Request, res as Response); @@ -77,12 +80,13 @@ describe('Teacher controllers', () => { expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ teacher: expect.objectContaining(teacher) })); }); - it('Create duplicate student', async () => { + it('Create duplicate teacher', async () => { + const teacher = getFooFighters(); req = { body: { - username: 'FooFighters', - firstName: 'Dave', - lastName: 'Grohl', + username: teacher.username, + firstName: teacher.firstName, + lastName: teacher.lastName, }, }; @@ -104,20 +108,22 @@ describe('Teacher controllers', () => { const result = jsonMock.mock.lastCall?.[0]; - expect(result.teachers).toContain('testleerkracht1'); + const teacher = getTestleerkracht1(); + expect(result.teachers).toContain(teacher.username); - expect(result.teachers).toHaveLength(5); + expect(result.teachers.length).toBeGreaterThan(0); }); - it('Deleting non-existent student', async () => { + it('Deleting non-existent teacher', async () => { req = { params: { username: 'doesnotexist' } }; await expect(async () => deleteTeacherHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException); }); it('Get teacher classes', async () => { + const class_ = getClass02(); req = { - params: { username: 'testleerkracht1' }, + params: { username: class_.teachers[0].username }, query: { full: 'true' }, }; @@ -130,9 +136,10 @@ describe('Teacher controllers', () => { expect(result.classes.length).toBeGreaterThan(0); }); - it('Get teacher students', async () => { + it('Get teacher teachers', async () => { + const teacher = getTestleerkracht1(); req = { - params: { username: 'testleerkracht1' }, + params: { username: teacher.username }, query: { full: 'true' }, }; @@ -145,30 +152,10 @@ describe('Teacher controllers', () => { expect(result.students.length).toBeGreaterThan(0); }); - /* - - It('Get teacher questions', async () => { - req = { - params: { username: 'FooFighters' }, - query: { full: 'true' }, - }; - - await getTeacherQuestionHandler(req as Request, res as Response); - - expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ questions: expect.anything() })); - - const result = jsonMock.mock.lastCall?.[0]; - // console.log('[TEACHER QUESTIONS]', result.questions); - expect(result.questions.length).toBeGreaterThan(0); - - // TODO fix - }); - - */ - it('Get join requests by class', async () => { + const jr = getClassJoinRequest01(); req = { - params: { classId: getClass02().classId }, + params: { classId: jr.class.classId! }, }; await getStudentJoinRequestHandler(req as Request, res as Response); @@ -181,8 +168,9 @@ describe('Teacher controllers', () => { }); it('Update join request status', async () => { + const jr = getClassJoinRequest01(); req = { - params: { classId: getClass02().classId, studentUsername: 'PinkFloyd' }, + params: { classId: jr.class.classId!, studentUsername: jr.requester.username }, body: { accepted: 'true' }, }; @@ -191,7 +179,7 @@ describe('Teacher controllers', () => { expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ request: expect.anything() })); req = { - params: { username: 'PinkFloyd' }, + params: { username: jr.requester.username }, }; await getStudentRequestsHandler(req as Request, res as Response); @@ -200,11 +188,11 @@ describe('Teacher controllers', () => { expect(status).toBeTruthy(); req = { - params: { id: getClass02().classId }, + params: { id: jr.class.classId! }, }; await getClassHandler(req as Request, res as Response); const students: string[] = jsonMock.mock.lastCall?.[0].class.students; - expect(students).contains('PinkFloyd'); + expect(students).contains(jr.requester.username); }); }); diff --git a/backend/tests/data/assignments/assignments.test.ts b/backend/tests/data/assignments/assignments.test.ts index f5452035..b0839d10 100644 --- a/backend/tests/data/assignments/assignments.test.ts +++ b/backend/tests/data/assignments/assignments.test.ts @@ -1,49 +1,60 @@ import { beforeAll, describe, expect, it } from 'vitest'; import { setupTestApp } from '../../setup-tests'; import { AssignmentRepository } from '../../../src/data/assignments/assignment-repository'; -import { getAssignmentRepository, getClassRepository } from '../../../src/data/repositories'; -import { ClassRepository } from '../../../src/data/classes/class-repository'; +import { getAssignmentRepository } from '../../../src/data/repositories'; import { getClass02 } from '../../test_assets/classes/classes.testdata'; +import { getAssignment02, getAssignment03 } from '../../test_assets/assignments/assignments.testdata'; +import { getTestleerkracht1 } from '../../test_assets/users/teachers.testdata'; describe('AssignmentRepository', () => { let assignmentRepository: AssignmentRepository; - let classRepository: ClassRepository; beforeAll(async () => { await setupTestApp(); assignmentRepository = getAssignmentRepository(); - classRepository = getClassRepository(); }); it('should return the requested assignment', async () => { - const class_ = await classRepository.findById(getClass02().classId); - const assignment = await assignmentRepository.findByClassAndId(class_!, 21001); + const class_ = getClass02(); + const usedAssignment = getAssignment02(); + const assignment = await assignmentRepository.findByClassAndId(class_, 21001); expect(assignment).toBeTruthy(); - expect(assignment!.title).toBe('tool'); + expect(assignment!.description).toBe(usedAssignment.description); + expect(assignment!.id).toBe(usedAssignment.id); + expect(assignment!.learningPathHruid).toBe(usedAssignment.learningPathHruid); + expect(assignment!.within.classId).toBe(usedAssignment.within.classId); + expect(assignment!.title).toBe(usedAssignment.title); }); it('should return all assignments for a class', async () => { - const class_ = await classRepository.findById(getClass02().classId); - const assignments = await assignmentRepository.findAllAssignmentsInClass(class_!); + const class_ = getClass02(); + const usedAssignment = getAssignment02(); + const assignments = await assignmentRepository.findAllAssignmentsInClass(class_); expect(assignments).toBeTruthy(); expect(assignments).toHaveLength(1); - expect(assignments[0].title).toBe('tool'); + const assignment = assignments[0]; + expect(assignment.description).toBe(usedAssignment.description); + expect(assignment.id).toBe(usedAssignment.id); + expect(assignment.learningPathHruid).toBe(usedAssignment.learningPathHruid); + expect(assignment.within.classId).toBe(usedAssignment.within.classId); + expect(assignment.title).toBe(usedAssignment.title); }); it('should find all by username of the responsible teacher', async () => { - const result = await assignmentRepository.findAllByResponsibleTeacher('testleerkracht1'); + const teacher = getTestleerkracht1(); + const result = await assignmentRepository.findAllByResponsibleTeacher(teacher.username); const resultIds = result.map((it) => it.id).sort((a, b) => (a ?? 0) - (b ?? 0)); expect(resultIds).toEqual([21000, 21002, 21003, 21004]); }); it('should not find removed assignment', async () => { - const class_ = await classRepository.findById('id01'); - await assignmentRepository.deleteByClassAndId(class_!, 3); + const deleted = getAssignment03(); + await assignmentRepository.deleteByClassAndId(deleted.within, deleted.id!); - const assignment = await assignmentRepository.findByClassAndId(class_!, 3); + const assignment = await assignmentRepository.findByClassAndId(deleted.within, deleted.id!); expect(assignment).toBeNull(); }); diff --git a/backend/tests/data/assignments/groups.test.ts b/backend/tests/data/assignments/groups.test.ts index 2368085d..5a70077a 100644 --- a/backend/tests/data/assignments/groups.test.ts +++ b/backend/tests/data/assignments/groups.test.ts @@ -1,50 +1,56 @@ import { beforeAll, describe, expect, it } from 'vitest'; import { setupTestApp } from '../../setup-tests'; import { GroupRepository } from '../../../src/data/assignments/group-repository'; -import { getAssignmentRepository, getClassRepository, getGroupRepository } from '../../../src/data/repositories'; -import { AssignmentRepository } from '../../../src/data/assignments/assignment-repository'; -import { ClassRepository } from '../../../src/data/classes/class-repository'; -import { getClass01, getClass02 } from '../../test_assets/classes/classes.testdata'; +import { getGroupRepository } from '../../../src/data/repositories'; +import { getAssignment01, getAssignment02 } from '../../test_assets/assignments/assignments.testdata'; +import { getTestGroup01, getTestGroup02, getTestGroup03 } from '../../test_assets/assignments/groups.testdata'; +import { getDireStraits, getNoordkaap } from '../../test_assets/users/students.testdata'; describe('GroupRepository', () => { let groupRepository: GroupRepository; - let assignmentRepository: AssignmentRepository; - let classRepository: ClassRepository; beforeAll(async () => { await setupTestApp(); groupRepository = getGroupRepository(); - assignmentRepository = getAssignmentRepository(); - classRepository = getClassRepository(); }); it('should return the requested group', async () => { - const id = getClass01().classId; - const class_ = await classRepository.findById(id); - const assignment = await assignmentRepository.findByClassAndId(class_!, 21000); + const assignment = getAssignment01(); + const usedGroup = getTestGroup01(); + const member1 = getNoordkaap(); + const member2 = getDireStraits(); - const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 21001); + const group = await groupRepository.findByAssignmentAndGroupNumber(assignment, usedGroup.groupNumber!); expect(group).toBeTruthy(); + expect(group?.groupNumber).toBe(usedGroup.groupNumber); + expect(group!.members[0].username).toBeOneOf([member1.username, member2.username]); + expect(group!.members[1].username).toBeOneOf([member1.username, member2.username]); + expect(group!.assignment.id).toBe(usedGroup.assignment.id); }); it('should return all groups for assignment', async () => { - const class_ = await classRepository.findById(getClass01().classId); - const assignment = await assignmentRepository.findByClassAndId(class_!, 21000); + const assignment = getAssignment01(); + const gr1 = getTestGroup01(); + const gr2 = getTestGroup02(); + const gr3 = getTestGroup03(); - const groups = await groupRepository.findAllGroupsForAssignment(assignment!); + const groups = await groupRepository.findAllGroupsForAssignment(assignment); expect(groups).toBeTruthy(); expect(groups).toHaveLength(3); + expect(groups[0].groupNumber).toBeOneOf([gr1.groupNumber, gr2.groupNumber, gr3.groupNumber]); + expect(groups[1].groupNumber).toBeOneOf([gr1.groupNumber, gr2.groupNumber, gr3.groupNumber]); + expect(groups[2].groupNumber).toBeOneOf([gr1.groupNumber, gr2.groupNumber, gr3.groupNumber]); }); it('should not find removed group', async () => { - const class_ = await classRepository.findById(getClass02().classId); - const assignment = await assignmentRepository.findByClassAndId(class_!, 21001); + const assignment = getAssignment02(); + const deleted = getTestGroup01(); - await groupRepository.deleteByAssignmentAndGroupNumber(assignment!, 21001); + await groupRepository.deleteByAssignmentAndGroupNumber(assignment, deleted.groupNumber!); - const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 1); + const group = await groupRepository.findByAssignmentAndGroupNumber(assignment, deleted.groupNumber!); expect(group).toBeNull(); }); diff --git a/backend/tests/data/assignments/submissions.test.ts b/backend/tests/data/assignments/submissions.test.ts index 77c163d2..16f0e5a2 100644 --- a/backend/tests/data/assignments/submissions.test.ts +++ b/backend/tests/data/assignments/submissions.test.ts @@ -1,81 +1,75 @@ import { beforeAll, describe, expect, it } from 'vitest'; import { setupTestApp } from '../../setup-tests'; import { SubmissionRepository } from '../../../src/data/assignments/submission-repository'; -import { - getAssignmentRepository, - getClassRepository, - getGroupRepository, - getStudentRepository, - getSubmissionRepository, -} from '../../../src/data/repositories'; +import { getSubmissionRepository } from '../../../src/data/repositories'; import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier'; -import { Language } from '@dwengo-1/common/util/language'; -import { StudentRepository } from '../../../src/data/users/student-repository'; -import { GroupRepository } from '../../../src/data/assignments/group-repository'; -import { AssignmentRepository } from '../../../src/data/assignments/assignment-repository'; -import { ClassRepository } from '../../../src/data/classes/class-repository'; import { Submission } from '../../../src/entities/assignments/submission.entity'; -import { Class } from '../../../src/entities/classes/class.entity'; -import { Assignment } from '../../../src/entities/assignments/assignment.entity'; import { testLearningObject01 } from '../../test_assets/content/learning-objects.testdata'; -import { getClass01 } from '../../test_assets/classes/classes.testdata'; +import { getSubmission01, getSubmission02, getSubmission07, getSubmission08 } from '../../test_assets/assignments/submission.testdata'; +import { getAssignment01 } from '../../test_assets/assignments/assignments.testdata'; +import { getTestGroup02 } from '../../test_assets/assignments/groups.testdata'; describe('SubmissionRepository', () => { let submissionRepository: SubmissionRepository; - let studentRepository: StudentRepository; - let groupRepository: GroupRepository; - let assignmentRepository: AssignmentRepository; - let classRepository: ClassRepository; beforeAll(async () => { await setupTestApp(); submissionRepository = getSubmissionRepository(); - studentRepository = getStudentRepository(); - groupRepository = getGroupRepository(); - assignmentRepository = getAssignmentRepository(); - classRepository = getClassRepository(); }); it('should find the requested submission', async () => { - const id = new LearningObjectIdentifier('id03', Language.English, 1); - const submission = await submissionRepository.findSubmissionByLearningObjectAndSubmissionNumber(id, 1); + const usedSubmission = getSubmission01(); + const id = new LearningObjectIdentifier( + usedSubmission.learningObjectHruid, + usedSubmission.learningObjectLanguage, + usedSubmission.learningObjectVersion + ); + const submission = await submissionRepository.findSubmissionByLearningObjectAndSubmissionNumber(id, usedSubmission.submissionNumber!); expect(submission).toBeTruthy(); - expect(submission?.content).toBe('sub1'); + expect(submission?.content).toBe(usedSubmission.content); + expect(submission?.submissionNumber).toBe(usedSubmission.submissionNumber); + expect(submission?.submitter.username).toBe(usedSubmission.submitter.username); }); it('should find the most recent submission for a student', async () => { - const id = new LearningObjectIdentifier('id02', Language.English, 1); - const student = await studentRepository.findByUsername('Noordkaap'); - const submission = await submissionRepository.findMostRecentSubmissionForStudent(id, student!); + const usedSubmission = getSubmission02(); + const id = new LearningObjectIdentifier( + usedSubmission.learningObjectHruid, + usedSubmission.learningObjectLanguage, + usedSubmission.learningObjectVersion + ); + + const submission = await submissionRepository.findMostRecentSubmissionForStudent(id, usedSubmission.submitter); expect(submission).toBeTruthy(); - expect(submission?.submissionTime.getDate()).toBe(25); + expect(submission?.submissionTime).toStrictEqual(usedSubmission.submissionTime); }); it('should find the most recent submission for a group', async () => { - const id = new LearningObjectIdentifier('id03', Language.English, 1); - const class_ = await classRepository.findById(getClass01().classId); - const assignment = await assignmentRepository.findByClassAndId(class_!, 21000); - const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 21001); - const submission = await submissionRepository.findMostRecentSubmissionForGroup(id, group!); + const usedSubmission = getSubmission02(); + const id = new LearningObjectIdentifier( + usedSubmission.learningObjectHruid, + usedSubmission.learningObjectLanguage, + usedSubmission.learningObjectVersion + ); + + const submission = await submissionRepository.findMostRecentSubmissionForGroup(id, usedSubmission.onBehalfOf); expect(submission).toBeTruthy(); - expect(submission?.submissionTime.getDate()).toBe(25); + expect(submission?.submissionTime).toStrictEqual(usedSubmission.submissionTime); }); - let clazz: Class | null; - let assignment: Assignment | null; - let loId: LearningObjectIdentifier; it('should find all submissions for a certain learning object and assignment', async () => { - clazz = await classRepository.findById(getClass01().classId); - assignment = await assignmentRepository.findByClassAndId(clazz!, 21000); - loId = { - hruid: 'id02', - language: Language.English, - version: 1, + const usedSubmission = getSubmission08(); + const assignment = getAssignment01(); + + const loId = { + hruid: usedSubmission.learningObjectHruid, + language: usedSubmission.learningObjectLanguage, + version: usedSubmission.learningObjectVersion, }; - const result = await submissionRepository.findAllSubmissionsForLearningObjectAndAssignment(loId, assignment!); + const result = await submissionRepository.findAllSubmissionsForLearningObjectAndAssignment(loId, assignment); sortSubmissions(result); expect(result).toHaveLength(3); @@ -94,8 +88,15 @@ describe('SubmissionRepository', () => { }); it('should find only the submissions for a certain learning object and assignment made for the given group', async () => { - const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 21002); - const result = await submissionRepository.findAllSubmissionsForLearningObjectAndGroup(loId, group!); + const group = getTestGroup02(); + const usedSubmission = getSubmission08(); + const loId = { + hruid: usedSubmission.learningObjectHruid, + language: usedSubmission.learningObjectLanguage, + version: usedSubmission.learningObjectVersion, + }; + + const result = await submissionRepository.findAllSubmissionsForLearningObjectAndGroup(loId, group); expect(result).toHaveLength(1); @@ -108,10 +109,11 @@ describe('SubmissionRepository', () => { }); it('should not find a deleted submission', async () => { + const usedSubmission = getSubmission07(); const id = new LearningObjectIdentifier(testLearningObject01.hruid, testLearningObject01.language, testLearningObject01.version); - await submissionRepository.deleteSubmissionByLearningObjectAndSubmissionNumber(id, 1); + await submissionRepository.deleteSubmissionByLearningObjectAndSubmissionNumber(id, usedSubmission.submissionNumber!); - const submission = await submissionRepository.findSubmissionByLearningObjectAndSubmissionNumber(id, 1); + const submission = await submissionRepository.findSubmissionByLearningObjectAndSubmissionNumber(id, usedSubmission.submissionNumber!); expect(submission).toBeNull(); }); diff --git a/backend/tests/data/classes/class-join-request.test.ts b/backend/tests/data/classes/class-join-request.test.ts index 4e18c116..d34525a1 100644 --- a/backend/tests/data/classes/class-join-request.test.ts +++ b/backend/tests/data/classes/class-join-request.test.ts @@ -1,45 +1,49 @@ import { beforeAll, describe, expect, it } from 'vitest'; import { setupTestApp } from '../../setup-tests'; import { ClassJoinRequestRepository } from '../../../src/data/classes/class-join-request-repository'; -import { getClassJoinRequestRepository, getClassRepository, getStudentRepository } from '../../../src/data/repositories'; -import { StudentRepository } from '../../../src/data/users/student-repository'; -import { ClassRepository } from '../../../src/data/classes/class-repository'; +import { getClassJoinRequestRepository } from '../../../src/data/repositories'; +import { getPinkFloyd, getSmashingPumpkins } from '../../test_assets/users/students.testdata'; import { getClass02, getClass03 } from '../../test_assets/classes/classes.testdata'; +import { getClassJoinRequest01, getClassJoinRequest02, getClassJoinRequest03 } from '../../test_assets/classes/class-join-requests.testdata'; describe('ClassJoinRequestRepository', () => { let classJoinRequestRepository: ClassJoinRequestRepository; - let studentRepository: StudentRepository; - let cassRepository: ClassRepository; beforeAll(async () => { await setupTestApp(); classJoinRequestRepository = getClassJoinRequestRepository(); - studentRepository = getStudentRepository(); - cassRepository = getClassRepository(); }); it('should list all requests from student to join classes', async () => { - const student = await studentRepository.findByUsername('PinkFloyd'); - const requests = await classJoinRequestRepository.findAllRequestsBy(student!); + const studentUsed = getPinkFloyd(); + const jr1 = getClassJoinRequest01(); + const jr2 = getClassJoinRequest03(); + const requests = await classJoinRequestRepository.findAllRequestsBy(studentUsed); expect(requests).toBeTruthy(); expect(requests).toHaveLength(2); + expect(requests[0].class.classId!).toBeOneOf([jr1.class.classId!, jr2.class.classId!]); + expect(requests[1].class.classId!).toBeOneOf([jr1.class.classId!, jr2.class.classId!]); }); it('should list all requests to a single class', async () => { - const class_ = await cassRepository.findById(getClass02().classId); - const requests = await classJoinRequestRepository.findAllOpenRequestsTo(class_!); + const class_ = getClass02(); + const jr1 = getClassJoinRequest01(); + const jr2 = getClassJoinRequest02(); + const requests = await classJoinRequestRepository.findAllOpenRequestsTo(class_); expect(requests).toBeTruthy(); expect(requests).toHaveLength(2); + expect(requests[0].class.classId).toBeOneOf([jr1.class.classId, jr2.class.classId]); + expect(requests[1].class.classId).toBeOneOf([jr1.class.classId, jr2.class.classId]); }); it('should not find a removed request', async () => { - const student = await studentRepository.findByUsername('SmashingPumpkins'); - const class_ = await cassRepository.findById(getClass03().classId); - await classJoinRequestRepository.deleteBy(student!, class_!); + const studentUsed = getSmashingPumpkins(); + const class_ = getClass03(); + await classJoinRequestRepository.deleteBy(studentUsed, class_); - const request = await classJoinRequestRepository.findAllRequestsBy(student!); + const request = await classJoinRequestRepository.findAllRequestsBy(studentUsed); expect(request).toHaveLength(0); }); diff --git a/backend/tests/data/classes/classes.test.ts b/backend/tests/data/classes/classes.test.ts index 6930e5ac..2f3683d8 100644 --- a/backend/tests/data/classes/classes.test.ts +++ b/backend/tests/data/classes/classes.test.ts @@ -3,6 +3,7 @@ import { ClassRepository } from '../../../src/data/classes/class-repository'; import { setupTestApp } from '../../setup-tests'; import { getClassRepository } from '../../../src/data/repositories'; import { getClass01, getClass04 } from '../../test_assets/classes/classes.testdata'; +import { getClass01, getClass04 } from '../../test_assets/classes/classes.testdata'; describe('ClassRepository', () => { let classRepository: ClassRepository; @@ -19,16 +20,18 @@ describe('ClassRepository', () => { }); it('should return requested class', async () => { - const classVar = await classRepository.findById(getClass01().classId); + const expected = getClass01(); + const classVar = await classRepository.findById(expected.classId!); expect(classVar).toBeTruthy(); - expect(classVar?.displayName).toBe('class01'); + expect(classVar?.displayName).toBe(expected.displayName); }); it('class should be gone after deletion', async () => { - await classRepository.deleteById(getClass04().classId); + const deleted = getClass04(); + await classRepository.deleteById(deleted.classId!); - const classVar = await classRepository.findById(getClass04().classId); + const classVar = await classRepository.findById(deleted.classId!); expect(classVar).toBeNull(); }); diff --git a/backend/tests/data/classes/teacher-invitation.test.ts b/backend/tests/data/classes/teacher-invitation.test.ts index 664e41d2..7b1a0540 100644 --- a/backend/tests/data/classes/teacher-invitation.test.ts +++ b/backend/tests/data/classes/teacher-invitation.test.ts @@ -1,54 +1,62 @@ import { beforeAll, describe, expect, it } from 'vitest'; import { setupTestApp } from '../../setup-tests'; -import { getClassRepository, getTeacherInvitationRepository, getTeacherRepository } from '../../../src/data/repositories'; +import { getTeacherInvitationRepository } from '../../../src/data/repositories'; import { TeacherInvitationRepository } from '../../../src/data/classes/teacher-invitation-repository'; -import { TeacherRepository } from '../../../src/data/users/teacher-repository'; -import { ClassRepository } from '../../../src/data/classes/class-repository'; +import { getFooFighters, getLimpBizkit } from '../../test_assets/users/teachers.testdata'; +import { getTeacherInvitation01, getTeacherInvitation02, getTeacherInvitation03 } from '../../test_assets/classes/teacher-invitations.testdata'; import { getClass01, getClass02 } from '../../test_assets/classes/classes.testdata'; describe('ClassRepository', () => { let teacherInvitationRepository: TeacherInvitationRepository; - let teacherRepository: TeacherRepository; - let classRepository: ClassRepository; beforeAll(async () => { await setupTestApp(); teacherInvitationRepository = getTeacherInvitationRepository(); - teacherRepository = getTeacherRepository(); - classRepository = getClassRepository(); }); it('should return all invitations from a teacher', async () => { - const teacher = await teacherRepository.findByUsername('LimpBizkit'); - const invitations = await teacherInvitationRepository.findAllInvitationsBy(teacher!); + const teacher = getLimpBizkit(); + const ti1 = getTeacherInvitation01(); + const ti2 = getTeacherInvitation02(); + const invitations = await teacherInvitationRepository.findAllInvitationsBy(teacher); expect(invitations).toBeTruthy(); expect(invitations).toHaveLength(2); + expect(invitations[0].class.classId).toBeOneOf([ti1.class.classId, ti2.class.classId]); + expect(invitations[1].class.classId).toBeOneOf([ti1.class.classId, ti2.class.classId]); }); it('should return all invitations for a teacher', async () => { - const teacher = await teacherRepository.findByUsername('FooFighters'); - const invitations = await teacherInvitationRepository.findAllInvitationsFor(teacher!); + const teacher = getFooFighters(); + const ti1 = getTeacherInvitation01(); + const ti2 = getTeacherInvitation03(); + const invitations = await teacherInvitationRepository.findAllInvitationsFor(teacher); expect(invitations).toBeTruthy(); expect(invitations).toHaveLength(2); + expect(invitations[0].class.classId).toBeOneOf([ti1.class.classId, ti2.class.classId]); + expect(invitations[1].class.classId).toBeOneOf([ti1.class.classId, ti2.class.classId]); }); it('should return all invitations for a class', async () => { - const class_ = await classRepository.findById(getClass02().classId); - const invitations = await teacherInvitationRepository.findAllInvitationsForClass(class_!); + const class_ = getClass02(); + const ti1 = getTeacherInvitation01(); + const ti2 = getTeacherInvitation02(); + const invitations = await teacherInvitationRepository.findAllInvitationsForClass(class_); expect(invitations).toBeTruthy(); expect(invitations).toHaveLength(2); + expect(invitations[0].class.classId).toBeOneOf([ti1.class.classId, ti2.class.classId]); + expect(invitations[1].class.classId).toBeOneOf([ti1.class.classId, ti2.class.classId]); }); it('should not find a removed invitation', async () => { - const class_ = await classRepository.findById(getClass01().classId); - const sender = await teacherRepository.findByUsername('FooFighters'); - const receiver = await teacherRepository.findByUsername('LimpBizkit'); - await teacherInvitationRepository.deleteBy(class_!, sender!, receiver!); + const class_ = getClass01(); + const sender = getFooFighters(); + const receiver = getLimpBizkit(); + await teacherInvitationRepository.deleteBy(class_, sender, receiver); - const invitation = await teacherInvitationRepository.findAllInvitationsBy(sender!); + const invitation = await teacherInvitationRepository.findAllInvitationsBy(sender); expect(invitation).toHaveLength(0); }); diff --git a/backend/tests/data/content/attachments.test.ts b/backend/tests/data/content/attachments.test.ts index 1a393b15..c271c60b 100644 --- a/backend/tests/data/content/attachments.test.ts +++ b/backend/tests/data/content/attachments.test.ts @@ -2,7 +2,7 @@ import { beforeAll, describe, expect, it } from 'vitest'; import { setupTestApp } from '../../setup-tests.js'; import { getAttachmentRepository } from '../../../src/data/repositories.js'; import { AttachmentRepository } from '../../../src/data/content/attachment-repository.js'; -import { testLearningObject02 } from '../../test_assets/content/learning-objects.testdata'; +import { getAttachment01 } from '../../test_assets/content/attachments.testdata.js'; describe('AttachmentRepository', () => { let attachmentRepository: AttachmentRepository; @@ -13,10 +13,11 @@ describe('AttachmentRepository', () => { }); it('should return the requested attachment', async () => { + const usedAttachment = getAttachment01(); const attachment = await attachmentRepository.findByMostRecentVersionOfLearningObjectAndName( - testLearningObject02.hruid, - testLearningObject02.language, - 'attachment01' + usedAttachment.learningObject.hruid, + usedAttachment.learningObject.language, + usedAttachment.name ); expect(attachment).toBeTruthy(); diff --git a/backend/tests/data/content/learning-object-repository.test.ts b/backend/tests/data/content/learning-object-repository.test.ts index 4761c297..88287bf5 100644 --- a/backend/tests/data/content/learning-object-repository.test.ts +++ b/backend/tests/data/content/learning-object-repository.test.ts @@ -37,7 +37,8 @@ describe('LearningObjectRepository', () => { let newerExample: LearningObject; it('should allow a learning object with the same id except a different version to be added', async () => { - const testLearningObject01Newer = structuredClone(testLearningObject01); + // StructeredClone failed on teacher, this copies all fields to a json object + const testLearningObject01Newer = { ...testLearningObject01 }; testLearningObject01Newer.version = 10; testLearningObject01Newer.title += ' (nieuw)'; testLearningObject01Newer.uuid = v4(); diff --git a/backend/tests/data/questions/answers.test.ts b/backend/tests/data/questions/answers.test.ts index 80cd3034..5447900e 100644 --- a/backend/tests/data/questions/answers.test.ts +++ b/backend/tests/data/questions/answers.test.ts @@ -1,48 +1,39 @@ import { beforeAll, describe, expect, it } from 'vitest'; import { setupTestApp } from '../../setup-tests'; import { AnswerRepository } from '../../../src/data/questions/answer-repository'; -import { getAnswerRepository, getQuestionRepository, getTeacherRepository } from '../../../src/data/repositories'; -import { QuestionRepository } from '../../../src/data/questions/question-repository'; -import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier'; -import { Language } from '@dwengo-1/common/util/language'; -import { TeacherRepository } from '../../../src/data/users/teacher-repository'; +import { getAnswerRepository } from '../../../src/data/repositories'; +import { getQuestion01, getQuestion02 } from '../../test_assets/questions/questions.testdata'; +import { getAnswer01, getAnswer02, getAnswer03 } from '../../test_assets/questions/answers.testdata'; +import { getFooFighters } from '../../test_assets/users/teachers.testdata'; describe('AnswerRepository', () => { let answerRepository: AnswerRepository; - let questionRepository: QuestionRepository; - let teacherRepository: TeacherRepository; beforeAll(async () => { await setupTestApp(); answerRepository = getAnswerRepository(); - questionRepository = getQuestionRepository(); - teacherRepository = getTeacherRepository(); }); it('should find all answers to a question', async () => { - const id = new LearningObjectIdentifier('id05', Language.English, 1); - const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); + const question = getQuestion02(); + const a1 = getAnswer01(); + const a2 = getAnswer02(); - const question = questions.find((it) => it.sequenceNumber === 2); - - const answers = await answerRepository.findAllAnswersToQuestion(question!); + const answers = await answerRepository.findAllAnswersToQuestion(question); expect(answers).toBeTruthy(); expect(answers).toHaveLength(2); - expect(answers[0].content).toBeOneOf(['answer', 'answer2']); - expect(answers[1].content).toBeOneOf(['answer', 'answer2']); + expect(answers[0].content).toBeOneOf([a1.content, a2.content]); + expect(answers[1].content).toBeOneOf([a1.content, a2.content]); }); it('should create an answer to a question', async () => { - const teacher = await teacherRepository.findByUsername('FooFighters'); - const id = new LearningObjectIdentifier('id05', Language.English, 1); - const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); - - const question = questions[0]; + const teacher = getFooFighters(); + const question = getQuestion01(); await answerRepository.createAnswer({ toQuestion: question, - author: teacher!, + author: teacher, content: 'created answer', }); @@ -54,12 +45,11 @@ describe('AnswerRepository', () => { }); it('should not find a removed answer', async () => { - const id = new LearningObjectIdentifier('id04', Language.English, 1); - const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); + const deleted = getAnswer03(); - await answerRepository.removeAnswerByQuestionAndSequenceNumber(questions[0], 1); + await answerRepository.removeAnswerByQuestionAndSequenceNumber(deleted.toQuestion, deleted.sequenceNumber!); - const emptyList = await answerRepository.findAllAnswersToQuestion(questions[0]); + const emptyList = await answerRepository.findAllAnswersToQuestion(deleted.toQuestion); expect(emptyList).toHaveLength(0); }); diff --git a/backend/tests/data/questions/questions.test.ts b/backend/tests/data/questions/questions.test.ts index 950845a6..1e52b743 100644 --- a/backend/tests/data/questions/questions.test.ts +++ b/backend/tests/data/questions/questions.test.ts @@ -1,70 +1,72 @@ import { beforeAll, describe, expect, it } from 'vitest'; import { setupTestApp } from '../../setup-tests'; import { QuestionRepository } from '../../../src/data/questions/question-repository'; -import { - getAssignmentRepository, - getClassRepository, - getGroupRepository, - getQuestionRepository, - getStudentRepository, -} from '../../../src/data/repositories'; -import { StudentRepository } from '../../../src/data/users/student-repository'; +import { getQuestionRepository } from '../../../src/data/repositories'; import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier'; -import { Language } from '@dwengo-1/common/util/language'; import { Question } from '../../../src/entities/questions/question.entity'; -import { Class } from '../../../src/entities/classes/class.entity'; -import { Assignment } from '../../../src/entities/assignments/assignment.entity'; -import { getClass01 } from '../../test_assets/classes/classes.testdata'; +import { testLearningObject03, testLearningObject05 } from '../../test_assets/content/learning-objects.testdata'; +import { getQuestion01, getQuestion02, getQuestion03, getQuestion05, getQuestion06 } from '../../test_assets/questions/questions.testdata'; +import { getNoordkaap, getTool } from '../../test_assets/users/students.testdata'; +import { getAssignment01 } from '../../test_assets/assignments/assignments.testdata'; +import { getTestGroup01 } from '../../test_assets/assignments/groups.testdata'; describe('QuestionRepository', () => { let questionRepository: QuestionRepository; - let studentRepository: StudentRepository; beforeAll(async () => { await setupTestApp(); questionRepository = getQuestionRepository(); - studentRepository = getStudentRepository(); }); it('should return all questions part of the given learning object', async () => { - const id = new LearningObjectIdentifier('id05', Language.English, 1); - const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); + const q1 = getQuestion01(); + const q2 = getQuestion02(); + const q3 = getQuestion05(); + const q4 = getQuestion06(); + const loid = { + hruid: q1.learningObjectHruid, + language: q1.learningObjectLanguage, + version: q1.learningObjectVersion, + } as LearningObjectIdentifier; + const questions = await questionRepository.findAllQuestionsAboutLearningObject(loid); expect(questions).toBeTruthy(); expect(questions).toHaveLength(4); + expect(questions[0].sequenceNumber!).toBeOneOf([q1.sequenceNumber, q2.sequenceNumber, q3.sequenceNumber, q4.sequenceNumber]); + expect(questions[1].sequenceNumber!).toBeOneOf([q1.sequenceNumber, q2.sequenceNumber, q3.sequenceNumber, q4.sequenceNumber]); + expect(questions[2].sequenceNumber!).toBeOneOf([q1.sequenceNumber, q2.sequenceNumber, q3.sequenceNumber, q4.sequenceNumber]); + expect(questions[3].sequenceNumber!).toBeOneOf([q1.sequenceNumber, q2.sequenceNumber, q3.sequenceNumber, q4.sequenceNumber]); }); it('should create new question', async () => { - const id = new LearningObjectIdentifier('id03', Language.English, 1); - const student = await studentRepository.findByUsername('Noordkaap'); - - const clazz = await getClassRepository().findById(getClass01().classId); - const assignment = await getAssignmentRepository().findByClassAndId(clazz!, 21000); - const group = await getGroupRepository().findByAssignmentAndGroupNumber(assignment!, 21001); + const id = { + hruid: testLearningObject03.hruid, + language: testLearningObject03.language, + version: testLearningObject03.version, + } as LearningObjectIdentifier; + const student = getNoordkaap(); + const group = getTestGroup01(); await questionRepository.createQuestion({ loId: id, - inGroup: group!, - author: student!, + inGroup: group, + author: student, content: 'question?', }); const question = await questionRepository.findAllQuestionsAboutLearningObject(id); expect(question).toBeTruthy(); expect(question).toHaveLength(1); + expect(question[0].content).toBe('question?'); }); - let clazz: Class | null; - let assignment: Assignment | null; - let loId: LearningObjectIdentifier; it('should find all questions for a certain learning object and assignment', async () => { - clazz = await getClassRepository().findById(getClass01().classId); - assignment = await getAssignmentRepository().findByClassAndId(clazz!, 21000); - loId = { - hruid: 'id05', - language: Language.English, - version: 1, + const assignment = getAssignment01(); + const loId = { + hruid: testLearningObject05.hruid, + language: testLearningObject05.language, + version: testLearningObject05.version, }; - const result = await questionRepository.findAllQuestionsAboutLearningObjectInAssignment(loId, assignment!); + const result = await questionRepository.findAllQuestionsAboutLearningObjectInAssignment(loId, assignment); sortQuestions(result); expect(result).toHaveLength(3); @@ -85,7 +87,14 @@ describe('QuestionRepository', () => { }); it("should find only the questions for a certain learning object and assignment asked by the user's group", async () => { - const result = await questionRepository.findAllQuestionsAboutLearningObjectInAssignment(loId, assignment!, 'Tool'); + const loId = { + hruid: testLearningObject05.hruid, + language: testLearningObject05.language, + version: testLearningObject05.version, + }; + const assignment = getAssignment01(); + + const result = await questionRepository.findAllQuestionsAboutLearningObjectInAssignment(loId, assignment, getTool().username); // (student Tool is in group #2) expect(result).toHaveLength(1); @@ -100,12 +109,17 @@ describe('QuestionRepository', () => { }); it('should not find removed question', async () => { - const id = new LearningObjectIdentifier('id04', Language.English, 1); - await questionRepository.removeQuestionByLearningObjectAndSequenceNumber(id, 1); + const usedQuestion = getQuestion03(); + const id = { + hruid: usedQuestion.learningObjectHruid, + language: usedQuestion.learningObjectLanguage, + version: usedQuestion.learningObjectVersion, + } as LearningObjectIdentifier; + await questionRepository.removeQuestionByLearningObjectAndSequenceNumber(id, usedQuestion.sequenceNumber!); - const question = await questionRepository.findAllQuestionsAboutLearningObject(id); + const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); - expect(question).toHaveLength(0); + expect(questions).toHaveLength(0); }); }); diff --git a/backend/tests/data/users/students.test.ts b/backend/tests/data/users/students.test.ts index 42822557..f5d4e2bc 100644 --- a/backend/tests/data/users/students.test.ts +++ b/backend/tests/data/users/students.test.ts @@ -2,6 +2,7 @@ import { setupTestApp } from '../../setup-tests.js'; import { describe, it, expect, beforeAll } from 'vitest'; import { StudentRepository } from '../../../src/data/users/student-repository.js'; import { getStudentRepository } from '../../../src/data/repositories.js'; +import { getNoordkaap } from '../../test_assets/users/students.testdata.js'; const username = 'teststudent'; const firstName = 'John'; @@ -21,11 +22,12 @@ describe('StudentRepository', () => { }); it('should return student from the datbase', async () => { - const student = await studentRepository.findByUsername('Noordkaap'); + const expectation = getNoordkaap(); + const student = await studentRepository.findByUsername(expectation.username); expect(student).toBeTruthy(); - expect(student?.firstName).toBe('Stijn'); - expect(student?.lastName).toBe('Meuris'); + expect(student?.firstName).toBe(expectation.firstName); + expect(student?.lastName).toBe(expectation.lastName); }); it('should return the queried student after he was added', async () => { diff --git a/backend/tests/data/users/teachers.test.ts b/backend/tests/data/users/teachers.test.ts index 62ad6d81..6ac59df0 100644 --- a/backend/tests/data/users/teachers.test.ts +++ b/backend/tests/data/users/teachers.test.ts @@ -2,6 +2,7 @@ import { describe, it, expect, beforeAll } from 'vitest'; import { TeacherRepository } from '../../../src/data/users/teacher-repository'; import { setupTestApp } from '../../setup-tests'; import { getTeacherRepository } from '../../../src/data/repositories'; +import { getFooFighters } from '../../test_assets/users/teachers.testdata'; const username = 'testteacher'; const firstName = 'John'; @@ -21,11 +22,12 @@ describe('TeacherRepository', () => { }); it('should return teacher from the datbase', async () => { - const teacher = await teacherRepository.findByUsername('FooFighters'); + const expected = getFooFighters(); + const teacher = await teacherRepository.findByUsername(expected.username); expect(teacher).toBeTruthy(); - expect(teacher?.firstName).toBe('Dave'); - expect(teacher?.lastName).toBe('Grohl'); + expect(teacher?.firstName).toBe(expected.firstName); + expect(teacher?.lastName).toBe(expected.lastName); }); it('should return the queried teacher after he was added', async () => { @@ -38,9 +40,9 @@ describe('TeacherRepository', () => { }); it('should no longer return the queried teacher after he was removed again', async () => { - await teacherRepository.deleteByUsername('ZesdeMetaal'); + await teacherRepository.deleteByUsername(username); - const retrievedTeacher = await teacherRepository.findByUsername('ZesdeMetaal'); + const retrievedTeacher = await teacherRepository.findByUsername(username); expect(retrievedTeacher).toBeNull(); }); }); diff --git a/backend/tests/setup-tests.ts b/backend/tests/setup-tests.ts index 23fc43ee..29f1bdc6 100644 --- a/backend/tests/setup-tests.ts +++ b/backend/tests/setup-tests.ts @@ -2,11 +2,11 @@ import { forkEntityManager, initORM } from '../src/orm.js'; import dotenv from 'dotenv'; import { makeTestStudents } from './test_assets/users/students.testdata.js'; import { makeTestTeachers } from './test_assets/users/teachers.testdata.js'; -import { makeTestLearningObjects } from './test_assets/content/learning-objects.testdata.js'; +import { makeTestLearningObjects, testLearningObject01 } from './test_assets/content/learning-objects.testdata.js'; import { makeTestLearningPaths } from './test_assets/content/learning-paths.testdata.js'; import { makeTestClasses } from './test_assets/classes/classes.testdata.js'; -import { makeTestAssignemnts } from './test_assets/assignments/assignments.testdata.js'; -import { makeTestGroups } from './test_assets/assignments/groups.testdata.js'; +import { getAssignment01, getAssignment02, makeTestAssignemnts } from './test_assets/assignments/assignments.testdata.js'; +import { getTestGroup01, getTestGroup02, getTestGroup03, getTestGroup04, makeTestGroups } from './test_assets/assignments/groups.testdata.js'; import { makeTestTeacherInvitations } from './test_assets/classes/teacher-invitations.testdata.js'; import { makeTestClassJoinRequests } from './test_assets/classes/class-join-requests.testdata.js'; import { makeTestAttachments } from './test_assets/content/attachments.testdata.js'; @@ -26,22 +26,26 @@ export async function setupTestApp(): Promise { const teachers = makeTestTeachers(em); const learningObjects = makeTestLearningObjects(em); const learningPaths = makeTestLearningPaths(em); - const classes = makeTestClasses(em, students, teachers); - const assignments = makeTestAssignemnts(em, classes); - const groups = makeTestGroups(em, students, assignments); + const classes = makeTestClasses(em); + const assignments = makeTestAssignemnts(em); + const groups = makeTestGroups(em); - assignments[0].groups = new Collection(groups.slice(0, 3)); - assignments[1].groups = new Collection(groups.slice(3, 4)); + const groups1 = [getTestGroup01(), getTestGroup02(), getTestGroup03()]; + const groups2 = [getTestGroup04()]; + const assignment1 = getAssignment01(); + const assignment2 = getAssignment02(); + assignment1.groups = new Collection(groups1); + assignment2.groups = new Collection(groups2); - const teacherInvitations = makeTestTeacherInvitations(em, teachers, classes); - const classJoinRequests = makeTestClassJoinRequests(em, students, classes); - const attachments = makeTestAttachments(em, learningObjects); + const teacherInvitations = makeTestTeacherInvitations(em); + const classJoinRequests = makeTestClassJoinRequests(em); + const attachments = makeTestAttachments(em); - learningObjects[1].attachments = attachments; + testLearningObject01.attachments = attachments; - const questions = makeTestQuestions(em, students, groups); - const answers = makeTestAnswers(em, teachers, questions); - const submissions = makeTestSubmissions(em, students, groups); + const questions = makeTestQuestions(em); + const answers = makeTestAnswers(em); + const submissions = makeTestSubmissions(em); await em.persistAndFlush([ ...students, diff --git a/backend/tests/test_assets/assignments/assignments.testdata.ts b/backend/tests/test_assets/assignments/assignments.testdata.ts index dc477828..021483bc 100644 --- a/backend/tests/test_assets/assignments/assignments.testdata.ts +++ b/backend/tests/test_assets/assignments/assignments.testdata.ts @@ -1,11 +1,10 @@ import { EntityManager } from '@mikro-orm/core'; import { Assignment } from '../../../src/entities/assignments/assignment.entity'; -import { Class } from '../../../src/entities/classes/class.entity'; import { Language } from '@dwengo-1/common/util/language'; -import { testLearningPathWithConditions } from '../content/learning-paths.testdata'; -import { getClassWithTestleerlingAndTestleerkracht } from '../classes/classes.testdata'; +import { testLearningPath01, testLearningPath02, testLearningPathWithConditions } from '../content/learning-paths.testdata'; +import { getClass01, getClass02, getClassWithTestleerlingAndTestleerkracht } from '../classes/classes.testdata'; -export function makeTestAssignemnts(em: EntityManager, classes: Class[]): Assignment[] { +export function makeTestAssignemnts(em: EntityManager): Assignment[] { const futureDate = new Date(); futureDate.setDate(futureDate.getDate() + 7); const pastDate = new Date(); @@ -14,44 +13,44 @@ export function makeTestAssignemnts(em: EntityManager, classes: Class[]): Assign today.setHours(23, 59); assignment01 = em.create(Assignment, { id: 21000, - within: classes[0], + within: getClass01(), title: 'dire straits', description: 'reading', - learningPathHruid: 'un_ai', - learningPathLanguage: Language.English, + learningPathHruid: testLearningPath02.hruid, + learningPathLanguage: testLearningPath02.language as Language, deadline: today, groups: [], }); assignment02 = em.create(Assignment, { id: 21001, - within: classes[1], + within: getClass02(), title: 'tool', description: 'reading', - learningPathHruid: 'id01', - learningPathLanguage: Language.English, + learningPathHruid: testLearningPath01.hruid, + learningPathLanguage: testLearningPath01.language as Language, deadline: futureDate, groups: [], }); assignment03 = em.create(Assignment, { id: 21002, - within: classes[0], + within: getClass01(), title: 'delete', description: 'will be deleted', - learningPathHruid: 'id02', - learningPathLanguage: Language.English, + learningPathHruid: testLearningPath02.hruid, + learningPathLanguage: testLearningPath02.language as Language, deadline: pastDate, groups: [], }); assignment04 = em.create(Assignment, { id: 21003, - within: classes[0], + within: getClass01(), title: 'another assignment', description: 'with a description', - learningPathHruid: 'id01', - learningPathLanguage: Language.English, + learningPathHruid: testLearningPath01.hruid, + learningPathLanguage: testLearningPath01.language as Language, deadline: pastDate, groups: [], }); diff --git a/backend/tests/test_assets/assignments/groups.testdata.ts b/backend/tests/test_assets/assignments/groups.testdata.ts index 4361383b..f2508108 100644 --- a/backend/tests/test_assets/assignments/groups.testdata.ts +++ b/backend/tests/test_assets/assignments/groups.testdata.ts @@ -1,19 +1,18 @@ import { EntityManager } from '@mikro-orm/core'; import { Group } from '../../../src/entities/assignments/group.entity'; -import { Assignment } from '../../../src/entities/assignments/assignment.entity'; -import { Student } from '../../../src/entities/users/student.entity'; -import { getConditionalPathAssignment } from './assignments.testdata'; -import { getTestleerling1 } from '../users/students.testdata'; +import { getAssignment01, getAssignment02, getAssignment04, getConditionalPathAssignment } from './assignments.testdata'; +import { getDireStraits, getNoordkaap, getPinkFloyd, getSmashingPumpkins, getTestleerling1, getTheDoors, getTool } from '../users/students.testdata'; -export function makeTestGroups(em: EntityManager, students: Student[], assignments: Assignment[]): Group[] { +export function makeTestGroups(em: EntityManager): Group[] { /* * Group #1 for Assignment #1 in class 'id01' * => Assigned to do learning path 'id02' */ + // Gets deleted group01 = em.create(Group, { - assignment: assignments[0], + assignment: getAssignment01(), groupNumber: 21001, - members: students.slice(0, 2), + members: [getNoordkaap(), getDireStraits()], }); /* @@ -21,9 +20,9 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen * => Assigned to do learning path 'id02' */ group02 = em.create(Group, { - assignment: assignments[0], + assignment: getAssignment01(), groupNumber: 21002, - members: students.slice(2, 4), + members: [getTool(), getSmashingPumpkins()], }); /* @@ -31,9 +30,9 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen * => Assigned to do learning path 'id02' */ group03 = em.create(Group, { - assignment: assignments[0], + assignment: getAssignment01(), groupNumber: 21003, - members: students.slice(4, 6), + members: [getPinkFloyd(), getTheDoors()], }); /* @@ -41,9 +40,9 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen * => Assigned to do learning path 'id01' */ group04 = em.create(Group, { - assignment: assignments[1], + assignment: getAssignment02(), groupNumber: 21004, - members: students.slice(3, 4), + members: getSmashingPumpkins(), }); /* @@ -51,9 +50,9 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen * => Assigned to do learning path 'id01' */ group05 = em.create(Group, { - assignment: assignments[3], + assignment: getAssignment04(), groupNumber: 21001, - members: students.slice(0, 2), + members: [getNoordkaap(), getDireStraits()], }); /** diff --git a/backend/tests/test_assets/assignments/submission.testdata.ts b/backend/tests/test_assets/assignments/submission.testdata.ts index 81db2229..01ef5d98 100644 --- a/backend/tests/test_assets/assignments/submission.testdata.ts +++ b/backend/tests/test_assets/assignments/submission.testdata.ts @@ -1,97 +1,139 @@ import { EntityManager } from '@mikro-orm/core'; import { Submission } from '../../../src/entities/assignments/submission.entity'; -import { Language } from '@dwengo-1/common/util/language'; -import { Student } from '../../../src/entities/users/student.entity'; -import { Group } from '../../../src/entities/assignments/group.entity'; +import { testLearningObject01, testLearningObject02, testLearningObject03 } from '../content/learning-objects.testdata'; +import { getDireStraits, getNoordkaap, getSmashingPumpkins } from '../users/students.testdata'; +import { getTestGroup01, getTestGroup02, getTestGroup04, getTestGroup05 } from './groups.testdata'; -export function makeTestSubmissions(em: EntityManager, students: Student[], groups: Group[]): Submission[] { - const submission01 = em.create(Submission, { - learningObjectHruid: 'id03', - learningObjectLanguage: Language.English, - learningObjectVersion: 1, +export function makeTestSubmissions(em: EntityManager): Submission[] { + submission01 = em.create(Submission, { + learningObjectHruid: testLearningObject03.hruid, + learningObjectLanguage: testLearningObject03.language, + learningObjectVersion: testLearningObject03.version, submissionNumber: 1, - submitter: students[0], + submitter: getNoordkaap(), submissionTime: new Date(2025, 2, 20), - onBehalfOf: groups[0], // Group #1 for Assignment #1 in class 'id01' + onBehalfOf: getTestGroup01(), // Group #1 for Assignment #1 in class 'id01' content: 'sub1', }); - const submission02 = em.create(Submission, { - learningObjectHruid: 'id03', - learningObjectLanguage: Language.English, - learningObjectVersion: 1, + submission02 = em.create(Submission, { + learningObjectHruid: testLearningObject03.hruid, + learningObjectLanguage: testLearningObject03.language, + learningObjectVersion: testLearningObject03.version, submissionNumber: 2, - submitter: students[0], + submitter: getNoordkaap(), submissionTime: new Date(2025, 2, 25), - onBehalfOf: groups[0], // Group #1 for Assignment #1 in class 'id01' + onBehalfOf: getTestGroup01(), // Group #1 for Assignment #1 in class 'id01' content: '', }); - const submission03 = em.create(Submission, { - learningObjectHruid: 'id02', - learningObjectLanguage: Language.English, - learningObjectVersion: 1, + submission03 = em.create(Submission, { + learningObjectHruid: testLearningObject02.hruid, + learningObjectLanguage: testLearningObject02.language, + learningObjectVersion: testLearningObject02.version, submissionNumber: 1, - submitter: students[0], + submitter: getNoordkaap(), submissionTime: new Date(2025, 2, 20), - onBehalfOf: groups[0], // Group #1 for Assignment #1 in class 'id01' + onBehalfOf: getTestGroup01(), // Group #1 for Assignment #1 in class 'id01' content: '', }); - const submission04 = em.create(Submission, { - learningObjectHruid: 'id02', - learningObjectLanguage: Language.English, - learningObjectVersion: 1, + submission04 = em.create(Submission, { + learningObjectHruid: testLearningObject02.hruid, + learningObjectLanguage: testLearningObject02.language, + learningObjectVersion: testLearningObject02.version, submissionNumber: 2, - submitter: students[0], + submitter: getNoordkaap(), submissionTime: new Date(2025, 2, 25), - onBehalfOf: groups[0], // Group #1 for Assignment #1 in class 'id01' + onBehalfOf: getTestGroup01(), // Group #1 for Assignment #1 in class 'id01' content: '', }); - const submission05 = em.create(Submission, { - learningObjectHruid: 'id01', - learningObjectLanguage: Language.English, - learningObjectVersion: 1, + submission05 = em.create(Submission, { + learningObjectHruid: testLearningObject01.hruid, + learningObjectLanguage: testLearningObject01.language, + learningObjectVersion: testLearningObject01.version, submissionNumber: 1, - submitter: students[1], + submitter: getDireStraits(), submissionTime: new Date(2025, 2, 20), - onBehalfOf: groups[1], // Group #2 for Assignment #1 in class 'id01' + onBehalfOf: getTestGroup02(), // Group #2 for Assignment #1 in class 'id01' content: '', }); - const submission06 = em.create(Submission, { - learningObjectHruid: 'id01', - learningObjectLanguage: Language.English, - learningObjectVersion: 1, + submission06 = em.create(Submission, { + learningObjectHruid: testLearningObject01.hruid, + learningObjectLanguage: testLearningObject01.language, + learningObjectVersion: testLearningObject01.version, submissionNumber: 2, - submitter: students[1], + submitter: getDireStraits(), submissionTime: new Date(2025, 2, 25), - onBehalfOf: groups[4], // Group #5 for Assignment #4 in class 'id01' + onBehalfOf: getTestGroup05(), // Group #5 for Assignment #4 in class 'id01' content: '', }); - const submission07 = em.create(Submission, { - learningObjectHruid: 'id01', - learningObjectLanguage: Language.English, - learningObjectVersion: 1, + // Gets deleted + submission07 = em.create(Submission, { + learningObjectHruid: testLearningObject01.hruid, + learningObjectLanguage: testLearningObject01.language, + learningObjectVersion: testLearningObject01.version, submissionNumber: 3, - submitter: students[3], + submitter: getSmashingPumpkins(), submissionTime: new Date(2025, 3, 25), - onBehalfOf: groups[3], // Group #4 for Assignment #2 in class 'id02' + onBehalfOf: getTestGroup04(), // Group #4 for Assignment #2 in class 'id02' content: '', }); - const submission08 = em.create(Submission, { - learningObjectHruid: 'id02', - learningObjectLanguage: Language.English, - learningObjectVersion: 1, + submission08 = em.create(Submission, { + learningObjectHruid: testLearningObject02.hruid, + learningObjectLanguage: testLearningObject02.language, + learningObjectVersion: testLearningObject02.version, submissionNumber: 3, - submitter: students[1], + submitter: getDireStraits(), submissionTime: new Date(2025, 4, 7), - onBehalfOf: groups[1], // Group #2 for Assignment #1 in class 'id01' + onBehalfOf: getTestGroup02(), // Group #2 for Assignment #1 in class 'id01' content: '', }); return [submission01, submission02, submission03, submission04, submission05, submission06, submission07, submission08]; } + +let submission01: Submission; +let submission02: Submission; +let submission03: Submission; +let submission04: Submission; +let submission05: Submission; +let submission06: Submission; +let submission07: Submission; +let submission08: Submission; + +export function getSubmission01(): Submission { + return submission01; +} + +export function getSubmission02(): Submission { + return submission02; +} + +export function getSubmission03(): Submission { + return submission03; +} + +export function getSubmission04(): Submission { + return submission04; +} + +export function getSubmission05(): Submission { + return submission05; +} + +export function getSubmission06(): Submission { + return submission06; +} + +export function getSubmission07(): Submission { + return submission07; +} + +export function getSubmission08(): Submission { + return submission08; +} diff --git a/backend/tests/test_assets/classes/class-join-requests.testdata.ts b/backend/tests/test_assets/classes/class-join-requests.testdata.ts index 63319dc4..f6fc63f9 100644 --- a/backend/tests/test_assets/classes/class-join-requests.testdata.ts +++ b/backend/tests/test_assets/classes/class-join-requests.testdata.ts @@ -1,33 +1,54 @@ import { EntityManager } from '@mikro-orm/core'; import { ClassJoinRequest } from '../../../src/entities/classes/class-join-request.entity'; -import { Student } from '../../../src/entities/users/student.entity'; -import { Class } from '../../../src/entities/classes/class.entity'; import { ClassStatus } from '@dwengo-1/common/util/class-join-request'; +import { getPinkFloyd, getSmashingPumpkins, getTool } from '../users/students.testdata'; +import { getClass02, getClass03 } from './classes.testdata'; -export function makeTestClassJoinRequests(em: EntityManager, students: Student[], classes: Class[]): ClassJoinRequest[] { - const classJoinRequest01 = em.create(ClassJoinRequest, { - requester: students[4], - class: classes[1], +export function makeTestClassJoinRequests(em: EntityManager): ClassJoinRequest[] { + classJoinRequest01 = em.create(ClassJoinRequest, { + requester: getPinkFloyd(), + class: getClass02(), status: ClassStatus.Open, }); - const classJoinRequest02 = em.create(ClassJoinRequest, { - requester: students[2], - class: classes[1], + classJoinRequest02 = em.create(ClassJoinRequest, { + requester: getTool(), + class: getClass02(), status: ClassStatus.Open, }); - const classJoinRequest03 = em.create(ClassJoinRequest, { - requester: students[4], - class: classes[2], + classJoinRequest03 = em.create(ClassJoinRequest, { + requester: getPinkFloyd(), + class: getClass03(), status: ClassStatus.Open, }); - const classJoinRequest04 = em.create(ClassJoinRequest, { - requester: students[3], - class: classes[2], + classJoinRequest04 = em.create(ClassJoinRequest, { + requester: getSmashingPumpkins(), + class: getClass03(), status: ClassStatus.Open, }); return [classJoinRequest01, classJoinRequest02, classJoinRequest03, classJoinRequest04]; } + +let classJoinRequest01: ClassJoinRequest; +let classJoinRequest02: ClassJoinRequest; +let classJoinRequest03: ClassJoinRequest; +let classJoinRequest04: ClassJoinRequest; + +export function getClassJoinRequest01(): ClassJoinRequest { + return classJoinRequest01; +} + +export function getClassJoinRequest02(): ClassJoinRequest { + return classJoinRequest02; +} + +export function getClassJoinRequest03(): ClassJoinRequest { + return classJoinRequest03; +} + +export function getClassJoinRequest04(): ClassJoinRequest { + return classJoinRequest04; +} diff --git a/backend/tests/test_assets/classes/classes.testdata.ts b/backend/tests/test_assets/classes/classes.testdata.ts index ae522a81..29a3ae80 100644 --- a/backend/tests/test_assets/classes/classes.testdata.ts +++ b/backend/tests/test_assets/classes/classes.testdata.ts @@ -2,12 +2,12 @@ import { EntityManager } from '@mikro-orm/core'; import { Class } from '../../../src/entities/classes/class.entity'; import { Student } from '../../../src/entities/users/student.entity'; import { Teacher } from '../../../src/entities/users/teacher.entity'; -import { getTestleerkracht1 } from '../users/teachers.testdata'; -import { getTestleerling1 } from '../users/students.testdata'; +import { getLimpBizkit, getStaind, getTestleerkracht1 } from '../users/teachers.testdata'; +import { getDireStraits, getNoordkaap, getSmashingPumpkins, getTestleerling1, getTool } from '../users/students.testdata'; -export function makeTestClasses(em: EntityManager, students: Student[], teachers: Teacher[]): Class[] { - const studentsClass01 = students.slice(0, 8); - const teacherClass01: Teacher[] = teachers.slice(4, 5); +export function makeTestClasses(em: EntityManager): Class[] { + const studentsClass01 = [getTestleerling1()]; + const teacherClass01: Teacher[] = [getTestleerkracht1()]; class01 = em.create(Class, { classId: 'X2J9QT', // 8764b861-90a6-42e5-9732-c0d9eb2f55f9 @@ -16,8 +16,8 @@ export function makeTestClasses(em: EntityManager, students: Student[], teachers students: studentsClass01, }); - const studentsClass02: Student[] = students.slice(0, 2).concat(students.slice(3, 4)); - const teacherClass02: Teacher[] = teachers.slice(1, 2); + const studentsClass02: Student[] = [getNoordkaap(), getDireStraits(), getSmashingPumpkins()]; + const teacherClass02: Teacher[] = [getLimpBizkit()]; class02 = em.create(Class, { classId: '7KLPMA', // 34d484a1-295f-4e9f-bfdc-3e7a23d86a89 @@ -26,8 +26,8 @@ export function makeTestClasses(em: EntityManager, students: Student[], teachers students: studentsClass02, }); - const studentsClass03: Student[] = students.slice(1, 4); - const teacherClass03: Teacher[] = teachers.slice(2, 3); + const studentsClass03: Student[] = [getDireStraits(), getTool(), getSmashingPumpkins()]; + const teacherClass03: Teacher[] = [getStaind()]; class03 = em.create(Class, { classId: 'R0D3UZ', // 80dcc3e0-1811-4091-9361-42c0eee91cfa @@ -36,9 +36,10 @@ export function makeTestClasses(em: EntityManager, students: Student[], teachers students: studentsClass03, }); - const studentsClass04: Student[] = students.slice(0, 2); - const teacherClass04: Teacher[] = teachers.slice(2, 3); + const studentsClass04: Student[] = [getNoordkaap(), getDireStraits()]; + const teacherClass04: Teacher[] = [getStaind()]; + // Gets deleted in test class04 = em.create(Class, { classId: 'Q8N5YC', // 33d03536-83b8-4880-9982-9bbf2f908ddf displayName: 'class04', diff --git a/backend/tests/test_assets/classes/teacher-invitations.testdata.ts b/backend/tests/test_assets/classes/teacher-invitations.testdata.ts index 6337a513..48ece518 100644 --- a/backend/tests/test_assets/classes/teacher-invitations.testdata.ts +++ b/backend/tests/test_assets/classes/teacher-invitations.testdata.ts @@ -1,37 +1,59 @@ import { EntityManager } from '@mikro-orm/core'; import { TeacherInvitation } from '../../../src/entities/classes/teacher-invitation.entity'; -import { Teacher } from '../../../src/entities/users/teacher.entity'; -import { Class } from '../../../src/entities/classes/class.entity'; import { ClassStatus } from '@dwengo-1/common/util/class-join-request'; +import { getFooFighters, getLimpBizkit, getStaind } from '../users/teachers.testdata'; +import { getClass01, getClass02, getClass03 } from './classes.testdata'; -export function makeTestTeacherInvitations(em: EntityManager, teachers: Teacher[], classes: Class[]): TeacherInvitation[] { - const teacherInvitation01 = em.create(TeacherInvitation, { - sender: teachers[1], - receiver: teachers[0], - class: classes[1], +export function makeTestTeacherInvitations(em: EntityManager): TeacherInvitation[] { + teacherInvitation01 = em.create(TeacherInvitation, { + sender: getLimpBizkit(), + receiver: getFooFighters(), + class: getClass02(), status: ClassStatus.Open, }); - const teacherInvitation02 = em.create(TeacherInvitation, { - sender: teachers[1], - receiver: teachers[2], - class: classes[1], + teacherInvitation02 = em.create(TeacherInvitation, { + sender: getLimpBizkit(), + receiver: getStaind(), + class: getClass02(), status: ClassStatus.Open, }); - const teacherInvitation03 = em.create(TeacherInvitation, { - sender: teachers[2], - receiver: teachers[0], - class: classes[2], + teacherInvitation03 = em.create(TeacherInvitation, { + sender: getStaind(), + receiver: getFooFighters(), + class: getClass03(), status: ClassStatus.Open, }); - const teacherInvitation04 = em.create(TeacherInvitation, { - sender: teachers[0], - receiver: teachers[1], - class: classes[0], + // Gets deleted in test + teacherInvitation04 = em.create(TeacherInvitation, { + sender: getFooFighters(), + receiver: getLimpBizkit(), + class: getClass01(), status: ClassStatus.Open, }); return [teacherInvitation01, teacherInvitation02, teacherInvitation03, teacherInvitation04]; } + +let teacherInvitation01: TeacherInvitation; +let teacherInvitation02: TeacherInvitation; +let teacherInvitation03: TeacherInvitation; +let teacherInvitation04: TeacherInvitation; + +export function getTeacherInvitation01(): TeacherInvitation { + return teacherInvitation01; +} + +export function getTeacherInvitation02(): TeacherInvitation { + return teacherInvitation02; +} + +export function getTeacherInvitation03(): TeacherInvitation { + return teacherInvitation03; +} + +export function getTeacherInvitation04(): TeacherInvitation { + return teacherInvitation04; +} diff --git a/backend/tests/test_assets/content/attachments.testdata.ts b/backend/tests/test_assets/content/attachments.testdata.ts index 6bc46078..11d12d78 100644 --- a/backend/tests/test_assets/content/attachments.testdata.ts +++ b/backend/tests/test_assets/content/attachments.testdata.ts @@ -1,10 +1,14 @@ import { EntityManager } from '@mikro-orm/core'; import { Attachment } from '../../../src/entities/content/attachment.entity'; +import { testLearningObject01 } from './learning-objects.testdata'; import { LearningObject } from '../../../src/entities/content/learning-object.entity'; -export function makeTestAttachments(em: EntityManager, learningObjects: LearningObject[]): Attachment[] { - const attachment01 = em.create(Attachment, { - learningObject: learningObjects[1], +export function makeTestAttachments(em: EntityManager): Attachment[] { + // Prevent duplicate insertion + const lo = em.merge(LearningObject, testLearningObject01); + + attachment01 = em.create(Attachment, { + learningObject: lo, name: 'attachment01', mimeType: '', content: Buffer.from(''), @@ -12,3 +16,9 @@ export function makeTestAttachments(em: EntityManager, learningObjects: Learning return [attachment01]; } + +let attachment01: Attachment; + +export function getAttachment01(): Attachment { + return attachment01; +} diff --git a/backend/tests/test_assets/content/learning-objects.testdata.ts b/backend/tests/test_assets/content/learning-objects.testdata.ts index 6ee3bccf..6d95b90a 100644 --- a/backend/tests/test_assets/content/learning-objects.testdata.ts +++ b/backend/tests/test_assets/content/learning-objects.testdata.ts @@ -75,6 +75,7 @@ export const testLearningObject02: RequiredEntityData = { description: 'second album', contentType: DwengoContentType.TEXT_MARKDOWN, keywords: [], + uuid: v4(), teacherExclusive: false, skosConcepts: [], educationalGoals: [], @@ -99,6 +100,7 @@ export const testLearningObject03: RequiredEntityData = { description: 'third album', contentType: DwengoContentType.TEXT_MARKDOWN, keywords: [], + uuid: v4(), teacherExclusive: false, skosConcepts: [], educationalGoals: [], @@ -126,6 +128,7 @@ export const testLearningObject04: RequiredEntityData = { description: 'fifth album', contentType: DwengoContentType.TEXT_MARKDOWN, keywords: [], + uuid: v4(), teacherExclusive: false, skosConcepts: [], educationalGoals: [], @@ -153,6 +156,7 @@ export const testLearningObject05: RequiredEntityData = { description: 'sixth album', contentType: DwengoContentType.TEXT_MARKDOWN, keywords: [], + uuid: v4(), teacherExclusive: false, skosConcepts: [], educationalGoals: [], @@ -173,6 +177,7 @@ export const testLearningObjectMultipleChoice: RequiredEntityData title: 'Reflection', description: 'Reflect on your learning progress.', keywords: ['test'], + uuid: v4(), teacherExclusive: false, skosConcepts: [], educationalGoals: [], diff --git a/backend/tests/test_assets/questions/answers.testdata.ts b/backend/tests/test_assets/questions/answers.testdata.ts index 5614cd6a..a329cdcb 100644 --- a/backend/tests/test_assets/questions/answers.testdata.ts +++ b/backend/tests/test_assets/questions/answers.testdata.ts @@ -1,36 +1,35 @@ import { EntityManager } from '@mikro-orm/core'; import { Answer } from '../../../src/entities/questions/answer.entity'; -import { Teacher } from '../../../src/entities/users/teacher.entity'; -import { Question } from '../../../src/entities/questions/question.entity'; -import { getTestleerkracht1 } from '../users/teachers.testdata'; -import { getQuestion07 } from './questions.testdata'; +import { getFooFighters, getLimpBizkit, getTestleerkracht1 } from '../users/teachers.testdata'; +import { getQuestion02, getQuestion04, getQuestion07 } from './questions.testdata'; -export function makeTestAnswers(em: EntityManager, teachers: Teacher[], questions: Question[]): Answer[] { - const answer01 = em.create(Answer, { - author: teachers[0], - toQuestion: questions[1], +export function makeTestAnswers(em: EntityManager): Answer[] { + answer01 = em.create(Answer, { + author: getFooFighters(), + toQuestion: getQuestion02(), sequenceNumber: 1, timestamp: new Date(), content: 'answer', }); - const answer02 = em.create(Answer, { - author: teachers[0], - toQuestion: questions[1], + answer02 = em.create(Answer, { + author: getFooFighters(), + toQuestion: getQuestion02(), sequenceNumber: 2, timestamp: new Date(), content: 'answer2', }); - const answer03 = em.create(Answer, { - author: teachers[1], - toQuestion: questions[3], + // Gets deleted + answer03 = em.create(Answer, { + author: getLimpBizkit(), + toQuestion: getQuestion04(), sequenceNumber: 1, timestamp: new Date(), content: 'answer3', }); - const answer04 = em.create(Answer, { + answer04 = em.create(Answer, { author: getTestleerkracht1(), toQuestion: getQuestion07(), sequenceNumber: 1, @@ -38,7 +37,7 @@ export function makeTestAnswers(em: EntityManager, teachers: Teacher[], question content: 'this is a test answer', }); - const answer05 = em.create(Answer, { + answer05 = em.create(Answer, { author: getTestleerkracht1(), toQuestion: getQuestion07(), sequenceNumber: 2, @@ -48,3 +47,29 @@ export function makeTestAnswers(em: EntityManager, teachers: Teacher[], question return [answer01, answer02, answer03, answer04, answer05]; } + +let answer01: Answer; +let answer02: Answer; +let answer03: Answer; +let answer04: Answer; +let answer05: Answer; + +export function getAnswer01(): Answer { + return answer01; +} + +export function getAnswer02(): Answer { + return answer02; +} + +export function getAnswer03(): Answer { + return answer03; +} + +export function getAnswer04(): Answer { + return answer04; +} + +export function getAnswer05(): Answer { + return answer05; +} diff --git a/backend/tests/test_assets/questions/questions.testdata.ts b/backend/tests/test_assets/questions/questions.testdata.ts index 9e8d6df3..b76f0119 100644 --- a/backend/tests/test_assets/questions/questions.testdata.ts +++ b/backend/tests/test_assets/questions/questions.testdata.ts @@ -1,82 +1,85 @@ import { EntityManager } from '@mikro-orm/core'; import { Question } from '../../../src/entities/questions/question.entity'; -import { Language } from '@dwengo-1/common/util/language'; -import { Student } from '../../../src/entities/users/student.entity'; -import { Group } from '../../../src/entities/assignments/group.entity'; -import { getTestleerling1 } from '../users/students.testdata'; -import { testLearningObjectMultipleChoice } from '../content/learning-objects.testdata'; -import { getGroup1ConditionalLearningPath } from '../assignments/groups.testdata'; +import { getDireStraits, getNoordkaap, getTestleerling1, getTool } from '../users/students.testdata'; +import { + testLearningObject01, + testLearningObject04, + testLearningObject05, + testLearningObjectMultipleChoice, +} from '../content/learning-objects.testdata'; +import { getGroup1ConditionalLearningPath, getTestGroup01, getTestGroup02 } from '../assignments/groups.testdata'; -export function makeTestQuestions(em: EntityManager, students: Student[], groups: Group[]): Question[] { - const question01 = em.create(Question, { - learningObjectLanguage: Language.English, - learningObjectVersion: 1, - learningObjectHruid: 'id05', - inGroup: groups[0], // Group #1 for Assignment #1 in class 'id01' +export function makeTestQuestions(em: EntityManager): Question[] { + question01 = em.create(Question, { + learningObjectLanguage: testLearningObject05.language, + learningObjectVersion: testLearningObject05.version, + learningObjectHruid: testLearningObject05.hruid, + inGroup: getTestGroup01(), // Group #1 for Assignment #1 in class 'id01' sequenceNumber: 1, - author: students[0], + author: getNoordkaap(), timestamp: new Date(), content: 'question', }); - const question02 = em.create(Question, { - learningObjectLanguage: Language.English, - learningObjectVersion: 1, - learningObjectHruid: 'id05', - inGroup: groups[0], // Group #1 for Assignment #1 in class 'id01' + question02 = em.create(Question, { + learningObjectLanguage: testLearningObject05.language, + learningObjectVersion: testLearningObject05.version, + learningObjectHruid: testLearningObject05.hruid, + inGroup: getTestGroup01(), // Group #1 for Assignment #1 in class 'id01' sequenceNumber: 2, - author: students[2], + author: getTool(), timestamp: new Date(), content: 'question', }); - const question03 = em.create(Question, { - learningObjectLanguage: Language.English, - learningObjectVersion: 1, - learningObjectHruid: 'id04', + //Gets deleted + question03 = em.create(Question, { + learningObjectLanguage: testLearningObject04.language, + learningObjectVersion: testLearningObject04.version, + learningObjectHruid: testLearningObject04.hruid, sequenceNumber: 1, - author: students[0], - inGroup: groups[0], // Group #1 for Assignment #1 in class 'id01' + author: getNoordkaap(), + inGroup: getTestGroup01(), // Group #1 for Assignment #1 in class 'id01' timestamp: new Date(), content: 'question', }); - const question04 = em.create(Question, { - learningObjectLanguage: Language.English, - learningObjectVersion: 1, - learningObjectHruid: 'id01', + question04 = em.create(Question, { + learningObjectLanguage: testLearningObject01.language, + learningObjectVersion: testLearningObject01.version, + learningObjectHruid: testLearningObject01.hruid, sequenceNumber: 1, - author: students[1], - inGroup: groups[1], // Group #2 for Assignment #1 in class 'id01' + author: getDireStraits(), + inGroup: getTestGroup02(), // Group #2 for Assignment #1 in class 'id01' timestamp: new Date(), content: 'question', }); - const question05 = em.create(Question, { - learningObjectLanguage: Language.English, - learningObjectVersion: 1, - learningObjectHruid: 'id05', + question05 = em.create(Question, { + learningObjectLanguage: testLearningObject05.language, + learningObjectVersion: testLearningObject05.version, + learningObjectHruid: testLearningObject05.hruid, sequenceNumber: 3, - author: students[1], - inGroup: groups[1], // Group #2 for Assignment #1 in class 'id01' + author: getDireStraits(), + inGroup: getTestGroup02(), // Group #2 for Assignment #1 in class 'id01' timestamp: new Date(), content: 'question', }); - const question06 = em.create(Question, { - learningObjectLanguage: Language.English, - learningObjectVersion: 1, - learningObjectHruid: 'id05', + question06 = em.create(Question, { + learningObjectLanguage: testLearningObject05.language, + learningObjectVersion: testLearningObject05.version, + learningObjectHruid: testLearningObject05.hruid, sequenceNumber: 4, - author: students[2], - inGroup: groups[5], // Group #4 for Assignment #2 in class 'id02' + author: getTool(), + inGroup: getGroup1ConditionalLearningPath(), // Group #4 for Assignment #2 in class 'id02' timestamp: new Date(), content: 'question', }); question07 = em.create(Question, { - learningObjectLanguage: Language.English, - learningObjectVersion: 1, + learningObjectLanguage: testLearningObjectMultipleChoice.language, + learningObjectVersion: testLearningObjectMultipleChoice.version, learningObjectHruid: testLearningObjectMultipleChoice.hruid, sequenceNumber: 1, author: getTestleerling1(), @@ -86,8 +89,8 @@ export function makeTestQuestions(em: EntityManager, students: Student[], groups }); question08 = em.create(Question, { - learningObjectLanguage: Language.English, - learningObjectVersion: 1, + learningObjectLanguage: testLearningObjectMultipleChoice.language, + learningObjectVersion: testLearningObjectMultipleChoice.version, learningObjectHruid: testLearningObjectMultipleChoice.hruid, sequenceNumber: 2, author: getTestleerling1(), @@ -99,8 +102,38 @@ export function makeTestQuestions(em: EntityManager, students: Student[], groups return [question01, question02, question03, question04, question05, question06, question07, question08]; } -let question08: Question; +let question01: Question; +let question02: Question; +let question03: Question; +let question04: Question; +let question05: Question; +let question06: Question; let question07: Question; +let question08: Question; + +export function getQuestion01(): Question { + return question01; +} + +export function getQuestion02(): Question { + return question02; +} + +export function getQuestion03(): Question { + return question03; +} + +export function getQuestion04(): Question { + return question04; +} + +export function getQuestion05(): Question { + return question05; +} + +export function getQuestion06(): Question { + return question06; +} export function getQuestion07(): Question { return question07; diff --git a/backend/tests/test_assets/users/students.testdata.ts b/backend/tests/test_assets/users/students.testdata.ts index e596b388..e29733fc 100644 --- a/backend/tests/test_assets/users/students.testdata.ts +++ b/backend/tests/test_assets/users/students.testdata.ts @@ -9,7 +9,6 @@ export const TEST_STUDENTS = [ { username: 'SmashingPumpkins', firstName: 'Billy', lastName: 'Corgan' }, { username: 'PinkFloyd', firstName: 'David', lastName: 'Gilmoure' }, { username: 'TheDoors', firstName: 'Jim', lastName: 'Morisson' }, - // ⚠️ Deze mag niet gebruikt worden in elke test! { username: 'Nirvana', firstName: 'Kurt', lastName: 'Cobain' }, // Makes sure when logged in as leerling1, there exists a corresponding user { username: 'testleerling1', firstName: 'Gerald', lastName: 'Schmittinger' }, @@ -24,5 +23,33 @@ export function makeTestStudents(em: EntityManager): Student[] { } export function getTestleerling1(): Student { - return testStudents.find((it) => it.username === 'testleerling1'); + return testStudents.find((it) => it.username === 'testleerling1')!; +} + +export function getNoordkaap(): Student { + return testStudents.find((it) => it.username === 'Noordkaap')!; +} + +export function getDireStraits(): Student { + return testStudents.find((it) => it.username === 'DireStraits')!; +} + +export function getTool(): Student { + return testStudents.find((it) => it.username === 'Tool')!; +} + +export function getSmashingPumpkins(): Student { + return testStudents.find((it) => it.username === 'SmashingPumpkins')!; +} + +export function getPinkFloyd(): Student { + return testStudents.find((it) => it.username === 'PinkFloyd')!; +} + +export function getTheDoors(): Student { + return testStudents.find((it) => it.username === 'TheDoors')!; +} + +export function getNirvana(): Student { + return testStudents.find((it) => it.username === 'Nirvana')!; } diff --git a/backend/tests/test_assets/users/teachers.testdata.ts b/backend/tests/test_assets/users/teachers.testdata.ts index cfb906b6..df89219b 100644 --- a/backend/tests/test_assets/users/teachers.testdata.ts +++ b/backend/tests/test_assets/users/teachers.testdata.ts @@ -43,19 +43,19 @@ let teacher03: Teacher; let teacher04: Teacher; let testleerkracht1: Teacher; -export function getTeacher01(): Teacher { +export function getFooFighters(): Teacher { return teacher01; } -export function getTeacher02(): Teacher { +export function getLimpBizkit(): Teacher { return teacher02; } -export function getTeacher03(): Teacher { +export function getStaind(): Teacher { return teacher03; } -export function getTeacher04(): Teacher { +export function getZesdeMetaal(): Teacher { return teacher04; } diff --git a/backend/tool/seed.ts b/backend/tool/seed.ts index 00e3c0bf..5fef0848 100644 --- a/backend/tool/seed.ts +++ b/backend/tool/seed.ts @@ -1,82 +1,23 @@ -import { forkEntityManager, initORM } from '../src/orm.js'; +import { initORM } from '../src/orm.js'; import dotenv from 'dotenv'; -import { makeTestAssignemnts } from '../tests/test_assets/assignments/assignments.testdata.js'; -import { makeTestGroups } from '../tests/test_assets/assignments/groups.testdata.js'; -import { makeTestSubmissions } from '../tests/test_assets/assignments/submission.testdata.js'; -import { makeTestClassJoinRequests } from '../tests/test_assets/classes/class-join-requests.testdata.js'; -import { makeTestClasses } from '../tests/test_assets/classes/classes.testdata.js'; -import { makeTestTeacherInvitations } from '../tests/test_assets/classes/teacher-invitations.testdata.js'; -import { makeTestAttachments } from '../tests/test_assets/content/attachments.testdata.js'; -import { makeTestLearningObjects } from '../tests/test_assets/content/learning-objects.testdata.js'; -import { makeTestLearningPaths } from '../tests/test_assets/content/learning-paths.testdata.js'; -import { makeTestAnswers } from '../tests/test_assets/questions/answers.testdata.js'; -import { makeTestQuestions } from '../tests/test_assets/questions/questions.testdata.js'; -import { makeTestStudents } from '../tests/test_assets/users/students.testdata.js'; -import { makeTestTeachers } from '../tests/test_assets/users/teachers.testdata.js'; import { getLogger, Logger } from '../src/logging/initalize.js'; -import { Collection, MikroORM } from '@mikro-orm/core'; -import { Group } from '../src/entities/assignments/group.entity'; +import { seedORM } from './seedORM.js'; const logger: Logger = getLogger(); -export async function seedORM(orm: MikroORM): Promise { - await orm.schema.clearDatabase(); - - const em = forkEntityManager(); - - logger.info('seeding database...'); - - const students = makeTestStudents(em); - const teachers = makeTestTeachers(em); - const learningObjects = makeTestLearningObjects(em); - const learningPaths = makeTestLearningPaths(em); - const classes = makeTestClasses(em, students, teachers); - const assignments = makeTestAssignemnts(em, classes); - - const groups = makeTestGroups(em, students, assignments); - - assignments[0].groups = new Collection(groups.slice(0, 3)); - assignments[1].groups = new Collection(groups.slice(3, 4)); - - const teacherInvitations = makeTestTeacherInvitations(em, teachers, classes); - const classJoinRequests = makeTestClassJoinRequests(em, students, classes); - const attachments = makeTestAttachments(em, learningObjects); - - learningObjects[1].attachments = attachments; - - const questions = makeTestQuestions(em, students, groups); - const answers = makeTestAnswers(em, teachers, questions); - const submissions = makeTestSubmissions(em, students, groups); - - // Persist all entities - await em.persistAndFlush([ - ...students, - ...teachers, - ...learningObjects, - ...learningPaths, - ...classes, - ...assignments, - ...groups, - ...teacherInvitations, - ...classJoinRequests, - ...attachments, - ...questions, - ...answers, - ...submissions, - ]); - - logger.info('Development database seeded successfully!'); -} - -export async function seedDatabase(envFile = '.env.development.local', testMode = false): Promise { +export async function seedDatabase( + envFile = '.env.development.local', + testMode = process.env.NODE_ENV !== undefined && process.env.NODE_ENV === 'test' +): Promise { dotenv.config({ path: envFile }); - const orm = await initORM(testMode); - await seedORM(orm); - - await orm.close(); + try { + const orm = await initORM(testMode); + await seedORM(orm); + await orm.close(); + } catch (err) { + logger.error(`Error: ${err}`); + } } -seedDatabase().catch((err) => { - logger.error(err); -}); +seedDatabase().catch((err) => logger.error(`Seeding: ${err}`)); diff --git a/backend/tool/seedORM.ts b/backend/tool/seedORM.ts new file mode 100644 index 00000000..eec73a77 --- /dev/null +++ b/backend/tool/seedORM.ts @@ -0,0 +1,70 @@ +import { Collection, MikroORM } from '@mikro-orm/core'; +import { forkEntityManager } from '../src/orm'; +import { makeTestStudents } from '../tests/test_assets/users/students.testdata'; +import { makeTestTeachers } from '../tests/test_assets/users/teachers.testdata'; +import { makeTestLearningObjects } from '../tests/test_assets/content/learning-objects.testdata'; +import { makeTestLearningPaths } from '../tests/test_assets/content/learning-paths.testdata'; +import { makeTestClasses } from '../tests/test_assets/classes/classes.testdata'; +import { makeTestAssignemnts } from '../tests/test_assets/assignments/assignments.testdata'; +import { getTestGroup01, getTestGroup02, getTestGroup03, getTestGroup04, makeTestGroups } from '../tests/test_assets/assignments/groups.testdata'; +import { Group } from '../src/entities/assignments/group.entity'; +import { makeTestTeacherInvitations } from '../tests/test_assets/classes/teacher-invitations.testdata'; +import { makeTestClassJoinRequests } from '../tests/test_assets/classes/class-join-requests.testdata'; +import { makeTestAttachments } from '../tests/test_assets/content/attachments.testdata'; +import { makeTestQuestions } from '../tests/test_assets/questions/questions.testdata'; +import { makeTestAnswers } from '../tests/test_assets/questions/answers.testdata'; +import { makeTestSubmissions } from '../tests/test_assets/assignments/submission.testdata'; +import { getLogger } from '../src/logging/initalize'; + +export async function seedORM(orm: MikroORM): Promise { + const logger = getLogger(); + + logger.debug('Clearing database...'); + await orm.schema.clearDatabase(); + + logger.debug('Forking entity manager...'); + const em = forkEntityManager(); + + logger.debug('Seeding database...'); + + const students = makeTestStudents(em); + const teachers = makeTestTeachers(em); + const learningObjects = makeTestLearningObjects(em); + const learningPaths = makeTestLearningPaths(em); + const classes = makeTestClasses(em); + const assignments = makeTestAssignemnts(em); + + const groups = makeTestGroups(em); + + assignments[0].groups = new Collection([getTestGroup01(), getTestGroup02(), getTestGroup03()]); + assignments[1].groups = new Collection([getTestGroup04()]); + + const teacherInvitations = makeTestTeacherInvitations(em); + const classJoinRequests = makeTestClassJoinRequests(em); + const attachments = makeTestAttachments(em); + + learningObjects[1].attachments = attachments; + + const questions = makeTestQuestions(em); + const answers = makeTestAnswers(em); + const submissions = makeTestSubmissions(em); + + // Persist all entities + await em.persistAndFlush([ + ...students, + ...teachers, + ...learningObjects, + ...learningPaths, + ...classes, + ...assignments, + ...groups, + ...teacherInvitations, + ...classJoinRequests, + ...attachments, + ...questions, + ...answers, + ...submissions, + ]); + + logger.info('Development database seeded successfully!'); +} diff --git a/backend/tool/startTestApp.ts b/backend/tool/startTestApp.ts index a5d0f852..d8e4ca63 100644 --- a/backend/tool/startTestApp.ts +++ b/backend/tool/startTestApp.ts @@ -5,7 +5,7 @@ import { errorHandler } from '../src/middleware/error-handling/error-handler.js' import dotenv from 'dotenv'; import cors from '../src/middleware/cors'; import { authenticateUser } from '../src/middleware/auth/auth'; -import { seedORM } from './seed'; +import { seedORM } from './seedORM'; const envFile = '../.env.test'; diff --git a/frontend/src/controllers/answers.ts b/frontend/src/controllers/answers.ts index 57407b19..bdfb5e4f 100644 --- a/frontend/src/controllers/answers.ts +++ b/frontend/src/controllers/answers.ts @@ -17,7 +17,7 @@ export class AnswerController extends BaseController { constructor(questionId: QuestionId) { super( - `learningObject/${questionId.learningObjectIdentifier.hruid}/:${questionId.learningObjectIdentifier.version}/questions/${questionId.sequenceNumber}/answers`, + `learningObject/${questionId.learningObjectIdentifier.hruid}/${questionId.learningObjectIdentifier.version}/questions/${questionId.sequenceNumber}/answers`, ); this.loId = questionId.learningObjectIdentifier; this.sequenceNumber = questionId.sequenceNumber; diff --git a/frontend/tests/controllers/answers-controller.test.ts b/frontend/tests/controllers/answers-controller.test.ts new file mode 100644 index 00000000..f1b7fd83 --- /dev/null +++ b/frontend/tests/controllers/answers-controller.test.ts @@ -0,0 +1,31 @@ +import { describe, it, expect, beforeEach } from "vitest"; +import { AnswerController } from "../../src/controllers/answers"; +import { Language } from "@dwengo-1/common/util/language"; + +describe("AnswerController Tests", () => { + let controller: AnswerController; + + beforeEach(() => { + const loiDTO = { + hruid: "u_test_multiple_choice", + language: Language.English, + version: 1, + }; + const questionId = { learningObjectIdentifier: loiDTO, sequenceNumber: 1 }; + controller = new AnswerController(questionId); + }); + + it("should fetch all answers", async () => { + const result = await controller.getAll(true); + expect(result).toHaveProperty("answers"); + expect(Array.isArray(result.answers)).toBe(true); + expect(result.answers.length).toBeGreaterThan(0); + }); + + it("should fetch an answer by sequencenumber", async () => { + const answerNumber = 1; // Example sequence number + const result = await controller.getBy(answerNumber); + expect(result).toHaveProperty("answer"); + expect(result.answer).toHaveProperty("sequenceNumber", answerNumber); + }); +}); diff --git a/frontend/tests/controllers/questions-controller.test.ts b/frontend/tests/controllers/questions-controller.test.ts new file mode 100644 index 00000000..cb657307 --- /dev/null +++ b/frontend/tests/controllers/questions-controller.test.ts @@ -0,0 +1,30 @@ +import { describe, it, expect, beforeEach } from "vitest"; +import { Language } from "@dwengo-1/common/util/language"; +import { QuestionController } from "../../src/controllers/questions"; + +describe("QuestionController Tests", () => { + let controller: QuestionController; + + beforeEach(() => { + const loiDTO = { + hruid: "u_test_multiple_choice", + language: Language.English, + version: 1, + }; + controller = new QuestionController(loiDTO); + }); + + it("should fetch all questions", async () => { + const result = await controller.getAll(true); + expect(result).toHaveProperty("questions"); + expect(Array.isArray(result.questions)).toBe(true); + expect(result.questions.length).toBeGreaterThan(0); + }); + + it("should fetch an question by sequencenumber", async () => { + const questionNumber = 1; // Example sequence number + const result = await controller.getBy(questionNumber); + expect(result).toHaveProperty("question"); + expect(result.question).toHaveProperty("sequenceNumber", questionNumber); + }); +}); diff --git a/frontend/tests/controllers/student-controller.test.ts b/frontend/tests/controllers/student-controller.test.ts index 925cf34d..189f6bb8 100644 --- a/frontend/tests/controllers/student-controller.test.ts +++ b/frontend/tests/controllers/student-controller.test.ts @@ -27,13 +27,8 @@ test.each([ { username: "DireStraits", firstName: "Mark", lastName: "Knopfler" }, { username: "Tool", firstName: "Maynard", lastName: "Keenan" }, { username: "SmashingPumpkins", firstName: "Billy", lastName: "Corgan" }, - { username: "PinkFloyd", firstName: "David", lastName: "Gilmoure" }, - { username: "TheDoors", firstName: "Jim", lastName: "Morisson" }, - // ⚠️ Deze mag niet gebruikt worden in elke test! - { username: "Nirvana", firstName: "Kurt", lastName: "Cobain" }, - // Makes sure when logged in as leerling1, there exists a corresponding user { username: "testleerling1", firstName: "Gerald", lastName: "Schmittinger" }, ])("Get classes of student", async (student) => { const data = await controller.getClasses(student.username, true); - expect(data.classes).to.have.length.greaterThan(0); + expect(data.classes).to.have.length.greaterThan(0, `Found no classes for ${student.username}`); }); diff --git a/frontend/tests/controllers/submissions-controller.test.ts b/frontend/tests/controllers/submissions-controller.test.ts deleted file mode 100644 index 7ea106c7..00000000 --- a/frontend/tests/controllers/submissions-controller.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { SubmissionController } from "../../src/controllers/submissions"; -import { Language } from "../../src/data-objects/language"; - -describe("Test controller submissions", () => { - it("Get submission by number", async () => { - const hruid = "id03"; - const classId = "X2J9QT"; // Class01 - const controller = new SubmissionController(hruid); - - const data = await controller.getByNumber(Language.English, 1, classId, 1, 1, 1); - - expect(data.submission).to.have.property("submissionNumber"); - }); -}); diff --git a/frontend/tests/setup-backend.ts b/frontend/tests/setup-backend.ts index 6a0a256d..d1278d55 100644 --- a/frontend/tests/setup-backend.ts +++ b/frontend/tests/setup-backend.ts @@ -1,5 +1,6 @@ import { spawn } from "child_process"; import { ChildProcess, spawnSync } from "node:child_process"; +import { getLogger } from "../../backend/src/logging/initalize"; let backendProcess: ChildProcess; @@ -35,6 +36,8 @@ export async function setup(): Promise { export async function teardown(): Promise { if (backendProcess) { - backendProcess.kill(); + while (!backendProcess.kill()) { + getLogger().error(`Failed to kill backend process! Retrying...`); + } } }