fix(backend): Testen DatabaseLearningPathProvider en LearningPathService gerepareerd na refactoring.
This commit is contained in:
parent
1815371a7b
commit
c624e36680
6 changed files with 163 additions and 204 deletions
|
@ -2,167 +2,84 @@ import { beforeAll, describe, expect, it } from 'vitest';
|
||||||
import { LearningObject } from '../../../src/entities/content/learning-object.entity.js';
|
import { LearningObject } from '../../../src/entities/content/learning-object.entity.js';
|
||||||
import { setupTestApp } from '../../setup-tests.js';
|
import { setupTestApp } from '../../setup-tests.js';
|
||||||
import { LearningPath } from '../../../src/entities/content/learning-path.entity.js';
|
import { LearningPath } from '../../../src/entities/content/learning-path.entity.js';
|
||||||
import {
|
import { getSubmissionRepository } from '../../../src/data/repositories.js';
|
||||||
getAssignmentRepository,
|
|
||||||
getClassRepository,
|
|
||||||
getGroupRepository,
|
|
||||||
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 databaseLearningPathProvider from '../../../src/services/learning-paths/database-learning-path-provider.js';
|
import databaseLearningPathProvider from '../../../src/services/learning-paths/database-learning-path-provider.js';
|
||||||
import { expectToBeCorrectLearningPath } from '../../test-utils/expectations.js';
|
import { expectToBeCorrectLearningPath } from '../../test-utils/expectations.js';
|
||||||
import learningObjectService from '../../../src/services/learning-objects/learning-object-service.js';
|
import learningObjectService from '../../../src/services/learning-objects/learning-object-service.js';
|
||||||
import { Language } from '@dwengo-1/common/util/language';
|
import { Language } from '@dwengo-1/common/util/language';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ConditionTestLearningPathAndLearningObjects,
|
LearningObjectNode,
|
||||||
createConditionTestLearningPathAndLearningObjects,
|
LearningPathResponse
|
||||||
} from '../../test-assets/learning-paths/test-conditions-example.js';
|
} from '@dwengo-1/common/interfaces/learning-content';
|
||||||
import { Student } from '../../../src/entities/users/student.entity.js';
|
import {
|
||||||
|
testLearningObject01, testLearningObjectEssayQuestion,
|
||||||
import { LearningObjectNode, LearningPathResponse } from '@dwengo-1/common/interfaces/learning-content';
|
testLearningObjectMultipleChoice
|
||||||
|
} from "../../test_assets/content/learning-objects.testdata";
|
||||||
const STUDENT_A_USERNAME = 'student_a';
|
import {testLearningPathWithConditions} from "../../test_assets/content/learning-paths.testdata";
|
||||||
const STUDENT_B_USERNAME = 'student_b';
|
import {mapToLearningPath} from "../../../src/services/learning-paths/learning-path-service";
|
||||||
const CLASS_NAME = 'test_class';
|
import {getTestGroup01, getTestGroup02} from "../../test_assets/assignments/groups.testdata";
|
||||||
|
import { Group } from '../../../src/entities/assignments/group.entity.js';
|
||||||
async function initExampleData(): Promise<{ learningObject: LearningObject; learningPath: LearningPath }> {
|
import {RequiredEntityData} from "@mikro-orm/core";
|
||||||
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 classRepo = getClassRepository();
|
|
||||||
const assignmentRepo = getAssignmentRepository();
|
|
||||||
const groupRepo = getGroupRepository();
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Create students
|
|
||||||
const studentA = studentRepo.create({
|
|
||||||
username: STUDENT_A_USERNAME,
|
|
||||||
firstName: 'Aron',
|
|
||||||
lastName: 'Student',
|
|
||||||
});
|
|
||||||
await studentRepo.save(studentA);
|
|
||||||
|
|
||||||
const studentB = studentRepo.create({
|
|
||||||
username: STUDENT_B_USERNAME,
|
|
||||||
firstName: 'Bill',
|
|
||||||
lastName: 'Student',
|
|
||||||
});
|
|
||||||
await studentRepo.save(studentB);
|
|
||||||
|
|
||||||
// Create class for students
|
|
||||||
const testClass = classRepo.create({
|
|
||||||
classId: CLASS_NAME,
|
|
||||||
displayName: 'Test class',
|
|
||||||
});
|
|
||||||
await classRepo.save(testClass);
|
|
||||||
|
|
||||||
// Create assignment for students and assign them to different groups
|
|
||||||
const assignment = assignmentRepo.create({
|
|
||||||
id: 0,
|
|
||||||
title: 'Test assignment',
|
|
||||||
description: 'Test description',
|
|
||||||
learningPathHruid: learningContent.learningPath.hruid,
|
|
||||||
learningPathLanguage: learningContent.learningPath.language,
|
|
||||||
within: testClass,
|
|
||||||
});
|
|
||||||
|
|
||||||
const groupA = groupRepo.create({
|
|
||||||
groupNumber: 0,
|
|
||||||
members: [studentA],
|
|
||||||
assignment,
|
|
||||||
});
|
|
||||||
await groupRepo.save(groupA);
|
|
||||||
|
|
||||||
const groupB = groupRepo.create({
|
|
||||||
groupNumber: 1,
|
|
||||||
members: [studentB],
|
|
||||||
assignment,
|
|
||||||
});
|
|
||||||
await groupRepo.save(groupB);
|
|
||||||
|
|
||||||
// Let each of the students make a submission in his own group.
|
|
||||||
const submissionA = submissionRepo.create({
|
|
||||||
learningObjectHruid: learningContent.branchingObject.hruid,
|
|
||||||
learningObjectLanguage: learningContent.branchingObject.language,
|
|
||||||
learningObjectVersion: learningContent.branchingObject.version,
|
|
||||||
onBehalfOf: groupA,
|
|
||||||
submitter: studentA,
|
|
||||||
submissionTime: new Date(),
|
|
||||||
content: '[0]',
|
|
||||||
});
|
|
||||||
await submissionRepo.save(submissionA);
|
|
||||||
|
|
||||||
const submissionB = submissionRepo.create({
|
|
||||||
learningObjectHruid: learningContent.branchingObject.hruid,
|
|
||||||
learningObjectLanguage: learningContent.branchingObject.language,
|
|
||||||
learningObjectVersion: learningContent.branchingObject.version,
|
|
||||||
onBehalfOf: groupA,
|
|
||||||
submitter: studentB,
|
|
||||||
submissionTime: new Date(),
|
|
||||||
content: '[1]',
|
|
||||||
});
|
|
||||||
await submissionRepo.save(submissionB);
|
|
||||||
|
|
||||||
return {
|
|
||||||
learningContent: learningContent,
|
|
||||||
studentA: studentA,
|
|
||||||
studentB: studentB,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function expectBranchingObjectNode(
|
function expectBranchingObjectNode(
|
||||||
result: LearningPathResponse,
|
result: LearningPathResponse
|
||||||
persTestData: {
|
|
||||||
learningContent: ConditionTestLearningPathAndLearningObjects;
|
|
||||||
studentA: Student;
|
|
||||||
studentB: Student;
|
|
||||||
}
|
|
||||||
): LearningObjectNode {
|
): LearningObjectNode {
|
||||||
const branchingObjectMatches = result.data![0].nodes.filter(
|
const branchingObjectMatches = result.data![0].nodes.filter(
|
||||||
(it) => it.learningobject_hruid === persTestData.learningContent.branchingObject.hruid
|
(it) => it.learningobject_hruid === testLearningObjectMultipleChoice.hruid
|
||||||
);
|
);
|
||||||
expect(branchingObjectMatches.length).toBe(1);
|
expect(branchingObjectMatches.length).toBe(1);
|
||||||
return branchingObjectMatches[0];
|
return branchingObjectMatches[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('DatabaseLearningPathProvider', () => {
|
describe('DatabaseLearningPathProvider', () => {
|
||||||
let example: { learningObject: LearningObject; learningPath: LearningPath };
|
let testLearningPath: LearningPath;
|
||||||
let persTestData: { learningContent: ConditionTestLearningPathAndLearningObjects; studentA: Student; studentB: Student };
|
let branchingLearningObject: RequiredEntityData<LearningObject>;
|
||||||
|
let extraExerciseLearningObject: RequiredEntityData<LearningObject>;
|
||||||
|
let finalLearningObject: RequiredEntityData<LearningObject>;
|
||||||
|
let groupA: Group;
|
||||||
|
let groupB: Group;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await setupTestApp();
|
await setupTestApp();
|
||||||
example = await initExampleData();
|
testLearningPath = mapToLearningPath(testLearningPathWithConditions, []);
|
||||||
persTestData = await initPersonalizationTestData();
|
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', () => {
|
describe('fetchLearningPaths', () => {
|
||||||
it('returns the learning path correctly', async () => {
|
it('returns the learning path correctly', async () => {
|
||||||
const result = await databaseLearningPathProvider.fetchLearningPaths(
|
const result = await databaseLearningPathProvider.fetchLearningPaths(
|
||||||
[example.learningPath.hruid],
|
[testLearningPath.hruid],
|
||||||
example.learningPath.language,
|
testLearningPath.language as Language,
|
||||||
'the source'
|
'the source'
|
||||||
);
|
);
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
|
@ -170,7 +87,7 @@ describe('DatabaseLearningPathProvider', () => {
|
||||||
|
|
||||||
const learningObjectsOnPath = (
|
const learningObjectsOnPath = (
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
example.learningPath.nodes.map(async (node) =>
|
testLearningPath.nodes.map(async (node) =>
|
||||||
learningObjectService.getLearningObjectById({
|
learningObjectService.getLearningObjectById({
|
||||||
hruid: node.learningObjectHruid,
|
hruid: node.learningObjectHruid,
|
||||||
version: node.version,
|
version: node.version,
|
||||||
|
@ -180,49 +97,65 @@ describe('DatabaseLearningPathProvider', () => {
|
||||||
)
|
)
|
||||||
).filter((it) => it !== null);
|
).filter((it) => it !== null);
|
||||||
|
|
||||||
expectToBeCorrectLearningPath(result.data![0], example.learningPath, learningObjectsOnPath);
|
expectToBeCorrectLearningPath(
|
||||||
|
result.data![0],
|
||||||
|
mapToLearningPath(testLearningPathWithConditions, []),
|
||||||
|
learningObjectsOnPath
|
||||||
|
);
|
||||||
});
|
});
|
||||||
it('returns the correct personalized learning path', async () => {
|
it('returns the correct personalized learning path', async () => {
|
||||||
// For student A:
|
// For student A:
|
||||||
let result = await databaseLearningPathProvider.fetchLearningPaths(
|
let result = await databaseLearningPathProvider.fetchLearningPaths(
|
||||||
[persTestData.learningContent.learningPath.hruid],
|
[testLearningPath.hruid],
|
||||||
persTestData.learningContent.learningPath.language,
|
testLearningPath.language,
|
||||||
'the source',
|
'the source',
|
||||||
{ type: 'student', student: persTestData.studentA }
|
groupA
|
||||||
);
|
);
|
||||||
expect(result.success).toBeTruthy();
|
expect(result.success).toBeTruthy();
|
||||||
expect(result.data?.length).toBe(1);
|
expect(result.data?.length).toBe(1);
|
||||||
|
|
||||||
// There should be exactly one branching object
|
// 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(
|
||||||
expect(branchingObject.transitions.filter((it) => it.next.hruid === persTestData.learningContent.extraExerciseObject.hruid).length).toBe(
|
branchingObject.transitions.filter(
|
||||||
1
|
it => it.next.hruid === finalLearningObject.hruid
|
||||||
); // There should however be a path to the extra exercise object.
|
).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:
|
// For student B:
|
||||||
result = await databaseLearningPathProvider.fetchLearningPaths(
|
result = await databaseLearningPathProvider.fetchLearningPaths(
|
||||||
[persTestData.learningContent.learningPath.hruid],
|
[testLearningPath.hruid],
|
||||||
persTestData.learningContent.learningPath.language,
|
testLearningPath.language,
|
||||||
'the source',
|
'the source',
|
||||||
{ type: 'student', student: persTestData.studentB }
|
groupB
|
||||||
);
|
);
|
||||||
expect(result.success).toBeTruthy();
|
expect(result.success).toBeTruthy();
|
||||||
expect(result.data?.length).toBe(1);
|
expect(result.data?.length).toBe(1);
|
||||||
|
|
||||||
// There should still be exactly one branching object
|
// There should still be exactly one branching object
|
||||||
branchingObject = expectBranchingObjectNode(result, persTestData);
|
branchingObject = expectBranchingObjectNode(result);
|
||||||
|
|
||||||
// However, now the student picks the other option.
|
// 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(
|
||||||
expect(branchingObject.transitions.filter((it) => it.next.hruid === persTestData.learningContent.extraExerciseObject.hruid).length).toBe(
|
branchingObject.transitions.filter(
|
||||||
0
|
(it) => it.next.hruid === finalLearningObject.hruid
|
||||||
); // There should not be a path anymore to the extra exercise object.
|
).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 () => {
|
it('returns a non-successful response if a non-existing learning path is queried', async () => {
|
||||||
const result = await databaseLearningPathProvider.fetchLearningPaths(
|
const result = await databaseLearningPathProvider.fetchLearningPaths(
|
||||||
[example.learningPath.hruid],
|
[testLearningPath.hruid],
|
||||||
Language.Abkhazian, // Wrong language
|
Language.Abkhazian, // Wrong language
|
||||||
'the source'
|
'the source'
|
||||||
);
|
);
|
||||||
|
@ -234,26 +167,26 @@ describe('DatabaseLearningPathProvider', () => {
|
||||||
describe('searchLearningPaths', () => {
|
describe('searchLearningPaths', () => {
|
||||||
it('returns the correct learning path when queried with a substring of its title', async () => {
|
it('returns the correct learning path when queried with a substring of its title', async () => {
|
||||||
const result = await databaseLearningPathProvider.searchLearningPaths(
|
const result = await databaseLearningPathProvider.searchLearningPaths(
|
||||||
example.learningPath.title.substring(2, 6),
|
testLearningPath.title.substring(2, 6),
|
||||||
example.learningPath.language
|
testLearningPath.language
|
||||||
);
|
);
|
||||||
expect(result.length).toBe(1);
|
expect(result.length).toBe(1);
|
||||||
expect(result[0].title).toBe(example.learningPath.title);
|
expect(result[0].title).toBe(testLearningPath.title);
|
||||||
expect(result[0].description).toBe(example.learningPath.description);
|
expect(result[0].description).toBe(testLearningPath.description);
|
||||||
});
|
});
|
||||||
it('returns the correct learning path when queried with a substring of the description', async () => {
|
it('returns the correct learning path when queried with a substring of the description', async () => {
|
||||||
const result = await databaseLearningPathProvider.searchLearningPaths(
|
const result = await databaseLearningPathProvider.searchLearningPaths(
|
||||||
example.learningPath.description.substring(5, 12),
|
testLearningPath.description.substring(5, 12),
|
||||||
example.learningPath.language
|
testLearningPath.language
|
||||||
);
|
);
|
||||||
expect(result.length).toBe(1);
|
expect(result.length).toBe(1);
|
||||||
expect(result[0].title).toBe(example.learningPath.title);
|
expect(result[0].title).toBe(testLearningPath.title);
|
||||||
expect(result[0].description).toBe(example.learningPath.description);
|
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 () => {
|
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(
|
const result = await databaseLearningPathProvider.searchLearningPaths(
|
||||||
'substring which does not occur in the title or the description of a learning object',
|
'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);
|
expect(result.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,22 +1,11 @@
|
||||||
import { beforeAll, describe, expect, it } from 'vitest';
|
import { beforeAll, describe, expect, it } from 'vitest';
|
||||||
import { setupTestApp } from '../../setup-tests';
|
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 learningPathService from '../../../src/services/learning-paths/learning-path-service';
|
import learningPathService from '../../../src/services/learning-paths/learning-path-service';
|
||||||
import { Language } from '@dwengo-1/common/util/language';
|
import { Language } from '@dwengo-1/common/util/language';
|
||||||
|
import {
|
||||||
async function initExampleData(): Promise<{ learningObject: LearningObject; learningPath: LearningPath }> {
|
testPartiallyDatabaseAndPartiallyDwengoApiLearningPath
|
||||||
const learningObjectRepo = getLearningObjectRepository();
|
} from "../../test_assets/content/learning-paths.testdata";
|
||||||
const learningPathRepo = getLearningPathRepository();
|
import {LearningPath as LearningPathDTO} from "@dwengo-1/common/interfaces/learning-content";
|
||||||
const learningObject = learningObjectExample.createLearningObject();
|
|
||||||
const learningPath = learningPathExample.createLearningPath();
|
|
||||||
await learningObjectRepo.save(learningObject);
|
|
||||||
await learningPathRepo.save(learningPath);
|
|
||||||
return { learningObject, learningPath };
|
|
||||||
}
|
|
||||||
|
|
||||||
const TEST_DWENGO_LEARNING_PATH_HRUID = 'pn_werking';
|
const TEST_DWENGO_LEARNING_PATH_HRUID = 'pn_werking';
|
||||||
const TEST_DWENGO_LEARNING_PATH_TITLE = 'Werken met notebooks';
|
const TEST_DWENGO_LEARNING_PATH_TITLE = 'Werken met notebooks';
|
||||||
|
@ -24,42 +13,49 @@ const TEST_DWENGO_EXCLUSIVE_LEARNING_PATH_SEARCH_QUERY = 'Microscopie';
|
||||||
const TEST_SEARCH_QUERY_EXPECTING_NO_MATCHES = 'su$m8f9usf89ud<p9<U8SDP8UP9';
|
const TEST_SEARCH_QUERY_EXPECTING_NO_MATCHES = 'su$m8f9usf89ud<p9<U8SDP8UP9';
|
||||||
|
|
||||||
describe('LearningPathService', () => {
|
describe('LearningPathService', () => {
|
||||||
let example: { learningObject: LearningObject; learningPath: LearningPath };
|
let testLearningPath: LearningPathDTO;
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await setupTestApp();
|
await setupTestApp();
|
||||||
example = await initExampleData();
|
testLearningPath = testPartiallyDatabaseAndPartiallyDwengoApiLearningPath
|
||||||
});
|
});
|
||||||
describe('fetchLearningPaths', () => {
|
describe('fetchLearningPaths', () => {
|
||||||
it('should return learning paths both from the database and from the Dwengo API', async () => {
|
it('should return learning paths both from the database and from the Dwengo API', async () => {
|
||||||
const result = await learningPathService.fetchLearningPaths(
|
const result = await learningPathService.fetchLearningPaths(
|
||||||
[example.learningPath.hruid, TEST_DWENGO_LEARNING_PATH_HRUID],
|
[testLearningPath.hruid, TEST_DWENGO_LEARNING_PATH_HRUID],
|
||||||
example.learningPath.language,
|
testLearningPath.language as Language,
|
||||||
'the source'
|
'the source'
|
||||||
);
|
);
|
||||||
expect(result.success).toBeTruthy();
|
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 === 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 === 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 === TEST_DWENGO_LEARNING_PATH_HRUID)?.title).toEqual(TEST_DWENGO_LEARNING_PATH_TITLE);
|
||||||
expect(result.data?.find((it) => it.hruid === example.learningPath.hruid)?.title).toEqual(example.learningPath.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 () => {
|
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.success).toBeTruthy();
|
||||||
expect(result.data?.length).toBe(1);
|
expect(result.data?.length).toBe(1);
|
||||||
|
|
||||||
// Should include all the nodes, even those pointing to foreign learning objects.
|
// Should include all the nodes, even those pointing to foreign learning objects.
|
||||||
expect([...result.data![0].nodes.map((it) => it.learningobject_hruid)].sort((a, b) => a.localeCompare(b))).toEqual(
|
expect([...result.data![0].nodes.map((it) => it.learningobject_hruid)].sort((a, b) => a.localeCompare(b))).toEqual(
|
||||||
example.learningPath.nodes.map((it) => it.learningObjectHruid).sort((a, b) => a.localeCompare(b))
|
testLearningPath.nodes.map((it) => it.learningobject_hruid).sort((a, b) => a.localeCompare(b))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('searchLearningPath', () => {
|
describe('searchLearningPath', () => {
|
||||||
it('should include both the learning paths from the Dwengo API and those from the database in its response', async () => {
|
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.
|
// 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
|
// 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.
|
// But should not only find that one.
|
||||||
expect(result.length).not.toBeLessThan(2);
|
expect(result.length).not.toBeLessThan(2);
|
||||||
|
@ -71,7 +67,7 @@ describe('LearningPathService', () => {
|
||||||
expect(result.length).not.toBe(0);
|
expect(result.length).not.toBe(0);
|
||||||
|
|
||||||
// But not the example learning path.
|
// 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 () => {
|
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);
|
const result = await learningPathService.searchLearningPaths(TEST_SEARCH_QUERY_EXPECTING_NO_MATCHES, Language.Dutch);
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { makeTestAnswers } from './test_assets/questions/answers.testdata.js';
|
||||||
import { makeTestSubmissions } from './test_assets/assignments/submission.testdata.js';
|
import { makeTestSubmissions } from './test_assets/assignments/submission.testdata.js';
|
||||||
import {Collection} from "@mikro-orm/core";
|
import {Collection} from "@mikro-orm/core";
|
||||||
import {Group} from "../src/entities/assignments/group.entity";
|
import {Group} from "../src/entities/assignments/group.entity";
|
||||||
|
import {LearningObject} from "../src/entities/content/learning-object.entity";
|
||||||
|
|
||||||
export async function setupTestApp(): Promise<void> {
|
export async function setupTestApp(): Promise<void> {
|
||||||
dotenv.config({ path: '.env.test' });
|
dotenv.config({ path: '.env.test' });
|
||||||
|
@ -58,4 +59,6 @@ export async function setupTestApp(): Promise<void> {
|
||||||
...answers,
|
...answers,
|
||||||
...submissions,
|
...submissions,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
console.log(await em.findAll(LearningObject));
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,7 @@ export function expectToBeCorrectLearningPath(
|
||||||
const expectedNode = [...expectedLearningPathNodes.entries()].find(
|
const expectedNode = [...expectedLearningPathNodes.entries()].find(
|
||||||
([key, _]) => key.learningObjectHruid === nodeKey.learningObjectHruid && key.language === node.language && key.version === node.version
|
([key, _]) => key.learningObjectHruid === nodeKey.learningObjectHruid && key.language === node.language && key.version === node.version
|
||||||
)![1];
|
)![1];
|
||||||
expect(node.start_node).toEqual(expectedNode.startNode);
|
expect(Boolean(node.start_node)).toEqual(Boolean(expectedNode.startNode));
|
||||||
|
|
||||||
expect(new Set(node.transitions.map((it) => it.next.hruid))).toEqual(
|
expect(new Set(node.transitions.map((it) => it.next.hruid))).toEqual(
|
||||||
new Set(expectedNode.transitions.map((it) => it.next.learningObjectHruid))
|
new Set(expectedNode.transitions.map((it) => it.next.learningObjectHruid))
|
||||||
|
|
|
@ -8,7 +8,7 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen
|
||||||
* Group #1 for Assignment #1 in class 'id01'
|
* Group #1 for Assignment #1 in class 'id01'
|
||||||
* => Assigned to do learning path 'id02'
|
* => Assigned to do learning path 'id02'
|
||||||
*/
|
*/
|
||||||
const group01 = em.create(Group, {
|
group01 = em.create(Group, {
|
||||||
assignment: assignments[0],
|
assignment: assignments[0],
|
||||||
groupNumber: 1,
|
groupNumber: 1,
|
||||||
members: students.slice(0, 2),
|
members: students.slice(0, 2),
|
||||||
|
@ -18,7 +18,7 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen
|
||||||
* Group #2 for Assignment #1 in class 'id01'
|
* Group #2 for Assignment #1 in class 'id01'
|
||||||
* => Assigned to do learning path 'id02'
|
* => Assigned to do learning path 'id02'
|
||||||
*/
|
*/
|
||||||
const group02 = em.create(Group, {
|
group02 = em.create(Group, {
|
||||||
assignment: assignments[0],
|
assignment: assignments[0],
|
||||||
groupNumber: 2,
|
groupNumber: 2,
|
||||||
members: students.slice(2, 4),
|
members: students.slice(2, 4),
|
||||||
|
@ -28,7 +28,7 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen
|
||||||
* Group #3 for Assignment #1 in class 'id01'
|
* Group #3 for Assignment #1 in class 'id01'
|
||||||
* => Assigned to do learning path 'id02'
|
* => Assigned to do learning path 'id02'
|
||||||
*/
|
*/
|
||||||
const group03 = em.create(Group, {
|
group03 = em.create(Group, {
|
||||||
assignment: assignments[0],
|
assignment: assignments[0],
|
||||||
groupNumber: 3,
|
groupNumber: 3,
|
||||||
members: students.slice(4, 6),
|
members: students.slice(4, 6),
|
||||||
|
@ -38,7 +38,7 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen
|
||||||
* Group #4 for Assignment #2 in class 'id02'
|
* Group #4 for Assignment #2 in class 'id02'
|
||||||
* => Assigned to do learning path 'id01'
|
* => Assigned to do learning path 'id01'
|
||||||
*/
|
*/
|
||||||
const group04 = em.create(Group, {
|
group04 = em.create(Group, {
|
||||||
assignment: assignments[1],
|
assignment: assignments[1],
|
||||||
groupNumber: 4,
|
groupNumber: 4,
|
||||||
members: students.slice(3, 4),
|
members: students.slice(3, 4),
|
||||||
|
@ -48,7 +48,7 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen
|
||||||
* Group #5 for Assignment #4 in class 'id01'
|
* Group #5 for Assignment #4 in class 'id01'
|
||||||
* => Assigned to do learning path 'id01'
|
* => Assigned to do learning path 'id01'
|
||||||
*/
|
*/
|
||||||
const group05 = em.create(Group, {
|
group05 = em.create(Group, {
|
||||||
assignment: assignments[3],
|
assignment: assignments[3],
|
||||||
groupNumber: 1,
|
groupNumber: 1,
|
||||||
members: students.slice(0, 2),
|
members: students.slice(0, 2),
|
||||||
|
@ -56,3 +56,30 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen
|
||||||
|
|
||||||
return [group01, group02, group03, group04, group05];
|
return [group01, group02, group03, group04, group05];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let group01: Group;
|
||||||
|
let group02: Group;
|
||||||
|
let group03: Group;
|
||||||
|
let group04: Group;
|
||||||
|
let group05: Group;
|
||||||
|
|
||||||
|
export function getTestGroup01() {
|
||||||
|
return group01;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTestGroup02() {
|
||||||
|
return group02;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTestGroup03() {
|
||||||
|
return group03;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTestGroup04() {
|
||||||
|
return group04;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTestGroup05() {
|
||||||
|
return group05;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ export function createReturnValue(): ReturnValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const testLearningObject01: RequiredEntityData<LearningObject> = {
|
export const testLearningObject01: RequiredEntityData<LearningObject> = {
|
||||||
hruid: 'id01',
|
hruid: `${getEnvVar(envVars.UserContentPrefix)}id01`,
|
||||||
language: Language.English,
|
language: Language.English,
|
||||||
version: 1,
|
version: 1,
|
||||||
admins: [],
|
admins: [],
|
||||||
|
@ -61,7 +61,7 @@ export const testLearningObject01: RequiredEntityData<LearningObject> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const testLearningObject02: RequiredEntityData<LearningObject> = {
|
export const testLearningObject02: RequiredEntityData<LearningObject> = {
|
||||||
hruid: 'id02',
|
hruid: `${getEnvVar(envVars.UserContentPrefix)}id02`,
|
||||||
language: Language.English,
|
language: Language.English,
|
||||||
version: 1,
|
version: 1,
|
||||||
admins: [],
|
admins: [],
|
||||||
|
@ -85,7 +85,7 @@ export const testLearningObject02: RequiredEntityData<LearningObject> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const testLearningObject03: RequiredEntityData<LearningObject> = {
|
export const testLearningObject03: RequiredEntityData<LearningObject> = {
|
||||||
hruid: 'id03',
|
hruid: `${getEnvVar(envVars.UserContentPrefix)}id03`,
|
||||||
language: Language.English,
|
language: Language.English,
|
||||||
version: 1,
|
version: 1,
|
||||||
admins: [],
|
admins: [],
|
||||||
|
@ -112,7 +112,7 @@ export const testLearningObject03: RequiredEntityData<LearningObject> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const testLearningObject04: RequiredEntityData<LearningObject> = {
|
export const testLearningObject04: RequiredEntityData<LearningObject> = {
|
||||||
hruid: 'id04',
|
hruid: `${getEnvVar(envVars.UserContentPrefix)}id04`,
|
||||||
language: Language.English,
|
language: Language.English,
|
||||||
version: 1,
|
version: 1,
|
||||||
admins: [],
|
admins: [],
|
||||||
|
@ -139,7 +139,7 @@ export const testLearningObject04: RequiredEntityData<LearningObject> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const testLearningObject05: RequiredEntityData<LearningObject> = {
|
export const testLearningObject05: RequiredEntityData<LearningObject> = {
|
||||||
hruid: 'id05',
|
hruid: `${getEnvVar(envVars.UserContentPrefix)}id05`,
|
||||||
language: Language.English,
|
language: Language.English,
|
||||||
version: 1,
|
version: 1,
|
||||||
admins: [],
|
admins: [],
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue