diff --git a/backend/src/services/learning-objects/database-learning-object-provider.ts b/backend/src/services/learning-objects/database-learning-object-provider.ts index 46fc23fe..56aa3a99 100644 --- a/backend/src/services/learning-objects/database-learning-object-provider.ts +++ b/backend/src/services/learning-objects/database-learning-object-provider.ts @@ -10,6 +10,7 @@ import {LearningObject} from "../../entities/content/learning-object.entity"; import {getUrlStringForLearningObject} from "../../util/links"; import processingService from "./processing/processing-service"; import {NotFoundError} from "@mikro-orm/core"; +import learningObjectService from "./learning-object-service"; function convertLearningObject(learningObject: LearningObject | null): FilteredLearningObject | null { @@ -90,7 +91,7 @@ const databaseLearningObjectProvider: LearningObjectProvider = { if (!learningPath) { throw new NotFoundError("The learning path with the given ID could not be found."); } - return learningPath.nodes.map(it => it.learningObjectHruid); // TODO: Determine this based on the submissions of the user. + return learningPath.nodes.map(it => it.learningObjectHruid); }, /** @@ -105,7 +106,7 @@ const databaseLearningObjectProvider: LearningObjectProvider = { } const learningObjects = await Promise.all( learningPath.nodes.map(it => { - const learningObject = this.getLearningObjectById({ + const learningObject = learningObjectService.getLearningObjectById({ hruid: it.learningObjectHruid, language: it.language, version: it.version @@ -116,7 +117,7 @@ const databaseLearningObjectProvider: LearningObjectProvider = { return learningObject; }) ); - return learningObjects.filter(it => it !== null); // TODO: Determine this based on the submissions of the user. + return learningObjects.filter(it => it !== null); } } diff --git a/backend/src/services/learning-paths/point-of-view.d.ts b/backend/src/services/learning-paths/point-of-view.d.ts new file mode 100644 index 00000000..e08685b8 --- /dev/null +++ b/backend/src/services/learning-paths/point-of-view.d.ts @@ -0,0 +1 @@ +type PointOfView = {type: "student", student: Student} | {type: "group", group: Group}; diff --git a/backend/tests/services/learning-objects/database-learning-object-provider.test.ts b/backend/tests/services/learning-objects/database-learning-object-provider.test.ts index 691b29ba..d7870eb9 100644 --- a/backend/tests/services/learning-objects/database-learning-object-provider.test.ts +++ b/backend/tests/services/learning-objects/database-learning-object-provider.test.ts @@ -1,29 +1,37 @@ import {beforeAll, describe, expect, it} from "vitest"; import {setupTestApp} from "../../setup-tests"; -import {getLearningObjectRepository} from "../../../src/data/repositories"; +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 { - createExampleLearningObjectWithAttachments -} from "../../test-assets/learning-objects/create-example-learning-object-with-attachments"; 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 { - let learningObjectRepo = getLearningObjectRepository(); - let exampleLearningObject = createExampleLearningObjectWithAttachments(example); - await learningObjectRepo.insert(exampleLearningObject); - return exampleLearningObject; +async function initExampleData(): Promise<{learningObject: LearningObject, learningPath: LearningPath}> { + const learningObjectRepo = getLearningObjectRepository(); + const learningPathRepo = getLearningPathRepository(); + let learningObject = learningObjectExample.createLearningObject(); + let learningPath = learningPathExample.createLearningPath(); + await learningObjectRepo.save(learningObject); + await learningPathRepo.save(learningPath); + return { learningObject, learningPath }; } +const EXPECTED_TITLE_FROM_DWENGO_LEARNING_OBJECT = "Notebook opslaan"; + describe("DatabaseLearningObjectProvider", () => { let exampleLearningObject: LearningObject; + let exampleLearningPath: LearningPath; beforeAll(async () => { await setupTestApp(); - exampleLearningObject = await initExampleData(); + let exampleData = await initExampleData(); + exampleLearningObject = exampleData.learningObject; + exampleLearningPath = exampleData.learningPath; }); describe("getLearningObjectById", () => { it("should return the learning object when it is queried by its id", async () => { @@ -54,5 +62,45 @@ describe("DatabaseLearningObjectProvider", () => { const result = await databaseLearningObjectProvider.getLearningObjectHTML(exampleLearningObject); expect(result).toEqual(example.getHTMLRendering()); }); + it("should return null for a non-existing learning object", async () => { + const result = await databaseLearningObjectProvider.getLearningObjectHTML({ + hruid: "non_existing_hruid", + language: Language.Dutch + }); + expect(result).toBeNull(); + }); + }); + 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))); + }); + it("should throw an error if queried with a path identifier for which there is no learning path", async () => { + await expect((async () => { + await databaseLearningObjectProvider.getLearningObjectIdsFromPath({ + hruid: "non_existing_hruid", + language: Language.Dutch + }); + })()).rejects.toThrowError(); + }); + }); + 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); + 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(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 () => { + await databaseLearningObjectProvider.getLearningObjectsFromPath({ + hruid: "non_existing_hruid", + language: Language.Dutch + }); + })()).rejects.toThrowError(); + }); }); }); diff --git a/backend/tests/test-utils/expectations.ts b/backend/tests/test-utils/expectations.ts index 19c2408d..e8e70845 100644 --- a/backend/tests/test-utils/expectations.ts +++ b/backend/tests/test-utils/expectations.ts @@ -78,7 +78,7 @@ export function expectToBeCorrectFilteredLearningObject(filtered: FilteredLearni expect(filtered.key).toEqual(original.hruid); expect(filtered.targetAges).toEqual(original.targetAges); expect(filtered.title).toEqual(original.title); - expect(!!filtered.teacherExclusive).toEqual(original.teacherExclusive) // !!: Workaround: MikroORM with SQLite returns 0 and 1 instead of booleans. + expect(!!filtered.teacherExclusive).toEqual(!!original.teacherExclusive) // !!: Workaround: MikroORM with SQLite returns 0 and 1 instead of booleans. expect(filtered.skosConcepts).toEqual(original.skosConcepts); expect(filtered.estimatedTime).toEqual(original.estimatedTime); expect(filtered.educationalGoals).toEqual(original.educationalGoals); @@ -87,7 +87,7 @@ export function expectToBeCorrectFilteredLearningObject(filtered: FilteredLearni expect(filtered.returnValue?.callback_url).toEqual(original.returnValue.callbackUrl); expect(filtered.returnValue?.callback_schema).toEqual(JSON.parse(original.returnValue.callbackSchema)); expect(filtered.contentType).toEqual(original.contentType); - expect(filtered.contentLocation).toEqual(original.contentLocation || null); + expect(filtered.contentLocation || null).toEqual(original.contentLocation || null); expect(filtered.htmlUrl).toContain(`/${original.hruid}/html`); expect(filtered.htmlUrl).toContain(`language=${original.language}`); expect(filtered.htmlUrl).toContain(`version=${original.version}`);