fix(backend): Fouten in isTransitionPossible en het opzetten van de testdata verbeterd.
This commit is contained in:
parent
b539c28d8c
commit
fc46e79d05
10 changed files with 249 additions and 68 deletions
|
@ -15,8 +15,8 @@ export class Submission {
|
||||||
})
|
})
|
||||||
learningObjectLanguage!: Language;
|
learningObjectLanguage!: Language;
|
||||||
|
|
||||||
@PrimaryKey({ type: 'string' })
|
@PrimaryKey({ type: 'numeric' })
|
||||||
learningObjectVersion: string = '1';
|
learningObjectVersion: number = 1;
|
||||||
|
|
||||||
@PrimaryKey({ type: 'integer' })
|
@PrimaryKey({ type: 'integer' })
|
||||||
submissionNumber!: number;
|
submissionNumber!: number;
|
||||||
|
|
|
@ -47,7 +47,7 @@ export class LearningObject {
|
||||||
teacherExclusive: boolean = false;
|
teacherExclusive: boolean = false;
|
||||||
|
|
||||||
@Property({ type: 'array' })
|
@Property({ type: 'array' })
|
||||||
skosConcepts!: string[];
|
skosConcepts: string[] = [];
|
||||||
|
|
||||||
@Embedded({
|
@Embedded({
|
||||||
entity: () => EducationalGoal,
|
entity: () => EducationalGoal,
|
||||||
|
@ -64,8 +64,8 @@ export class LearningObject {
|
||||||
@Property({ type: 'smallint', nullable: true })
|
@Property({ type: 'smallint', nullable: true })
|
||||||
difficulty?: number;
|
difficulty?: number;
|
||||||
|
|
||||||
@Property({ type: 'integer' })
|
@Property({ type: 'integer', nullable: true })
|
||||||
estimatedTime!: number;
|
estimatedTime?: number;
|
||||||
|
|
||||||
@Embedded({
|
@Embedded({
|
||||||
entity: () => ReturnValue,
|
entity: () => ReturnValue,
|
||||||
|
|
|
@ -97,14 +97,26 @@ async function convertNodes(
|
||||||
learningobject_hruid: node.learningObjectHruid,
|
learningobject_hruid: node.learningObjectHruid,
|
||||||
version: learningObject.version,
|
version: learningObject.version,
|
||||||
transitions: node.transitions
|
transitions: node.transitions
|
||||||
.filter((trans) => !personalizedFor || isTransitionPossible(trans, lastSubmission)) // If we want a personalized learning path, remove all transitions that aren't possible.
|
.filter((trans) =>
|
||||||
.map((trans, i) => convertTransition(trans, i, nodesToLearningObjects)), // Then convert all the transition
|
!personalizedFor || isTransitionPossible(trans, optionalJsonStringToObject(lastSubmission?.content)) // If we want a personalized learning path, remove all transitions that aren't possible.
|
||||||
|
).map((trans, i) => convertTransition(trans, i, nodesToLearningObjects)), // Then convert all the transition
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.toArray();
|
.toArray();
|
||||||
return await Promise.all(nodesPromise);
|
return await Promise.all(nodesPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to convert a json string to an object, or null if it is undefined.
|
||||||
|
*/
|
||||||
|
function optionalJsonStringToObject(jsonString?: string): object | null {
|
||||||
|
if (!jsonString) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return JSON.parse(jsonString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function which converts a transition in the database representation to a transition in the representation
|
* Helper function which converts a transition in the database representation to a transition in the representation
|
||||||
* the Dwengo API uses.
|
* the Dwengo API uses.
|
||||||
|
|
|
@ -36,5 +36,6 @@ export function isTransitionPossible(transition: LearningPathTransition, submitt
|
||||||
if (submitted === null) {
|
if (submitted === null) {
|
||||||
return false; // If the transition is not unconditional and there was no submission, the transition is not possible.
|
return false; // If the transition is not unconditional and there was no submission, the transition is not possible.
|
||||||
}
|
}
|
||||||
return JSONPath({ path: transition.condition, json: submitted }).length === 0;
|
const match = JSONPath({ path: transition.condition, json: {submission: submitted} })
|
||||||
|
return match.length === 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,11 @@ import { beforeAll, describe, expect, it } from 'vitest';
|
||||||
import { LearningObject } from '../../../src/entities/content/learning-object.entity';
|
import { LearningObject } from '../../../src/entities/content/learning-object.entity';
|
||||||
import { setupTestApp } from '../../setup-tests';
|
import { setupTestApp } from '../../setup-tests';
|
||||||
import { LearningPath } from '../../../src/entities/content/learning-path.entity';
|
import { LearningPath } from '../../../src/entities/content/learning-path.entity';
|
||||||
import { getLearningObjectRepository, getLearningPathRepository } from '../../../src/data/repositories';
|
import {
|
||||||
|
getLearningObjectRepository,
|
||||||
|
getLearningPathRepository,
|
||||||
|
getStudentRepository, getSubmissionRepository
|
||||||
|
} from '../../../src/data/repositories';
|
||||||
import learningObjectExample from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example';
|
import learningObjectExample from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example';
|
||||||
import learningPathExample from '../../test-assets/learning-paths/pn-werking-example';
|
import learningPathExample from '../../test-assets/learning-paths/pn-werking-example';
|
||||||
import databaseLearningPathProvider from '../../../src/services/learning-paths/database-learning-path-provider';
|
import databaseLearningPathProvider from '../../../src/services/learning-paths/database-learning-path-provider';
|
||||||
|
@ -10,6 +14,12 @@ import { expectToBeCorrectLearningPath } from '../../test-utils/expectations';
|
||||||
import { LearningObjectRepository } from '../../../src/data/content/learning-object-repository';
|
import { LearningObjectRepository } from '../../../src/data/content/learning-object-repository';
|
||||||
import learningObjectService from '../../../src/services/learning-objects/learning-object-service';
|
import learningObjectService from '../../../src/services/learning-objects/learning-object-service';
|
||||||
import { Language } from '../../../src/entities/content/language';
|
import { Language } from '../../../src/entities/content/language';
|
||||||
|
import {
|
||||||
|
ConditionTestLearningPathAndLearningObjects,
|
||||||
|
createConditionTestLearningPathAndLearningObjects
|
||||||
|
} from "../../test-assets/learning-paths/test-conditions-example";
|
||||||
|
import {Student} from "../../../src/entities/users/student.entity";
|
||||||
|
import {LearningObjectNode, LearningPathResponse} from "../../../src/interfaces/learning-content";
|
||||||
|
|
||||||
async function initExampleData(): Promise<{ learningObject: LearningObject; learningPath: LearningPath }> {
|
async function initExampleData(): Promise<{ learningObject: LearningObject; learningPath: LearningPath }> {
|
||||||
const learningObjectRepo = getLearningObjectRepository();
|
const learningObjectRepo = getLearningObjectRepository();
|
||||||
|
@ -21,13 +31,85 @@ async function initExampleData(): Promise<{ learningObject: LearningObject; lear
|
||||||
return { learningObject, 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,
|
||||||
|
submissionNumber: 0,
|
||||||
|
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,
|
||||||
|
submissionNumber: 1,
|
||||||
|
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 {
|
||||||
|
let branchingObjectMatches = result.data![0].nodes.filter(
|
||||||
|
it => it.learningobject_hruid === persTestData.learningContent.branchingObject.hruid
|
||||||
|
);
|
||||||
|
expect(branchingObjectMatches.length).toBe(1);
|
||||||
|
return branchingObjectMatches[0];
|
||||||
|
}
|
||||||
|
|
||||||
describe('DatabaseLearningPathProvider', () => {
|
describe('DatabaseLearningPathProvider', () => {
|
||||||
let learningObjectRepo: LearningObjectRepository;
|
let learningObjectRepo: LearningObjectRepository;
|
||||||
let example: { learningObject: LearningObject; learningPath: LearningPath };
|
let example: { learningObject: LearningObject; learningPath: LearningPath };
|
||||||
|
let persTestData: { learningContent: ConditionTestLearningPathAndLearningObjects, studentA: Student, studentB: Student }
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await setupTestApp();
|
await setupTestApp();
|
||||||
example = await initExampleData();
|
example = await initExampleData();
|
||||||
|
persTestData = await initPersonalizationTestData();
|
||||||
learningObjectRepo = getLearningObjectRepository();
|
learningObjectRepo = getLearningObjectRepository();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -55,6 +137,60 @@ describe('DatabaseLearningPathProvider', () => {
|
||||||
|
|
||||||
expectToBeCorrectLearningPath(result.data![0], example.learningPath, learningObjectsOnPath);
|
expectToBeCorrectLearningPath(result.data![0], example.learningPath, learningObjectsOnPath);
|
||||||
});
|
});
|
||||||
|
it("returns the correct personalized learning path", async () => {
|
||||||
|
// For student A:
|
||||||
|
let result = await databaseLearningPathProvider.fetchLearningPaths(
|
||||||
|
[persTestData.learningContent.learningPath.hruid],
|
||||||
|
persTestData.learningContent.learningPath.language,
|
||||||
|
'the source',
|
||||||
|
{type: 'student', student: persTestData.studentA}
|
||||||
|
);
|
||||||
|
expect(result.success).toBeTruthy();
|
||||||
|
expect(result.data?.length).toBe(1);
|
||||||
|
|
||||||
|
// There should be exactly one branching object
|
||||||
|
let branchingObject = expectBranchingObjectNode(result, persTestData);
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
// For student B:
|
||||||
|
result = await databaseLearningPathProvider.fetchLearningPaths(
|
||||||
|
[persTestData.learningContent.learningPath.hruid],
|
||||||
|
persTestData.learningContent.learningPath.language,
|
||||||
|
'the source',
|
||||||
|
{type: 'student', student: persTestData.studentB}
|
||||||
|
);
|
||||||
|
expect(result.success).toBeTruthy();
|
||||||
|
expect(result.data?.length).toBe(1);
|
||||||
|
|
||||||
|
// There should still be exactly one branching object
|
||||||
|
branchingObject = expectBranchingObjectNode(result, persTestData);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
});
|
||||||
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],
|
[example.learningPath.hruid],
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { LearningObject } from '../../../../src/entities/content/learning-object
|
||||||
import { Language } from '../../../../src/entities/content/language';
|
import { Language } from '../../../../src/entities/content/language';
|
||||||
import { loadTestAsset } from '../../../test-utils/load-test-asset';
|
import { loadTestAsset } from '../../../test-utils/load-test-asset';
|
||||||
import { DwengoContentType } from '../../../../src/services/learning-objects/processing/content-type';
|
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
|
* Create a dummy learning object to be used in tests where multiple learning objects are needed (for example for use
|
||||||
|
@ -12,13 +13,17 @@ export function dummyLearningObject(hruid: string, language: Language, title: st
|
||||||
return {
|
return {
|
||||||
createLearningObject: () => {
|
createLearningObject: () => {
|
||||||
const learningObject = new LearningObject();
|
const learningObject = new LearningObject();
|
||||||
learningObject.hruid = hruid;
|
learningObject.hruid = getEnvVar(EnvVars.UserContentPrefix) + hruid;
|
||||||
learningObject.language = language;
|
learningObject.language = language;
|
||||||
learningObject.version = 1;
|
learningObject.version = 1;
|
||||||
learningObject.title = title;
|
learningObject.title = title;
|
||||||
learningObject.description = 'Just a dummy learning object for testing purposes';
|
learningObject.description = 'Just a dummy learning object for testing purposes';
|
||||||
learningObject.contentType = DwengoContentType.TEXT_PLAIN;
|
learningObject.contentType = DwengoContentType.TEXT_PLAIN;
|
||||||
learningObject.content = Buffer.from('Dummy content');
|
learningObject.content = Buffer.from('Dummy content');
|
||||||
|
learningObject.returnValue = {
|
||||||
|
callbackUrl: `/learningObject/${hruid}/submissions`,
|
||||||
|
callbackSchema: "[]"
|
||||||
|
}
|
||||||
return learningObject;
|
return learningObject;
|
||||||
},
|
},
|
||||||
createAttachment: {},
|
createAttachment: {},
|
||||||
|
|
|
@ -14,6 +14,10 @@ const example: LearningObjectExample = {
|
||||||
learningObject.title = 'Essay question for testing';
|
learningObject.title = 'Essay question for testing';
|
||||||
learningObject.description = 'This essay question was only created for testing purposes.';
|
learningObject.description = 'This essay question was only created for testing purposes.';
|
||||||
learningObject.contentType = DwengoContentType.GIFT;
|
learningObject.contentType = DwengoContentType.GIFT;
|
||||||
|
learningObject.returnValue = {
|
||||||
|
callbackUrl: `/learningObject/${learningObject.hruid}/submissions`,
|
||||||
|
callbackSchema: '["antwoord vraag 1"]'
|
||||||
|
}
|
||||||
learningObject.content = loadTestAsset('learning-objects/test-essay/content.txt');
|
learningObject.content = loadTestAsset('learning-objects/test-essay/content.txt');
|
||||||
return learningObject;
|
return learningObject;
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,6 +14,10 @@ const example: LearningObjectExample = {
|
||||||
learningObject.title = 'Multiple choice question for testing';
|
learningObject.title = 'Multiple choice question for testing';
|
||||||
learningObject.description = 'This multiple choice question was only created for testing purposes.';
|
learningObject.description = 'This multiple choice question was only created for testing purposes.';
|
||||||
learningObject.contentType = DwengoContentType.GIFT;
|
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');
|
learningObject.content = loadTestAsset('learning-objects/test-multiple-choice/content.txt');
|
||||||
return learningObject;
|
return learningObject;
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,66 +3,84 @@ import { Language } from '../../../src/entities/content/language';
|
||||||
import testMultipleChoiceExample from '../learning-objects/test-multiple-choice/test-multiple-choice-example';
|
import testMultipleChoiceExample from '../learning-objects/test-multiple-choice/test-multiple-choice-example';
|
||||||
import { dummyLearningObject } from '../learning-objects/dummy/dummy-learning-object-example';
|
import { dummyLearningObject } from '../learning-objects/dummy/dummy-learning-object-example';
|
||||||
import { createLearningPathNode, createLearningPathTransition } from './learning-path-utils';
|
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 = {
|
const example: LearningPathExample = {
|
||||||
createLearningPath: () => {
|
createLearningPath: () => {
|
||||||
const learningPath = new LearningPath();
|
return createConditionTestLearningPathAndLearningObjects().learningPath;
|
||||||
learningPath.hruid = '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 learningPath;
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,5 +4,6 @@ export default defineConfig({
|
||||||
test: {
|
test: {
|
||||||
environment: 'node',
|
environment: 'node',
|
||||||
globals: true,
|
globals: true,
|
||||||
|
testTimeout: 10000,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue