Merge remote-tracking branch 'origin/dev' into feat/endpoints-finaliseren-tests-backend-adriaan
# Conflicts: # backend/src/controllers/assignments.ts # backend/src/controllers/classes.ts # backend/src/controllers/groups.ts # backend/src/controllers/questions.ts # backend/src/controllers/submissions.ts # backend/src/data/assignments/submission-repository.ts # backend/src/data/users/student-repository.ts # backend/src/services/classes.ts # backend/src/services/submissions.ts # backend/tests/controllers/classes.test.ts
This commit is contained in:
commit
ded1a5908e
375 changed files with 23425 additions and 7033 deletions
87
backend/tests/controllers/answers.test.ts
Normal file
87
backend/tests/controllers/answers.test.ts
Normal file
|
@ -0,0 +1,87 @@
|
|||
import { Request, Response } from 'express';
|
||||
import { beforeAll, beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import { setupTestApp } from '../setup-tests';
|
||||
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';
|
||||
|
||||
describe('Questions controllers', () => {
|
||||
let req: Partial<Request>;
|
||||
let res: Partial<Response>;
|
||||
|
||||
let jsonMock: Mock;
|
||||
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jsonMock = vi.fn();
|
||||
res = {
|
||||
json: jsonMock,
|
||||
};
|
||||
});
|
||||
|
||||
it('Get answers list', async () => {
|
||||
req = {
|
||||
params: { hruid: 'id05', version: '1', seq: '2' },
|
||||
query: { lang: Language.English, full: 'true' },
|
||||
};
|
||||
|
||||
await getAllAnswersHandler(req as Request, res as Response);
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ answers: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
// Console.log(result.answers);
|
||||
expect(result.answers).to.have.length.greaterThan(1);
|
||||
});
|
||||
|
||||
it('Get answer', async () => {
|
||||
req = {
|
||||
params: { hruid: 'id05', version: '1', seq: '2', seqAnswer: '2' },
|
||||
query: { lang: Language.English, full: 'true' },
|
||||
};
|
||||
|
||||
await getAnswerHandler(req as Request, res as Response);
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ answer: expect.anything() }));
|
||||
|
||||
// Const result = jsonMock.mock.lastCall?.[0];
|
||||
// Console.log(result.answer);
|
||||
});
|
||||
|
||||
it('Get answer hruid does not exist', async () => {
|
||||
req = {
|
||||
params: { hruid: 'id_not_exist' },
|
||||
query: { lang: Language.English, full: 'true' },
|
||||
};
|
||||
|
||||
await expect(async () => getAnswerHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException);
|
||||
});
|
||||
|
||||
it('Get answer no hruid given', async () => {
|
||||
req = {
|
||||
params: {},
|
||||
query: { lang: Language.English, full: 'true' },
|
||||
};
|
||||
|
||||
await expect(async () => getAnswerHandler(req as Request, res as Response)).rejects.toThrow(BadRequestException);
|
||||
});
|
||||
|
||||
it('Update question', async () => {
|
||||
const newContent = 'updated question';
|
||||
req = {
|
||||
params: { hruid: 'id05', version: '1', seq: '2', seqAnswer: '2' },
|
||||
query: { lang: Language.English },
|
||||
body: { content: newContent },
|
||||
};
|
||||
|
||||
await updateAnswerHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ answer: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
// Console.log(result.question);
|
||||
expect(result.answer.content).to.eq(newContent);
|
||||
});
|
||||
});
|
|
@ -1,10 +1,7 @@
|
|||
import { setupTestApp } from '../setup-tests.js';
|
||||
import { describe, it, expect, beforeAll, beforeEach, vi, Mock } from 'vitest';
|
||||
import { createClassHandler, getAllClassesHandler, getClassHandler, getClassStudentsHandler, getTeacherInvitationsHandler } from '../../src/controllers/classes.js';
|
||||
import { createClassHandler, deleteClassHandler, getAllClassesHandler, getClassHandler, getClassStudentsHandler, getTeacherInvitationsHandler } from '../../src/controllers/classes.js';
|
||||
import { Request, Response } from 'express';
|
||||
import { getAllClasses } from '../../src/services/class.js';
|
||||
import { checkReturnList, checkReturn404 } from './qol.js';
|
||||
|
||||
describe('Class controllers', () => {
|
||||
let req: Partial<Request>;
|
||||
let res: Partial<Response>;
|
||||
|
@ -15,8 +12,8 @@ describe('Class controllers', () => {
|
|||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
jsonMock = vi.fn();
|
||||
statusMock = vi.fn().mockReturnThis();
|
||||
|
||||
|
@ -26,13 +23,34 @@ describe('Class controllers', () => {
|
|||
};
|
||||
});
|
||||
|
||||
it('create and delete class', async () => {
|
||||
req = {
|
||||
body: { displayName: 'coole_nieuwe_klas' },
|
||||
};
|
||||
|
||||
await createClassHandler(req as Request, res as Response);
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
// Console.log('class', result.class);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ class: expect.anything() }));
|
||||
|
||||
req = {
|
||||
params: { id: result.class.id },
|
||||
};
|
||||
|
||||
await deleteClassHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ class: expect.anything() }));
|
||||
});
|
||||
|
||||
it('should return 404 and error if class is not found', async () => {
|
||||
req = {
|
||||
params: { id: 'doesnotexist'},
|
||||
}
|
||||
|
||||
await getClassHandler(req as Request, res as Response);
|
||||
|
||||
|
||||
expect(statusMock).toHaveBeenCalledWith(404);
|
||||
expect(jsonMock).toHaveBeenCalledWith({ error: 'Class not found' });
|
||||
});
|
||||
|
@ -43,7 +61,7 @@ describe('Class controllers', () => {
|
|||
}
|
||||
|
||||
await getClassHandler(req as Request, res as Response);
|
||||
|
||||
|
||||
// status can either not be called or called with code 200
|
||||
expect(
|
||||
statusMock.mock.calls.length === 0 || statusMock.mock.calls.some(([arg]) => arg === 200)
|
||||
|
@ -54,13 +72,13 @@ describe('Class controllers', () => {
|
|||
req = {
|
||||
body: { displayName: 'coolenieuweklas' },
|
||||
};
|
||||
|
||||
|
||||
await createClassHandler(req as Request, res as Response);
|
||||
|
||||
|
||||
expect(statusMock).toHaveBeenCalledWith(201);
|
||||
// TODO: return json should be a classDTO and not named (fixed in #130)
|
||||
//expect(jsonMock).toHaveBeenCalledWith();
|
||||
|
||||
|
||||
// TODO: check if class is actually added to db
|
||||
});
|
||||
it.todo('return json should be a classDTO and not named (fixed in #130)')
|
||||
|
@ -85,7 +103,7 @@ describe('Class controllers', () => {
|
|||
|
||||
await getClassStudentsHandler(req as Request, res as Response);
|
||||
|
||||
checkReturnList(jsonMock, 'students');
|
||||
checkReturnList(jsonMock, 'students');
|
||||
});
|
||||
|
||||
it('should return 404 not found when calling getClassStudentsHandler on a non-existent class', async () => {
|
||||
|
@ -109,12 +127,12 @@ describe('Class controllers', () => {
|
|||
await getTeacherInvitationsHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith({"invitations": [
|
||||
{
|
||||
"class": "id01",
|
||||
"receiver": "LimpBizkit",
|
||||
"sender": "FooFighters",
|
||||
}
|
||||
]});
|
||||
{
|
||||
"class": "id01",
|
||||
"receiver": "LimpBizkit",
|
||||
"sender": "FooFighters",
|
||||
}
|
||||
]});
|
||||
});
|
||||
|
||||
it('should return 404 not found when calling teacher-invitations on a non-existent class', async () => {
|
||||
|
@ -142,4 +160,5 @@ describe('Class controllers', () => {
|
|||
|
||||
expect("classes" in result).toBeTruthy();
|
||||
})
|
||||
})
|
||||
|
||||
});
|
||||
|
|
117
backend/tests/controllers/questions.test.ts
Normal file
117
backend/tests/controllers/questions.test.ts
Normal file
|
@ -0,0 +1,117 @@
|
|||
import { beforeAll, beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import { Request, Response } from 'express';
|
||||
import { setupTestApp } from '../setup-tests';
|
||||
import { getAllQuestionsHandler, getQuestionHandler, updateQuestionHandler } from '../../src/controllers/questions';
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
import { NotFoundException } from '../../src/exceptions/not-found-exception';
|
||||
import { BadRequestException } from '../../src/exceptions/bad-request-exception';
|
||||
|
||||
describe('Questions controllers', () => {
|
||||
let req: Partial<Request>;
|
||||
let res: Partial<Response>;
|
||||
|
||||
let jsonMock: Mock;
|
||||
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jsonMock = vi.fn();
|
||||
res = {
|
||||
json: jsonMock,
|
||||
};
|
||||
});
|
||||
|
||||
it('Get question list', async () => {
|
||||
req = {
|
||||
params: { hruid: 'id05', version: '1' },
|
||||
query: { lang: Language.English, full: 'true' },
|
||||
};
|
||||
|
||||
await getAllQuestionsHandler(req as Request, res as Response);
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ questions: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
// Console.log(result.questions);
|
||||
expect(result.questions).to.have.length.greaterThan(1);
|
||||
});
|
||||
|
||||
it('Get question', async () => {
|
||||
req = {
|
||||
params: { hruid: 'id05', version: '1', seq: '1' },
|
||||
query: { lang: Language.English, full: 'true' },
|
||||
};
|
||||
|
||||
await getQuestionHandler(req as Request, res as Response);
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ question: expect.anything() }));
|
||||
|
||||
// Const result = jsonMock.mock.lastCall?.[0];
|
||||
// Console.log(result.question);
|
||||
});
|
||||
|
||||
it('Get question with fallback sequence number and version', async () => {
|
||||
req = {
|
||||
params: { hruid: 'id05' },
|
||||
query: { lang: Language.English, full: 'true' },
|
||||
};
|
||||
|
||||
await getQuestionHandler(req as Request, res as Response);
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ question: expect.anything() }));
|
||||
|
||||
// Const result = jsonMock.mock.lastCall?.[0];
|
||||
// Console.log(result.question);
|
||||
});
|
||||
|
||||
it('Get question hruid does not exist', async () => {
|
||||
req = {
|
||||
params: { hruid: 'id_not_exist' },
|
||||
query: { lang: Language.English, full: 'true' },
|
||||
};
|
||||
|
||||
await expect(async () => getQuestionHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException);
|
||||
});
|
||||
|
||||
it('Get question no hruid given', async () => {
|
||||
req = {
|
||||
params: {},
|
||||
query: { lang: Language.English, full: 'true' },
|
||||
};
|
||||
|
||||
await expect(async () => getQuestionHandler(req as Request, res as Response)).rejects.toThrow(BadRequestException);
|
||||
});
|
||||
|
||||
/*
|
||||
It('Create and delete question', async() => {
|
||||
req = {
|
||||
params: { hruid: 'id05', version: '1', seq: '2'},
|
||||
query: { lang: Language.English },
|
||||
};
|
||||
|
||||
await deleteQuestionHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ question: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
console.log(result.question);
|
||||
});
|
||||
|
||||
*/
|
||||
|
||||
it('Update question', async () => {
|
||||
const newContent = 'updated question';
|
||||
req = {
|
||||
params: { hruid: 'id05', version: '1', seq: '1' },
|
||||
query: { lang: Language.English },
|
||||
body: { content: newContent },
|
||||
};
|
||||
|
||||
await updateQuestionHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ question: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
// Console.log(result.question);
|
||||
expect(result.question.content).to.eq(newContent);
|
||||
});
|
||||
});
|
240
backend/tests/controllers/students.test.ts
Normal file
240
backend/tests/controllers/students.test.ts
Normal file
|
@ -0,0 +1,240 @@
|
|||
import { setupTestApp } from '../setup-tests.js';
|
||||
import { describe, it, expect, beforeAll, beforeEach, vi, Mock } from 'vitest';
|
||||
import { Request, Response } from 'express';
|
||||
import {
|
||||
getAllStudentsHandler,
|
||||
getStudentHandler,
|
||||
createStudentHandler,
|
||||
deleteStudentHandler,
|
||||
getStudentClassesHandler,
|
||||
getStudentGroupsHandler,
|
||||
getStudentSubmissionsHandler,
|
||||
getStudentQuestionsHandler,
|
||||
createStudentRequestHandler,
|
||||
getStudentRequestsHandler,
|
||||
deleteClassJoinRequestHandler,
|
||||
getStudentRequestHandler,
|
||||
} from '../../src/controllers/students.js';
|
||||
import { TEST_STUDENTS } from '../test_assets/users/students.testdata.js';
|
||||
import { NotFoundException } from '../../src/exceptions/not-found-exception.js';
|
||||
import { BadRequestException } from '../../src/exceptions/bad-request-exception.js';
|
||||
import { ConflictException } from '../../src/exceptions/conflict-exception.js';
|
||||
import { EntityAlreadyExistsException } from '../../src/exceptions/entity-already-exists-exception.js';
|
||||
import { StudentDTO } from '@dwengo-1/common/interfaces/student';
|
||||
import { getClass02 } from '../test_assets/classes/classes.testdata';
|
||||
|
||||
describe('Student controllers', () => {
|
||||
let req: Partial<Request>;
|
||||
let res: Partial<Response>;
|
||||
|
||||
let jsonMock: Mock;
|
||||
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jsonMock = vi.fn();
|
||||
res = {
|
||||
json: jsonMock,
|
||||
};
|
||||
});
|
||||
|
||||
it('Get student', async () => {
|
||||
req = { params: { username: 'DireStraits' } };
|
||||
|
||||
await getStudentHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ student: expect.anything() }));
|
||||
});
|
||||
|
||||
it('Student not found', async () => {
|
||||
req = { params: { username: 'doesnotexist' } };
|
||||
|
||||
await expect(async () => getStudentHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException);
|
||||
});
|
||||
|
||||
it('No username', async () => {
|
||||
req = { params: {} };
|
||||
|
||||
await expect(async () => getStudentHandler(req as Request, res as Response)).rejects.toThrowError(BadRequestException);
|
||||
});
|
||||
|
||||
it('Create and delete student', async () => {
|
||||
const student = {
|
||||
id: 'coolstudent',
|
||||
username: 'coolstudent',
|
||||
firstName: 'New',
|
||||
lastName: 'Student',
|
||||
} as StudentDTO;
|
||||
req = {
|
||||
body: student,
|
||||
};
|
||||
|
||||
await createStudentHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ student: expect.objectContaining(student) }));
|
||||
|
||||
req = { params: { username: 'coolstudent' } };
|
||||
|
||||
await deleteStudentHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ student: expect.objectContaining(student) }));
|
||||
});
|
||||
|
||||
it('Create duplicate student', async () => {
|
||||
req = {
|
||||
body: {
|
||||
username: 'DireStraits',
|
||||
firstName: 'dupe',
|
||||
lastName: 'dupe',
|
||||
},
|
||||
};
|
||||
|
||||
await expect(async () => createStudentHandler(req as Request, res as Response)).rejects.toThrowError(EntityAlreadyExistsException);
|
||||
});
|
||||
|
||||
it('Create student no body', async () => {
|
||||
req = { body: {} };
|
||||
|
||||
await expect(async () => createStudentHandler(req as Request, res as Response)).rejects.toThrowError(BadRequestException);
|
||||
});
|
||||
|
||||
it('Student list', async () => {
|
||||
req = { query: { full: 'true' } };
|
||||
|
||||
await getAllStudentsHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ students: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
|
||||
// Check is DireStraits is part of the student list
|
||||
const studentUsernames = result.students.map((s: StudentDTO) => s.username);
|
||||
expect(studentUsernames).toContain('DireStraits');
|
||||
|
||||
// Check length, +1 because of create
|
||||
expect(result.students).toHaveLength(TEST_STUDENTS.length);
|
||||
});
|
||||
|
||||
it('Student classes', async () => {
|
||||
req = { params: { username: 'DireStraits' }, query: {} };
|
||||
|
||||
await getStudentClassesHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ classes: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
expect(result.classes).to.have.length.greaterThan(0);
|
||||
});
|
||||
|
||||
it('Student groups', async () => {
|
||||
req = { params: { username: 'DireStraits' }, query: {} };
|
||||
|
||||
await getStudentGroupsHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ groups: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
expect(result.groups).to.have.length.greaterThan(0);
|
||||
});
|
||||
|
||||
it('Student submissions', async () => {
|
||||
req = { params: { username: 'DireStraits' }, query: { full: 'true' } };
|
||||
|
||||
await getStudentSubmissionsHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ submissions: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
expect(result.submissions).to.have.length.greaterThan(0);
|
||||
});
|
||||
|
||||
it('Student questions', async () => {
|
||||
req = { params: { username: 'DireStraits' }, query: { full: 'true' } };
|
||||
|
||||
await getStudentQuestionsHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ questions: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
expect(result.questions).to.have.length.greaterThan(0);
|
||||
});
|
||||
|
||||
it('Deleting non-existent student', async () => {
|
||||
req = { params: { username: 'doesnotexist' } };
|
||||
|
||||
await expect(async () => deleteStudentHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException);
|
||||
});
|
||||
|
||||
it('Get join requests by student', async () => {
|
||||
req = {
|
||||
params: { username: 'PinkFloyd' },
|
||||
};
|
||||
|
||||
await getStudentRequestsHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
requests: expect.anything(),
|
||||
})
|
||||
);
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
// Console.log('[JOIN REQUESTS]', result.requests);
|
||||
expect(result.requests.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('Get join request by student and class', async () => {
|
||||
req = {
|
||||
params: { username: 'PinkFloyd', classId: getClass02().classId },
|
||||
};
|
||||
|
||||
await getStudentRequestHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
request: expect.anything(),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('Create and delete join request', async () => {
|
||||
req = {
|
||||
params: { username: 'TheDoors' },
|
||||
body: { classId: getClass02().classId },
|
||||
};
|
||||
|
||||
await createStudentRequestHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ request: expect.anything() }));
|
||||
|
||||
req = {
|
||||
params: { username: 'TheDoors', classId: getClass02().classId },
|
||||
};
|
||||
|
||||
await deleteClassJoinRequestHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ request: expect.anything() }));
|
||||
|
||||
await expect(async () => deleteClassJoinRequestHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException);
|
||||
});
|
||||
|
||||
it('Create join request student already in class error', async () => {
|
||||
req = {
|
||||
params: { username: 'Noordkaap' },
|
||||
body: { classId: getClass02().classId },
|
||||
};
|
||||
|
||||
await expect(async () => createStudentRequestHandler(req as Request, res as Response)).rejects.toThrow(ConflictException);
|
||||
});
|
||||
|
||||
it('Create join request duplicate', async () => {
|
||||
req = {
|
||||
params: { username: 'Tool' },
|
||||
body: { classId: getClass02().classId },
|
||||
};
|
||||
|
||||
await expect(async () => createStudentRequestHandler(req as Request, res as Response)).rejects.toThrow(ConflictException);
|
||||
});
|
||||
});
|
124
backend/tests/controllers/teacher-invitations.test.ts
Normal file
124
backend/tests/controllers/teacher-invitations.test.ts
Normal file
|
@ -0,0 +1,124 @@
|
|||
import { beforeAll, beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import { Request, Response } from 'express';
|
||||
import { setupTestApp } from '../setup-tests.js';
|
||||
import {
|
||||
createInvitationHandler,
|
||||
deleteInvitationHandler,
|
||||
getAllInvitationsHandler,
|
||||
getInvitationHandler,
|
||||
updateInvitationHandler,
|
||||
} from '../../src/controllers/teacher-invitations';
|
||||
import { TeacherInvitationData } from '@dwengo-1/common/interfaces/teacher-invitation';
|
||||
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';
|
||||
|
||||
describe('Teacher controllers', () => {
|
||||
let req: Partial<Request>;
|
||||
let res: Partial<Response>;
|
||||
|
||||
let jsonMock: Mock;
|
||||
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jsonMock = vi.fn();
|
||||
res = {
|
||||
json: jsonMock,
|
||||
};
|
||||
});
|
||||
|
||||
it('Get teacher invitations by', async () => {
|
||||
req = { params: { username: 'LimpBizkit' }, query: { sent: 'true' } };
|
||||
|
||||
await getAllInvitationsHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ invitations: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
// Console.log(result.invitations);
|
||||
expect(result.invitations).to.have.length.greaterThan(0);
|
||||
});
|
||||
|
||||
it('Get teacher invitations for', async () => {
|
||||
req = { params: { username: 'FooFighters' }, query: { by: 'false' } };
|
||||
|
||||
await getAllInvitationsHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ invitations: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
expect(result.invitations).to.have.length.greaterThan(0);
|
||||
});
|
||||
|
||||
it('Create and delete invitation', async () => {
|
||||
const body = {
|
||||
sender: 'LimpBizkit',
|
||||
receiver: 'testleerkracht1',
|
||||
class: getClass02().classId,
|
||||
} as TeacherInvitationData;
|
||||
req = { body };
|
||||
|
||||
await createInvitationHandler(req as Request, res as Response);
|
||||
|
||||
req = {
|
||||
params: {
|
||||
sender: 'LimpBizkit',
|
||||
receiver: 'testleerkracht1',
|
||||
classId: getClass02().classId,
|
||||
},
|
||||
body: { accepted: 'false' },
|
||||
};
|
||||
|
||||
await deleteInvitationHandler(req as Request, res as Response);
|
||||
});
|
||||
|
||||
it('Get invitation', async () => {
|
||||
req = {
|
||||
params: {
|
||||
sender: 'LimpBizkit',
|
||||
receiver: 'FooFighters',
|
||||
classId: getClass02().classId,
|
||||
},
|
||||
};
|
||||
await getInvitationHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ invitation: expect.anything() }));
|
||||
});
|
||||
|
||||
it('Get invitation error', async () => {
|
||||
req = {
|
||||
params: { no: 'no params' },
|
||||
};
|
||||
|
||||
await expect(async () => getInvitationHandler(req as Request, res as Response)).rejects.toThrowError(BadRequestException);
|
||||
});
|
||||
|
||||
it('Accept invitation', async () => {
|
||||
const body = {
|
||||
sender: 'LimpBizkit',
|
||||
receiver: 'FooFighters',
|
||||
class: getClass02().classId,
|
||||
} as TeacherInvitationData;
|
||||
req = { body };
|
||||
|
||||
await updateInvitationHandler(req as Request, res as Response);
|
||||
|
||||
const result1 = jsonMock.mock.lastCall?.[0];
|
||||
expect(result1.invitation.status).toEqual(ClassStatus.Accepted);
|
||||
|
||||
req = {
|
||||
params: {
|
||||
id: getClass02().classId,
|
||||
},
|
||||
};
|
||||
|
||||
await getClassHandler(req as Request, res as Response);
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
expect(result.class.teachers).toContain('FooFighters');
|
||||
});
|
||||
});
|
212
backend/tests/controllers/teachers.test.ts
Normal file
212
backend/tests/controllers/teachers.test.ts
Normal file
|
@ -0,0 +1,212 @@
|
|||
import { beforeAll, beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import { Request, Response } from 'express';
|
||||
import { setupTestApp } from '../setup-tests.js';
|
||||
import { NotFoundException } from '../../src/exceptions/not-found-exception.js';
|
||||
import {
|
||||
createTeacherHandler,
|
||||
deleteTeacherHandler,
|
||||
getAllTeachersHandler,
|
||||
getStudentJoinRequestHandler,
|
||||
getTeacherClassHandler,
|
||||
getTeacherHandler,
|
||||
getTeacherStudentHandler,
|
||||
updateStudentJoinRequestHandler,
|
||||
} from '../../src/controllers/teachers.js';
|
||||
import { BadRequestException } from '../../src/exceptions/bad-request-exception.js';
|
||||
import { EntityAlreadyExistsException } from '../../src/exceptions/entity-already-exists-exception.js';
|
||||
import { getStudentRequestsHandler } from '../../src/controllers/students.js';
|
||||
import { TeacherDTO } from '@dwengo-1/common/interfaces/teacher';
|
||||
import { getClassHandler } from '../../src/controllers/classes';
|
||||
import { getClass02 } from '../test_assets/classes/classes.testdata';
|
||||
|
||||
describe('Teacher controllers', () => {
|
||||
let req: Partial<Request>;
|
||||
let res: Partial<Response>;
|
||||
|
||||
let jsonMock: Mock;
|
||||
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jsonMock = vi.fn();
|
||||
res = {
|
||||
json: jsonMock,
|
||||
};
|
||||
});
|
||||
|
||||
it('Get teacher', async () => {
|
||||
req = { params: { username: 'FooFighters' } };
|
||||
|
||||
await getTeacherHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ teacher: expect.anything() }));
|
||||
});
|
||||
|
||||
it('Teacher not found', async () => {
|
||||
req = { params: { username: 'doesnotexist' } };
|
||||
|
||||
await expect(async () => getTeacherHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException);
|
||||
});
|
||||
|
||||
it('No username', async () => {
|
||||
req = { params: {} };
|
||||
|
||||
await expect(async () => getTeacherHandler(req as Request, res as Response)).rejects.toThrowError(BadRequestException);
|
||||
});
|
||||
|
||||
it('Create and delete teacher', async () => {
|
||||
const teacher = {
|
||||
id: 'coolteacher',
|
||||
username: 'coolteacher',
|
||||
firstName: 'New',
|
||||
lastName: 'Teacher',
|
||||
};
|
||||
req = {
|
||||
body: teacher,
|
||||
};
|
||||
|
||||
await createTeacherHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ teacher: expect.objectContaining(teacher) }));
|
||||
|
||||
req = { params: { username: 'coolteacher' } };
|
||||
|
||||
await deleteTeacherHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ teacher: expect.objectContaining(teacher) }));
|
||||
});
|
||||
|
||||
it('Create duplicate student', async () => {
|
||||
req = {
|
||||
body: {
|
||||
username: 'FooFighters',
|
||||
firstName: 'Dave',
|
||||
lastName: 'Grohl',
|
||||
},
|
||||
};
|
||||
|
||||
await expect(async () => createTeacherHandler(req as Request, res as Response)).rejects.toThrowError(EntityAlreadyExistsException);
|
||||
});
|
||||
|
||||
it('Create teacher no body', async () => {
|
||||
req = { body: {} };
|
||||
|
||||
await expect(async () => createTeacherHandler(req as Request, res as Response)).rejects.toThrowError(BadRequestException);
|
||||
});
|
||||
|
||||
it('Teacher list', async () => {
|
||||
req = { query: { full: 'true' } };
|
||||
|
||||
await getAllTeachersHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ teachers: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
|
||||
const teacherUsernames = result.teachers.map((s: TeacherDTO) => s.username);
|
||||
expect(teacherUsernames).toContain('testleerkracht1');
|
||||
|
||||
expect(result.teachers).toHaveLength(5);
|
||||
});
|
||||
|
||||
it('Deleting non-existent student', async () => {
|
||||
req = { params: { username: 'doesnotexist' } };
|
||||
|
||||
await expect(async () => deleteTeacherHandler(req as Request, res as Response)).rejects.toThrow(NotFoundException);
|
||||
});
|
||||
|
||||
it('Get teacher classes', async () => {
|
||||
req = {
|
||||
params: { username: 'testleerkracht1' },
|
||||
query: { full: 'true' },
|
||||
};
|
||||
|
||||
await getTeacherClassHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ classes: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
// Console.log('[TEACHER CLASSES]', result);
|
||||
expect(result.classes.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('Get teacher students', async () => {
|
||||
req = {
|
||||
params: { username: 'testleerkracht1' },
|
||||
query: { full: 'true' },
|
||||
};
|
||||
|
||||
await getTeacherStudentHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ students: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
// Console.log('[TEACHER STUDENTS]', result.students);
|
||||
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 () => {
|
||||
req = {
|
||||
params: { classId: getClass02().classId },
|
||||
};
|
||||
|
||||
await getStudentJoinRequestHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ joinRequests: expect.anything() }));
|
||||
|
||||
const result = jsonMock.mock.lastCall?.[0];
|
||||
// Console.log('[JOIN REQUESTS FOR CLASS]', result.joinRequests);
|
||||
expect(result.joinRequests.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('Update join request status', async () => {
|
||||
req = {
|
||||
params: { classId: getClass02().classId, studentUsername: 'PinkFloyd' },
|
||||
body: { accepted: 'true' },
|
||||
};
|
||||
|
||||
await updateStudentJoinRequestHandler(req as Request, res as Response);
|
||||
|
||||
expect(jsonMock).toHaveBeenCalledWith(expect.objectContaining({ request: expect.anything() }));
|
||||
|
||||
req = {
|
||||
params: { username: 'PinkFloyd' },
|
||||
};
|
||||
|
||||
await getStudentRequestsHandler(req as Request, res as Response);
|
||||
|
||||
const status: boolean = jsonMock.mock.lastCall?.[0].requests[0].status;
|
||||
expect(status).toBeTruthy();
|
||||
|
||||
req = {
|
||||
params: { id: getClass02().classId },
|
||||
};
|
||||
|
||||
await getClassHandler(req as Request, res as Response);
|
||||
const students: string[] = jsonMock.mock.lastCall?.[0].class.students;
|
||||
expect(students).contains('PinkFloyd');
|
||||
});
|
||||
});
|
|
@ -3,6 +3,7 @@ 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 { getClass02 } from '../../test_assets/classes/classes.testdata';
|
||||
|
||||
describe('AssignmentRepository', () => {
|
||||
let assignmentRepository: AssignmentRepository;
|
||||
|
@ -15,15 +16,15 @@ describe('AssignmentRepository', () => {
|
|||
});
|
||||
|
||||
it('should return the requested assignment', async () => {
|
||||
const class_ = await classRepository.findById('id02');
|
||||
const assignment = await assignmentRepository.findByClassAndId(class_!, 2);
|
||||
const class_ = await classRepository.findById(getClass02().classId);
|
||||
const assignment = await assignmentRepository.findByClassAndId(class_!, 21001);
|
||||
|
||||
expect(assignment).toBeTruthy();
|
||||
expect(assignment!.title).toBe('tool');
|
||||
});
|
||||
|
||||
it('should return all assignments for a class', async () => {
|
||||
const class_ = await classRepository.findById('id02');
|
||||
const class_ = await classRepository.findById(getClass02().classId);
|
||||
const assignments = await assignmentRepository.findAllAssignmentsInClass(class_!);
|
||||
|
||||
expect(assignments).toBeTruthy();
|
||||
|
@ -31,6 +32,13 @@ describe('AssignmentRepository', () => {
|
|||
expect(assignments[0].title).toBe('tool');
|
||||
});
|
||||
|
||||
it('should find all by username of the responsible teacher', async () => {
|
||||
const result = await assignmentRepository.findAllByResponsibleTeacher('testleerkracht1');
|
||||
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);
|
||||
|
|
|
@ -4,6 +4,7 @@ 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';
|
||||
|
||||
describe('GroupRepository', () => {
|
||||
let groupRepository: GroupRepository;
|
||||
|
@ -18,17 +19,18 @@ describe('GroupRepository', () => {
|
|||
});
|
||||
|
||||
it('should return the requested group', async () => {
|
||||
const class_ = await classRepository.findById('id01');
|
||||
const assignment = await assignmentRepository.findByClassAndId(class_!, 1);
|
||||
const id = getClass01().classId;
|
||||
const class_ = await classRepository.findById(id);
|
||||
const assignment = await assignmentRepository.findByClassAndId(class_!, 21000);
|
||||
|
||||
const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 1);
|
||||
const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 21001);
|
||||
|
||||
expect(group).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return all groups for assignment', async () => {
|
||||
const class_ = await classRepository.findById('id01');
|
||||
const assignment = await assignmentRepository.findByClassAndId(class_!, 1);
|
||||
const class_ = await classRepository.findById(getClass01().classId);
|
||||
const assignment = await assignmentRepository.findByClassAndId(class_!, 21000);
|
||||
|
||||
const groups = await groupRepository.findAllGroupsForAssignment(assignment!);
|
||||
|
||||
|
@ -37,10 +39,10 @@ describe('GroupRepository', () => {
|
|||
});
|
||||
|
||||
it('should not find removed group', async () => {
|
||||
const class_ = await classRepository.findById('id02');
|
||||
const assignment = await assignmentRepository.findByClassAndId(class_!, 2);
|
||||
const class_ = await classRepository.findById(getClass02().classId);
|
||||
const assignment = await assignmentRepository.findByClassAndId(class_!, 21001);
|
||||
|
||||
await groupRepository.deleteByAssignmentAndGroupNumber(assignment!, 1);
|
||||
await groupRepository.deleteByAssignmentAndGroupNumber(assignment!, 21001);
|
||||
|
||||
const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 1);
|
||||
|
||||
|
|
|
@ -9,11 +9,16 @@ import {
|
|||
getSubmissionRepository,
|
||||
} from '../../../src/data/repositories';
|
||||
import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier';
|
||||
import { Language } from '../../../src/entities/content/language';
|
||||
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';
|
||||
|
||||
describe('SubmissionRepository', () => {
|
||||
let submissionRepository: SubmissionRepository;
|
||||
|
@ -50,17 +55,60 @@ describe('SubmissionRepository', () => {
|
|||
|
||||
it('should find the most recent submission for a group', async () => {
|
||||
const id = new LearningObjectIdentifier('id03', Language.English, 1);
|
||||
const class_ = await classRepository.findById('id01');
|
||||
const assignment = await assignmentRepository.findByClassAndId(class_!, 1);
|
||||
const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 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!);
|
||||
|
||||
expect(submission).toBeTruthy();
|
||||
expect(submission?.submissionTime.getDate()).toBe(25);
|
||||
});
|
||||
|
||||
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 result = await submissionRepository.findAllSubmissionsForLearningObjectAndAssignment(loId, assignment!);
|
||||
sortSubmissions(result);
|
||||
|
||||
expect(result).toHaveLength(3);
|
||||
|
||||
// Submission3 should be found (for learning object 'id02' by group #1 for Assignment #1 in class 'id01')
|
||||
expect(result[0].learningObjectHruid).toBe(loId.hruid);
|
||||
expect(result[0].submissionNumber).toBe(1);
|
||||
|
||||
// Submission4 should be found (for learning object 'id02' by group #1 for Assignment #1 in class 'id01')
|
||||
expect(result[1].learningObjectHruid).toBe(loId.hruid);
|
||||
expect(result[1].submissionNumber).toBe(2);
|
||||
|
||||
// Submission8 should be found (for learning object 'id02' by group #2 for Assignment #1 in class 'id01')
|
||||
expect(result[2].learningObjectHruid).toBe(loId.hruid);
|
||||
expect(result[2].submissionNumber).toBe(3);
|
||||
});
|
||||
|
||||
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!);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
|
||||
// Submission8 should be found (for learning object 'id02' by group #2 for Assignment #1 in class 'id01')
|
||||
expect(result[0].learningObjectHruid).toBe(loId.hruid);
|
||||
expect(result[0].submissionNumber).toBe(3);
|
||||
|
||||
// The other submissions found in the previous test case should not be found anymore as they were made on
|
||||
// Behalf of group #1 which Tool is no member of.
|
||||
});
|
||||
|
||||
it('should not find a deleted submission', async () => {
|
||||
const id = new LearningObjectIdentifier('id01', Language.English, 1);
|
||||
const id = new LearningObjectIdentifier(testLearningObject01.hruid, testLearningObject01.language, testLearningObject01.version);
|
||||
await submissionRepository.deleteSubmissionByLearningObjectAndSubmissionNumber(id, 1);
|
||||
|
||||
const submission = await submissionRepository.findSubmissionByLearningObjectAndSubmissionNumber(id, 1);
|
||||
|
@ -68,3 +116,15 @@ describe('SubmissionRepository', () => {
|
|||
expect(submission).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
function sortSubmissions(submissions: Submission[]): void {
|
||||
submissions.sort((a, b) => {
|
||||
if (a.learningObjectHruid < b.learningObjectHruid) {
|
||||
return -1;
|
||||
}
|
||||
if (a.learningObjectHruid > b.learningObjectHruid) {
|
||||
return 1;
|
||||
}
|
||||
return a.submissionNumber! - b.submissionNumber!;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,9 +3,8 @@ 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 { Class } from '../../../src/entities/classes/class.entity';
|
||||
import { ClassRepository } from '../../../src/data/classes/class-repository';
|
||||
import { Student } from '../../../src/entities/users/student.entity';
|
||||
import { getClass02, getClass03 } from '../../test_assets/classes/classes.testdata';
|
||||
|
||||
describe('ClassJoinRequestRepository', () => {
|
||||
let classJoinRequestRepository: ClassJoinRequestRepository;
|
||||
|
@ -28,7 +27,7 @@ describe('ClassJoinRequestRepository', () => {
|
|||
});
|
||||
|
||||
it('should list all requests to a single class', async () => {
|
||||
const class_ = await cassRepository.findById('id02');
|
||||
const class_ = await cassRepository.findById(getClass02().classId);
|
||||
const requests = await classJoinRequestRepository.findAllOpenRequestsTo(class_!);
|
||||
|
||||
expect(requests).toBeTruthy();
|
||||
|
@ -37,7 +36,7 @@ describe('ClassJoinRequestRepository', () => {
|
|||
|
||||
it('should not find a removed request', async () => {
|
||||
const student = await studentRepository.findByUsername('SmashingPumpkins');
|
||||
const class_ = await cassRepository.findById('id03');
|
||||
const class_ = await cassRepository.findById(getClass03().classId);
|
||||
await classJoinRequestRepository.deleteBy(student!, class_!);
|
||||
|
||||
const request = await classJoinRequestRepository.findAllRequestsBy(student!);
|
||||
|
|
|
@ -2,6 +2,7 @@ import { beforeAll, describe, expect, it } from 'vitest';
|
|||
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';
|
||||
|
||||
describe('ClassRepository', () => {
|
||||
let classRepository: ClassRepository;
|
||||
|
@ -18,16 +19,16 @@ describe('ClassRepository', () => {
|
|||
});
|
||||
|
||||
it('should return requested class', async () => {
|
||||
const classVar = await classRepository.findById('id01');
|
||||
const classVar = await classRepository.findById(getClass01().classId);
|
||||
|
||||
expect(classVar).toBeTruthy();
|
||||
expect(classVar?.displayName).toBe('class01');
|
||||
});
|
||||
|
||||
it('class should be gone after deletion', async () => {
|
||||
await classRepository.deleteById('id04');
|
||||
await classRepository.deleteById(getClass04().classId);
|
||||
|
||||
const classVar = await classRepository.findById('id04');
|
||||
const classVar = await classRepository.findById(getClass04().classId);
|
||||
|
||||
expect(classVar).toBeNull();
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@ import { getClassRepository, getTeacherInvitationRepository, getTeacherRepositor
|
|||
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 { getClass01, getClass02 } from '../../test_assets/classes/classes.testdata';
|
||||
|
||||
describe('ClassRepository', () => {
|
||||
let teacherInvitationRepository: TeacherInvitationRepository;
|
||||
|
@ -34,7 +35,7 @@ describe('ClassRepository', () => {
|
|||
});
|
||||
|
||||
it('should return all invitations for a class', async () => {
|
||||
const class_ = await classRepository.findById('id02');
|
||||
const class_ = await classRepository.findById(getClass02().classId);
|
||||
const invitations = await teacherInvitationRepository.findAllInvitationsForClass(class_!);
|
||||
|
||||
expect(invitations).toBeTruthy();
|
||||
|
@ -42,7 +43,7 @@ describe('ClassRepository', () => {
|
|||
});
|
||||
|
||||
it('should not find a removed invitation', async () => {
|
||||
const class_ = await classRepository.findById('id01');
|
||||
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!);
|
||||
|
|
|
@ -2,65 +2,57 @@ import { beforeAll, describe, expect, it } from 'vitest';
|
|||
import { setupTestApp } from '../../setup-tests.js';
|
||||
import { getAttachmentRepository, getLearningObjectRepository } from '../../../src/data/repositories.js';
|
||||
import { AttachmentRepository } from '../../../src/data/content/attachment-repository.js';
|
||||
import { LearningObjectRepository } from '../../../src/data/content/learning-object-repository.js';
|
||||
import example from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example.js';
|
||||
import { LearningObject } from '../../../src/entities/content/learning-object.entity.js';
|
||||
import { Attachment } from '../../../src/entities/content/attachment.entity.js';
|
||||
import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier.js';
|
||||
|
||||
const NEWER_TEST_SUFFIX = 'nEweR';
|
||||
|
||||
function createTestLearningObjects(learningObjectRepo: LearningObjectRepository): { older: LearningObject; newer: LearningObject } {
|
||||
const olderExample = example.createLearningObject();
|
||||
learningObjectRepo.save(olderExample);
|
||||
|
||||
const newerExample = example.createLearningObject();
|
||||
newerExample.title = 'Newer example';
|
||||
newerExample.version = 100;
|
||||
|
||||
return {
|
||||
older: olderExample,
|
||||
newer: newerExample,
|
||||
};
|
||||
}
|
||||
import { testLearningObjectPnNotebooks } from '../../test_assets/content/learning-objects.testdata';
|
||||
import { v4 as uuidV4 } from 'uuid';
|
||||
|
||||
describe('AttachmentRepository', () => {
|
||||
let attachmentRepo: AttachmentRepository;
|
||||
let exampleLearningObjects: { older: LearningObject; newer: LearningObject };
|
||||
let newLearningObject: LearningObject;
|
||||
let attachmentsOlderLearningObject: Attachment[];
|
||||
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
|
||||
attachmentsOlderLearningObject = testLearningObjectPnNotebooks.attachments as Attachment[];
|
||||
|
||||
attachmentRepo = getAttachmentRepository();
|
||||
exampleLearningObjects = createTestLearningObjects(getLearningObjectRepository());
|
||||
});
|
||||
const learningObjectRepo = getLearningObjectRepository();
|
||||
|
||||
it('can add attachments to learning objects without throwing an error', () => {
|
||||
attachmentsOlderLearningObject = Object.values(example.createAttachment).map((fn) => fn(exampleLearningObjects.older));
|
||||
const newLearningObjectData = structuredClone(testLearningObjectPnNotebooks);
|
||||
newLearningObjectData.title = 'Newer example';
|
||||
newLearningObjectData.version = 101;
|
||||
newLearningObjectData.attachments = [];
|
||||
newLearningObjectData.uuid = uuidV4();
|
||||
newLearningObjectData.content = Buffer.from('Content of the newer example');
|
||||
|
||||
for (const attachment of attachmentsOlderLearningObject) {
|
||||
attachmentRepo.save(attachment);
|
||||
}
|
||||
newLearningObject = learningObjectRepo.create(newLearningObjectData);
|
||||
await learningObjectRepo.save(newLearningObject);
|
||||
});
|
||||
|
||||
let attachmentOnlyNewer: Attachment;
|
||||
it('allows us to add attachments with the same name to a different learning object without throwing an error', () => {
|
||||
attachmentOnlyNewer = Object.values(example.createAttachment)[0](exampleLearningObjects.newer);
|
||||
attachmentOnlyNewer.content.write(NEWER_TEST_SUFFIX);
|
||||
it('allows us to add attachments with the same name to a different learning object without throwing an error', async () => {
|
||||
attachmentOnlyNewer = structuredClone(attachmentsOlderLearningObject[0]);
|
||||
attachmentOnlyNewer.learningObject = newLearningObject;
|
||||
attachmentOnlyNewer.content = Buffer.from('New attachment content');
|
||||
|
||||
attachmentRepo.save(attachmentOnlyNewer);
|
||||
await attachmentRepo.save(attachmentRepo.create(attachmentOnlyNewer));
|
||||
});
|
||||
|
||||
let olderLearningObjectId: LearningObjectIdentifier;
|
||||
it('returns the correct attachment when queried by learningObjectId and attachment name', async () => {
|
||||
olderLearningObjectId = {
|
||||
hruid: exampleLearningObjects.older.hruid,
|
||||
language: exampleLearningObjects.older.language,
|
||||
version: exampleLearningObjects.older.version,
|
||||
hruid: testLearningObjectPnNotebooks.hruid,
|
||||
language: testLearningObjectPnNotebooks.language,
|
||||
version: testLearningObjectPnNotebooks.version,
|
||||
};
|
||||
|
||||
const result = await attachmentRepo.findByLearningObjectIdAndName(olderLearningObjectId, attachmentsOlderLearningObject[0].name);
|
||||
expect(result).toBe(attachmentsOlderLearningObject[0]);
|
||||
expect(result).not.toBeNull();
|
||||
expect(result!.name).toEqual(attachmentsOlderLearningObject[0].name);
|
||||
expect(result!.content).toEqual(attachmentsOlderLearningObject[0].content);
|
||||
});
|
||||
|
||||
it('returns null when queried by learningObjectId and non-existing attachment name', async () => {
|
||||
|
@ -70,10 +62,12 @@ describe('AttachmentRepository', () => {
|
|||
|
||||
it('returns the newer version of the attachment when only queried by hruid, language and attachment name (but not version)', async () => {
|
||||
const result = await attachmentRepo.findByMostRecentVersionOfLearningObjectAndName(
|
||||
exampleLearningObjects.older.hruid,
|
||||
exampleLearningObjects.older.language,
|
||||
testLearningObjectPnNotebooks.hruid,
|
||||
testLearningObjectPnNotebooks.language,
|
||||
attachmentOnlyNewer.name
|
||||
);
|
||||
expect(result).toBe(attachmentOnlyNewer);
|
||||
expect(result).not.toBeNull();
|
||||
expect(result!.name).toEqual(attachmentOnlyNewer.name);
|
||||
expect(result!.content).toEqual(attachmentOnlyNewer.content);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,28 +1,21 @@
|
|||
import { beforeAll, describe, expect, it } from 'vitest';
|
||||
import { setupTestApp } from '../../setup-tests.js';
|
||||
import { getAttachmentRepository, getLearningObjectRepository } from '../../../src/data/repositories.js';
|
||||
import { getAttachmentRepository } from '../../../src/data/repositories.js';
|
||||
import { AttachmentRepository } from '../../../src/data/content/attachment-repository.js';
|
||||
import { LearningObjectRepository } from '../../../src/data/content/learning-object-repository.js';
|
||||
import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier.js';
|
||||
import { Language } from '../../../src/entities/content/language.js';
|
||||
import { testLearningObject02 } from '../../test_assets/content/learning-objects.testdata';
|
||||
|
||||
describe('AttachmentRepository', () => {
|
||||
let attachmentRepository: AttachmentRepository;
|
||||
let learningObjectRepository: LearningObjectRepository;
|
||||
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
attachmentRepository = getAttachmentRepository();
|
||||
learningObjectRepository = getLearningObjectRepository();
|
||||
});
|
||||
|
||||
it('should return the requested attachment', async () => {
|
||||
const id = new LearningObjectIdentifier('id02', Language.English, 1);
|
||||
const learningObject = await learningObjectRepository.findByIdentifier(id);
|
||||
|
||||
const attachment = await attachmentRepository.findByMostRecentVersionOfLearningObjectAndName(
|
||||
learningObject!.hruid,
|
||||
Language.English,
|
||||
testLearningObject02.hruid,
|
||||
testLearningObject02.language,
|
||||
'attachment01'
|
||||
);
|
||||
|
||||
|
|
|
@ -2,48 +2,33 @@ import { beforeAll, describe, it, expect } from 'vitest';
|
|||
import { LearningObjectRepository } from '../../../src/data/content/learning-object-repository.js';
|
||||
import { setupTestApp } from '../../setup-tests.js';
|
||||
import { getLearningObjectRepository } from '../../../src/data/repositories.js';
|
||||
import example from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example.js';
|
||||
import { LearningObject } from '../../../src/entities/content/learning-object.entity.js';
|
||||
import { expectToBeCorrectEntity } from '../../test-utils/expectations.js';
|
||||
import { testLearningObject01, testLearningObject02, testLearningObject03 } from '../../test_assets/content/learning-objects.testdata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
describe('LearningObjectRepository', () => {
|
||||
let learningObjectRepository: LearningObjectRepository;
|
||||
|
||||
let exampleLearningObject: LearningObject;
|
||||
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
learningObjectRepository = getLearningObjectRepository();
|
||||
});
|
||||
|
||||
it('should be able to add a learning object to it without an error', async () => {
|
||||
exampleLearningObject = example.createLearningObject();
|
||||
await learningObjectRepository.insert(exampleLearningObject);
|
||||
});
|
||||
|
||||
it('should return the learning object when queried by id', async () => {
|
||||
it('should return a learning object when queried by id', async () => {
|
||||
const result = await learningObjectRepository.findByIdentifier({
|
||||
hruid: exampleLearningObject.hruid,
|
||||
language: exampleLearningObject.language,
|
||||
version: exampleLearningObject.version,
|
||||
hruid: testLearningObject01.hruid,
|
||||
language: testLearningObject02.language,
|
||||
version: testLearningObject03.version,
|
||||
});
|
||||
expect(result).toBeInstanceOf(LearningObject);
|
||||
expectToBeCorrectEntity(
|
||||
{
|
||||
name: 'actual',
|
||||
entity: result!,
|
||||
},
|
||||
{
|
||||
name: 'expected',
|
||||
entity: exampleLearningObject,
|
||||
}
|
||||
);
|
||||
expectToBeCorrectEntity(result!, testLearningObject01);
|
||||
});
|
||||
|
||||
it('should return null when non-existing version is queried', async () => {
|
||||
const result = await learningObjectRepository.findByIdentifier({
|
||||
hruid: exampleLearningObject.hruid,
|
||||
language: exampleLearningObject.language,
|
||||
hruid: testLearningObject01.hruid,
|
||||
language: testLearningObject01.language,
|
||||
version: 100,
|
||||
});
|
||||
expect(result).toBe(null);
|
||||
|
@ -52,9 +37,12 @@ describe('LearningObjectRepository', () => {
|
|||
let newerExample: LearningObject;
|
||||
|
||||
it('should allow a learning object with the same id except a different version to be added', async () => {
|
||||
newerExample = example.createLearningObject();
|
||||
newerExample.version = 10;
|
||||
newerExample.title += ' (nieuw)';
|
||||
const testLearningObject01Newer = structuredClone(testLearningObject01);
|
||||
testLearningObject01Newer.version = 10;
|
||||
testLearningObject01Newer.title += ' (nieuw)';
|
||||
testLearningObject01Newer.uuid = v4();
|
||||
testLearningObject01Newer.content = Buffer.from('This is the new content.');
|
||||
newerExample = learningObjectRepository.create(testLearningObject01Newer);
|
||||
await learningObjectRepository.save(newerExample);
|
||||
});
|
||||
|
||||
|
@ -66,7 +54,7 @@ describe('LearningObjectRepository', () => {
|
|||
});
|
||||
|
||||
it('should return null when queried by non-existing hruid or language', async () => {
|
||||
const result = await learningObjectRepository.findLatestByHruidAndLanguage('something_that_does_not_exist', exampleLearningObject.language);
|
||||
const result = await learningObjectRepository.findLatestByHruidAndLanguage('something_that_does_not_exist', testLearningObject01.language);
|
||||
expect(result).toBe(null);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,7 +3,8 @@ import { LearningObjectRepository } from '../../../src/data/content/learning-obj
|
|||
import { getLearningObjectRepository } from '../../../src/data/repositories';
|
||||
import { setupTestApp } from '../../setup-tests';
|
||||
import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier';
|
||||
import { Language } from '../../../src/entities/content/language';
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
import { testLearningObject01 } from '../../test_assets/content/learning-objects.testdata';
|
||||
|
||||
describe('LearningObjectRepository', () => {
|
||||
let learningObjectRepository: LearningObjectRepository;
|
||||
|
@ -13,8 +14,8 @@ describe('LearningObjectRepository', () => {
|
|||
learningObjectRepository = getLearningObjectRepository();
|
||||
});
|
||||
|
||||
const id01 = new LearningObjectIdentifier('id01', Language.English, 1);
|
||||
const id02 = new LearningObjectIdentifier('test_id', Language.English, 1);
|
||||
const id01 = new LearningObjectIdentifier(testLearningObject01.hruid, testLearningObject01.language, testLearningObject01.version);
|
||||
const id02 = new LearningObjectIdentifier('non_existing_id', Language.English, 1);
|
||||
|
||||
it('should return the learning object that matches identifier 1', async () => {
|
||||
const learningObject = await learningObjectRepository.findByIdentifier(id01);
|
||||
|
|
|
@ -2,41 +2,27 @@ import { beforeAll, describe, expect, it } from 'vitest';
|
|||
import { setupTestApp } from '../../setup-tests.js';
|
||||
import { getLearningPathRepository } from '../../../src/data/repositories.js';
|
||||
import { LearningPathRepository } from '../../../src/data/content/learning-path-repository.js';
|
||||
import example from '../../test-assets/learning-paths/pn-werking-example.js';
|
||||
import { LearningPath } from '../../../src/entities/content/learning-path.entity.js';
|
||||
import { expectToBeCorrectEntity } from '../../test-utils/expectations.js';
|
||||
import { Language } from '../../../src/entities/content/language.js';
|
||||
|
||||
function expectToHaveFoundPrecisely(expected: LearningPath, result: LearningPath[]): void {
|
||||
expect(result).toHaveProperty('length');
|
||||
expect(result.length).toBe(1);
|
||||
expectToBeCorrectEntity({ entity: result[0]! }, { entity: expected });
|
||||
}
|
||||
|
||||
function expectToHaveFoundNothing(result: LearningPath[]): void {
|
||||
expect(result).toHaveProperty('length');
|
||||
expect(result.length).toBe(0);
|
||||
}
|
||||
import { expectToBeCorrectEntity, expectToHaveFoundNothing, expectToHaveFoundPrecisely } from '../../test-utils/expectations.js';
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
import { testLearningPath01 } from '../../test_assets/content/learning-paths.testdata';
|
||||
import { mapToLearningPath } from '../../../src/services/learning-paths/learning-path-service';
|
||||
|
||||
describe('LearningPathRepository', () => {
|
||||
let learningPathRepo: LearningPathRepository;
|
||||
let examplePath: LearningPath;
|
||||
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
learningPathRepo = getLearningPathRepository();
|
||||
|
||||
examplePath = mapToLearningPath(testLearningPath01, []);
|
||||
});
|
||||
|
||||
let examplePath: LearningPath;
|
||||
|
||||
it('should be able to add a learning path without throwing an error', async () => {
|
||||
examplePath = example.createLearningPath();
|
||||
await learningPathRepo.insert(examplePath);
|
||||
});
|
||||
|
||||
it('should return the added path when it is queried by hruid and language', async () => {
|
||||
const result = await learningPathRepo.findByHruidAndLanguage(examplePath.hruid, examplePath.language);
|
||||
it('should return a learning path when it is queried by hruid and language', async () => {
|
||||
const result = await learningPathRepo.findByHruidAndLanguage(testLearningPath01.hruid, testLearningPath01.language as Language);
|
||||
expect(result).toBeInstanceOf(LearningPath);
|
||||
expectToBeCorrectEntity({ entity: result! }, { entity: examplePath });
|
||||
expectToBeCorrectEntity(result!, examplePath);
|
||||
});
|
||||
|
||||
it('should return null to a query on a non-existing hruid or language', async () => {
|
||||
|
@ -45,7 +31,7 @@ describe('LearningPathRepository', () => {
|
|||
});
|
||||
|
||||
it('should return the learning path when we search for a search term occurring in its title', async () => {
|
||||
const result = await learningPathRepo.findByQueryStringAndLanguage(examplePath.title.slice(4, 9), examplePath.language);
|
||||
const result = await learningPathRepo.findByQueryStringAndLanguage(examplePath.title.slice(9, 13), examplePath.language);
|
||||
expectToHaveFoundPrecisely(examplePath, result);
|
||||
});
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@ import { beforeAll, describe, expect, it } from 'vitest';
|
|||
import { getLearningPathRepository } from '../../../src/data/repositories';
|
||||
import { LearningPathRepository } from '../../../src/data/content/learning-path-repository';
|
||||
import { setupTestApp } from '../../setup-tests';
|
||||
import { Language } from '../../../src/entities/content/language';
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
import { testLearningPath01 } from '../../test_assets/content/learning-paths.testdata';
|
||||
|
||||
describe('LearningPathRepository', () => {
|
||||
let learningPathRepository: LearningPathRepository;
|
||||
|
@ -19,10 +20,10 @@ describe('LearningPathRepository', () => {
|
|||
});
|
||||
|
||||
it('should return requested learning path', async () => {
|
||||
const learningPath = await learningPathRepository.findByHruidAndLanguage('id01', Language.English);
|
||||
const learningPath = await learningPathRepository.findByHruidAndLanguage(testLearningPath01.hruid, testLearningPath01.language as Language);
|
||||
|
||||
expect(learningPath).toBeTruthy();
|
||||
expect(learningPath?.title).toBe('repertoire Tool');
|
||||
expect(learningPath?.description).toBe('all about Tool');
|
||||
expect(learningPath?.title).toBe(testLearningPath01.title);
|
||||
expect(learningPath?.description).toBe(testLearningPath01.description);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@ 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 '../../../src/entities/content/language';
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
import { TeacherRepository } from '../../../src/data/users/teacher-repository';
|
||||
|
||||
describe('AnswerRepository', () => {
|
||||
|
@ -23,9 +23,9 @@ describe('AnswerRepository', () => {
|
|||
const id = new LearningObjectIdentifier('id05', Language.English, 1);
|
||||
const questions = await questionRepository.findAllQuestionsAboutLearningObject(id);
|
||||
|
||||
const question = questions.filter((it) => it.sequenceNumber == 2)[0];
|
||||
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);
|
||||
|
|
|
@ -1,22 +1,29 @@
|
|||
import { beforeAll, describe, expect, it } from 'vitest';
|
||||
import { setupTestApp } from '../../setup-tests';
|
||||
import { QuestionRepository } from '../../../src/data/questions/question-repository';
|
||||
import { getLearningObjectRepository, getQuestionRepository, getStudentRepository } from '../../../src/data/repositories';
|
||||
import {
|
||||
getAssignmentRepository,
|
||||
getClassRepository,
|
||||
getGroupRepository,
|
||||
getQuestionRepository,
|
||||
getStudentRepository,
|
||||
} from '../../../src/data/repositories';
|
||||
import { StudentRepository } from '../../../src/data/users/student-repository';
|
||||
import { LearningObjectRepository } from '../../../src/data/content/learning-object-repository';
|
||||
import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier';
|
||||
import { Language } from '../../../src/entities/content/language';
|
||||
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';
|
||||
|
||||
describe('QuestionRepository', () => {
|
||||
let questionRepository: QuestionRepository;
|
||||
let studentRepository: StudentRepository;
|
||||
let learningObjectRepository: LearningObjectRepository;
|
||||
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
questionRepository = getQuestionRepository();
|
||||
studentRepository = getStudentRepository();
|
||||
learningObjectRepository = getLearningObjectRepository();
|
||||
});
|
||||
|
||||
it('should return all questions part of the given learning object', async () => {
|
||||
|
@ -24,14 +31,19 @@ describe('QuestionRepository', () => {
|
|||
const questions = await questionRepository.findAllQuestionsAboutLearningObject(id);
|
||||
|
||||
expect(questions).toBeTruthy();
|
||||
expect(questions).toHaveLength(2);
|
||||
expect(questions).toHaveLength(4);
|
||||
});
|
||||
|
||||
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);
|
||||
await questionRepository.createQuestion({
|
||||
loId: id,
|
||||
inGroup: group!,
|
||||
author: student!,
|
||||
content: 'question?',
|
||||
});
|
||||
|
@ -41,6 +53,52 @@ describe('QuestionRepository', () => {
|
|||
expect(question).toHaveLength(1);
|
||||
});
|
||||
|
||||
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 result = await questionRepository.findAllQuestionsAboutLearningObjectInAssignment(loId, assignment!);
|
||||
sortQuestions(result);
|
||||
|
||||
expect(result).toHaveLength(3);
|
||||
|
||||
// Question01: About learning object 'id05', in group #1 for Assignment #1 in class 'id01'
|
||||
expect(result[0].learningObjectHruid).toEqual(loId.hruid);
|
||||
expect(result[0].sequenceNumber).toEqual(1);
|
||||
|
||||
// Question02: About learning object 'id05', in group #1 for Assignment #1 in class 'id01'
|
||||
expect(result[1].learningObjectHruid).toEqual(loId.hruid);
|
||||
expect(result[1].sequenceNumber).toEqual(2);
|
||||
|
||||
// Question05: About learning object 'id05', in group #2 for Assignment #1 in class 'id01'
|
||||
expect(result[2].learningObjectHruid).toEqual(loId.hruid);
|
||||
expect(result[2].sequenceNumber).toEqual(3);
|
||||
|
||||
// Question06: About learning object 'id05', but for Assignment #2 in class 'id01' => not expected.
|
||||
});
|
||||
|
||||
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');
|
||||
// (student Tool is in group #2)
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
|
||||
// Question01 and question02 are in group #1 => not displayed.
|
||||
|
||||
// Question05: About learning object 'id05', in group #2 for Assignment #1 in class 'id01'
|
||||
expect(result[0].learningObjectHruid).toEqual(loId.hruid);
|
||||
expect(result[0].sequenceNumber).toEqual(3);
|
||||
|
||||
// Question06: About learning object 'id05', but for Assignment #2 in class 'id01' => not expected.
|
||||
});
|
||||
|
||||
it('should not find removed question', async () => {
|
||||
const id = new LearningObjectIdentifier('id04', Language.English, 1);
|
||||
await questionRepository.removeQuestionByLearningObjectAndSequenceNumber(id, 1);
|
||||
|
@ -50,3 +108,14 @@ describe('QuestionRepository', () => {
|
|||
expect(question).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
function sortQuestions(questions: Question[]): void {
|
||||
questions.sort((a, b) => {
|
||||
if (a.learningObjectHruid < b.learningObjectHruid) {
|
||||
return -1;
|
||||
} else if (a.learningObjectHruid > b.learningObjectHruid) {
|
||||
return 1;
|
||||
}
|
||||
return a.sequenceNumber! - b.sequenceNumber!;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { setupTestApp } from '../../setup-tests.js';
|
||||
import { Student } from '../../../src/entities/users/student.entity.js';
|
||||
import { describe, it, expect, beforeAll } from 'vitest';
|
||||
import { StudentRepository } from '../../../src/data/users/student-repository.js';
|
||||
import { getStudentRepository } from '../../../src/data/repositories.js';
|
||||
|
@ -30,7 +29,7 @@ describe('StudentRepository', () => {
|
|||
});
|
||||
|
||||
it('should return the queried student after he was added', async () => {
|
||||
await studentRepository.insert(new Student(username, firstName, lastName));
|
||||
await studentRepository.insert(studentRepository.create({ username, firstName, lastName }));
|
||||
|
||||
const retrievedStudent = await studentRepository.findByUsername(username);
|
||||
expect(retrievedStudent).toBeTruthy();
|
||||
|
|
|
@ -2,7 +2,6 @@ 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 { Teacher } from '../../../src/entities/users/teacher.entity';
|
||||
|
||||
const username = 'testteacher';
|
||||
const firstName = 'John';
|
||||
|
@ -30,7 +29,7 @@ describe('TeacherRepository', () => {
|
|||
});
|
||||
|
||||
it('should return the queried teacher after he was added', async () => {
|
||||
await teacherRepository.insert(new Teacher(username, firstName, lastName));
|
||||
await teacherRepository.insert(teacherRepository.create({ username, firstName, lastName }));
|
||||
|
||||
const retrievedTeacher = await teacherRepository.findByUsername(username);
|
||||
expect(retrievedTeacher).toBeTruthy();
|
||||
|
|
|
@ -1,43 +1,38 @@
|
|||
import { beforeAll, describe, expect, it } from 'vitest';
|
||||
import { setupTestApp } from '../../setup-tests';
|
||||
import { getLearningObjectRepository, getLearningPathRepository } from '../../../src/data/repositories';
|
||||
import example from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example';
|
||||
import { LearningObject } from '../../../src/entities/content/learning-object.entity';
|
||||
import databaseLearningObjectProvider from '../../../src/services/learning-objects/database-learning-object-provider';
|
||||
import { expectToBeCorrectFilteredLearningObject } from '../../test-utils/expectations';
|
||||
import { FilteredLearningObject } from '../../../src/interfaces/learning-content';
|
||||
import { Language } from '../../../src/entities/content/language';
|
||||
import learningObjectExample from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example';
|
||||
import learningPathExample from '../../test-assets/learning-paths/pn-werking-example';
|
||||
import { LearningPath } from '../../../src/entities/content/learning-path.entity';
|
||||
|
||||
async function initExampleData(): Promise<{ learningObject: LearningObject; learningPath: LearningPath }> {
|
||||
const learningObjectRepo = getLearningObjectRepository();
|
||||
const learningPathRepo = getLearningPathRepository();
|
||||
const learningObject = learningObjectExample.createLearningObject();
|
||||
const learningPath = learningPathExample.createLearningPath();
|
||||
await learningObjectRepo.save(learningObject);
|
||||
await learningPathRepo.save(learningPath);
|
||||
return { learningObject, learningPath };
|
||||
}
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
import { FilteredLearningObject, LearningObjectNode, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content';
|
||||
import { testPartiallyDatabaseAndPartiallyDwengoApiLearningPath } from '../../test_assets/content/learning-paths.testdata';
|
||||
import { testLearningObjectPnNotebooks } from '../../test_assets/content/learning-objects.testdata';
|
||||
import { LearningPath } from '@dwengo-1/common/dist/interfaces/learning-content';
|
||||
import { RequiredEntityData } from '@mikro-orm/core';
|
||||
import { getHtmlRenderingForTestLearningObject } from '../../test-utils/get-html-rendering';
|
||||
|
||||
const EXPECTED_TITLE_FROM_DWENGO_LEARNING_OBJECT = 'Notebook opslaan';
|
||||
|
||||
describe('DatabaseLearningObjectProvider', () => {
|
||||
let exampleLearningObject: LearningObject;
|
||||
let exampleLearningObject: RequiredEntityData<LearningObject>;
|
||||
let exampleLearningPath: LearningPath;
|
||||
let exampleLearningPathId: LearningPathIdentifier;
|
||||
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
const exampleData = await initExampleData();
|
||||
exampleLearningObject = exampleData.learningObject;
|
||||
exampleLearningPath = exampleData.learningPath;
|
||||
exampleLearningObject = testLearningObjectPnNotebooks;
|
||||
exampleLearningPath = testPartiallyDatabaseAndPartiallyDwengoApiLearningPath;
|
||||
|
||||
exampleLearningPathId = {
|
||||
hruid: exampleLearningPath.hruid,
|
||||
language: exampleLearningPath.language as Language,
|
||||
};
|
||||
});
|
||||
describe('getLearningObjectById', () => {
|
||||
it('should return the learning object when it is queried by its id', async () => {
|
||||
const result: FilteredLearningObject | null = await databaseLearningObjectProvider.getLearningObjectById(exampleLearningObject);
|
||||
expect(result).toBeTruthy();
|
||||
expectToBeCorrectFilteredLearningObject(result!, exampleLearningObject);
|
||||
expectToBeCorrectFilteredLearningObject(result, exampleLearningObject);
|
||||
});
|
||||
|
||||
it('should return the learning object when it is queried by only hruid and language (but not version)', async () => {
|
||||
|
@ -46,7 +41,7 @@ describe('DatabaseLearningObjectProvider', () => {
|
|||
language: exampleLearningObject.language,
|
||||
});
|
||||
expect(result).toBeTruthy();
|
||||
expectToBeCorrectFilteredLearningObject(result!, exampleLearningObject);
|
||||
expectToBeCorrectFilteredLearningObject(result, exampleLearningObject);
|
||||
});
|
||||
|
||||
it('should return null when queried with an id that does not exist', async () => {
|
||||
|
@ -61,7 +56,7 @@ describe('DatabaseLearningObjectProvider', () => {
|
|||
it('should return the correct rendering of the learning object', async () => {
|
||||
const result = await databaseLearningObjectProvider.getLearningObjectHTML(exampleLearningObject);
|
||||
// Set newlines so your tests are platform-independent.
|
||||
expect(result).toEqual(example.getHTMLRendering().replace(/\r\n/g, '\n'));
|
||||
expect(result).toEqual(getHtmlRenderingForTestLearningObject(exampleLearningObject).replace(/\r\n/g, '\n'));
|
||||
});
|
||||
it('should return null for a non-existing learning object', async () => {
|
||||
const result = await databaseLearningObjectProvider.getLearningObjectHTML({
|
||||
|
@ -73,12 +68,12 @@ describe('DatabaseLearningObjectProvider', () => {
|
|||
});
|
||||
describe('getLearningObjectIdsFromPath', () => {
|
||||
it('should return all learning object IDs from a path', async () => {
|
||||
const result = await databaseLearningObjectProvider.getLearningObjectIdsFromPath(exampleLearningPath);
|
||||
expect(new Set(result)).toEqual(new Set(exampleLearningPath.nodes.map((it) => it.learningObjectHruid)));
|
||||
const result = await databaseLearningObjectProvider.getLearningObjectIdsFromPath(exampleLearningPathId);
|
||||
expect(new Set(result)).toEqual(new Set(exampleLearningPath.nodes.map((it: LearningObjectNode) => it.learningobject_hruid)));
|
||||
});
|
||||
it('should throw an error if queried with a path identifier for which there is no learning path', async () => {
|
||||
await expect(
|
||||
(async () => {
|
||||
(async (): Promise<void> => {
|
||||
await databaseLearningObjectProvider.getLearningObjectIdsFromPath({
|
||||
hruid: 'non_existing_hruid',
|
||||
language: Language.Dutch,
|
||||
|
@ -89,15 +84,17 @@ describe('DatabaseLearningObjectProvider', () => {
|
|||
});
|
||||
describe('getLearningObjectsFromPath', () => {
|
||||
it('should correctly return all learning objects which are on the path, even those who are not in the database', async () => {
|
||||
const result = await databaseLearningObjectProvider.getLearningObjectsFromPath(exampleLearningPath);
|
||||
const result = await databaseLearningObjectProvider.getLearningObjectsFromPath(exampleLearningPathId);
|
||||
expect(result.length).toBe(exampleLearningPath.nodes.length);
|
||||
expect(new Set(result.map((it) => it.key))).toEqual(new Set(exampleLearningPath.nodes.map((it) => it.learningObjectHruid)));
|
||||
expect(new Set(result.map((it) => it.key))).toEqual(
|
||||
new Set(exampleLearningPath.nodes.map((it: LearningObjectNode) => it.learningobject_hruid))
|
||||
);
|
||||
|
||||
expect(result.map((it) => it.title)).toContainEqual(EXPECTED_TITLE_FROM_DWENGO_LEARNING_OBJECT);
|
||||
});
|
||||
it('should throw an error if queried with a path identifier for which there is no learning path', async () => {
|
||||
await expect(
|
||||
(async () => {
|
||||
(async (): Promise<void> => {
|
||||
await databaseLearningObjectProvider.getLearningObjectsFromPath({
|
||||
hruid: 'non_existing_hruid',
|
||||
language: Language.Dutch,
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import { beforeAll, describe, expect, it } from 'vitest';
|
||||
import { setupTestApp } from '../../setup-tests';
|
||||
import { LearningObject } from '../../../src/entities/content/learning-object.entity';
|
||||
import { getLearningObjectRepository, getLearningPathRepository } from '../../../src/data/repositories';
|
||||
import learningObjectExample from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example';
|
||||
import learningObjectService from '../../../src/services/learning-objects/learning-object-service';
|
||||
import { LearningObjectIdentifier, LearningPathIdentifier } from '../../../src/interfaces/learning-content';
|
||||
import { Language } from '../../../src/entities/content/language';
|
||||
import { EnvVars, getEnvVar } from '../../../src/util/envvars';
|
||||
import { LearningPath } from '../../../src/entities/content/learning-path.entity';
|
||||
import learningPathExample from '../../test-assets/learning-paths/pn-werking-example';
|
||||
import { envVars, getEnvVar } from '../../../src/util/envVars';
|
||||
import { LearningObjectIdentifierDTO, LearningPath as LearningPathDTO, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content';
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
import { testLearningObjectPnNotebooks } from '../../test_assets/content/learning-objects.testdata';
|
||||
import { testPartiallyDatabaseAndPartiallyDwengoApiLearningPath } from '../../test_assets/content/learning-paths.testdata';
|
||||
import { RequiredEntityData } from '@mikro-orm/core';
|
||||
import { getHtmlRenderingForTestLearningObject } from '../../test-utils/get-html-rendering';
|
||||
|
||||
const EXPECTED_DWENGO_LEARNING_OBJECT_TITLE = 'Werken met notebooks';
|
||||
const DWENGO_TEST_LEARNING_OBJECT_ID: LearningObjectIdentifier = {
|
||||
const DWENGO_TEST_LEARNING_OBJECT_ID: LearningObjectIdentifierDTO = {
|
||||
hruid: 'pn_werkingnotebooks',
|
||||
language: Language.Dutch,
|
||||
version: 3,
|
||||
|
@ -23,25 +23,20 @@ const DWENGO_TEST_LEARNING_PATH_ID: LearningPathIdentifier = {
|
|||
};
|
||||
const DWENGO_TEST_LEARNING_PATH_HRUIDS = new Set(['pn_werkingnotebooks', 'pn_werkingnotebooks2', 'pn_werkingnotebooks3']);
|
||||
|
||||
async function initExampleData(): Promise<{ learningObject: LearningObject; learningPath: LearningPath }> {
|
||||
const learningObjectRepo = getLearningObjectRepository();
|
||||
const learningPathRepo = getLearningPathRepository();
|
||||
const learningObject = learningObjectExample.createLearningObject();
|
||||
const learningPath = learningPathExample.createLearningPath();
|
||||
await learningObjectRepo.save(learningObject);
|
||||
await learningPathRepo.save(learningPath);
|
||||
return { learningObject, learningPath };
|
||||
}
|
||||
|
||||
describe('LearningObjectService', () => {
|
||||
let exampleLearningObject: LearningObject;
|
||||
let exampleLearningPath: LearningPath;
|
||||
let exampleLearningObject: RequiredEntityData<LearningObject>;
|
||||
let exampleLearningPath: LearningPathDTO;
|
||||
let exampleLearningPathId: LearningPathIdentifier;
|
||||
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
const exampleData = await initExampleData();
|
||||
exampleLearningObject = exampleData.learningObject;
|
||||
exampleLearningPath = exampleData.learningPath;
|
||||
exampleLearningObject = testLearningObjectPnNotebooks;
|
||||
exampleLearningPath = testPartiallyDatabaseAndPartiallyDwengoApiLearningPath;
|
||||
|
||||
exampleLearningPathId = {
|
||||
hruid: exampleLearningPath.hruid,
|
||||
language: exampleLearningPath.language as Language,
|
||||
};
|
||||
});
|
||||
|
||||
describe('getLearningObjectById', () => {
|
||||
|
@ -69,7 +64,7 @@ describe('LearningObjectService', () => {
|
|||
const result = await learningObjectService.getLearningObjectHTML(exampleLearningObject);
|
||||
expect(result).not.toBeNull();
|
||||
// Set newlines so your tests are platform-independent.
|
||||
expect(result).toEqual(learningObjectExample.getHTMLRendering().replace(/\r\n/g, '\n'));
|
||||
expect(result).toEqual(getHtmlRenderingForTestLearningObject(exampleLearningObject).replace(/\r\n/g, '\n'));
|
||||
});
|
||||
it(
|
||||
'returns the same HTML as the Dwengo API when queried with the identifier of a learning object that does ' +
|
||||
|
@ -79,7 +74,7 @@ describe('LearningObjectService', () => {
|
|||
expect(result).not.toBeNull();
|
||||
|
||||
const responseFromDwengoApi = await fetch(
|
||||
getEnvVar(EnvVars.LearningContentRepoApiBaseUrl) +
|
||||
getEnvVar(envVars.LearningContentRepoApiBaseUrl) +
|
||||
`/learningObject/getRaw?hruid=${DWENGO_TEST_LEARNING_OBJECT_ID.hruid}&language=${DWENGO_TEST_LEARNING_OBJECT_ID.language}&version=${DWENGO_TEST_LEARNING_OBJECT_ID.version}`
|
||||
);
|
||||
const responseHtml = await responseFromDwengoApi.text();
|
||||
|
@ -97,31 +92,37 @@ describe('LearningObjectService', () => {
|
|||
|
||||
describe('getLearningObjectsFromPath', () => {
|
||||
it('returns all learning objects when a learning path in the database is queried', async () => {
|
||||
const result = await learningObjectService.getLearningObjectsFromPath(exampleLearningPath);
|
||||
expect(result.map((it) => it.key)).toEqual(exampleLearningPath.nodes.map((it) => it.learningObjectHruid));
|
||||
const result = await learningObjectService.getLearningObjectsFromPath(exampleLearningPathId);
|
||||
expect(result.map((it) => it.key)).toEqual(exampleLearningPath.nodes.map((it) => it.learningobject_hruid));
|
||||
});
|
||||
it('also returns all learning objects when a learning path from the Dwengo API is queried', async () => {
|
||||
const result = await learningObjectService.getLearningObjectsFromPath(DWENGO_TEST_LEARNING_PATH_ID);
|
||||
expect(new Set(result.map((it) => it.key))).toEqual(DWENGO_TEST_LEARNING_PATH_HRUIDS);
|
||||
});
|
||||
it('returns an empty list when queried with a non-existing learning path id', async () => {
|
||||
const result = await learningObjectService.getLearningObjectsFromPath({ hruid: 'non_existing', language: Language.Dutch });
|
||||
expect(result).toEqual([]);
|
||||
const result = await learningObjectService.getLearningObjectsFromPath({
|
||||
hruid: 'non_existing',
|
||||
language: Language.Dutch,
|
||||
});
|
||||
expect(result).toStrictEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getLearningObjectIdsFromPath', () => {
|
||||
it('returns all learning objects when a learning path in the database is queried', async () => {
|
||||
const result = await learningObjectService.getLearningObjectIdsFromPath(exampleLearningPath);
|
||||
expect(result).toEqual(exampleLearningPath.nodes.map((it) => it.learningObjectHruid));
|
||||
const result = await learningObjectService.getLearningObjectIdsFromPath(exampleLearningPathId);
|
||||
expect(result).toEqual(exampleLearningPath.nodes.map((it) => it.learningobject_hruid));
|
||||
});
|
||||
it('also returns all learning object hruids when a learning path from the Dwengo API is queried', async () => {
|
||||
const result = await learningObjectService.getLearningObjectIdsFromPath(DWENGO_TEST_LEARNING_PATH_ID);
|
||||
expect(new Set(result)).toEqual(DWENGO_TEST_LEARNING_PATH_HRUIDS);
|
||||
});
|
||||
it('returns an empty list when queried with a non-existing learning path id', async () => {
|
||||
const result = await learningObjectService.getLearningObjectIdsFromPath({ hruid: 'non_existing', language: Language.Dutch });
|
||||
expect(result).toEqual([]);
|
||||
const result = await learningObjectService.getLearningObjectIdsFromPath({
|
||||
hruid: 'non_existing',
|
||||
language: Language.Dutch,
|
||||
});
|
||||
expect(result).toStrictEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,26 +1,35 @@
|
|||
import { describe, expect, it } from 'vitest';
|
||||
import mdExample from '../../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example';
|
||||
import multipleChoiceExample from '../../../test-assets/learning-objects/test-multiple-choice/test-multiple-choice-example';
|
||||
import essayExample from '../../../test-assets/learning-objects/test-essay/test-essay-example';
|
||||
import { beforeAll, describe, expect, it } from 'vitest';
|
||||
import processingService from '../../../../src/services/learning-objects/processing/processing-service';
|
||||
import {
|
||||
testLearningObjectEssayQuestion,
|
||||
testLearningObjectMultipleChoice,
|
||||
testLearningObjectPnNotebooks,
|
||||
} from '../../../test_assets/content/learning-objects.testdata';
|
||||
import { getHtmlRenderingForTestLearningObject } from '../../../test-utils/get-html-rendering';
|
||||
import { getLearningObjectRepository } from '../../../../src/data/repositories';
|
||||
import { setupTestApp } from '../../../setup-tests';
|
||||
|
||||
describe('ProcessingService', () => {
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
});
|
||||
|
||||
it('renders a markdown learning object correctly', async () => {
|
||||
const markdownLearningObject = mdExample.createLearningObject();
|
||||
const markdownLearningObject = getLearningObjectRepository().create(testLearningObjectPnNotebooks);
|
||||
const result = await processingService.render(markdownLearningObject);
|
||||
// Set newlines so your tests are platform-independent.
|
||||
expect(result).toEqual(mdExample.getHTMLRendering().replace(/\r\n/g, '\n'));
|
||||
expect(result).toEqual(getHtmlRenderingForTestLearningObject(markdownLearningObject).replace(/\r\n/g, '\n'));
|
||||
});
|
||||
|
||||
it('renders a multiple choice question correctly', async () => {
|
||||
const multipleChoiceLearningObject = multipleChoiceExample.createLearningObject();
|
||||
const result = await processingService.render(multipleChoiceLearningObject);
|
||||
expect(result).toEqual(multipleChoiceExample.getHTMLRendering().replace(/\r\n/g, '\n'));
|
||||
const testLearningObject = getLearningObjectRepository().create(testLearningObjectMultipleChoice);
|
||||
const result = await processingService.render(testLearningObject);
|
||||
expect(result).toEqual(getHtmlRenderingForTestLearningObject(testLearningObjectMultipleChoice).replace(/\r\n/g, '\n'));
|
||||
});
|
||||
|
||||
it('renders an essay question correctly', async () => {
|
||||
const essayLearningObject = essayExample.createLearningObject();
|
||||
const essayLearningObject = getLearningObjectRepository().create(testLearningObjectEssayQuestion);
|
||||
const result = await processingService.render(essayLearningObject);
|
||||
expect(result).toEqual(essayExample.getHTMLRendering().replace(/\r\n/g, '\n'));
|
||||
expect(result).toEqual(getHtmlRenderingForTestLearningObject(essayLearningObject).replace(/\r\n/g, '\n'));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,181 +2,112 @@ import { beforeAll, describe, expect, it } from 'vitest';
|
|||
import { LearningObject } from '../../../src/entities/content/learning-object.entity.js';
|
||||
import { setupTestApp } from '../../setup-tests.js';
|
||||
import { LearningPath } from '../../../src/entities/content/learning-path.entity.js';
|
||||
import {
|
||||
getLearningObjectRepository,
|
||||
getLearningPathRepository,
|
||||
getStudentRepository,
|
||||
getSubmissionRepository,
|
||||
} from '../../../src/data/repositories.js';
|
||||
import learningObjectExample from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example.js';
|
||||
import learningPathExample from '../../test-assets/learning-paths/pn-werking-example.js';
|
||||
import { getSubmissionRepository } from '../../../src/data/repositories.js';
|
||||
|
||||
import databaseLearningPathProvider from '../../../src/services/learning-paths/database-learning-path-provider.js';
|
||||
import { expectToBeCorrectLearningPath } from '../../test-utils/expectations.js';
|
||||
import learningObjectService from '../../../src/services/learning-objects/learning-object-service.js';
|
||||
import { Language } from '../../../src/entities/content/language.js';
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
|
||||
import { LearningObjectNode, LearningPathResponse } from '@dwengo-1/common/interfaces/learning-content';
|
||||
import {
|
||||
ConditionTestLearningPathAndLearningObjects,
|
||||
createConditionTestLearningPathAndLearningObjects,
|
||||
} from '../../test-assets/learning-paths/test-conditions-example.js';
|
||||
import { Student } from '../../../src/entities/users/student.entity.js';
|
||||
import { LearningObjectNode, LearningPathResponse } from '../../../src/interfaces/learning-content.js';
|
||||
testLearningObject01,
|
||||
testLearningObjectEssayQuestion,
|
||||
testLearningObjectMultipleChoice,
|
||||
} from '../../test_assets/content/learning-objects.testdata';
|
||||
import { testLearningPathWithConditions } from '../../test_assets/content/learning-paths.testdata';
|
||||
import { mapToLearningPath } from '../../../src/services/learning-paths/learning-path-service';
|
||||
import { getTestGroup01, getTestGroup02 } from '../../test_assets/assignments/groups.testdata';
|
||||
import { Group } from '../../../src/entities/assignments/group.entity.js';
|
||||
import { RequiredEntityData } from '@mikro-orm/core';
|
||||
|
||||
async function initExampleData(): Promise<{ learningObject: LearningObject; learningPath: LearningPath }> {
|
||||
const learningObjectRepo = getLearningObjectRepository();
|
||||
const learningPathRepo = getLearningPathRepository();
|
||||
const learningObject = learningObjectExample.createLearningObject();
|
||||
const learningPath = learningPathExample.createLearningPath();
|
||||
await learningObjectRepo.save(learningObject);
|
||||
await learningPathRepo.save(learningPath);
|
||||
return { learningObject, learningPath };
|
||||
}
|
||||
|
||||
async function initPersonalizationTestData(): Promise<{
|
||||
learningContent: ConditionTestLearningPathAndLearningObjects;
|
||||
studentA: Student;
|
||||
studentB: Student;
|
||||
}> {
|
||||
const studentRepo = getStudentRepository();
|
||||
const submissionRepo = getSubmissionRepository();
|
||||
const learningPathRepo = getLearningPathRepository();
|
||||
const learningObjectRepo = getLearningObjectRepository();
|
||||
const learningContent = createConditionTestLearningPathAndLearningObjects();
|
||||
await learningObjectRepo.save(learningContent.branchingObject);
|
||||
await learningObjectRepo.save(learningContent.finalObject);
|
||||
await learningObjectRepo.save(learningContent.extraExerciseObject);
|
||||
await learningPathRepo.save(learningContent.learningPath);
|
||||
|
||||
console.log(await getSubmissionRepository().findAll({}));
|
||||
|
||||
const studentA = studentRepo.create({
|
||||
username: 'student_a',
|
||||
firstName: 'Aron',
|
||||
lastName: 'Student',
|
||||
});
|
||||
await studentRepo.save(studentA);
|
||||
const submissionA = submissionRepo.create({
|
||||
learningObjectHruid: learningContent.branchingObject.hruid,
|
||||
learningObjectLanguage: learningContent.branchingObject.language,
|
||||
learningObjectVersion: learningContent.branchingObject.version,
|
||||
submitter: studentA,
|
||||
submissionTime: new Date(),
|
||||
content: '[0]',
|
||||
});
|
||||
await submissionRepo.save(submissionA);
|
||||
|
||||
const studentB = studentRepo.create({
|
||||
username: 'student_b',
|
||||
firstName: 'Bill',
|
||||
lastName: 'Student',
|
||||
});
|
||||
await studentRepo.save(studentB);
|
||||
const submissionB = submissionRepo.create({
|
||||
learningObjectHruid: learningContent.branchingObject.hruid,
|
||||
learningObjectLanguage: learningContent.branchingObject.language,
|
||||
learningObjectVersion: learningContent.branchingObject.version,
|
||||
submitter: studentB,
|
||||
submissionTime: new Date(),
|
||||
content: '[1]',
|
||||
});
|
||||
await submissionRepo.save(submissionB);
|
||||
|
||||
return {
|
||||
learningContent: learningContent,
|
||||
studentA: studentA,
|
||||
studentB: studentB,
|
||||
};
|
||||
}
|
||||
|
||||
function expectBranchingObjectNode(
|
||||
result: LearningPathResponse,
|
||||
persTestData: {
|
||||
learningContent: ConditionTestLearningPathAndLearningObjects;
|
||||
studentA: Student;
|
||||
studentB: Student;
|
||||
}
|
||||
): LearningObjectNode {
|
||||
const branchingObjectMatches = result.data![0].nodes.filter(
|
||||
(it) => it.learningobject_hruid === persTestData.learningContent.branchingObject.hruid
|
||||
);
|
||||
function expectBranchingObjectNode(result: LearningPathResponse): LearningObjectNode {
|
||||
const branchingObjectMatches = result.data![0].nodes.filter((it) => it.learningobject_hruid === testLearningObjectMultipleChoice.hruid);
|
||||
expect(branchingObjectMatches.length).toBe(1);
|
||||
return branchingObjectMatches[0];
|
||||
}
|
||||
|
||||
describe('DatabaseLearningPathProvider', () => {
|
||||
let example: { learningObject: LearningObject; learningPath: LearningPath };
|
||||
let persTestData: { learningContent: ConditionTestLearningPathAndLearningObjects; studentA: Student; studentB: Student };
|
||||
let testLearningPath: LearningPath;
|
||||
let branchingLearningObject: RequiredEntityData<LearningObject>;
|
||||
let extraExerciseLearningObject: RequiredEntityData<LearningObject>;
|
||||
let finalLearningObject: RequiredEntityData<LearningObject>;
|
||||
let groupA: Group;
|
||||
let groupB: Group;
|
||||
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
example = await initExampleData();
|
||||
persTestData = await initPersonalizationTestData();
|
||||
testLearningPath = mapToLearningPath(testLearningPathWithConditions, []);
|
||||
branchingLearningObject = testLearningObjectMultipleChoice;
|
||||
extraExerciseLearningObject = testLearningObject01;
|
||||
finalLearningObject = testLearningObjectEssayQuestion;
|
||||
groupA = getTestGroup01();
|
||||
groupB = getTestGroup02();
|
||||
|
||||
// Place different submissions for group A and B.
|
||||
const submissionRepo = getSubmissionRepository();
|
||||
const submissionA = submissionRepo.create({
|
||||
learningObjectHruid: branchingLearningObject.hruid,
|
||||
learningObjectLanguage: branchingLearningObject.language,
|
||||
learningObjectVersion: branchingLearningObject.version,
|
||||
content: '[0]',
|
||||
onBehalfOf: groupA,
|
||||
submissionTime: new Date(),
|
||||
submitter: groupA.members[0],
|
||||
});
|
||||
await submissionRepo.save(submissionA);
|
||||
|
||||
const submissionB = submissionRepo.create({
|
||||
learningObjectHruid: branchingLearningObject.hruid,
|
||||
learningObjectLanguage: branchingLearningObject.language,
|
||||
learningObjectVersion: branchingLearningObject.version,
|
||||
content: '[1]',
|
||||
onBehalfOf: groupB,
|
||||
submissionTime: new Date(),
|
||||
submitter: groupB.members[0],
|
||||
});
|
||||
await submissionRepo.save(submissionB);
|
||||
});
|
||||
|
||||
describe('fetchLearningPaths', () => {
|
||||
it('returns the learning path correctly', async () => {
|
||||
const result = await databaseLearningPathProvider.fetchLearningPaths(
|
||||
[example.learningPath.hruid],
|
||||
example.learningPath.language,
|
||||
'the source'
|
||||
);
|
||||
const result = await databaseLearningPathProvider.fetchLearningPaths([testLearningPath.hruid], testLearningPath.language, 'the source');
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data?.length).toBe(1);
|
||||
|
||||
const learningObjectsOnPath = (
|
||||
await Promise.all(
|
||||
example.learningPath.nodes.map((node) =>
|
||||
learningObjectService.getLearningObjectById({
|
||||
hruid: node.learningObjectHruid,
|
||||
version: node.version,
|
||||
language: node.language,
|
||||
})
|
||||
)
|
||||
)
|
||||
).filter((it) => it !== null);
|
||||
|
||||
expectToBeCorrectLearningPath(result.data![0], example.learningPath, learningObjectsOnPath);
|
||||
expectToBeCorrectLearningPath(result.data![0], testLearningPathWithConditions);
|
||||
});
|
||||
it('returns the correct personalized learning path', async () => {
|
||||
// For student A:
|
||||
let result = await databaseLearningPathProvider.fetchLearningPaths(
|
||||
[persTestData.learningContent.learningPath.hruid],
|
||||
persTestData.learningContent.learningPath.language,
|
||||
[testLearningPath.hruid],
|
||||
testLearningPath.language,
|
||||
'the source',
|
||||
{ type: 'student', student: persTestData.studentA }
|
||||
groupA
|
||||
);
|
||||
expect(result.success).toBeTruthy();
|
||||
expect(result.data?.length).toBe(1);
|
||||
|
||||
// There should be exactly one branching object
|
||||
let branchingObject = expectBranchingObjectNode(result, persTestData);
|
||||
let branchingObject = expectBranchingObjectNode(result);
|
||||
|
||||
expect(branchingObject.transitions.filter((it) => it.next.hruid === persTestData.learningContent.finalObject.hruid).length).toBe(0); // StudentA picked the first option, therefore, there should be no direct path to the final object.
|
||||
expect(branchingObject.transitions.filter((it) => it.next.hruid === persTestData.learningContent.extraExerciseObject.hruid).length).toBe(
|
||||
1
|
||||
); // There should however be a path to the extra exercise object.
|
||||
expect(branchingObject.transitions.filter((it) => it.next.hruid === finalLearningObject.hruid).length).toBe(0); // StudentA picked the first option, therefore, there should be no direct path to the final object.
|
||||
expect(branchingObject.transitions.filter((it) => it.next.hruid === extraExerciseLearningObject.hruid).length).toBe(1); // There should however be a path to the extra exercise object.
|
||||
|
||||
// For student B:
|
||||
result = await databaseLearningPathProvider.fetchLearningPaths(
|
||||
[persTestData.learningContent.learningPath.hruid],
|
||||
persTestData.learningContent.learningPath.language,
|
||||
'the source',
|
||||
{ type: 'student', student: persTestData.studentB }
|
||||
);
|
||||
result = await databaseLearningPathProvider.fetchLearningPaths([testLearningPath.hruid], testLearningPath.language, 'the source', groupB);
|
||||
expect(result.success).toBeTruthy();
|
||||
expect(result.data?.length).toBe(1);
|
||||
|
||||
// There should still be exactly one branching object
|
||||
branchingObject = expectBranchingObjectNode(result, persTestData);
|
||||
branchingObject = expectBranchingObjectNode(result);
|
||||
|
||||
// However, now the student picks the other option.
|
||||
expect(branchingObject.transitions.filter((it) => it.next.hruid === persTestData.learningContent.finalObject.hruid).length).toBe(1); // StudentB picked the second option, therefore, there should be a direct path to the final object.
|
||||
expect(branchingObject.transitions.filter((it) => it.next.hruid === persTestData.learningContent.extraExerciseObject.hruid).length).toBe(
|
||||
0
|
||||
); // There should not be a path anymore to the extra exercise object.
|
||||
expect(branchingObject.transitions.filter((it) => it.next.hruid === finalLearningObject.hruid).length).toBe(1); // StudentB picked the second option, therefore, there should be a direct path to the final object.
|
||||
expect(branchingObject.transitions.filter((it) => it.next.hruid === extraExerciseLearningObject.hruid).length).toBe(0); // There should not be a path anymore to the extra exercise object.
|
||||
});
|
||||
it('returns a non-successful response if a non-existing learning path is queried', async () => {
|
||||
const result = await databaseLearningPathProvider.fetchLearningPaths(
|
||||
[example.learningPath.hruid],
|
||||
[testLearningPath.hruid],
|
||||
Language.Abkhazian, // Wrong language
|
||||
'the source'
|
||||
);
|
||||
|
@ -187,27 +118,24 @@ describe('DatabaseLearningPathProvider', () => {
|
|||
|
||||
describe('searchLearningPaths', () => {
|
||||
it('returns the correct learning path when queried with a substring of its title', async () => {
|
||||
const result = await databaseLearningPathProvider.searchLearningPaths(
|
||||
example.learningPath.title.substring(2, 6),
|
||||
example.learningPath.language
|
||||
);
|
||||
const result = await databaseLearningPathProvider.searchLearningPaths(testLearningPath.title.substring(2, 6), testLearningPath.language);
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0].title).toBe(example.learningPath.title);
|
||||
expect(result[0].description).toBe(example.learningPath.description);
|
||||
expect(result[0].title).toBe(testLearningPath.title);
|
||||
expect(result[0].description).toBe(testLearningPath.description);
|
||||
});
|
||||
it('returns the correct learning path when queried with a substring of the description', async () => {
|
||||
const result = await databaseLearningPathProvider.searchLearningPaths(
|
||||
example.learningPath.description.substring(5, 12),
|
||||
example.learningPath.language
|
||||
testLearningPath.description.substring(5, 12),
|
||||
testLearningPath.language
|
||||
);
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0].title).toBe(example.learningPath.title);
|
||||
expect(result[0].description).toBe(example.learningPath.description);
|
||||
expect(result[0].title).toBe(testLearningPath.title);
|
||||
expect(result[0].description).toBe(testLearningPath.description);
|
||||
});
|
||||
it('returns an empty result when queried with a text which is not a substring of the title or the description of a learning path', async () => {
|
||||
const result = await databaseLearningPathProvider.searchLearningPaths(
|
||||
'substring which does not occur in the title or the description of a learning object',
|
||||
example.learningPath.language
|
||||
testLearningPath.language
|
||||
);
|
||||
expect(result.length).toBe(0);
|
||||
});
|
||||
|
|
|
@ -1,22 +1,9 @@
|
|||
import { beforeAll, describe, expect, it } from 'vitest';
|
||||
import { setupTestApp } from '../../setup-tests';
|
||||
import { LearningObject } from '../../../src/entities/content/learning-object.entity';
|
||||
import { LearningPath } from '../../../src/entities/content/learning-path.entity';
|
||||
import { getLearningObjectRepository, getLearningPathRepository } from '../../../src/data/repositories';
|
||||
import learningObjectExample from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example';
|
||||
import learningPathExample from '../../test-assets/learning-paths/pn-werking-example';
|
||||
import { Language } from '../../../src/entities/content/language';
|
||||
import learningPathService from '../../../src/services/learning-paths/learning-path-service';
|
||||
|
||||
async function initExampleData(): Promise<{ learningObject: LearningObject; learningPath: LearningPath }> {
|
||||
const learningObjectRepo = getLearningObjectRepository();
|
||||
const learningPathRepo = getLearningPathRepository();
|
||||
const learningObject = learningObjectExample.createLearningObject();
|
||||
const learningPath = learningPathExample.createLearningPath();
|
||||
await learningObjectRepo.save(learningObject);
|
||||
await learningPathRepo.save(learningPath);
|
||||
return { learningObject, learningPath };
|
||||
}
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
import { testPartiallyDatabaseAndPartiallyDwengoApiLearningPath } from '../../test_assets/content/learning-paths.testdata';
|
||||
import { LearningPath as LearningPathDTO } from '@dwengo-1/common/interfaces/learning-content';
|
||||
|
||||
const TEST_DWENGO_LEARNING_PATH_HRUID = 'pn_werking';
|
||||
const TEST_DWENGO_LEARNING_PATH_TITLE = 'Werken met notebooks';
|
||||
|
@ -24,42 +11,49 @@ const TEST_DWENGO_EXCLUSIVE_LEARNING_PATH_SEARCH_QUERY = 'Microscopie';
|
|||
const TEST_SEARCH_QUERY_EXPECTING_NO_MATCHES = 'su$m8f9usf89ud<p9<U8SDP8UP9';
|
||||
|
||||
describe('LearningPathService', () => {
|
||||
let example: { learningObject: LearningObject; learningPath: LearningPath };
|
||||
let testLearningPath: LearningPathDTO;
|
||||
beforeAll(async () => {
|
||||
await setupTestApp();
|
||||
example = await initExampleData();
|
||||
testLearningPath = testPartiallyDatabaseAndPartiallyDwengoApiLearningPath;
|
||||
});
|
||||
describe('fetchLearningPaths', () => {
|
||||
it('should return learning paths both from the database and from the Dwengo API', async () => {
|
||||
const result = await learningPathService.fetchLearningPaths(
|
||||
[example.learningPath.hruid, TEST_DWENGO_LEARNING_PATH_HRUID],
|
||||
example.learningPath.language,
|
||||
[testLearningPath.hruid, TEST_DWENGO_LEARNING_PATH_HRUID],
|
||||
testLearningPath.language as Language,
|
||||
'the source'
|
||||
);
|
||||
expect(result.success).toBeTruthy();
|
||||
expect(result.data?.filter((it) => it.hruid === TEST_DWENGO_LEARNING_PATH_HRUID).length).not.toBe(0);
|
||||
expect(result.data?.filter((it) => it.hruid === example.learningPath.hruid).length).not.toBe(0);
|
||||
expect(result.data?.filter((it) => it.hruid === TEST_DWENGO_LEARNING_PATH_HRUID)[0].title).toEqual(TEST_DWENGO_LEARNING_PATH_TITLE);
|
||||
expect(result.data?.filter((it) => it.hruid === example.learningPath.hruid)[0].title).toEqual(example.learningPath.title);
|
||||
expect(result.data?.filter((it) => it.hruid === testLearningPath.hruid).length).not.toBe(0);
|
||||
expect(result.data?.find((it) => it.hruid === TEST_DWENGO_LEARNING_PATH_HRUID)?.title).toEqual(TEST_DWENGO_LEARNING_PATH_TITLE);
|
||||
expect(result.data?.find((it) => it.hruid === testLearningPath.hruid)?.title).toEqual(testLearningPath.title);
|
||||
});
|
||||
it('should include both the learning objects from the Dwengo API and learning objects from the database in its response', async () => {
|
||||
const result = await learningPathService.fetchLearningPaths([example.learningPath.hruid], example.learningPath.language, 'the source');
|
||||
const result = await learningPathService.fetchLearningPaths(
|
||||
[testLearningPath.hruid],
|
||||
testLearningPath.language as Language,
|
||||
'the source'
|
||||
);
|
||||
expect(result.success).toBeTruthy();
|
||||
expect(result.data?.length).toBe(1);
|
||||
|
||||
// Should include all the nodes, even those pointing to foreign learning objects.
|
||||
expect([...result.data![0].nodes.map((it) => it.learningobject_hruid)].sort()).toEqual(
|
||||
example.learningPath.nodes.map((it) => it.learningObjectHruid).sort()
|
||||
expect([...result.data![0].nodes.map((it) => it.learningobject_hruid)].sort((a, b) => a.localeCompare(b))).toEqual(
|
||||
testLearningPath.nodes.map((it) => it.learningobject_hruid).sort((a, b) => a.localeCompare(b))
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('searchLearningPath', () => {
|
||||
it('should include both the learning paths from the Dwengo API and those from the database in its response', async () => {
|
||||
// This matches the learning object in the database, but definitely also some learning objects in the Dwengo API.
|
||||
const result = await learningPathService.searchLearningPaths(example.learningPath.title.substring(2, 3), example.learningPath.language);
|
||||
const result = await learningPathService.searchLearningPaths(
|
||||
testLearningPath.title.substring(2, 3),
|
||||
testLearningPath.language as Language
|
||||
);
|
||||
|
||||
// Should find the one from the database
|
||||
expect(result.filter((it) => it.hruid === example.learningPath.hruid && it.title === example.learningPath.title).length).toBe(1);
|
||||
expect(result.filter((it) => it.hruid === testLearningPath.hruid && it.title === testLearningPath.title).length).toBe(1);
|
||||
|
||||
// But should not only find that one.
|
||||
expect(result.length).not.toBeLessThan(2);
|
||||
|
@ -71,7 +65,7 @@ describe('LearningPathService', () => {
|
|||
expect(result.length).not.toBe(0);
|
||||
|
||||
// But not the example learning path.
|
||||
expect(result.filter((it) => it.hruid === example.learningPath.hruid && it.title === example.learningPath.title).length).toBe(0);
|
||||
expect(result.filter((it) => it.hruid === testLearningPath.hruid && it.title === testLearningPath.title).length).toBe(0);
|
||||
});
|
||||
it('should return an empty list if neither the Dwengo API nor the database contains matches', async () => {
|
||||
const result = await learningPathService.searchLearningPaths(TEST_SEARCH_QUERY_EXPECTING_NO_MATCHES, Language.Dutch);
|
||||
|
|
|
@ -13,8 +13,10 @@ import { makeTestAttachments } from './test_assets/content/attachments.testdata.
|
|||
import { makeTestQuestions } from './test_assets/questions/questions.testdata.js';
|
||||
import { makeTestAnswers } from './test_assets/questions/answers.testdata.js';
|
||||
import { makeTestSubmissions } from './test_assets/assignments/submission.testdata.js';
|
||||
import { Collection } from '@mikro-orm/core';
|
||||
import { Group } from '../src/entities/assignments/group.entity';
|
||||
|
||||
export async function setupTestApp() {
|
||||
export async function setupTestApp(): Promise<void> {
|
||||
dotenv.config({ path: '.env.test' });
|
||||
await initORM(true);
|
||||
|
||||
|
@ -28,8 +30,8 @@ export async function setupTestApp() {
|
|||
const assignments = makeTestAssignemnts(em, classes);
|
||||
const groups = makeTestGroups(em, students, assignments);
|
||||
|
||||
assignments[0].groups = groups.slice(0, 3);
|
||||
assignments[1].groups = groups.slice(3, 4);
|
||||
assignments[0].groups = new Collection<Group>(groups.slice(0, 3));
|
||||
assignments[1].groups = new Collection<Group>(groups.slice(3, 4));
|
||||
|
||||
const teacherInvitations = makeTestTeacherInvitations(em, teachers, classes);
|
||||
const classJoinRequests = makeTestClassJoinRequests(em, students, classes);
|
||||
|
@ -37,7 +39,7 @@ export async function setupTestApp() {
|
|||
|
||||
learningObjects[1].attachments = attachments;
|
||||
|
||||
const questions = makeTestQuestions(em, students);
|
||||
const questions = makeTestQuestions(em, students, groups);
|
||||
const answers = makeTestAnswers(em, teachers, questions);
|
||||
const submissions = makeTestSubmissions(em, students, groups);
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
import { LearningObjectExample } from './learning-object-example';
|
||||
import { LearningObject } from '../../../src/entities/content/learning-object.entity';
|
||||
|
||||
export function createExampleLearningObjectWithAttachments(example: LearningObjectExample): LearningObject {
|
||||
const learningObject = example.createLearningObject();
|
||||
for (const creationFn of Object.values(example.createAttachment)) {
|
||||
learningObject.attachments.push(creationFn(learningObject));
|
||||
}
|
||||
return learningObject;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
import { LearningObjectExample } from '../learning-object-example';
|
||||
import { LearningObject } from '../../../../src/entities/content/learning-object.entity';
|
||||
import { Language } from '../../../../src/entities/content/language';
|
||||
import { loadTestAsset } from '../../../test-utils/load-test-asset';
|
||||
import { DwengoContentType } from '../../../../src/services/learning-objects/processing/content-type';
|
||||
import { EnvVars, getEnvVar } from '../../../../src/util/envvars';
|
||||
|
||||
/**
|
||||
* Create a dummy learning object to be used in tests where multiple learning objects are needed (for example for use
|
||||
* on a path), but where the precise contents of the learning object are not important.
|
||||
*/
|
||||
export function dummyLearningObject(hruid: string, language: Language, title: string): LearningObjectExample {
|
||||
return {
|
||||
createLearningObject: () => {
|
||||
const learningObject = new LearningObject();
|
||||
learningObject.hruid = getEnvVar(EnvVars.UserContentPrefix) + hruid;
|
||||
learningObject.language = language;
|
||||
learningObject.version = 1;
|
||||
learningObject.title = title;
|
||||
learningObject.description = 'Just a dummy learning object for testing purposes';
|
||||
learningObject.contentType = DwengoContentType.TEXT_PLAIN;
|
||||
learningObject.content = Buffer.from('Dummy content');
|
||||
learningObject.returnValue = {
|
||||
callbackUrl: `/learningObject/${hruid}/submissions`,
|
||||
callbackSchema: '[]',
|
||||
};
|
||||
return learningObject;
|
||||
},
|
||||
createAttachment: {},
|
||||
getHTMLRendering: () => loadTestAsset('learning-objects/dummy/rendering.txt').toString(),
|
||||
};
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import { LearningObject } from '../../../src/entities/content/learning-object.entity';
|
||||
import { Attachment } from '../../../src/entities/content/attachment.entity';
|
||||
|
||||
type LearningObjectExample = {
|
||||
createLearningObject: () => LearningObject;
|
||||
createAttachment: { [key: string]: (owner: LearningObject) => Attachment };
|
||||
getHTMLRendering: () => string;
|
||||
};
|
|
@ -1,72 +0,0 @@
|
|||
import { LearningObjectExample } from '../learning-object-example';
|
||||
import { Language } from '../../../../src/entities/content/language';
|
||||
import { DwengoContentType } from '../../../../src/services/learning-objects/processing/content-type';
|
||||
import { loadTestAsset } from '../../../test-utils/load-test-asset';
|
||||
import { EducationalGoal, LearningObject, ReturnValue } from '../../../../src/entities/content/learning-object.entity';
|
||||
import { Attachment } from '../../../../src/entities/content/attachment.entity';
|
||||
import { EnvVars, getEnvVar } from '../../../../src/util/envvars';
|
||||
|
||||
const ASSETS_PREFIX = 'learning-objects/pn-werkingnotebooks/';
|
||||
|
||||
const example: LearningObjectExample = {
|
||||
createLearningObject: () => {
|
||||
const learningObject = new LearningObject();
|
||||
learningObject.hruid = `${getEnvVar(EnvVars.UserContentPrefix)}pn_werkingnotebooks`;
|
||||
learningObject.version = 3;
|
||||
learningObject.language = Language.Dutch;
|
||||
learningObject.title = 'Werken met notebooks';
|
||||
learningObject.description = 'Leren werken met notebooks';
|
||||
learningObject.keywords = ['Python', 'KIKS', 'Wiskunde', 'STEM', 'AI'];
|
||||
|
||||
const educationalGoal1 = new EducationalGoal();
|
||||
educationalGoal1.source = 'Source';
|
||||
educationalGoal1.id = 'id';
|
||||
|
||||
const educationalGoal2 = new EducationalGoal();
|
||||
educationalGoal2.source = 'Source2';
|
||||
educationalGoal2.id = 'id2';
|
||||
|
||||
learningObject.educationalGoals = [educationalGoal1, educationalGoal2];
|
||||
learningObject.admins = [];
|
||||
learningObject.contentType = DwengoContentType.TEXT_MARKDOWN;
|
||||
learningObject.teacherExclusive = false;
|
||||
learningObject.skosConcepts = [
|
||||
'http://ilearn.ilabt.imec.be/vocab/curr1/s-vaktaal',
|
||||
'http://ilearn.ilabt.imec.be/vocab/curr1/s-digitale-media-en-toepassingen',
|
||||
'http://ilearn.ilabt.imec.be/vocab/curr1/s-computers-en-systemen',
|
||||
];
|
||||
learningObject.copyright = 'dwengo';
|
||||
learningObject.license = 'dwengo';
|
||||
learningObject.estimatedTime = 10;
|
||||
|
||||
const returnValue = new ReturnValue();
|
||||
returnValue.callbackUrl = 'callback_url_example';
|
||||
returnValue.callbackSchema = '{"att": "test", "att2": "test2"}';
|
||||
|
||||
learningObject.returnValue = returnValue;
|
||||
learningObject.available = true;
|
||||
learningObject.content = loadTestAsset(`${ASSETS_PREFIX}/content.md`);
|
||||
|
||||
return learningObject;
|
||||
},
|
||||
createAttachment: {
|
||||
dwengoLogo: (learningObject) => {
|
||||
const att = new Attachment();
|
||||
att.learningObject = learningObject;
|
||||
att.name = 'dwengo.png';
|
||||
att.mimeType = 'image/png';
|
||||
att.content = loadTestAsset(`${ASSETS_PREFIX}/dwengo.png`);
|
||||
return att;
|
||||
},
|
||||
knop: (learningObject) => {
|
||||
const att = new Attachment();
|
||||
att.learningObject = learningObject;
|
||||
att.name = 'Knop.png';
|
||||
att.mimeType = 'image/png';
|
||||
att.content = loadTestAsset(`${ASSETS_PREFIX}/Knop.png`);
|
||||
return att;
|
||||
},
|
||||
},
|
||||
getHTMLRendering: () => loadTestAsset(`${ASSETS_PREFIX}/rendering.txt`).toString(),
|
||||
};
|
||||
export default example;
|
|
@ -1,2 +0,0 @@
|
|||
::MC basic::
|
||||
How are you? {}
|
|
@ -1,7 +0,0 @@
|
|||
<div class="learning-object-gift">
|
||||
<div id="gift-q1" class="gift-question">
|
||||
<h2 id="gift-q1-title" class="gift-title">MC basic</h2>
|
||||
<p id="gift-q1-stem" class="gift-stem">How are you?</p>
|
||||
<textarea id="gift-q1-answer" class="gift-essay-answer"></textarea>
|
||||
</div>
|
||||
</div>
|
|
@ -1,28 +0,0 @@
|
|||
import { LearningObjectExample } from '../learning-object-example';
|
||||
import { LearningObject } from '../../../../src/entities/content/learning-object.entity';
|
||||
import { loadTestAsset } from '../../../test-utils/load-test-asset';
|
||||
import { EnvVars, getEnvVar } from '../../../../src/util/envvars';
|
||||
import { Language } from '../../../../src/entities/content/language';
|
||||
import { DwengoContentType } from '../../../../src/services/learning-objects/processing/content-type';
|
||||
|
||||
const example: LearningObjectExample = {
|
||||
createLearningObject: () => {
|
||||
const learningObject = new LearningObject();
|
||||
learningObject.hruid = `${getEnvVar(EnvVars.UserContentPrefix)}test_essay`;
|
||||
learningObject.language = Language.English;
|
||||
learningObject.version = 1;
|
||||
learningObject.title = 'Essay question for testing';
|
||||
learningObject.description = 'This essay question was only created for testing purposes.';
|
||||
learningObject.contentType = DwengoContentType.GIFT;
|
||||
learningObject.returnValue = {
|
||||
callbackUrl: `/learningObject/${learningObject.hruid}/submissions`,
|
||||
callbackSchema: '["antwoord vraag 1"]',
|
||||
};
|
||||
learningObject.content = loadTestAsset('learning-objects/test-essay/content.txt');
|
||||
return learningObject;
|
||||
},
|
||||
createAttachment: {},
|
||||
getHTMLRendering: () => loadTestAsset('learning-objects/test-essay/rendering.txt').toString(),
|
||||
};
|
||||
|
||||
export default example;
|
|
@ -1,28 +0,0 @@
|
|||
import { LearningObjectExample } from '../learning-object-example';
|
||||
import { LearningObject } from '../../../../src/entities/content/learning-object.entity';
|
||||
import { loadTestAsset } from '../../../test-utils/load-test-asset';
|
||||
import { EnvVars, getEnvVar } from '../../../../src/util/envvars';
|
||||
import { Language } from '../../../../src/entities/content/language';
|
||||
import { DwengoContentType } from '../../../../src/services/learning-objects/processing/content-type';
|
||||
|
||||
const example: LearningObjectExample = {
|
||||
createLearningObject: () => {
|
||||
const learningObject = new LearningObject();
|
||||
learningObject.hruid = `${getEnvVar(EnvVars.UserContentPrefix)}test_multiple_choice`;
|
||||
learningObject.language = Language.English;
|
||||
learningObject.version = 1;
|
||||
learningObject.title = 'Multiple choice question for testing';
|
||||
learningObject.description = 'This multiple choice question was only created for testing purposes.';
|
||||
learningObject.contentType = DwengoContentType.GIFT;
|
||||
learningObject.returnValue = {
|
||||
callbackUrl: `/learningObject/${learningObject.hruid}/submissions`,
|
||||
callbackSchema: '["antwoord vraag 1"]',
|
||||
};
|
||||
learningObject.content = loadTestAsset('learning-objects/test-multiple-choice/content.txt');
|
||||
return learningObject;
|
||||
},
|
||||
createAttachment: {},
|
||||
getHTMLRendering: () => loadTestAsset('learning-objects/test-multiple-choice/rendering.txt').toString(),
|
||||
};
|
||||
|
||||
export default example;
|
|
@ -1,3 +0,0 @@
|
|||
type LearningPathExample = {
|
||||
createLearningPath: () => LearningPath;
|
||||
};
|
|
@ -1,31 +0,0 @@
|
|||
import { Language } from '../../../src/entities/content/language';
|
||||
import { LearningPathTransition } from '../../../src/entities/content/learning-path-transition.entity';
|
||||
import { LearningPathNode } from '../../../src/entities/content/learning-path-node.entity';
|
||||
import { LearningPath } from '../../../src/entities/content/learning-path.entity';
|
||||
|
||||
export function createLearningPathTransition(node: LearningPathNode, transitionNumber: number, condition: string | null, to: LearningPathNode) {
|
||||
const trans = new LearningPathTransition();
|
||||
trans.node = node;
|
||||
trans.transitionNumber = transitionNumber;
|
||||
trans.condition = condition || 'true';
|
||||
trans.next = to;
|
||||
return trans;
|
||||
}
|
||||
|
||||
export function createLearningPathNode(
|
||||
learningPath: LearningPath,
|
||||
nodeNumber: number,
|
||||
learningObjectHruid: string,
|
||||
version: number,
|
||||
language: Language,
|
||||
startNode: boolean
|
||||
) {
|
||||
const node = new LearningPathNode();
|
||||
node.learningPath = learningPath;
|
||||
node.nodeNumber = nodeNumber;
|
||||
node.learningObjectHruid = learningObjectHruid;
|
||||
node.version = version;
|
||||
node.language = language;
|
||||
node.startNode = startNode;
|
||||
return node;
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
import { LearningPath } from '../../../src/entities/content/learning-path.entity';
|
||||
import { Language } from '../../../src/entities/content/language';
|
||||
import { EnvVars, getEnvVar } from '../../../src/util/envvars';
|
||||
import { createLearningPathNode, createLearningPathTransition } from './learning-path-utils';
|
||||
import { LearningPathNode } from '../../../src/entities/content/learning-path-node.entity';
|
||||
|
||||
function createNodes(learningPath: LearningPath): LearningPathNode[] {
|
||||
const nodes = [
|
||||
createLearningPathNode(learningPath, 0, 'u_pn_werkingnotebooks', 3, Language.Dutch, true),
|
||||
createLearningPathNode(learningPath, 1, 'pn_werkingnotebooks2', 3, Language.Dutch, false),
|
||||
createLearningPathNode(learningPath, 2, 'pn_werkingnotebooks3', 3, Language.Dutch, false),
|
||||
];
|
||||
nodes[0].transitions.push(createLearningPathTransition(nodes[0], 0, 'true', nodes[1]));
|
||||
nodes[1].transitions.push(createLearningPathTransition(nodes[1], 0, 'true', nodes[2]));
|
||||
return nodes;
|
||||
}
|
||||
|
||||
const example: LearningPathExample = {
|
||||
createLearningPath: () => {
|
||||
const path = new LearningPath();
|
||||
path.language = Language.Dutch;
|
||||
path.hruid = `${getEnvVar(EnvVars.UserContentPrefix)}pn_werking`;
|
||||
path.title = 'Werken met notebooks';
|
||||
path.description = 'Een korte inleiding tot Python notebooks. Hoe ga je gemakkelijk en efficiënt met de notebooks aan de slag?';
|
||||
path.nodes = createNodes(path);
|
||||
return path;
|
||||
},
|
||||
};
|
||||
|
||||
export default example;
|
|
@ -1,84 +0,0 @@
|
|||
import { LearningPath } from '../../../src/entities/content/learning-path.entity';
|
||||
import { Language } from '../../../src/entities/content/language';
|
||||
import testMultipleChoiceExample from '../learning-objects/test-multiple-choice/test-multiple-choice-example';
|
||||
import { dummyLearningObject } from '../learning-objects/dummy/dummy-learning-object-example';
|
||||
import { createLearningPathNode, createLearningPathTransition } from './learning-path-utils';
|
||||
import { LearningObject } from '../../../src/entities/content/learning-object.entity';
|
||||
import { EnvVars, getEnvVar } from '../../../src/util/envvars';
|
||||
|
||||
export type ConditionTestLearningPathAndLearningObjects = {
|
||||
branchingObject: LearningObject;
|
||||
extraExerciseObject: LearningObject;
|
||||
finalObject: LearningObject;
|
||||
learningPath: LearningPath;
|
||||
};
|
||||
|
||||
export function createConditionTestLearningPathAndLearningObjects() {
|
||||
const learningPath = new LearningPath();
|
||||
learningPath.hruid = `${getEnvVar(EnvVars.UserContentPrefix)}test_conditions`;
|
||||
learningPath.language = Language.English;
|
||||
learningPath.title = 'Example learning path with conditional transitions';
|
||||
learningPath.description = 'This learning path was made for the purpose of testing conditional transitions';
|
||||
|
||||
const branchingLearningObject = testMultipleChoiceExample.createLearningObject();
|
||||
const extraExerciseLearningObject = dummyLearningObject(
|
||||
'test_extra_exercise',
|
||||
Language.English,
|
||||
'Extra exercise (for students with difficulties)'
|
||||
).createLearningObject();
|
||||
const finalLearningObject = dummyLearningObject(
|
||||
'test_final_learning_object',
|
||||
Language.English,
|
||||
'Final exercise (for everyone)'
|
||||
).createLearningObject();
|
||||
|
||||
const branchingNode = createLearningPathNode(
|
||||
learningPath,
|
||||
0,
|
||||
branchingLearningObject.hruid,
|
||||
branchingLearningObject.version,
|
||||
branchingLearningObject.language,
|
||||
true
|
||||
);
|
||||
const extraExerciseNode = createLearningPathNode(
|
||||
learningPath,
|
||||
1,
|
||||
extraExerciseLearningObject.hruid,
|
||||
extraExerciseLearningObject.version,
|
||||
extraExerciseLearningObject.language,
|
||||
false
|
||||
);
|
||||
const finalNode = createLearningPathNode(
|
||||
learningPath,
|
||||
2,
|
||||
finalLearningObject.hruid,
|
||||
finalLearningObject.version,
|
||||
finalLearningObject.language,
|
||||
false
|
||||
);
|
||||
|
||||
const transitionToExtraExercise = createLearningPathTransition(
|
||||
branchingNode,
|
||||
0,
|
||||
'$[?(@[0] == 0)]', // The answer to the first question was the first one, which says that it is difficult for the student to follow along.
|
||||
extraExerciseNode
|
||||
);
|
||||
const directTransitionToFinal = createLearningPathTransition(branchingNode, 1, '$[?(@[0] == 1)]', finalNode);
|
||||
const transitionExtraExerciseToFinal = createLearningPathTransition(extraExerciseNode, 0, 'true', finalNode);
|
||||
|
||||
branchingNode.transitions = [transitionToExtraExercise, directTransitionToFinal];
|
||||
extraExerciseNode.transitions = [transitionExtraExerciseToFinal];
|
||||
|
||||
learningPath.nodes = [branchingNode, extraExerciseNode, finalNode];
|
||||
|
||||
return {
|
||||
branchingObject: branchingLearningObject,
|
||||
finalObject: finalLearningObject,
|
||||
extraExerciseObject: extraExerciseLearningObject,
|
||||
learningPath: learningPath,
|
||||
};
|
||||
}
|
||||
|
||||
const example: LearningPathExample = {
|
||||
createLearningPath: () => createConditionTestLearningPathAndLearningObjects().learningPath,
|
||||
};
|
|
@ -1,8 +1,8 @@
|
|||
import { AssertionError } from 'node:assert';
|
||||
import { LearningObject } from '../../src/entities/content/learning-object.entity';
|
||||
import { FilteredLearningObject, LearningPath } from '../../src/interfaces/learning-content';
|
||||
import { LearningPath as LearningPathEntity } from '../../src/entities/content/learning-path.entity';
|
||||
import { expect } from 'vitest';
|
||||
import { FilteredLearningObject, LearningPath } from '@dwengo-1/common/interfaces/learning-content';
|
||||
import { RequiredEntityData } from '@mikro-orm/core';
|
||||
|
||||
// Ignored properties because they belang for example to the class, not to the entity itself.
|
||||
const IGNORE_PROPERTIES = ['parent'];
|
||||
|
@ -11,53 +11,44 @@ const IGNORE_PROPERTIES = ['parent'];
|
|||
* Checks if the actual entity from the database conforms to the entity that was added previously.
|
||||
* @param actual The actual entity retrieved from the database
|
||||
* @param expected The (previously added) entity we would expect to retrieve
|
||||
* @param propertyPrefix Prefix to append to property in error messages.
|
||||
*/
|
||||
export function expectToBeCorrectEntity<T extends object>(actual: { entity: T; name?: string }, expected: { entity: T; name?: string }): void {
|
||||
if (!actual.name) {
|
||||
actual.name = 'actual';
|
||||
}
|
||||
if (!expected.name) {
|
||||
expected.name = 'expected';
|
||||
}
|
||||
for (const property in expected.entity) {
|
||||
if (
|
||||
property! in IGNORE_PROPERTIES &&
|
||||
expected.entity[property] !== undefined && // If we don't expect a certain value for a property, we assume it can be filled in by the database however it wants.
|
||||
typeof expected.entity[property] !== 'function' // Functions obviously are not persisted via the database
|
||||
) {
|
||||
if (!actual.entity.hasOwnProperty(property)) {
|
||||
throw new AssertionError({
|
||||
message: `${expected.name} has defined property ${property}, but ${actual.name} is missing it.`,
|
||||
});
|
||||
}
|
||||
if (typeof expected.entity[property] === 'boolean') {
|
||||
// Sometimes, booleans get represented by numbers 0 and 1 in the objects actual from the database.
|
||||
if (Boolean(expected.entity[property]) !== Boolean(actual.entity[property])) {
|
||||
export function expectToBeCorrectEntity<T extends object>(actual: T, expected: T, propertyPrefix = ''): void {
|
||||
for (const property in expected) {
|
||||
if (Object.prototype.hasOwnProperty.call(expected, property)) {
|
||||
const prefixedProperty = propertyPrefix + property;
|
||||
if (
|
||||
property in IGNORE_PROPERTIES &&
|
||||
expected[property] !== undefined && // If we don't expect a certain value for a property, we assume it can be filled in by the database however it wants.
|
||||
typeof expected[property] !== 'function' // Functions obviously are not persisted via the database
|
||||
) {
|
||||
if (!Object.prototype.hasOwnProperty.call(actual, property)) {
|
||||
throw new AssertionError({
|
||||
message: `${property} was ${expected.entity[property]} in ${expected.name},
|
||||
but ${actual.entity[property]} (${Boolean(expected.entity[property])}) in ${actual.name}`,
|
||||
message: `Expected property ${prefixedProperty}, but it is missing.`,
|
||||
});
|
||||
}
|
||||
} else if (typeof expected.entity[property] !== typeof actual.entity[property]) {
|
||||
throw new AssertionError({
|
||||
message: `${property} has type ${typeof expected.entity[property]} in ${expected.name}, but type ${typeof actual.entity[property]} in ${actual.name}.`,
|
||||
});
|
||||
} else if (typeof expected.entity[property] === 'object') {
|
||||
expectToBeCorrectEntity(
|
||||
{
|
||||
name: actual.name + '.' + property,
|
||||
entity: actual.entity[property] as object,
|
||||
},
|
||||
{
|
||||
name: expected.name + '.' + property,
|
||||
entity: expected.entity[property] as object,
|
||||
if (typeof expected[property] === 'boolean') {
|
||||
// Sometimes, booleans get represented by numbers 0 and 1 in the objects actual from the database.
|
||||
if (Boolean(expected[property]) !== Boolean(actual[property])) {
|
||||
throw new AssertionError({
|
||||
message: `Expected ${prefixedProperty} to be ${expected[property]},
|
||||
but was ${actual[property]} (${Boolean(expected[property])}).`,
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
if (expected.entity[property] !== actual.entity[property]) {
|
||||
} else if (typeof expected[property] !== typeof actual[property]) {
|
||||
throw new AssertionError({
|
||||
message: `${property} was ${expected.entity[property]} in ${expected.name}, but ${actual.entity[property]} in ${actual.name}`,
|
||||
message:
|
||||
`${prefixedProperty} was expected to have type ${typeof expected[property]},` +
|
||||
`but had type ${typeof actual[property]}.`,
|
||||
});
|
||||
} else if (typeof expected[property] === 'object') {
|
||||
expectToBeCorrectEntity(actual[property] as object, expected[property] as object, property);
|
||||
} else {
|
||||
if (expected[property] !== actual[property]) {
|
||||
throw new AssertionError({
|
||||
message: `${prefixedProperty} was expected to be ${expected[property]}, ` + `but was ${actual[property]}.`,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,9 +58,9 @@ export function expectToBeCorrectEntity<T extends object>(actual: { entity: T; n
|
|||
/**
|
||||
* Checks that filtered is the correct representation of original as FilteredLearningObject.
|
||||
* @param filtered the representation as FilteredLearningObject
|
||||
* @param original the original entity added to the database
|
||||
* @param original the data of the entity in the database that was filtered.
|
||||
*/
|
||||
export function expectToBeCorrectFilteredLearningObject(filtered: FilteredLearningObject, original: LearningObject) {
|
||||
export function expectToBeCorrectFilteredLearningObject(filtered: FilteredLearningObject, original: RequiredEntityData<LearningObject>): void {
|
||||
expect(filtered.uuid).toEqual(original.uuid);
|
||||
expect(filtered.version).toEqual(original.version);
|
||||
expect(filtered.language).toEqual(original.language);
|
||||
|
@ -97,54 +88,55 @@ export function expectToBeCorrectFilteredLearningObject(filtered: FilteredLearni
|
|||
* is a correct representation of the given learning path entity.
|
||||
*
|
||||
* @param learningPath The learning path returned by the retriever, service or endpoint
|
||||
* @param expectedEntity The expected entity
|
||||
* @param learningObjectsOnPath The learning objects on LearningPath. Necessary since some information in
|
||||
* the learning path returned from the API endpoint
|
||||
* @param expected The learning path that should have been returned.
|
||||
*/
|
||||
export function expectToBeCorrectLearningPath(
|
||||
learningPath: LearningPath,
|
||||
expectedEntity: LearningPathEntity,
|
||||
learningObjectsOnPath: FilteredLearningObject[]
|
||||
) {
|
||||
expect(learningPath.hruid).toEqual(expectedEntity.hruid);
|
||||
expect(learningPath.language).toEqual(expectedEntity.language);
|
||||
expect(learningPath.description).toEqual(expectedEntity.description);
|
||||
expect(learningPath.title).toEqual(expectedEntity.title);
|
||||
export function expectToBeCorrectLearningPath(learningPath: LearningPath, expected: LearningPath): void {
|
||||
expect(learningPath.hruid).toEqual(expected.hruid);
|
||||
expect(learningPath.language).toEqual(expected.language);
|
||||
expect(learningPath.description).toEqual(expected.description);
|
||||
expect(learningPath.title).toEqual(expected.title);
|
||||
|
||||
const keywords = new Set(learningObjectsOnPath.flatMap((it) => it.keywords || []));
|
||||
expect(new Set(learningPath.keywords.split(' '))).toEqual(keywords);
|
||||
expect(new Set(learningPath.keywords.split(' '))).toEqual(new Set(learningPath.keywords.split(' ')));
|
||||
|
||||
const targetAges = new Set(learningObjectsOnPath.flatMap((it) => it.targetAges || []));
|
||||
expect(new Set(learningPath.target_ages)).toEqual(targetAges);
|
||||
expect(learningPath.min_age).toEqual(Math.min(...targetAges));
|
||||
expect(learningPath.max_age).toEqual(Math.max(...targetAges));
|
||||
expect(new Set(learningPath.target_ages)).toEqual(new Set(expected.target_ages));
|
||||
expect(learningPath.min_age).toEqual(Math.min(...expected.target_ages));
|
||||
expect(learningPath.max_age).toEqual(Math.max(...expected.target_ages));
|
||||
|
||||
expect(learningPath.num_nodes).toEqual(expectedEntity.nodes.length);
|
||||
expect(learningPath.image || null).toEqual(expectedEntity.image);
|
||||
expect(learningPath.num_nodes).toEqual(expected.nodes.length);
|
||||
expect(learningPath.image ?? null).toEqual(expected.image ?? null);
|
||||
|
||||
const expectedLearningPathNodes = new Map(
|
||||
expectedEntity.nodes.map((node) => [
|
||||
{ learningObjectHruid: node.learningObjectHruid, language: node.language, version: node.version },
|
||||
{ startNode: node.startNode, transitions: node.transitions },
|
||||
])
|
||||
);
|
||||
|
||||
for (const node of learningPath.nodes) {
|
||||
const nodeKey = {
|
||||
learningObjectHruid: node.learningobject_hruid,
|
||||
language: node.language,
|
||||
version: node.version,
|
||||
};
|
||||
expect(expectedLearningPathNodes.keys()).toContainEqual(nodeKey);
|
||||
const expectedNode = [...expectedLearningPathNodes.entries()].filter(
|
||||
([key, _]) => key.learningObjectHruid === nodeKey.learningObjectHruid && key.language === node.language && key.version === node.version
|
||||
)[0][1];
|
||||
expect(node.start_node).toEqual(expectedNode?.startNode);
|
||||
|
||||
expect(new Set(node.transitions.map((it) => it.next.hruid))).toEqual(
|
||||
new Set(expectedNode.transitions.map((it) => it.next.learningObjectHruid))
|
||||
for (const node of expected.nodes) {
|
||||
const correspondingNode = learningPath.nodes.find(
|
||||
(it) => node.learningobject_hruid === it.learningobject_hruid && node.language === it.language && node.version === it.version
|
||||
);
|
||||
expect(new Set(node.transitions.map((it) => it.next.language))).toEqual(new Set(expectedNode.transitions.map((it) => it.next.language)));
|
||||
expect(new Set(node.transitions.map((it) => it.next.version))).toEqual(new Set(expectedNode.transitions.map((it) => it.next.version)));
|
||||
expect(correspondingNode).toBeTruthy();
|
||||
expect(Boolean(correspondingNode!.start_node)).toEqual(Boolean(node.start_node));
|
||||
|
||||
for (const transition of node.transitions) {
|
||||
const correspondingTransition = correspondingNode!.transitions.find(
|
||||
(it) =>
|
||||
it.next.hruid === transition.next.hruid &&
|
||||
it.next.language === transition.next.language &&
|
||||
it.next.version === transition.next.version
|
||||
);
|
||||
expect(correspondingTransition).toBeTruthy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Expect that the given result is a singleton list with exactly the given element.
|
||||
*/
|
||||
export function expectToHaveFoundPrecisely<T extends object>(expected: T, result: T[]): void {
|
||||
expect(result).toHaveProperty('length');
|
||||
expect(result.length).toBe(1);
|
||||
expectToBeCorrectEntity(result[0], expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expect that the given result is an empty list.
|
||||
*/
|
||||
export function expectToHaveFoundNothing<T>(result: T[]): void {
|
||||
expect(result).toHaveProperty('length');
|
||||
expect(result.length).toBe(0);
|
||||
}
|
||||
|
|
10
backend/tests/test-utils/get-html-rendering.ts
Normal file
10
backend/tests/test-utils/get-html-rendering.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { RequiredEntityData } from '@mikro-orm/core';
|
||||
import { loadTestAsset } from './load-test-asset';
|
||||
import { LearningObject } from '../../src/entities/content/learning-object.entity';
|
||||
import { envVars, getEnvVar } from '../../src/util/envVars';
|
||||
|
||||
export function getHtmlRenderingForTestLearningObject(learningObject: RequiredEntityData<LearningObject>): string {
|
||||
const userPrefix = getEnvVar(envVars.UserContentPrefix);
|
||||
const cleanedHruid = learningObject.hruid.startsWith(userPrefix) ? learningObject.hruid.substring(userPrefix.length) : learningObject.hruid;
|
||||
return loadTestAsset(`/content/learning-object-resources/${cleanedHruid}/rendering.txt`).toString();
|
||||
}
|
|
@ -1,10 +1,14 @@
|
|||
import fs from 'fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const fileName = fileURLToPath(import.meta.url);
|
||||
const dirName = path.dirname(fileName);
|
||||
|
||||
/**
|
||||
* Load the asset at the given path.
|
||||
* @param relPath Path of the asset relative to the test-assets folder.
|
||||
*/
|
||||
export function loadTestAsset(relPath: string): Buffer {
|
||||
return fs.readFileSync(path.resolve(__dirname, `../test-assets/${relPath}`));
|
||||
return fs.readFileSync(path.resolve(dirName, `../test_assets/${relPath}`));
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import { Connection, EntityManager, IDatabaseDriver } from '@mikro-orm/core';
|
||||
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 '../../../src/entities/content/language';
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
import { testLearningPathWithConditions } from '../content/learning-paths.testdata';
|
||||
import { getClassWithTestleerlingAndTestleerkracht } from '../classes/classes.testdata';
|
||||
|
||||
export function makeTestAssignemnts(em: EntityManager<IDatabaseDriver<Connection>>, classes: Array<Class>): Array<Assignment> {
|
||||
const assignment01 = em.create(Assignment, {
|
||||
export function makeTestAssignemnts(em: EntityManager, classes: Class[]): Assignment[] {
|
||||
assignment01 = em.create(Assignment, {
|
||||
id: 21000,
|
||||
within: classes[0],
|
||||
id: 1,
|
||||
title: 'dire straits',
|
||||
description: 'reading',
|
||||
learningPathHruid: 'id02',
|
||||
|
@ -14,9 +16,9 @@ export function makeTestAssignemnts(em: EntityManager<IDatabaseDriver<Connection
|
|||
groups: [],
|
||||
});
|
||||
|
||||
const assignment02 = em.create(Assignment, {
|
||||
assignment02 = em.create(Assignment, {
|
||||
id: 21001,
|
||||
within: classes[1],
|
||||
id: 2,
|
||||
title: 'tool',
|
||||
description: 'reading',
|
||||
learningPathHruid: 'id01',
|
||||
|
@ -24,9 +26,9 @@ export function makeTestAssignemnts(em: EntityManager<IDatabaseDriver<Connection
|
|||
groups: [],
|
||||
});
|
||||
|
||||
const assignment03 = em.create(Assignment, {
|
||||
assignment03 = em.create(Assignment, {
|
||||
id: 21002,
|
||||
within: classes[0],
|
||||
id: 3,
|
||||
title: 'delete',
|
||||
description: 'will be deleted',
|
||||
learningPathHruid: 'id02',
|
||||
|
@ -34,5 +36,51 @@ export function makeTestAssignemnts(em: EntityManager<IDatabaseDriver<Connection
|
|||
groups: [],
|
||||
});
|
||||
|
||||
return [assignment01, assignment02, assignment03];
|
||||
assignment04 = em.create(Assignment, {
|
||||
id: 21003,
|
||||
within: classes[0],
|
||||
title: 'another assignment',
|
||||
description: 'with a description',
|
||||
learningPathHruid: 'id01',
|
||||
learningPathLanguage: Language.English,
|
||||
groups: [],
|
||||
});
|
||||
|
||||
conditionalPathAssignment = em.create(Assignment, {
|
||||
within: getClassWithTestleerlingAndTestleerkracht(),
|
||||
id: 21004,
|
||||
title: 'Assignment: Conditional Learning Path',
|
||||
description: 'You have to do the testing learning path with a condition.',
|
||||
learningPathHruid: testLearningPathWithConditions.hruid,
|
||||
learningPathLanguage: testLearningPathWithConditions.language as Language,
|
||||
groups: [],
|
||||
});
|
||||
|
||||
return [assignment01, assignment02, assignment03, assignment04, conditionalPathAssignment];
|
||||
}
|
||||
|
||||
let assignment01: Assignment;
|
||||
let assignment02: Assignment;
|
||||
let assignment03: Assignment;
|
||||
let assignment04: Assignment;
|
||||
let conditionalPathAssignment: Assignment;
|
||||
|
||||
export function getAssignment01(): Assignment {
|
||||
return assignment01;
|
||||
}
|
||||
|
||||
export function getAssignment02(): Assignment {
|
||||
return assignment02;
|
||||
}
|
||||
|
||||
export function getAssignment03(): Assignment {
|
||||
return assignment03;
|
||||
}
|
||||
|
||||
export function getAssignment04(): Assignment {
|
||||
return assignment04;
|
||||
}
|
||||
|
||||
export function getConditionalPathAssignment(): Assignment {
|
||||
return conditionalPathAssignment;
|
||||
}
|
||||
|
|
|
@ -1,36 +1,100 @@
|
|||
import { Connection, EntityManager, IDatabaseDriver } from '@mikro-orm/core';
|
||||
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';
|
||||
|
||||
export function makeTestGroups(
|
||||
em: EntityManager<IDatabaseDriver<Connection>>,
|
||||
students: Array<Student>,
|
||||
assignments: Array<Assignment>
|
||||
): Array<Group> {
|
||||
const group01 = em.create(Group, {
|
||||
export function makeTestGroups(em: EntityManager, students: Student[], assignments: Assignment[]): Group[] {
|
||||
/*
|
||||
* Group #1 for Assignment #1 in class 'id01'
|
||||
* => Assigned to do learning path 'id02'
|
||||
*/
|
||||
group01 = em.create(Group, {
|
||||
assignment: assignments[0],
|
||||
groupNumber: 1,
|
||||
groupNumber: 21001,
|
||||
members: students.slice(0, 2),
|
||||
});
|
||||
|
||||
const group02 = em.create(Group, {
|
||||
/*
|
||||
* Group #2 for Assignment #1 in class 'id01'
|
||||
* => Assigned to do learning path 'id02'
|
||||
*/
|
||||
group02 = em.create(Group, {
|
||||
assignment: assignments[0],
|
||||
groupNumber: 2,
|
||||
groupNumber: 21002,
|
||||
members: students.slice(2, 4),
|
||||
});
|
||||
|
||||
const group03 = em.create(Group, {
|
||||
/*
|
||||
* Group #3 for Assignment #1 in class 'id01'
|
||||
* => Assigned to do learning path 'id02'
|
||||
*/
|
||||
group03 = em.create(Group, {
|
||||
assignment: assignments[0],
|
||||
groupNumber: 3,
|
||||
groupNumber: 21003,
|
||||
members: students.slice(4, 6),
|
||||
});
|
||||
|
||||
const group04 = em.create(Group, {
|
||||
/*
|
||||
* Group #4 for Assignment #2 in class 'id02'
|
||||
* => Assigned to do learning path 'id01'
|
||||
*/
|
||||
group04 = em.create(Group, {
|
||||
assignment: assignments[1],
|
||||
groupNumber: 4,
|
||||
groupNumber: 21004,
|
||||
members: students.slice(3, 4),
|
||||
});
|
||||
|
||||
return [group01, group02, group03, group04];
|
||||
/*
|
||||
* Group #5 for Assignment #4 in class 'id01'
|
||||
* => Assigned to do learning path 'id01'
|
||||
*/
|
||||
group05 = em.create(Group, {
|
||||
assignment: assignments[3],
|
||||
groupNumber: 21001,
|
||||
members: students.slice(0, 2),
|
||||
});
|
||||
|
||||
/**
|
||||
* Group 1 for the assignment of the testing learning path with conditions.
|
||||
*/
|
||||
group1ConditionalLearningPath = em.create(Group, {
|
||||
assignment: getConditionalPathAssignment(),
|
||||
groupNumber: 21005,
|
||||
members: [getTestleerling1()],
|
||||
});
|
||||
|
||||
return [group01, group02, group03, group04, group05, group1ConditionalLearningPath];
|
||||
}
|
||||
|
||||
let group01: Group;
|
||||
let group02: Group;
|
||||
let group03: Group;
|
||||
let group04: Group;
|
||||
let group05: Group;
|
||||
let group1ConditionalLearningPath: Group;
|
||||
|
||||
export function getTestGroup01(): Group {
|
||||
return group01;
|
||||
}
|
||||
|
||||
export function getTestGroup02(): Group {
|
||||
return group02;
|
||||
}
|
||||
|
||||
export function getTestGroup03(): Group {
|
||||
return group03;
|
||||
}
|
||||
|
||||
export function getTestGroup04(): Group {
|
||||
return group04;
|
||||
}
|
||||
|
||||
export function getTestGroup05(): Group {
|
||||
return group05;
|
||||
}
|
||||
|
||||
export function getGroup1ConditionalLearningPath(): Group {
|
||||
return group1ConditionalLearningPath;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
import { Connection, EntityManager, IDatabaseDriver } from '@mikro-orm/core';
|
||||
import { EntityManager } from '@mikro-orm/core';
|
||||
import { Submission } from '../../../src/entities/assignments/submission.entity';
|
||||
import { Language } from '../../../src/entities/content/language';
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
import { Student } from '../../../src/entities/users/student.entity';
|
||||
import { Group } from '../../../src/entities/assignments/group.entity';
|
||||
|
||||
export function makeTestSubmissions(
|
||||
em: EntityManager<IDatabaseDriver<Connection>>,
|
||||
students: Array<Student>,
|
||||
groups: Array<Group>
|
||||
): Array<Submission> {
|
||||
export function makeTestSubmissions(em: EntityManager, students: Student[], groups: Group[]): Submission[] {
|
||||
const submission01 = em.create(Submission, {
|
||||
learningObjectHruid: 'id03',
|
||||
learningObjectLanguage: Language.English,
|
||||
|
@ -16,7 +12,7 @@ export function makeTestSubmissions(
|
|||
submissionNumber: 1,
|
||||
submitter: students[0],
|
||||
submissionTime: new Date(2025, 2, 20),
|
||||
onBehalfOf: groups[0],
|
||||
onBehalfOf: groups[0], // Group #1 for Assignment #1 in class 'id01'
|
||||
content: 'sub1',
|
||||
});
|
||||
|
||||
|
@ -27,7 +23,7 @@ export function makeTestSubmissions(
|
|||
submissionNumber: 2,
|
||||
submitter: students[0],
|
||||
submissionTime: new Date(2025, 2, 25),
|
||||
onBehalfOf: groups[0],
|
||||
onBehalfOf: groups[0], // Group #1 for Assignment #1 in class 'id01'
|
||||
content: '',
|
||||
});
|
||||
|
||||
|
@ -38,6 +34,7 @@ export function makeTestSubmissions(
|
|||
submissionNumber: 1,
|
||||
submitter: students[0],
|
||||
submissionTime: new Date(2025, 2, 20),
|
||||
onBehalfOf: groups[0], // Group #1 for Assignment #1 in class 'id01'
|
||||
content: '',
|
||||
});
|
||||
|
||||
|
@ -48,6 +45,7 @@ export function makeTestSubmissions(
|
|||
submissionNumber: 2,
|
||||
submitter: students[0],
|
||||
submissionTime: new Date(2025, 2, 25),
|
||||
onBehalfOf: groups[0], // Group #1 for Assignment #1 in class 'id01'
|
||||
content: '',
|
||||
});
|
||||
|
||||
|
@ -58,8 +56,42 @@ export function makeTestSubmissions(
|
|||
submissionNumber: 1,
|
||||
submitter: students[1],
|
||||
submissionTime: new Date(2025, 2, 20),
|
||||
onBehalfOf: groups[1], // Group #2 for Assignment #1 in class 'id01'
|
||||
content: '',
|
||||
});
|
||||
|
||||
return [submission01, submission02, submission03, submission04, submission05];
|
||||
const submission06 = em.create(Submission, {
|
||||
learningObjectHruid: 'id01',
|
||||
learningObjectLanguage: Language.English,
|
||||
learningObjectVersion: 1,
|
||||
submissionNumber: 2,
|
||||
submitter: students[1],
|
||||
submissionTime: new Date(2025, 2, 25),
|
||||
onBehalfOf: groups[4], // Group #5 for Assignment #4 in class 'id01'
|
||||
content: '',
|
||||
});
|
||||
|
||||
const submission07 = em.create(Submission, {
|
||||
learningObjectHruid: 'id01',
|
||||
learningObjectLanguage: Language.English,
|
||||
learningObjectVersion: 1,
|
||||
submissionNumber: 3,
|
||||
submitter: students[3],
|
||||
submissionTime: new Date(2025, 3, 25),
|
||||
onBehalfOf: groups[3], // Group #4 for Assignment #2 in class 'id02'
|
||||
content: '',
|
||||
});
|
||||
|
||||
const submission08 = em.create(Submission, {
|
||||
learningObjectHruid: 'id02',
|
||||
learningObjectLanguage: Language.English,
|
||||
learningObjectVersion: 1,
|
||||
submissionNumber: 3,
|
||||
submitter: students[1],
|
||||
submissionTime: new Date(2025, 4, 7),
|
||||
onBehalfOf: groups[1], // Group #2 for Assignment #1 in class 'id01'
|
||||
content: '',
|
||||
});
|
||||
|
||||
return [submission01, submission02, submission03, submission04, submission05, submission06, submission07, submission08];
|
||||
}
|
||||
|
|
|
@ -1,35 +1,32 @@
|
|||
import { Connection, EntityManager, IDatabaseDriver } from '@mikro-orm/core';
|
||||
import { ClassJoinRequest, ClassJoinRequestStatus } from '../../../src/entities/classes/class-join-request.entity';
|
||||
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';
|
||||
|
||||
export function makeTestClassJoinRequests(
|
||||
em: EntityManager<IDatabaseDriver<Connection>>,
|
||||
students: Array<Student>,
|
||||
classes: Array<Class>
|
||||
): Array<ClassJoinRequest> {
|
||||
export function makeTestClassJoinRequests(em: EntityManager, students: Student[], classes: Class[]): ClassJoinRequest[] {
|
||||
const classJoinRequest01 = em.create(ClassJoinRequest, {
|
||||
requester: students[4],
|
||||
class: classes[1],
|
||||
status: ClassJoinRequestStatus.Open,
|
||||
status: ClassStatus.Open,
|
||||
});
|
||||
|
||||
const classJoinRequest02 = em.create(ClassJoinRequest, {
|
||||
requester: students[2],
|
||||
class: classes[1],
|
||||
status: ClassJoinRequestStatus.Open,
|
||||
status: ClassStatus.Open,
|
||||
});
|
||||
|
||||
const classJoinRequest03 = em.create(ClassJoinRequest, {
|
||||
requester: students[4],
|
||||
class: classes[2],
|
||||
status: ClassJoinRequestStatus.Open,
|
||||
status: ClassStatus.Open,
|
||||
});
|
||||
|
||||
const classJoinRequest04 = em.create(ClassJoinRequest, {
|
||||
requester: students[3],
|
||||
class: classes[2],
|
||||
status: ClassJoinRequestStatus.Open,
|
||||
status: ClassStatus.Open,
|
||||
});
|
||||
|
||||
return [classJoinRequest01, classJoinRequest02, classJoinRequest03, classJoinRequest04];
|
||||
|
|
|
@ -1,48 +1,83 @@
|
|||
import { Connection, EntityManager, IDatabaseDriver } from '@mikro-orm/core';
|
||||
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';
|
||||
|
||||
export function makeTestClasses(em: EntityManager<IDatabaseDriver<Connection>>, students: Array<Student>, teachers: Array<Teacher>): Array<Class> {
|
||||
const studentsClass01 = students.slice(0, 7);
|
||||
const teacherClass01: Array<Teacher> = teachers.slice(0, 1);
|
||||
export function makeTestClasses(em: EntityManager, students: Student[], teachers: Teacher[]): Class[] {
|
||||
const studentsClass01 = students.slice(0, 8);
|
||||
const teacherClass01: Teacher[] = teachers.slice(4, 5);
|
||||
|
||||
const class01 = em.create(Class, {
|
||||
classId: 'id01',
|
||||
class01 = em.create(Class, {
|
||||
classId: 'X2J9QT', // 8764b861-90a6-42e5-9732-c0d9eb2f55f9
|
||||
displayName: 'class01',
|
||||
teachers: teacherClass01,
|
||||
students: studentsClass01,
|
||||
});
|
||||
|
||||
const studentsClass02: Array<Student> = students.slice(0, 2).concat(students.slice(3, 4));
|
||||
const teacherClass02: Array<Teacher> = teachers.slice(1, 2);
|
||||
const studentsClass02: Student[] = students.slice(0, 2).concat(students.slice(3, 4));
|
||||
const teacherClass02: Teacher[] = teachers.slice(1, 2);
|
||||
|
||||
const class02 = em.create(Class, {
|
||||
classId: 'id02',
|
||||
class02 = em.create(Class, {
|
||||
classId: '7KLPMA', // 34d484a1-295f-4e9f-bfdc-3e7a23d86a89
|
||||
displayName: 'class02',
|
||||
teachers: teacherClass02,
|
||||
students: studentsClass02,
|
||||
});
|
||||
|
||||
const studentsClass03: Array<Student> = students.slice(1, 4);
|
||||
const teacherClass03: Array<Teacher> = teachers.slice(2, 3);
|
||||
const studentsClass03: Student[] = students.slice(1, 4);
|
||||
const teacherClass03: Teacher[] = teachers.slice(2, 3);
|
||||
|
||||
const class03 = em.create(Class, {
|
||||
classId: 'id03',
|
||||
class03 = em.create(Class, {
|
||||
classId: 'R0D3UZ', // 80dcc3e0-1811-4091-9361-42c0eee91cfa
|
||||
displayName: 'class03',
|
||||
teachers: teacherClass03,
|
||||
students: studentsClass03,
|
||||
});
|
||||
|
||||
const studentsClass04: Array<Student> = students.slice(0, 2);
|
||||
const teacherClass04: Array<Teacher> = teachers.slice(2, 3);
|
||||
const studentsClass04: Student[] = students.slice(0, 2);
|
||||
const teacherClass04: Teacher[] = teachers.slice(2, 3);
|
||||
|
||||
const class04 = em.create(Class, {
|
||||
classId: 'id04',
|
||||
class04 = em.create(Class, {
|
||||
classId: 'Q8N5YC', // 33d03536-83b8-4880-9982-9bbf2f908ddf
|
||||
displayName: 'class04',
|
||||
teachers: teacherClass04,
|
||||
students: studentsClass04,
|
||||
});
|
||||
|
||||
return [class01, class02, class03, class04];
|
||||
classWithTestleerlingAndTestleerkracht = em.create(Class, {
|
||||
classId: 'ZAV71B', // Was a75298b5-18aa-471d-8eeb-5d77eb989393
|
||||
displayName: 'Testklasse',
|
||||
teachers: [getTestleerkracht1()],
|
||||
students: [getTestleerling1()],
|
||||
});
|
||||
|
||||
return [class01, class02, class03, class04, classWithTestleerlingAndTestleerkracht];
|
||||
}
|
||||
|
||||
let class01: Class;
|
||||
let class02: Class;
|
||||
let class03: Class;
|
||||
let class04: Class;
|
||||
let classWithTestleerlingAndTestleerkracht: Class;
|
||||
|
||||
export function getClass01(): Class {
|
||||
return class01;
|
||||
}
|
||||
|
||||
export function getClass02(): Class {
|
||||
return class02;
|
||||
}
|
||||
|
||||
export function getClass03(): Class {
|
||||
return class03;
|
||||
}
|
||||
|
||||
export function getClass04(): Class {
|
||||
return class04;
|
||||
}
|
||||
|
||||
export function getClassWithTestleerlingAndTestleerkracht(): Class {
|
||||
return classWithTestleerlingAndTestleerkracht;
|
||||
}
|
||||
|
|
|
@ -1,35 +1,36 @@
|
|||
import { Connection, EntityManager, IDatabaseDriver } from '@mikro-orm/core';
|
||||
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';
|
||||
|
||||
export function makeTestTeacherInvitations(
|
||||
em: EntityManager<IDatabaseDriver<Connection>>,
|
||||
teachers: Array<Teacher>,
|
||||
classes: Array<Class>
|
||||
): Array<TeacherInvitation> {
|
||||
export function makeTestTeacherInvitations(em: EntityManager, teachers: Teacher[], classes: Class[]): TeacherInvitation[] {
|
||||
const teacherInvitation01 = em.create(TeacherInvitation, {
|
||||
sender: teachers[1],
|
||||
receiver: teachers[0],
|
||||
class: classes[1],
|
||||
status: ClassStatus.Open,
|
||||
});
|
||||
|
||||
const teacherInvitation02 = em.create(TeacherInvitation, {
|
||||
sender: teachers[1],
|
||||
receiver: teachers[2],
|
||||
class: classes[1],
|
||||
status: ClassStatus.Open,
|
||||
});
|
||||
|
||||
const teacherInvitation03 = em.create(TeacherInvitation, {
|
||||
sender: teachers[2],
|
||||
receiver: teachers[0],
|
||||
class: classes[2],
|
||||
status: ClassStatus.Open,
|
||||
});
|
||||
|
||||
const teacherInvitation04 = em.create(TeacherInvitation, {
|
||||
sender: teachers[0],
|
||||
receiver: teachers[1],
|
||||
class: classes[0],
|
||||
status: ClassStatus.Open,
|
||||
});
|
||||
|
||||
return [teacherInvitation01, teacherInvitation02, teacherInvitation03, teacherInvitation04];
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { Connection, EntityManager, IDatabaseDriver } from '@mikro-orm/core';
|
||||
import { EntityManager } from '@mikro-orm/core';
|
||||
import { Attachment } from '../../../src/entities/content/attachment.entity';
|
||||
import { LearningObject } from '../../../src/entities/content/learning-object.entity';
|
||||
|
||||
export function makeTestAttachments(em: EntityManager<IDatabaseDriver<Connection>>, learningObjects: Array<LearningObject>): Array<Attachment> {
|
||||
export function makeTestAttachments(em: EntityManager, learningObjects: LearningObject[]): Attachment[] {
|
||||
const attachment01 = em.create(Attachment, {
|
||||
learningObject: learningObjects[1],
|
||||
name: 'attachment01',
|
||||
|
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
@ -0,0 +1,2 @@
|
|||
::Reflection::
|
||||
Reflect on this learning path. What have you learned today? {}
|
|
@ -0,0 +1,7 @@
|
|||
<div class="learning-object-gift">
|
||||
<div id="gift-q1" class="gift-question gift-question-type-Essay">
|
||||
<h2 id="gift-q1-title" class="gift-title">Reflection</h2>
|
||||
<p id="gift-q1-stem" class="gift-stem">Reflect on this learning path. What have you learned today?</p>
|
||||
<textarea id="gift-q1-answer" class="gift-essay-answer"></textarea>
|
||||
</div>
|
||||
</div>
|
|
@ -1,5 +1,5 @@
|
|||
::MC basic::
|
||||
Are you following along well with the class? {
|
||||
::Self-evaluation::
|
||||
Are you following along well? {
|
||||
~No, it's very difficult to follow along.
|
||||
=Yes, no problem!
|
||||
}
|
|
@ -1,14 +1,14 @@
|
|||
<div class="learning-object-gift">
|
||||
<div id="gift-q1" class="gift-question">
|
||||
<h2 id="gift-q1-title" class="gift-title">MC basic</h2>
|
||||
<p id="gift-q1-stem" class="gift-stem">Are you following along well with the class?</p>
|
||||
<div id="gift-q1" class="gift-question gift-question-type-MC">
|
||||
<h2 id="gift-q1-title" class="gift-title">Self-evaluation</h2>
|
||||
<p id="gift-q1-stem" class="gift-stem">Are you following along well?</p>
|
||||
<div class="gift-choice-div">
|
||||
<input value="0" name="gift-q1-choices" id="gift-q1-choice-0" type="radio">
|
||||
<label for="gift-q1-choice-0">[object Object]</label>
|
||||
<label for="gift-q1-choice-0">No, it's very difficult to follow along.</label>
|
||||
</div>
|
||||
<div class="gift-choice-div">
|
||||
<input value="1" name="gift-q1-choices" id="gift-q1-choice-1" type="radio">
|
||||
<label for="gift-q1-choice-1">[object Object]</label>
|
||||
<label for="gift-q1-choice-1">Yes, no problem!</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,134 +1,261 @@
|
|||
import { Connection, EntityManager, IDatabaseDriver } from '@mikro-orm/core';
|
||||
import { LearningObject, ReturnValue } from '../../../src/entities/content/learning-object.entity';
|
||||
import { Language } from '../../../src/entities/content/language';
|
||||
import { EntityManager, RequiredEntityData } from '@mikro-orm/core';
|
||||
import { LearningObject } from '../../../src/entities/content/learning-object.entity';
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
import { DwengoContentType } from '../../../src/services/learning-objects/processing/content-type';
|
||||
import { ReturnValue } from '../../../src/entities/content/return-value.entity';
|
||||
import { envVars, getEnvVar } from '../../../src/util/envVars';
|
||||
import { loadTestAsset } from '../../test-utils/load-test-asset';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export function makeTestLearningObjects(em: EntityManager<IDatabaseDriver<Connection>>): Array<LearningObject> {
|
||||
export function makeTestLearningObjects(em: EntityManager): LearningObject[] {
|
||||
const returnValue: ReturnValue = new ReturnValue();
|
||||
returnValue.callbackSchema = '';
|
||||
returnValue.callbackUrl = '';
|
||||
|
||||
const learningObject01 = em.create(LearningObject, {
|
||||
hruid: 'id01',
|
||||
language: Language.English,
|
||||
version: 1,
|
||||
admins: [],
|
||||
title: 'Undertow',
|
||||
description: 'debute',
|
||||
contentType: DwengoContentType.TEXT_MARKDOWN,
|
||||
keywords: [],
|
||||
teacherExclusive: false,
|
||||
skosConcepts: [],
|
||||
educationalGoals: [],
|
||||
copyright: '',
|
||||
license: '',
|
||||
estimatedTime: 45,
|
||||
returnValue: returnValue,
|
||||
available: true,
|
||||
contentLocation: '',
|
||||
attachments: [],
|
||||
content: Buffer.from("there's a shadow just behind me, shrouding every step i take, making every promise empty pointing every finger at me"),
|
||||
});
|
||||
const learningObject01 = em.create(LearningObject, testLearningObject01);
|
||||
const learningObject02 = em.create(LearningObject, testLearningObject02);
|
||||
const learningObject03 = em.create(LearningObject, testLearningObject03);
|
||||
const learningObject04 = em.create(LearningObject, testLearningObject04);
|
||||
const learningObject05 = em.create(LearningObject, testLearningObject05);
|
||||
|
||||
const learningObject02 = em.create(LearningObject, {
|
||||
hruid: 'id02',
|
||||
language: Language.English,
|
||||
version: 1,
|
||||
admins: [],
|
||||
title: 'Aenema',
|
||||
description: 'second album',
|
||||
contentType: DwengoContentType.TEXT_MARKDOWN,
|
||||
keywords: [],
|
||||
teacherExclusive: false,
|
||||
skosConcepts: [],
|
||||
educationalGoals: [],
|
||||
copyright: '',
|
||||
license: '',
|
||||
estimatedTime: 80,
|
||||
returnValue: returnValue,
|
||||
available: true,
|
||||
contentLocation: '',
|
||||
attachments: [],
|
||||
content: Buffer.from(
|
||||
"I've been crawling on my belly clearing out what could've been I've been wallowing in my own confused and insecure delusions"
|
||||
),
|
||||
});
|
||||
const learningObjectMultipleChoice = em.create(LearningObject, testLearningObjectMultipleChoice);
|
||||
const learningObjectEssayQuestion = em.create(LearningObject, testLearningObjectEssayQuestion);
|
||||
|
||||
const learningObject03 = em.create(LearningObject, {
|
||||
hruid: 'id03',
|
||||
language: Language.English,
|
||||
version: 1,
|
||||
admins: [],
|
||||
title: 'love over gold',
|
||||
description: 'third album',
|
||||
contentType: DwengoContentType.TEXT_MARKDOWN,
|
||||
keywords: [],
|
||||
teacherExclusive: false,
|
||||
skosConcepts: [],
|
||||
educationalGoals: [],
|
||||
copyright: '',
|
||||
license: '',
|
||||
estimatedTime: 55,
|
||||
returnValue: returnValue,
|
||||
available: true,
|
||||
contentLocation: '',
|
||||
attachments: [],
|
||||
content: Buffer.from(
|
||||
'he wrote me a prescription, he said you are depressed, \
|
||||
but I am glad you came to see me to get this off your chest, \
|
||||
come back and see me later next patient please \
|
||||
send in another victim of industrial disease'
|
||||
),
|
||||
});
|
||||
const learningObjectPnNotebooks = em.create(LearningObject, testLearningObjectPnNotebooks);
|
||||
|
||||
const learningObject04 = em.create(LearningObject, {
|
||||
hruid: 'id04',
|
||||
language: Language.English,
|
||||
version: 1,
|
||||
admins: [],
|
||||
title: 'making movies',
|
||||
description: 'fifth album',
|
||||
contentType: DwengoContentType.TEXT_MARKDOWN,
|
||||
keywords: [],
|
||||
teacherExclusive: false,
|
||||
skosConcepts: [],
|
||||
educationalGoals: [],
|
||||
copyright: '',
|
||||
license: '',
|
||||
estimatedTime: 55,
|
||||
returnValue: returnValue,
|
||||
available: true,
|
||||
contentLocation: '',
|
||||
attachments: [],
|
||||
content: Buffer.from(
|
||||
'I put my hand upon the lever \
|
||||
Said let it rock and let it roll \
|
||||
I had the one-arm bandit fever \
|
||||
There was an arrow through my heart and my soul'
|
||||
),
|
||||
});
|
||||
|
||||
const learningObject05 = em.create(LearningObject, {
|
||||
hruid: 'id05',
|
||||
language: Language.English,
|
||||
version: 1,
|
||||
admins: [],
|
||||
title: 'on every street',
|
||||
description: 'sixth album',
|
||||
contentType: DwengoContentType.TEXT_MARKDOWN,
|
||||
keywords: [],
|
||||
teacherExclusive: false,
|
||||
skosConcepts: [],
|
||||
educationalGoals: [],
|
||||
copyright: '',
|
||||
license: '',
|
||||
estimatedTime: 55,
|
||||
returnValue: returnValue,
|
||||
available: true,
|
||||
contentLocation: '',
|
||||
attachments: [],
|
||||
content: Buffer.from('calling Elvis, is anybody home, calling elvis, I am here all alone'),
|
||||
});
|
||||
|
||||
return [learningObject01, learningObject02, learningObject03, learningObject04, learningObject05];
|
||||
return [
|
||||
learningObject01,
|
||||
learningObject02,
|
||||
learningObject03,
|
||||
learningObject04,
|
||||
learningObject05,
|
||||
learningObjectMultipleChoice,
|
||||
learningObjectEssayQuestion,
|
||||
learningObjectPnNotebooks,
|
||||
];
|
||||
}
|
||||
|
||||
export function createReturnValue(): ReturnValue {
|
||||
const returnValue: ReturnValue = new ReturnValue();
|
||||
returnValue.callbackSchema = '[]';
|
||||
returnValue.callbackUrl = '%SUBMISSION%';
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
export const testLearningObject01: RequiredEntityData<LearningObject> = {
|
||||
hruid: `${getEnvVar(envVars.UserContentPrefix)}id01`,
|
||||
language: Language.English,
|
||||
version: 1,
|
||||
admins: [],
|
||||
title: 'Undertow',
|
||||
description: 'debute',
|
||||
contentType: DwengoContentType.TEXT_MARKDOWN,
|
||||
keywords: [],
|
||||
uuid: v4(),
|
||||
targetAges: [16, 17, 18],
|
||||
teacherExclusive: false,
|
||||
skosConcepts: [],
|
||||
educationalGoals: [],
|
||||
copyright: '',
|
||||
license: '',
|
||||
estimatedTime: 45,
|
||||
returnValue: createReturnValue(),
|
||||
available: true,
|
||||
contentLocation: '',
|
||||
attachments: [],
|
||||
content: Buffer.from("there's a shadow just behind me, shrouding every step i take, making every promise empty pointing every finger at me"),
|
||||
};
|
||||
|
||||
export const testLearningObject02: RequiredEntityData<LearningObject> = {
|
||||
hruid: `${getEnvVar(envVars.UserContentPrefix)}id02`,
|
||||
language: Language.English,
|
||||
version: 1,
|
||||
admins: [],
|
||||
title: 'Aenema',
|
||||
description: 'second album',
|
||||
contentType: DwengoContentType.TEXT_MARKDOWN,
|
||||
keywords: [],
|
||||
teacherExclusive: false,
|
||||
skosConcepts: [],
|
||||
educationalGoals: [],
|
||||
copyright: '',
|
||||
license: '',
|
||||
estimatedTime: 80,
|
||||
returnValue: createReturnValue(),
|
||||
available: true,
|
||||
contentLocation: '',
|
||||
attachments: [],
|
||||
content: Buffer.from(
|
||||
"I've been crawling on my belly clearing out what could've been I've been wallowing in my own confused and insecure delusions"
|
||||
),
|
||||
};
|
||||
|
||||
export const testLearningObject03: RequiredEntityData<LearningObject> = {
|
||||
hruid: `${getEnvVar(envVars.UserContentPrefix)}id03`,
|
||||
language: Language.English,
|
||||
version: 1,
|
||||
admins: [],
|
||||
title: 'love over gold',
|
||||
description: 'third album',
|
||||
contentType: DwengoContentType.TEXT_MARKDOWN,
|
||||
keywords: [],
|
||||
teacherExclusive: false,
|
||||
skosConcepts: [],
|
||||
educationalGoals: [],
|
||||
copyright: '',
|
||||
license: '',
|
||||
estimatedTime: 55,
|
||||
returnValue: createReturnValue(),
|
||||
available: true,
|
||||
contentLocation: '',
|
||||
attachments: [],
|
||||
content: Buffer.from(
|
||||
'he wrote me a prescription, he said you are depressed, \
|
||||
but I am glad you came to see me to get this off your chest, \
|
||||
come back and see me later next patient please \
|
||||
send in another victim of industrial disease'
|
||||
),
|
||||
};
|
||||
|
||||
export const testLearningObject04: RequiredEntityData<LearningObject> = {
|
||||
hruid: `${getEnvVar(envVars.UserContentPrefix)}id04`,
|
||||
language: Language.English,
|
||||
version: 1,
|
||||
admins: [],
|
||||
title: 'making movies',
|
||||
description: 'fifth album',
|
||||
contentType: DwengoContentType.TEXT_MARKDOWN,
|
||||
keywords: [],
|
||||
teacherExclusive: false,
|
||||
skosConcepts: [],
|
||||
educationalGoals: [],
|
||||
copyright: '',
|
||||
license: '',
|
||||
estimatedTime: 55,
|
||||
returnValue: createReturnValue(),
|
||||
available: true,
|
||||
contentLocation: '',
|
||||
attachments: [],
|
||||
content: Buffer.from(
|
||||
'I put my hand upon the lever \
|
||||
Said let it rock and let it roll \
|
||||
I had the one-arm bandit fever \
|
||||
There was an arrow through my heart and my soul'
|
||||
),
|
||||
};
|
||||
|
||||
export const testLearningObject05: RequiredEntityData<LearningObject> = {
|
||||
hruid: `${getEnvVar(envVars.UserContentPrefix)}id05`,
|
||||
language: Language.English,
|
||||
version: 1,
|
||||
admins: [],
|
||||
title: 'on every street',
|
||||
description: 'sixth album',
|
||||
contentType: DwengoContentType.TEXT_MARKDOWN,
|
||||
keywords: [],
|
||||
teacherExclusive: false,
|
||||
skosConcepts: [],
|
||||
educationalGoals: [],
|
||||
copyright: '',
|
||||
license: '',
|
||||
estimatedTime: 55,
|
||||
returnValue: createReturnValue(),
|
||||
available: true,
|
||||
contentLocation: '',
|
||||
attachments: [],
|
||||
content: Buffer.from('calling Elvis, is anybody home, calling elvis, I am here all alone'),
|
||||
};
|
||||
|
||||
export const testLearningObjectMultipleChoice: RequiredEntityData<LearningObject> = {
|
||||
hruid: `${getEnvVar(envVars.UserContentPrefix)}test_multiple_choice`,
|
||||
language: Language.English,
|
||||
version: 1,
|
||||
title: 'Self-evaluation',
|
||||
description: "Time to evaluate how well you understand what you've learned so far.",
|
||||
keywords: ['test'],
|
||||
teacherExclusive: false,
|
||||
skosConcepts: [],
|
||||
educationalGoals: [],
|
||||
copyright: 'Groep 1 SEL-2 2025',
|
||||
license: 'CC0',
|
||||
difficulty: 1,
|
||||
estimatedTime: 1,
|
||||
attachments: [],
|
||||
available: true,
|
||||
targetAges: [10, 11, 12, 13, 14, 15, 16, 17, 18],
|
||||
admins: [],
|
||||
contentType: DwengoContentType.GIFT,
|
||||
content: loadTestAsset('content/learning-object-resources/test_multiple_choice/content.txt'),
|
||||
returnValue: {
|
||||
callbackUrl: `%SUBMISSION%`,
|
||||
callbackSchema: '["antwoord vraag 1"]',
|
||||
},
|
||||
};
|
||||
|
||||
export const testLearningObjectEssayQuestion: RequiredEntityData<LearningObject> = {
|
||||
hruid: `${getEnvVar(envVars.UserContentPrefix)}test_essay_question`,
|
||||
language: Language.English,
|
||||
version: 1,
|
||||
title: 'Reflection',
|
||||
description: 'Reflect on your learning progress.',
|
||||
keywords: ['test'],
|
||||
teacherExclusive: false,
|
||||
skosConcepts: [],
|
||||
educationalGoals: [],
|
||||
copyright: 'Groep 1 SEL-2 2025',
|
||||
license: 'CC0',
|
||||
difficulty: 1,
|
||||
estimatedTime: 1,
|
||||
attachments: [],
|
||||
available: true,
|
||||
targetAges: [10, 11, 12, 13, 14, 15, 16, 17, 18],
|
||||
admins: [],
|
||||
contentType: DwengoContentType.GIFT,
|
||||
content: loadTestAsset('content/learning-object-resources/test_essay_question/content.txt'),
|
||||
returnValue: {
|
||||
callbackUrl: `%SUBMISSION%`,
|
||||
callbackSchema: '["antwoord vraag 1"]',
|
||||
},
|
||||
};
|
||||
|
||||
export const testLearningObjectPnNotebooks: RequiredEntityData<LearningObject> = {
|
||||
hruid: `${getEnvVar(envVars.UserContentPrefix)}pn_werkingnotebooks`,
|
||||
version: 3,
|
||||
language: Language.Dutch,
|
||||
title: 'Werken met notebooks',
|
||||
description: 'Leren werken met notebooks',
|
||||
keywords: ['Python', 'KIKS', 'Wiskunde', 'STEM', 'AI'],
|
||||
targetAges: [14, 15, 16, 17, 18],
|
||||
admins: [],
|
||||
copyright: 'dwengo',
|
||||
educationalGoals: [],
|
||||
license: 'dwengo',
|
||||
contentType: DwengoContentType.TEXT_MARKDOWN,
|
||||
difficulty: 3,
|
||||
estimatedTime: 10,
|
||||
uuid: '2adf9929-b424-4650-bf60-186f730d38ab',
|
||||
teacherExclusive: false,
|
||||
skosConcepts: [
|
||||
'http://ilearn.ilabt.imec.be/vocab/curr1/s-vaktaal',
|
||||
'http://ilearn.ilabt.imec.be/vocab/curr1/s-digitale-media-en-toepassingen',
|
||||
'http://ilearn.ilabt.imec.be/vocab/curr1/s-computers-en-systemen',
|
||||
],
|
||||
attachments: [
|
||||
{
|
||||
name: 'dwengo.png',
|
||||
mimeType: 'image/png',
|
||||
content: loadTestAsset('/content/learning-object-resources/pn_werkingnotebooks/dwengo.png'),
|
||||
},
|
||||
{
|
||||
name: 'Knop.png',
|
||||
mimeType: 'image/png',
|
||||
content: loadTestAsset('/content/learning-object-resources/pn_werkingnotebooks/Knop.png'),
|
||||
},
|
||||
],
|
||||
available: false,
|
||||
content: loadTestAsset('/content/learning-object-resources/pn_werkingnotebooks/content.md'),
|
||||
returnValue: {
|
||||
callbackUrl: '%SUBMISSION%',
|
||||
callbackSchema: '[]',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,100 +1,236 @@
|
|||
import { Connection, EntityManager, IDatabaseDriver } from '@mikro-orm/core';
|
||||
import { EntityManager } from '@mikro-orm/core';
|
||||
import { LearningPath } from '../../../src/entities/content/learning-path.entity';
|
||||
import { Language } from '../../../src/entities/content/language';
|
||||
import { LearningPathTransition } from '../../../src/entities/content/learning-path-transition.entity';
|
||||
import { LearningPathNode } from '../../../src/entities/content/learning-path-node.entity';
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
import { mapToLearningPath } from '../../../src/services/learning-paths/learning-path-service';
|
||||
import { envVars, getEnvVar } from '../../../src/util/envVars';
|
||||
import { LearningPath as LearningPathDTO } from '@dwengo-1/common/interfaces/learning-content';
|
||||
import {
|
||||
testLearningObject01,
|
||||
testLearningObject02,
|
||||
testLearningObject03,
|
||||
testLearningObject04,
|
||||
testLearningObject05,
|
||||
testLearningObjectEssayQuestion,
|
||||
testLearningObjectMultipleChoice,
|
||||
testLearningObjectPnNotebooks,
|
||||
} from './learning-objects.testdata';
|
||||
|
||||
export function makeTestLearningPaths(em: EntityManager<IDatabaseDriver<Connection>>): Array<LearningPath> {
|
||||
const learningPathNode01: LearningPathNode = new LearningPathNode();
|
||||
const learningPathNode02: LearningPathNode = new LearningPathNode();
|
||||
const learningPathNode03: LearningPathNode = new LearningPathNode();
|
||||
const learningPathNode04: LearningPathNode = new LearningPathNode();
|
||||
const learningPathNode05: LearningPathNode = new LearningPathNode();
|
||||
export function makeTestLearningPaths(_em: EntityManager): LearningPath[] {
|
||||
const learningPath01 = mapToLearningPath(testLearningPath01, []);
|
||||
const learningPath02 = mapToLearningPath(testLearningPath02, []);
|
||||
|
||||
const transitions01: LearningPathTransition = new LearningPathTransition();
|
||||
const transitions02: LearningPathTransition = new LearningPathTransition();
|
||||
const transitions03: LearningPathTransition = new LearningPathTransition();
|
||||
const transitions04: LearningPathTransition = new LearningPathTransition();
|
||||
const transitions05: LearningPathTransition = new LearningPathTransition();
|
||||
const partiallyDatabasePartiallyDwengoApiLearningPath = mapToLearningPath(testPartiallyDatabaseAndPartiallyDwengoApiLearningPath, []);
|
||||
const learningPathWithConditions = mapToLearningPath(testLearningPathWithConditions, []);
|
||||
|
||||
transitions01.condition = 'true';
|
||||
transitions01.next = learningPathNode02;
|
||||
|
||||
transitions02.condition = 'true';
|
||||
transitions02.next = learningPathNode02;
|
||||
|
||||
transitions03.condition = 'true';
|
||||
transitions03.next = learningPathNode04;
|
||||
|
||||
transitions04.condition = 'true';
|
||||
transitions04.next = learningPathNode05;
|
||||
|
||||
transitions05.condition = 'true';
|
||||
transitions05.next = learningPathNode05;
|
||||
|
||||
learningPathNode01.instruction = '';
|
||||
learningPathNode01.language = Language.English;
|
||||
learningPathNode01.learningObjectHruid = 'id01';
|
||||
learningPathNode01.startNode = true;
|
||||
learningPathNode01.transitions = [transitions01];
|
||||
learningPathNode01.version = 1;
|
||||
|
||||
learningPathNode02.instruction = '';
|
||||
learningPathNode02.language = Language.English;
|
||||
learningPathNode02.learningObjectHruid = 'id02';
|
||||
learningPathNode02.startNode = false;
|
||||
learningPathNode02.transitions = [transitions02];
|
||||
learningPathNode02.version = 1;
|
||||
|
||||
learningPathNode03.instruction = '';
|
||||
learningPathNode03.language = Language.English;
|
||||
learningPathNode03.learningObjectHruid = 'id03';
|
||||
learningPathNode03.startNode = true;
|
||||
learningPathNode03.transitions = [transitions03];
|
||||
learningPathNode03.version = 1;
|
||||
|
||||
learningPathNode04.instruction = '';
|
||||
learningPathNode04.language = Language.English;
|
||||
learningPathNode04.learningObjectHruid = 'id04';
|
||||
learningPathNode04.startNode = false;
|
||||
learningPathNode04.transitions = [transitions04];
|
||||
learningPathNode04.version = 1;
|
||||
|
||||
learningPathNode05.instruction = '';
|
||||
learningPathNode05.language = Language.English;
|
||||
learningPathNode05.learningObjectHruid = 'id05';
|
||||
learningPathNode05.startNode = false;
|
||||
learningPathNode05.transitions = [transitions05];
|
||||
learningPathNode05.version = 1;
|
||||
|
||||
const nodes01: Array<LearningPathNode> = [
|
||||
// LearningPathNode01,
|
||||
// LearningPathNode02,
|
||||
];
|
||||
const learningPath01 = em.create(LearningPath, {
|
||||
hruid: 'id01',
|
||||
language: Language.English,
|
||||
admins: [],
|
||||
title: 'repertoire Tool',
|
||||
description: 'all about Tool',
|
||||
image: null,
|
||||
nodes: nodes01,
|
||||
});
|
||||
|
||||
const nodes02: Array<LearningPathNode> = [
|
||||
// LearningPathNode03,
|
||||
// LearningPathNode04,
|
||||
// LearningPathNode05,
|
||||
];
|
||||
const learningPath02 = em.create(LearningPath, {
|
||||
hruid: 'id02',
|
||||
language: Language.English,
|
||||
admins: [],
|
||||
title: 'repertoire Dire Straits',
|
||||
description: 'all about Dire Straits',
|
||||
image: null,
|
||||
nodes: nodes02,
|
||||
});
|
||||
|
||||
return [learningPath01, learningPath02];
|
||||
return [learningPath01, learningPath02, partiallyDatabasePartiallyDwengoApiLearningPath, learningPathWithConditions];
|
||||
}
|
||||
|
||||
const nowString = new Date().toString();
|
||||
|
||||
export const testLearningPath01: LearningPathDTO = {
|
||||
keywords: 'test',
|
||||
target_ages: [16, 17, 18],
|
||||
hruid: `${getEnvVar(envVars.UserContentPrefix)}id01`,
|
||||
language: Language.English,
|
||||
title: 'repertoire Tool',
|
||||
description: 'all about Tool',
|
||||
nodes: [
|
||||
{
|
||||
learningobject_hruid: testLearningObject01.hruid,
|
||||
language: testLearningObject01.language,
|
||||
version: testLearningObject01.version,
|
||||
start_node: true,
|
||||
created_at: nowString,
|
||||
updatedAt: nowString,
|
||||
transitions: [
|
||||
{
|
||||
next: {
|
||||
hruid: testLearningObject02.hruid,
|
||||
language: testLearningObject02.language,
|
||||
version: testLearningObject02.version,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
learningobject_hruid: testLearningObject02.hruid,
|
||||
language: testLearningObject02.language,
|
||||
version: testLearningObject02.version,
|
||||
created_at: nowString,
|
||||
updatedAt: nowString,
|
||||
transitions: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const testLearningPath02: LearningPathDTO = {
|
||||
keywords: 'test',
|
||||
target_ages: [16, 17, 18],
|
||||
hruid: `${getEnvVar(envVars.UserContentPrefix)}id02`,
|
||||
language: Language.English,
|
||||
title: 'repertoire Dire Straits',
|
||||
description: 'all about Dire Straits',
|
||||
nodes: [
|
||||
{
|
||||
learningobject_hruid: testLearningObject03.hruid,
|
||||
language: testLearningObject03.language,
|
||||
version: testLearningObject03.version,
|
||||
start_node: true,
|
||||
created_at: nowString,
|
||||
updatedAt: nowString,
|
||||
transitions: [
|
||||
{
|
||||
next: {
|
||||
hruid: testLearningObject04.hruid,
|
||||
language: testLearningObject04.language,
|
||||
version: testLearningObject04.version,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
learningobject_hruid: testLearningObject04.hruid,
|
||||
language: testLearningObject04.language,
|
||||
version: testLearningObject04.version,
|
||||
created_at: nowString,
|
||||
updatedAt: nowString,
|
||||
transitions: [
|
||||
{
|
||||
next: {
|
||||
hruid: testLearningObject05.hruid,
|
||||
language: testLearningObject05.language,
|
||||
version: testLearningObject05.version,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
learningobject_hruid: testLearningObject05.hruid,
|
||||
language: testLearningObject05.language,
|
||||
version: testLearningObject05.version,
|
||||
created_at: nowString,
|
||||
updatedAt: nowString,
|
||||
transitions: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const testPartiallyDatabaseAndPartiallyDwengoApiLearningPath: LearningPathDTO = {
|
||||
hruid: `${getEnvVar(envVars.UserContentPrefix)}pn_werking`,
|
||||
title: 'Werken met notebooks',
|
||||
language: Language.Dutch,
|
||||
description: 'Een korte inleiding tot Python notebooks. Hoe ga je gemakkelijk en efficiënt met de notebooks aan de slag?',
|
||||
keywords: 'Python KIKS Wiskunde STEM AI',
|
||||
target_ages: [14, 15, 16, 17, 18],
|
||||
nodes: [
|
||||
{
|
||||
learningobject_hruid: testLearningObjectPnNotebooks.hruid,
|
||||
language: testLearningObjectPnNotebooks.language,
|
||||
version: testLearningObjectPnNotebooks.version,
|
||||
start_node: true,
|
||||
created_at: nowString,
|
||||
updatedAt: nowString,
|
||||
transitions: [
|
||||
{
|
||||
default: true,
|
||||
next: {
|
||||
hruid: 'pn_werkingnotebooks2',
|
||||
language: Language.Dutch,
|
||||
version: 3,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
learningobject_hruid: 'pn_werkingnotebooks2',
|
||||
language: Language.Dutch,
|
||||
version: 3,
|
||||
created_at: nowString,
|
||||
updatedAt: nowString,
|
||||
transitions: [
|
||||
{
|
||||
default: true,
|
||||
next: {
|
||||
hruid: 'pn_werkingnotebooks3',
|
||||
language: Language.Dutch,
|
||||
version: 3,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
learningobject_hruid: 'pn_werkingnotebooks3',
|
||||
language: Language.Dutch,
|
||||
version: 3,
|
||||
created_at: nowString,
|
||||
updatedAt: nowString,
|
||||
transitions: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const testLearningPathWithConditions: LearningPathDTO = {
|
||||
hruid: `${getEnvVar(envVars.UserContentPrefix)}test_conditions`,
|
||||
language: Language.English,
|
||||
title: 'Example learning path with conditional transitions',
|
||||
description: 'This learning path was made for the purpose of testing conditional transitions',
|
||||
keywords: 'test',
|
||||
target_ages: [10, 11, 12, 13, 14, 15, 16, 17, 18],
|
||||
nodes: [
|
||||
{
|
||||
learningobject_hruid: testLearningObjectMultipleChoice.hruid,
|
||||
language: testLearningObjectMultipleChoice.language,
|
||||
version: testLearningObjectMultipleChoice.version,
|
||||
start_node: true,
|
||||
created_at: nowString,
|
||||
updatedAt: nowString,
|
||||
transitions: [
|
||||
{
|
||||
// If the answer to the first question was the first one (It's difficult to follow along):
|
||||
condition: '$[?(@[0] == 0)]',
|
||||
next: {
|
||||
//... we let the student do an extra exercise.
|
||||
hruid: testLearningObject01.hruid,
|
||||
language: testLearningObject01.language,
|
||||
version: testLearningObject01.version,
|
||||
},
|
||||
},
|
||||
{
|
||||
// If the answer to the first question was the second one (I can follow along):
|
||||
condition: '$[?(@[0] == 1)]',
|
||||
next: {
|
||||
//... we let the student right through to the final question.
|
||||
hruid: testLearningObjectEssayQuestion.hruid,
|
||||
language: testLearningObjectEssayQuestion.language,
|
||||
version: testLearningObjectEssayQuestion.version,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
learningobject_hruid: testLearningObject01.hruid,
|
||||
language: testLearningObject01.language,
|
||||
version: testLearningObject01.version,
|
||||
created_at: nowString,
|
||||
updatedAt: nowString,
|
||||
transitions: [
|
||||
{
|
||||
default: true,
|
||||
next: {
|
||||
hruid: testLearningObjectEssayQuestion.hruid,
|
||||
language: testLearningObjectEssayQuestion.language,
|
||||
version: testLearningObjectEssayQuestion.version,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
learningobject_hruid: testLearningObjectEssayQuestion.hruid,
|
||||
language: testLearningObjectEssayQuestion.language,
|
||||
version: testLearningObjectEssayQuestion.version,
|
||||
created_at: nowString,
|
||||
updatedAt: nowString,
|
||||
transitions: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { Connection, EntityManager, IDatabaseDriver } from '@mikro-orm/core';
|
||||
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';
|
||||
|
||||
export function makeTestAnswers(em: EntityManager<IDatabaseDriver<Connection>>, teachers: Array<Teacher>, questions: Array<Question>): Array<Answer> {
|
||||
export function makeTestAnswers(em: EntityManager, teachers: Teacher[], questions: Question[]): Answer[] {
|
||||
const answer01 = em.create(Answer, {
|
||||
author: teachers[0],
|
||||
toQuestion: questions[1],
|
||||
|
@ -28,5 +30,21 @@ export function makeTestAnswers(em: EntityManager<IDatabaseDriver<Connection>>,
|
|||
content: 'answer3',
|
||||
});
|
||||
|
||||
return [answer01, answer02, answer03];
|
||||
const answer04 = em.create(Answer, {
|
||||
author: getTestleerkracht1(),
|
||||
toQuestion: getQuestion07(),
|
||||
sequenceNumber: 1,
|
||||
timestamp: new Date(),
|
||||
content: 'this is a test answer',
|
||||
});
|
||||
|
||||
const answer05 = em.create(Answer, {
|
||||
author: getTestleerkracht1(),
|
||||
toQuestion: getQuestion07(),
|
||||
sequenceNumber: 2,
|
||||
timestamp: new Date(),
|
||||
content: 'this is a test answer',
|
||||
});
|
||||
|
||||
return [answer01, answer02, answer03, answer04, answer05];
|
||||
}
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
import { Connection, EntityManager, IDatabaseDriver } from '@mikro-orm/core';
|
||||
import { EntityManager } from '@mikro-orm/core';
|
||||
import { Question } from '../../../src/entities/questions/question.entity';
|
||||
import { Language } from '../../../src/entities/content/language';
|
||||
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';
|
||||
|
||||
export function makeTestQuestions(em: EntityManager<IDatabaseDriver<Connection>>, students: Array<Student>): Array<Question> {
|
||||
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'
|
||||
sequenceNumber: 1,
|
||||
author: students[0],
|
||||
timestamp: new Date(),
|
||||
|
@ -18,6 +23,7 @@ export function makeTestQuestions(em: EntityManager<IDatabaseDriver<Connection>>
|
|||
learningObjectLanguage: Language.English,
|
||||
learningObjectVersion: 1,
|
||||
learningObjectHruid: 'id05',
|
||||
inGroup: groups[0], // Group #1 for Assignment #1 in class 'id01'
|
||||
sequenceNumber: 2,
|
||||
author: students[2],
|
||||
timestamp: new Date(),
|
||||
|
@ -30,6 +36,7 @@ export function makeTestQuestions(em: EntityManager<IDatabaseDriver<Connection>>
|
|||
learningObjectHruid: 'id04',
|
||||
sequenceNumber: 1,
|
||||
author: students[0],
|
||||
inGroup: groups[0], // Group #1 for Assignment #1 in class 'id01'
|
||||
timestamp: new Date(),
|
||||
content: 'question',
|
||||
});
|
||||
|
@ -40,9 +47,65 @@ export function makeTestQuestions(em: EntityManager<IDatabaseDriver<Connection>>
|
|||
learningObjectHruid: 'id01',
|
||||
sequenceNumber: 1,
|
||||
author: students[1],
|
||||
inGroup: groups[1], // Group #2 for Assignment #1 in class 'id01'
|
||||
timestamp: new Date(),
|
||||
content: 'question',
|
||||
});
|
||||
|
||||
return [question01, question02, question03, question04];
|
||||
const question05 = em.create(Question, {
|
||||
learningObjectLanguage: Language.English,
|
||||
learningObjectVersion: 1,
|
||||
learningObjectHruid: 'id05',
|
||||
sequenceNumber: 3,
|
||||
author: students[1],
|
||||
inGroup: groups[1], // 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',
|
||||
sequenceNumber: 4,
|
||||
author: students[2],
|
||||
inGroup: groups[5], // Group #4 for Assignment #2 in class 'id02'
|
||||
timestamp: new Date(),
|
||||
content: 'question',
|
||||
});
|
||||
|
||||
question07 = em.create(Question, {
|
||||
learningObjectLanguage: Language.English,
|
||||
learningObjectVersion: 1,
|
||||
learningObjectHruid: testLearningObjectMultipleChoice.hruid,
|
||||
sequenceNumber: 1,
|
||||
author: getTestleerling1(),
|
||||
inGroup: getGroup1ConditionalLearningPath(),
|
||||
timestamp: new Date(),
|
||||
content: 'this is a test question',
|
||||
});
|
||||
|
||||
question08 = em.create(Question, {
|
||||
learningObjectLanguage: Language.English,
|
||||
learningObjectVersion: 1,
|
||||
learningObjectHruid: testLearningObjectMultipleChoice.hruid,
|
||||
sequenceNumber: 2,
|
||||
author: getTestleerling1(),
|
||||
inGroup: getGroup1ConditionalLearningPath(),
|
||||
timestamp: new Date(),
|
||||
content: 'this is a second test question',
|
||||
});
|
||||
|
||||
return [question01, question02, question03, question04, question05, question06, question07, question08];
|
||||
}
|
||||
|
||||
let question08: Question;
|
||||
let question07: Question;
|
||||
|
||||
export function getQuestion07(): Question {
|
||||
return question07;
|
||||
}
|
||||
|
||||
export function getQuestion08(): Question {
|
||||
return question08;
|
||||
}
|
||||
|
|
|
@ -1,49 +1,28 @@
|
|||
import { Connection, EntityManager, IDatabaseDriver } from '@mikro-orm/core';
|
||||
import { EntityManager } from '@mikro-orm/core';
|
||||
import { Student } from '../../../src/entities/users/student.entity';
|
||||
|
||||
export function makeTestStudents(em: EntityManager<IDatabaseDriver<Connection>>): Array<Student> {
|
||||
const student01 = em.create(Student, {
|
||||
username: 'Noordkaap',
|
||||
firstName: 'Stijn',
|
||||
lastName: 'Meuris',
|
||||
});
|
||||
// 🔓 Ruwe testdata array — herbruikbaar in assertions
|
||||
export const TEST_STUDENTS = [
|
||||
{ username: 'Noordkaap', firstName: 'Stijn', lastName: 'Meuris' },
|
||||
{ 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' },
|
||||
];
|
||||
|
||||
const student02 = em.create(Student, {
|
||||
username: 'DireStraits',
|
||||
firstName: 'Mark',
|
||||
lastName: 'Knopfler',
|
||||
});
|
||||
let testStudents: Student[];
|
||||
|
||||
const student03 = em.create(Student, {
|
||||
username: 'Tool',
|
||||
firstName: 'Maynard',
|
||||
lastName: 'Keenan',
|
||||
});
|
||||
|
||||
const student04 = em.create(Student, {
|
||||
username: 'SmashingPumpkins',
|
||||
firstName: 'Billy',
|
||||
lastName: 'Corgan',
|
||||
});
|
||||
|
||||
const student05 = em.create(Student, {
|
||||
username: 'PinkFloyd',
|
||||
firstName: 'David',
|
||||
lastName: 'Gilmoure',
|
||||
});
|
||||
|
||||
const student06 = em.create(Student, {
|
||||
username: 'TheDoors',
|
||||
firstName: 'Jim',
|
||||
lastName: 'Morisson',
|
||||
});
|
||||
|
||||
// Do not use for any tests, gets deleted in a unit test
|
||||
const student07 = em.create(Student, {
|
||||
username: 'Nirvana',
|
||||
firstName: 'Kurt',
|
||||
lastName: 'Cobain',
|
||||
});
|
||||
|
||||
return [student01, student02, student03, student04, student05, student06, student07];
|
||||
// 🏗️ Functie die ORM entities maakt uit de data array
|
||||
export function makeTestStudents(em: EntityManager): Student[] {
|
||||
testStudents = TEST_STUDENTS.map((data) => em.create(Student, data));
|
||||
return testStudents;
|
||||
}
|
||||
|
||||
export function getTestleerling1(): Student {
|
||||
return testStudents.find((it) => it.username === 'testleerling1');
|
||||
}
|
||||
|
|
|
@ -1,31 +1,64 @@
|
|||
import { Teacher } from '../../../src/entities/users/teacher.entity';
|
||||
import { Connection, EntityManager, IDatabaseDriver } from '@mikro-orm/core';
|
||||
import { EntityManager } from '@mikro-orm/core';
|
||||
|
||||
export function makeTestTeachers(em: EntityManager<IDatabaseDriver<Connection>>): Array<Teacher> {
|
||||
const teacher01 = em.create(Teacher, {
|
||||
export function makeTestTeachers(em: EntityManager): Teacher[] {
|
||||
teacher01 = em.create(Teacher, {
|
||||
username: 'FooFighters',
|
||||
firstName: 'Dave',
|
||||
lastName: 'Grohl',
|
||||
});
|
||||
|
||||
const teacher02 = em.create(Teacher, {
|
||||
teacher02 = em.create(Teacher, {
|
||||
username: 'LimpBizkit',
|
||||
firstName: 'Fred',
|
||||
lastName: 'Durst',
|
||||
});
|
||||
|
||||
const teacher03 = em.create(Teacher, {
|
||||
teacher03 = em.create(Teacher, {
|
||||
username: 'Staind',
|
||||
firstName: 'Aaron',
|
||||
lastName: 'Lewis',
|
||||
});
|
||||
|
||||
// Should not be used, gets deleted in a unit test
|
||||
const teacher04 = em.create(Teacher, {
|
||||
teacher04 = em.create(Teacher, {
|
||||
username: 'ZesdeMetaal',
|
||||
firstName: 'Wannes',
|
||||
lastName: 'Cappelle',
|
||||
});
|
||||
|
||||
return [teacher01, teacher02, teacher03, teacher04];
|
||||
// Makes sure when logged in as testleerkracht1, there exists a corresponding user
|
||||
testleerkracht1 = em.create(Teacher, {
|
||||
username: 'testleerkracht1',
|
||||
firstName: 'David',
|
||||
lastName: 'Bowie',
|
||||
});
|
||||
|
||||
return [teacher01, teacher02, teacher03, teacher04, testleerkracht1];
|
||||
}
|
||||
|
||||
let teacher01: Teacher;
|
||||
let teacher02: Teacher;
|
||||
let teacher03: Teacher;
|
||||
let teacher04: Teacher;
|
||||
let testleerkracht1: Teacher;
|
||||
|
||||
export function getTeacher01(): Teacher {
|
||||
return teacher01;
|
||||
}
|
||||
|
||||
export function getTeacher02(): Teacher {
|
||||
return teacher02;
|
||||
}
|
||||
|
||||
export function getTeacher03(): Teacher {
|
||||
return teacher03;
|
||||
}
|
||||
|
||||
export function getTeacher04(): Teacher {
|
||||
return teacher04;
|
||||
}
|
||||
|
||||
export function getTestleerkracht1(): Teacher {
|
||||
return testleerkracht1;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue