From a3b995393bd70a5e18aa62831ac8a8fa8b123a16 Mon Sep 17 00:00:00 2001 From: Gerald Schmittinger Date: Sun, 9 Mar 2025 15:57:55 +0100 Subject: [PATCH] test(backend): Testen voor DatabaseLearningObjectProvider.getLearningObjectById toegevoegd. --- .../database-learning-path-provider.ts | 10 ++-- .../learning-object-repository.test.ts | 3 +- .../content/learning-path-repository.test.ts | 2 +- .../database-learning-object-provider.test.ts | 52 +++++++++++++++++++ ...xample-learning-object-with-attachments.ts | 10 ++++ .../pn-werkingnotebooks-example.ts | 5 +- ...o-be-correct-entity.ts => expectations.ts} | 31 +++++++++++ 7 files changed, 102 insertions(+), 11 deletions(-) create mode 100644 backend/tests/services/learning-objects/database-learning-object-provider.test.ts create mode 100644 backend/tests/test-assets/learning-objects/create-example-learning-object-with-attachments.ts rename backend/tests/test-utils/{expect-to-be-correct-entity.ts => expectations.ts} (60%) diff --git a/backend/src/services/learning-paths/database-learning-path-provider.ts b/backend/src/services/learning-paths/database-learning-path-provider.ts index 879996e4..b9fa9ff6 100644 --- a/backend/src/services/learning-paths/database-learning-path-provider.ts +++ b/backend/src/services/learning-paths/database-learning-path-provider.ts @@ -7,13 +7,13 @@ import { Transition } from "../../interfaces/learning-content"; import { - LearningPath as LearningPathEntity, - LearningPathNode, - LearningPathTransition + LearningPath as LearningPathEntity } from "../../entities/content/learning-path.entity" import {getLearningPathRepository} from "../../data/repositories"; import {Language} from "../../entities/content/language"; import learningObjectService from "../learning-objects/learning-object-service"; +import { LearningPathNode } from "../../entities/content/learning-path-node.entity"; +import {LearningPathTransition} from "../../entities/content/learning-path-transition.entity"; /** * Fetches the corresponding learning object for each of the nodes and creates a map that maps each node to its @@ -55,13 +55,15 @@ async function convertLearningPath(learningPath: LearningPathEntity, order: numb const keywords = nodesToLearningObjects.values().flatMap(it => it.keywords || []).toArray(); + const image = learningPath.image ? learningPath.image.toString("base64") : undefined; + return { _id: `${learningPath.hruid}/${learningPath.language}`, // for backwards compatibility with the original Dwengo API. __order: order, hruid: learningPath.hruid, language: learningPath.language, description: learningPath.description, - image: learningPath.image, + image: image, title: learningPath.title, nodes: convertNodes(nodesToLearningObjects), num_nodes: learningPath.nodes.length, diff --git a/backend/tests/data/content/learning-object-repository.test.ts b/backend/tests/data/content/learning-object-repository.test.ts index 366e5a81..87b8511e 100644 --- a/backend/tests/data/content/learning-object-repository.test.ts +++ b/backend/tests/data/content/learning-object-repository.test.ts @@ -4,7 +4,7 @@ import {setupTestApp} from "../../setup-tests"; import {getLearningObjectRepository} from "../../../src/data/repositories"; import example from "../../test-assets/learning-objects/pn_werkingnotebooks/pn-werkingnotebooks-example.js" import {LearningObject} from "../../../src/entities/content/learning-object.entity"; -import {expectToBeCorrectEntity} from "../../test-utils/expect-to-be-correct-entity"; +import {expectToBeCorrectEntity} from "../../test-utils/expectations"; describe("LearningObjectRepository", () => { let learningObjectRepository: LearningObjectRepository; @@ -28,7 +28,6 @@ describe("LearningObjectRepository", () => { version: exampleLearningObject.version }); expect(result).toBeInstanceOf(LearningObject); - console.log(result); expectToBeCorrectEntity({ name: "actual", entity: result! diff --git a/backend/tests/data/content/learning-path-repository.test.ts b/backend/tests/data/content/learning-path-repository.test.ts index 5e946dfd..5298d3c4 100644 --- a/backend/tests/data/content/learning-path-repository.test.ts +++ b/backend/tests/data/content/learning-path-repository.test.ts @@ -4,7 +4,7 @@ import {getLearningPathRepository} from "../../../src/data/repositories"; import {LearningPathRepository} from "../../../src/data/content/learning-path-repository"; import example from "../../test-assets/learning-paths/pn-werking-example"; import {LearningPath} from "../../../src/entities/content/learning-path.entity"; -import {expectToBeCorrectEntity} from "../../test-utils/expect-to-be-correct-entity"; +import {expectToBeCorrectEntity} from "../../test-utils/expectations"; import {Language} from "../../../src/entities/content/language"; function expectToHaveFoundPrecisely(expected: LearningPath, result: LearningPath[]): void { 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 new file mode 100644 index 00000000..509b5e2e --- /dev/null +++ b/backend/tests/services/learning-objects/database-learning-object-provider.test.ts @@ -0,0 +1,52 @@ +import {beforeAll, describe, expect, it} from "vitest"; +import {setupTestApp} from "../../setup-tests"; +import {getLearningObjectRepository} 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"; + +async function initExampleData(): Promise { + let learningObjectRepo = getLearningObjectRepository(); + let exampleLearningObject = createExampleLearningObjectWithAttachments(example); + await learningObjectRepo.insert(exampleLearningObject); + return exampleLearningObject; +} + +describe("DatabaseLearningObjectProvider", () => { + let exampleLearningObject: LearningObject; + + beforeAll(async () => { + await setupTestApp(); + exampleLearningObject = await initExampleData(); + }); + + 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); + }); + + it("should return the learning object when it is queried by only hruid and language (but not version)", async () => { + const result: FilteredLearningObject | null = await databaseLearningObjectProvider.getLearningObjectById({ + hruid: exampleLearningObject.hruid, + language: exampleLearningObject.language + }); + expect(result).toBeTruthy(); + expectToBeCorrectFilteredLearningObject(result!, exampleLearningObject); + }); + + it("should return null when queried with an id that does not exist", async () => { + const result: FilteredLearningObject | null = await databaseLearningObjectProvider.getLearningObjectById({ + hruid: "non_existing_hruid", + language: Language.Dutch + }); + expect(result).toBeNull(); + }); + +}); diff --git a/backend/tests/test-assets/learning-objects/create-example-learning-object-with-attachments.ts b/backend/tests/test-assets/learning-objects/create-example-learning-object-with-attachments.ts new file mode 100644 index 00000000..65d2b62e --- /dev/null +++ b/backend/tests/test-assets/learning-objects/create-example-learning-object-with-attachments.ts @@ -0,0 +1,10 @@ +import {LearningObjectExample} from "./learning-object-example"; +import {LearningObject} from "../../../src/entities/content/learning-object.entity"; + +export function createExampleLearningObjectWithAttachments(example: LearningObjectExample): LearningObject { + let learningObject = example.createLearningObject(); + for (let creationFn of Object.values(example.createAttachment)) { + learningObject.attachments.push(creationFn(learningObject)); + } + return learningObject; +} diff --git a/backend/tests/test-assets/learning-objects/pn_werkingnotebooks/pn-werkingnotebooks-example.ts b/backend/tests/test-assets/learning-objects/pn_werkingnotebooks/pn-werkingnotebooks-example.ts index 576f3d6c..abca3ab3 100644 --- a/backend/tests/test-assets/learning-objects/pn_werkingnotebooks/pn-werkingnotebooks-example.ts +++ b/backend/tests/test-assets/learning-objects/pn_werkingnotebooks/pn-werkingnotebooks-example.ts @@ -41,10 +41,7 @@ const example: LearningObjectExample = { let returnValue = new ReturnValue(); returnValue.callbackUrl = "callback_url_example"; - returnValue.callbackSchema = `{ - att: "test", - att2: "test2" - }`; + returnValue.callbackSchema = '{"att": "test", "att2": "test2"}'; learningObject.returnValue = returnValue; learningObject.available = true; diff --git a/backend/tests/test-utils/expect-to-be-correct-entity.ts b/backend/tests/test-utils/expectations.ts similarity index 60% rename from backend/tests/test-utils/expect-to-be-correct-entity.ts rename to backend/tests/test-utils/expectations.ts index c978aab3..048a327e 100644 --- a/backend/tests/test-utils/expect-to-be-correct-entity.ts +++ b/backend/tests/test-utils/expectations.ts @@ -1,4 +1,7 @@ import {AssertionError} from "node:assert"; +import {LearningObject} from "../../src/entities/content/learning-object.entity"; +import {FilteredLearningObject} from "../../src/interfaces/learning-content"; +import { expect } from "vitest"; // Ignored properties because they belang for example to the class, not to the entity itself. const IGNORE_PROPERTIES = ["parent"]; @@ -60,3 +63,31 @@ export function expectToBeCorrectEntity( } } } + +/** + * 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 + */ +export function expectToBeCorrectFilteredLearningObject(filtered: FilteredLearningObject, original: LearningObject) { + expect(filtered.uuid).toEqual(original.uuid); + expect(filtered.version).toEqual(original.version); + expect(filtered.language).toEqual(original.language); + expect(filtered.keywords).toEqual(original.keywords); + 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.skosConcepts).toEqual(original.skosConcepts); + expect(filtered.estimatedTime).toEqual(original.estimatedTime); + expect(filtered.educationalGoals).toEqual(original.educationalGoals); + expect(filtered.difficulty).toEqual(original.difficulty || 1); + expect(filtered.description).toEqual(original.description); + 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.htmlUrl).toContain(`/${original.hruid}/html`); + expect(filtered.htmlUrl).toContain(`language=${original.language}`); + expect(filtered.htmlUrl).toContain(`version=${original.version}`); +}