diff --git a/backend/src/controllers/learning-paths.ts b/backend/src/controllers/learning-paths.ts index 59db773a..65f3b457 100644 --- a/backend/src/controllers/learning-paths.ts +++ b/backend/src/controllers/learning-paths.ts @@ -5,8 +5,8 @@ import learningPathService from '../services/learning-paths/learning-path-servic import { Language } from '@dwengo-1/common/util/language'; import { BadRequestException } from '../exceptions/bad-request-exception.js'; import { NotFoundException } from '../exceptions/not-found-exception.js'; -import {Group} from "../entities/assignments/group.entity"; -import {getAssignmentRepository, getGroupRepository} from "../data/repositories"; +import { Group } from '../entities/assignments/group.entity'; +import { getAssignmentRepository, getGroupRepository } from '../data/repositories'; /** * Fetch learning paths based on query parameters. @@ -27,13 +27,9 @@ export async function getLearningPaths(req: Request, res: Response): Promise theme.hruids); } - const learningPaths = await learningPathService.fetchLearningPaths( - hruidList, - language as Language, - `HRUIDs: ${hruidList.join(', ')}`, - forGroup - ); + const learningPaths = await learningPathService.fetchLearningPaths(hruidList, language as Language, `HRUIDs: ${hruidList.join(', ')}`, forGroup); res.json(learningPaths.data); } diff --git a/backend/src/data/assignments/submission-repository.ts b/backend/src/data/assignments/submission-repository.ts index 743409bd..e9889bcf 100644 --- a/backend/src/data/assignments/submission-repository.ts +++ b/backend/src/data/assignments/submission-repository.ts @@ -62,18 +62,15 @@ export class SubmissionRepository extends DwengoEntityRepository { /** * Looks up all submissions for the given learning object which were submitted as part of the given assignment. */ - public async findAllSubmissionsForLearningObjectAndAssignment( - loId: LearningObjectIdentifier, - assignment: Assignment, - ): Promise { + public async findAllSubmissionsForLearningObjectAndAssignment(loId: LearningObjectIdentifier, assignment: Assignment): Promise { return this.findAll({ where: { learningObjectHruid: loId.hruid, learningObjectLanguage: loId.language, learningObjectVersion: loId.version, onBehalfOf: { - assignment - } + assignment, + }, }, }); } @@ -81,16 +78,13 @@ export class SubmissionRepository extends DwengoEntityRepository { /** * Looks up all submissions for the given learning object which were submitted by the given group */ - public async findAllSubmissionsForLearningObjectAndGroup( - loId: LearningObjectIdentifier, - group: Group, - ): Promise { + public async findAllSubmissionsForLearningObjectAndGroup(loId: LearningObjectIdentifier, group: Group): Promise { return this.findAll({ where: { learningObjectHruid: loId.hruid, learningObjectLanguage: loId.language, learningObjectVersion: loId.version, - onBehalfOf: group + onBehalfOf: group, }, }); } diff --git a/backend/src/data/content/learning-path-repository.ts b/backend/src/data/content/learning-path-repository.ts index c405cd1f..60f37948 100644 --- a/backend/src/data/content/learning-path-repository.ts +++ b/backend/src/data/content/learning-path-repository.ts @@ -1,10 +1,10 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { LearningPath } from '../../entities/content/learning-path.entity.js'; import { Language } from '@dwengo-1/common/util/language'; -import {LearningPathNode} from "../../entities/content/learning-path-node.entity"; -import {RequiredEntityData} from "@mikro-orm/core"; -import {LearningPathTransition} from "../../entities/content/learning-path-transition.entity"; -import {EntityAlreadyExistsException} from "../../exceptions/entity-already-exists-exception"; +import { LearningPathNode } from '../../entities/content/learning-path-node.entity'; +import { RequiredEntityData } from '@mikro-orm/core'; +import { LearningPathTransition } from '../../entities/content/learning-path-transition.entity'; +import { EntityAlreadyExistsException } from '../../exceptions/entity-already-exists-exception'; export class LearningPathRepository extends DwengoEntityRepository { public async findByHruidAndLanguage(hruid: string, language: Language): Promise { @@ -28,32 +28,26 @@ export class LearningPathRepository extends DwengoEntityRepository }); } - public createNode( - nodeData: RequiredEntityData - ): LearningPathNode { + public createNode(nodeData: RequiredEntityData): LearningPathNode { return this.em.create(LearningPathNode, nodeData); } - public createTransition( - transitionData: RequiredEntityData - ): LearningPathTransition { - return this.em.create(LearningPathTransition, transitionData) + public createTransition(transitionData: RequiredEntityData): LearningPathTransition { + return this.em.create(LearningPathTransition, transitionData); } public async saveLearningPathNodesAndTransitions( path: LearningPath, nodes: LearningPathNode[], transitions: LearningPathTransition[], - options?: {preventOverwrite?: boolean} + options?: { preventOverwrite?: boolean } ): Promise { if (options?.preventOverwrite && (await this.findOne(path))) { - throw new EntityAlreadyExistsException( - "A learning path with this hruid/language combination already exists." - ); + throw new EntityAlreadyExistsException('A learning path with this hruid/language combination already exists.'); } const em = this.getEntityManager(); await em.persistAndFlush(path); - await Promise.all(nodes.map(async it => em.persistAndFlush(it))); - await Promise.all(transitions.map(async it => em.persistAndFlush(it))); + await Promise.all(nodes.map(async (it) => em.persistAndFlush(it))); + await Promise.all(transitions.map(async (it) => em.persistAndFlush(it))); } } diff --git a/backend/src/entities/content/learning-object.entity.ts b/backend/src/entities/content/learning-object.entity.ts index 3fe2a884..e0ae09d6 100644 --- a/backend/src/entities/content/learning-object.entity.ts +++ b/backend/src/entities/content/learning-object.entity.ts @@ -1,4 +1,4 @@ -import {ArrayType, Embedded, Entity, Enum, ManyToMany, OneToMany, PrimaryKey, Property} from '@mikro-orm/core'; +import { ArrayType, Embedded, Entity, Enum, ManyToMany, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; import { Attachment } from './attachment.entity.js'; import { Teacher } from '../users/teacher.entity.js'; import { DwengoContentType } from '../../services/learning-objects/processing/content-type.js'; @@ -42,7 +42,7 @@ export class LearningObject { @Property({ type: 'array' }) keywords: string[] = []; - @Property({ type: new ArrayType(i => Number(i)), nullable: true }) + @Property({ type: new ArrayType((i) => Number(i)), nullable: true }) targetAges?: number[] = []; @Property({ type: 'bool' }) diff --git a/backend/src/entities/content/learning-path-node.entity.ts b/backend/src/entities/content/learning-path-node.entity.ts index f21adc78..fd870dcd 100644 --- a/backend/src/entities/content/learning-path-node.entity.ts +++ b/backend/src/entities/content/learning-path-node.entity.ts @@ -1,4 +1,4 @@ -import {Collection, Entity, Enum, ManyToOne, OneToMany, PrimaryKey, Property, Rel} from '@mikro-orm/core'; +import { Collection, Entity, Enum, ManyToOne, OneToMany, PrimaryKey, Property, Rel } from '@mikro-orm/core'; import { LearningPath } from './learning-path.entity.js'; import { LearningPathTransition } from './learning-path-transition.entity.js'; import { Language } from '@dwengo-1/common/util/language'; diff --git a/backend/src/entities/content/learning-path.entity.ts b/backend/src/entities/content/learning-path.entity.ts index 57d095b8..1b96d8ea 100644 --- a/backend/src/entities/content/learning-path.entity.ts +++ b/backend/src/entities/content/learning-path.entity.ts @@ -1,4 +1,4 @@ -import {Collection, Entity, Enum, ManyToMany, OneToMany, PrimaryKey, Property} from '@mikro-orm/core'; +import { Collection, Entity, Enum, ManyToMany, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; import { Teacher } from '../users/teacher.entity.js'; import { LearningPathRepository } from '../../data/content/learning-path-repository.js'; import { LearningPathNode } from './learning-path-node.entity.js'; diff --git a/backend/src/middleware/error-handling/error-handler.ts b/backend/src/middleware/error-handling/error-handler.ts index 12de68be..8ec93e37 100644 --- a/backend/src/middleware/error-handling/error-handler.ts +++ b/backend/src/middleware/error-handling/error-handler.ts @@ -9,7 +9,7 @@ export function errorHandler(err: unknown, _req: Request, res: Response, _: Next logger.warn(`An error occurred while handling a request: ${err} (-> HTTP ${err.status})`); res.status(err.status).json(err); } else { - logger.error(`Unexpected error occurred while handing a request: ${(err as {stack: string})?.stack ?? JSON.stringify(err)}`); + logger.error(`Unexpected error occurred while handing a request: ${(err as { stack: string })?.stack ?? JSON.stringify(err)}`); res.status(500).json(err); } } diff --git a/backend/src/services/learning-objects.ts b/backend/src/services/learning-objects.ts index 146a7664..089fd25a 100644 --- a/backend/src/services/learning-objects.ts +++ b/backend/src/services/learning-objects.ts @@ -8,7 +8,7 @@ import { LearningPathResponse, } from '@dwengo-1/common/interfaces/learning-content'; import { getLogger } from '../logging/initalize.js'; -import {v4} from "uuid"; +import { v4 } from 'uuid'; function filterData(data: LearningObjectMetadata, htmlUrl: string): FilteredLearningObject { return { 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 712802b3..0b805a56 100644 --- a/backend/src/services/learning-objects/database-learning-object-provider.ts +++ b/backend/src/services/learning-objects/database-learning-object-provider.ts @@ -32,8 +32,7 @@ function convertLearningObject(learningObject: LearningObject | null): FilteredL educationalGoals: learningObject.educationalGoals, returnValue: { callback_url: learningObject.returnValue.callbackUrl, - callback_schema: learningObject.returnValue.callbackSchema === "" ? "" - : JSON.parse(learningObject.returnValue.callbackSchema), + callback_schema: learningObject.returnValue.callbackSchema === '' ? '' : JSON.parse(learningObject.returnValue.callbackSchema), }, skosConcepts: learningObject.skosConcepts, targetAges: learningObject.targetAges || [], diff --git a/backend/src/services/learning-objects/dwengo-api-learning-object-provider.ts b/backend/src/services/learning-objects/dwengo-api-learning-object-provider.ts index a3863505..4a4bdc54 100644 --- a/backend/src/services/learning-objects/dwengo-api-learning-object-provider.ts +++ b/backend/src/services/learning-objects/dwengo-api-learning-object-provider.ts @@ -11,7 +11,7 @@ import { LearningPathIdentifier, LearningPathResponse, } from '@dwengo-1/common/interfaces/learning-content'; -import {v4} from "uuid"; +import { v4 } from 'uuid'; const logger: Logger = getLogger(); 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 86372194..fe05dda1 100644 --- a/backend/src/services/learning-paths/database-learning-path-provider.ts +++ b/backend/src/services/learning-paths/database-learning-path-provider.ts @@ -13,9 +13,9 @@ import { Transition, } from '@dwengo-1/common/interfaces/learning-content'; import { Language } from '@dwengo-1/common/util/language'; -import {Group} from "../../entities/assignments/group.entity"; -import {Collection} from "@mikro-orm/core"; -import {v4} from "uuid"; +import { Group } from '../../entities/assignments/group.entity'; +import { Collection } from '@mikro-orm/core'; +import { v4 } from 'uuid'; /** * Fetches the corresponding learning object for each of the nodes and creates a map that maps each node to its @@ -165,7 +165,7 @@ function convertTransition( _id: String(index), // Retained for backwards compatibility. The index uniquely identifies the transition within the learning path. default: false, // We don't work with default transitions but retain this for backwards compatibility. next: { - _id: nextNode._id ? (nextNode._id + index) : v4(), // Construct a unique ID for the transition for backwards compatibility. + _id: nextNode._id ? nextNode._id + index : v4(), // Construct a unique ID for the transition for backwards compatibility. hruid: transition.next.learningObjectHruid, language: nextNode.language, version: nextNode.version, @@ -181,12 +181,7 @@ const databaseLearningPathProvider: LearningPathProvider = { /** * Fetch the learning paths with the given hruids from the database. */ - async fetchLearningPaths( - hruids: string[], - language: Language, - source: string, - personalizedFor?: Group - ): Promise { + async fetchLearningPaths(hruids: string[], language: Language, source: string, personalizedFor?: Group): Promise { const learningPathRepo = getLearningPathRepository(); const learningPaths = (await Promise.all(hruids.map(async (hruid) => learningPathRepo.findByHruidAndLanguage(hruid, language)))).filter( @@ -211,7 +206,7 @@ const databaseLearningPathProvider: LearningPathProvider = { const searchResults = await learningPathRepo.findByQueryStringAndLanguage(query, language); return await Promise.all(searchResults.map(async (result, index) => convertLearningPath(result, index, personalizedFor))); - } + }, }; export default databaseLearningPathProvider; diff --git a/backend/src/services/learning-paths/learning-path-provider.ts b/backend/src/services/learning-paths/learning-path-provider.ts index bc067a41..086777bd 100644 --- a/backend/src/services/learning-paths/learning-path-provider.ts +++ b/backend/src/services/learning-paths/learning-path-provider.ts @@ -1,6 +1,6 @@ import { LearningPath, LearningPathResponse } from '@dwengo-1/common/interfaces/learning-content'; import { Language } from '@dwengo-1/common/util/language'; -import { Group } from "../../entities/assignments/group.entity"; +import { Group } from '../../entities/assignments/group.entity'; /** * Generic interface for a service which provides access to learning paths from a data source. diff --git a/backend/src/services/learning-paths/learning-path-service.ts b/backend/src/services/learning-paths/learning-path-service.ts index 3a0109ec..730d7ba8 100644 --- a/backend/src/services/learning-paths/learning-path-service.ts +++ b/backend/src/services/learning-paths/learning-path-service.ts @@ -1,25 +1,23 @@ import dwengoApiLearningPathProvider from './dwengo-api-learning-path-provider.js'; import databaseLearningPathProvider from './database-learning-path-provider.js'; import { envVars, getEnvVar } from '../../util/envVars.js'; -import {LearningObjectNode, LearningPath, LearningPathResponse} from '@dwengo-1/common/interfaces/learning-content'; +import { LearningObjectNode, LearningPath, LearningPathResponse } from '@dwengo-1/common/interfaces/learning-content'; import { Language } from '@dwengo-1/common/util/language'; -import {Group} from "../../entities/assignments/group.entity"; -import {LearningPath as LearningPathEntity} from "../../entities/content/learning-path.entity"; -import {getLearningPathRepository} from "../../data/repositories"; -import {LearningPathNode} from "../../entities/content/learning-path-node.entity"; -import {LearningPathTransition} from "../../entities/content/learning-path-transition.entity"; -import {base64ToArrayBuffer} from "../../util/base64-buffer-conversion"; -import {TeacherDTO} from "@dwengo-1/common/interfaces/teacher"; -import {mapToTeacher} from "../../interfaces/teacher"; -import {Collection} from "@mikro-orm/core"; +import { Group } from '../../entities/assignments/group.entity'; +import { LearningPath as LearningPathEntity } from '../../entities/content/learning-path.entity'; +import { getLearningPathRepository } from '../../data/repositories'; +import { LearningPathNode } from '../../entities/content/learning-path-node.entity'; +import { LearningPathTransition } from '../../entities/content/learning-path-transition.entity'; +import { base64ToArrayBuffer } from '../../util/base64-buffer-conversion'; +import { TeacherDTO } from '@dwengo-1/common/interfaces/teacher'; +import { mapToTeacher } from '../../interfaces/teacher'; +import { Collection } from '@mikro-orm/core'; const userContentPrefix = getEnvVar(envVars.UserContentPrefix); const allProviders = [dwengoApiLearningPathProvider, databaseLearningPathProvider]; -export function mapToLearningPath( - dto: LearningPath, adminsDto: TeacherDTO[] -): LearningPathEntity { - const admins = adminsDto.map(admin => mapToTeacher(admin)); +export function mapToLearningPath(dto: LearningPath, adminsDto: TeacherDTO[]): LearningPathEntity { + const admins = adminsDto.map((admin) => mapToTeacher(admin)); const repo = getLearningPathRepository(); const path = repo.create({ hruid: dto.hruid, @@ -27,7 +25,7 @@ export function mapToLearningPath( description: dto.description, title: dto.title, admins, - image: dto.image ? Buffer.from(base64ToArrayBuffer(dto.image)) : null + image: dto.image ? Buffer.from(base64ToArrayBuffer(dto.image)) : null, }); const nodes = dto.nodes.map((nodeDto: LearningObjectNode, i: number) => repo.createNode({ @@ -38,33 +36,34 @@ export function mapToLearningPath( version: nodeDto.version, startNode: nodeDto.start_node ?? false, createdAt: new Date(), - updatedAt: new Date() + updatedAt: new Date(), }) ); - dto.nodes.forEach(nodeDto => { - const fromNode = nodes.find(it => - it.learningObjectHruid === nodeDto.learningobject_hruid - && it.language === nodeDto.language - && it.version === nodeDto.version + dto.nodes.forEach((nodeDto) => { + const fromNode = nodes.find( + (it) => it.learningObjectHruid === nodeDto.learningobject_hruid && it.language === nodeDto.language && it.version === nodeDto.version )!; - const transitions = nodeDto.transitions.map((transDto, i) => { - const toNode = nodes.find(it => - it.learningObjectHruid === transDto.next.hruid - && it.language === transDto.next.language - && it.version === transDto.next.version - ); + const transitions = nodeDto.transitions + .map((transDto, i) => { + const toNode = nodes.find( + (it) => + it.learningObjectHruid === transDto.next.hruid && + it.language === transDto.next.language && + it.version === transDto.next.version + ); - if (toNode) { - return repo.createTransition({ - transitionNumber: i, - node: fromNode, - next: toNode, - condition: transDto.condition ?? "true" - }); - } + if (toNode) { + return repo.createTransition({ + transitionNumber: i, + node: fromNode, + next: toNode, + condition: transDto.condition ?? 'true', + }); + } return undefined; - - }).filter(it => it).map(it => it!); + }) + .filter((it) => it) + .map((it) => it!); fromNode.transitions = new Collection(fromNode, transitions); }); @@ -85,12 +84,7 @@ const learningPathService = { * @param source * @param personalizedFor If this is set, a learning path personalized for the given group or student will be returned. */ - async fetchLearningPaths( - hruids: string[], - language: Language, - source: string, - personalizedFor?: Group - ): Promise { + async fetchLearningPaths(hruids: string[], language: Language, source: string, personalizedFor?: Group): Promise { const userContentHruids = hruids.filter((hruid) => hruid.startsWith(userContentPrefix)); const nonUserContentHruids = hruids.filter((hruid) => !hruid.startsWith(userContentPrefix)); @@ -129,8 +123,8 @@ const learningPathService = { async createNewLearningPath(dto: LearningPath, admins: TeacherDTO[]): Promise { const repo = getLearningPathRepository(); const path = mapToLearningPath(dto, admins); - await repo.save(path, {preventOverwrite: true}) - } + await repo.save(path, { preventOverwrite: true }); + }, }; export default learningPathService; diff --git a/backend/src/services/submissions.ts b/backend/src/services/submissions.ts index bd217ea0..b6d1600a 100644 --- a/backend/src/services/submissions.ts +++ b/backend/src/services/submissions.ts @@ -1,4 +1,4 @@ -import {getAssignmentRepository, getGroupRepository, getSubmissionRepository} from '../data/repositories.js'; +import { getAssignmentRepository, getGroupRepository, getSubmissionRepository } from '../data/repositories.js'; import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; import { NotFoundException } from '../exceptions/not-found-exception.js'; import { mapToSubmission, mapToSubmissionDTO } from '../interfaces/submission.js'; diff --git a/backend/src/sqlite-autoincrement-workaround.ts b/backend/src/sqlite-autoincrement-workaround.ts index c50488a9..5ed48ee6 100644 --- a/backend/src/sqlite-autoincrement-workaround.ts +++ b/backend/src/sqlite-autoincrement-workaround.ts @@ -27,10 +27,7 @@ export class SqliteAutoincrementSubscriber implements EventSubscriber { for (const prop of Object.values(args.meta.properties)) { const property = prop as EntityProperty; - if ( - property.primary && property.autoincrement - && (args.entity as Record)[property.name] === undefined - ) { + if (property.primary && property.autoincrement && (args.entity as Record)[property.name] === undefined) { // Obtain and increment sequence number of this entity. const propertyKey = args.meta.class.name + '.' + property.name; const nextSeqNumber = this.sequenceNumbersForEntityType.get(propertyKey) || 0; diff --git a/backend/tests/data/assignments/assignments.test.ts b/backend/tests/data/assignments/assignments.test.ts index 6ac15d09..49504400 100644 --- a/backend/tests/data/assignments/assignments.test.ts +++ b/backend/tests/data/assignments/assignments.test.ts @@ -33,8 +33,7 @@ describe('AssignmentRepository', () => { 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)); + const resultIds = result.map((it) => it.id).sort((a, b) => (a ?? 0) - (b ?? 0)); expect(resultIds).toEqual([1, 1, 3, 4]); }); diff --git a/backend/tests/data/assignments/submissions.test.ts b/backend/tests/data/assignments/submissions.test.ts index e5d656da..dd2cc8c4 100644 --- a/backend/tests/data/assignments/submissions.test.ts +++ b/backend/tests/data/assignments/submissions.test.ts @@ -91,11 +91,9 @@ describe('SubmissionRepository', () => { 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 () => { + 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!, 2); - const result = await submissionRepository.findAllSubmissionsForLearningObjectAndGroup( - loId, group! - ); + const result = await submissionRepository.findAllSubmissionsForLearningObjectAndGroup(loId, group!); expect(result).toHaveLength(1); diff --git a/backend/tests/data/content/attachment-repository.test.ts b/backend/tests/data/content/attachment-repository.test.ts index af128177..162d8cbb 100644 --- a/backend/tests/data/content/attachment-repository.test.ts +++ b/backend/tests/data/content/attachment-repository.test.ts @@ -5,8 +5,8 @@ import { AttachmentRepository } from '../../../src/data/content/attachment-repos 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'; -import {testLearningObjectPnNotebooks} from "../../test_assets/content/learning-objects.testdata"; -import {v4 as uuidV4} from "uuid"; +import { testLearningObjectPnNotebooks } from '../../test_assets/content/learning-objects.testdata'; +import { v4 as uuidV4 } from 'uuid'; describe('AttachmentRepository', () => { let attachmentRepo: AttachmentRepository; @@ -26,7 +26,7 @@ describe('AttachmentRepository', () => { newLearningObjectData.version = 101; newLearningObjectData.attachments = []; newLearningObjectData.uuid = uuidV4(); - newLearningObjectData.content = Buffer.from("Content of the newer example"); + newLearningObjectData.content = Buffer.from('Content of the newer example'); newLearningObject = learningObjectRepo.create(newLearningObjectData); await learningObjectRepo.save(newLearningObject); @@ -36,7 +36,7 @@ describe('AttachmentRepository', () => { 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"); + attachmentOnlyNewer.content = Buffer.from('New attachment content'); await attachmentRepo.save(attachmentRepo.create(attachmentOnlyNewer)); }); @@ -49,10 +49,7 @@ describe('AttachmentRepository', () => { version: testLearningObjectPnNotebooks.version, }; - const result = await attachmentRepo.findByLearningObjectIdAndName( - olderLearningObjectId, - attachmentsOlderLearningObject[0].name - ); + const result = await attachmentRepo.findByLearningObjectIdAndName(olderLearningObjectId, attachmentsOlderLearningObject[0].name); expect(result).not.toBeNull(); expect(result!.name).toEqual(attachmentsOlderLearningObject[0].name); expect(result!.content).toEqual(attachmentsOlderLearningObject[0].content); diff --git a/backend/tests/data/content/attachments.test.ts b/backend/tests/data/content/attachments.test.ts index 7d0bfd6b..1a393b15 100644 --- a/backend/tests/data/content/attachments.test.ts +++ b/backend/tests/data/content/attachments.test.ts @@ -2,7 +2,7 @@ import { beforeAll, describe, expect, it } from 'vitest'; import { setupTestApp } from '../../setup-tests.js'; import { getAttachmentRepository } from '../../../src/data/repositories.js'; import { AttachmentRepository } from '../../../src/data/content/attachment-repository.js'; -import { testLearningObject02 } from "../../test_assets/content/learning-objects.testdata"; +import { testLearningObject02 } from '../../test_assets/content/learning-objects.testdata'; describe('AttachmentRepository', () => { let attachmentRepository: AttachmentRepository; diff --git a/backend/tests/data/content/learning-object-repository.test.ts b/backend/tests/data/content/learning-object-repository.test.ts index 3400c913..4761c297 100644 --- a/backend/tests/data/content/learning-object-repository.test.ts +++ b/backend/tests/data/content/learning-object-repository.test.ts @@ -4,12 +4,8 @@ import { setupTestApp } from '../../setup-tests.js'; import { getLearningObjectRepository } from '../../../src/data/repositories.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"; +import { testLearningObject01, testLearningObject02, testLearningObject03 } from '../../test_assets/content/learning-objects.testdata'; +import { v4 } from 'uuid'; describe('LearningObjectRepository', () => { let learningObjectRepository: LearningObjectRepository; @@ -43,26 +39,22 @@ describe('LearningObjectRepository', () => { it('should allow a learning object with the same id except a different version to be added', async () => { const testLearningObject01Newer = structuredClone(testLearningObject01); testLearningObject01Newer.version = 10; - testLearningObject01Newer.title += " (nieuw)"; + testLearningObject01Newer.title += ' (nieuw)'; testLearningObject01Newer.uuid = v4(); - testLearningObject01Newer.content = Buffer.from("This is the new content."); + testLearningObject01Newer.content = Buffer.from('This is the new content.'); newerExample = learningObjectRepository.create(testLearningObject01Newer); await learningObjectRepository.save(newerExample); }); it('should return the newest version of the learning object when queried by only hruid and language', async () => { - const result = await learningObjectRepository.findLatestByHruidAndLanguage( - newerExample.hruid, newerExample.language - ); + const result = await learningObjectRepository.findLatestByHruidAndLanguage(newerExample.hruid, newerExample.language); expect(result).toBeInstanceOf(LearningObject); expect(result?.version).toBe(10); expect(result?.title).toContain('(nieuw)'); }); it('should return null when queried by non-existing hruid or language', async () => { - const result = await learningObjectRepository.findLatestByHruidAndLanguage( - 'something_that_does_not_exist', testLearningObject01.language - ); + const result = await learningObjectRepository.findLatestByHruidAndLanguage('something_that_does_not_exist', testLearningObject01.language); expect(result).toBe(null); }); }); diff --git a/backend/tests/data/content/learning-objects.test.ts b/backend/tests/data/content/learning-objects.test.ts index ef7fca79..aa8d3bda 100644 --- a/backend/tests/data/content/learning-objects.test.ts +++ b/backend/tests/data/content/learning-objects.test.ts @@ -4,7 +4,7 @@ import { getLearningObjectRepository } from '../../../src/data/repositories'; import { setupTestApp } from '../../setup-tests'; import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier'; import { Language } from '@dwengo-1/common/util/language'; -import {testLearningObject01} from "../../test_assets/content/learning-objects.testdata"; +import { testLearningObject01 } from '../../test_assets/content/learning-objects.testdata'; describe('LearningObjectRepository', () => { let learningObjectRepository: LearningObjectRepository; diff --git a/backend/tests/data/content/learning-path-repository.test.ts b/backend/tests/data/content/learning-path-repository.test.ts index 370eec2a..9fadae11 100644 --- a/backend/tests/data/content/learning-path-repository.test.ts +++ b/backend/tests/data/content/learning-path-repository.test.ts @@ -3,14 +3,10 @@ import { setupTestApp } from '../../setup-tests.js'; import { getLearningPathRepository } from '../../../src/data/repositories.js'; import { LearningPathRepository } from '../../../src/data/content/learning-path-repository.js'; import { LearningPath } from '../../../src/entities/content/learning-path.entity.js'; -import { - expectToBeCorrectEntity, - expectToHaveFoundNothing, - expectToHaveFoundPrecisely -} from '../../test-utils/expectations.js'; +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"; +import { testLearningPath01 } from '../../test_assets/content/learning-paths.testdata'; +import { mapToLearningPath } from '../../../src/services/learning-paths/learning-path-service'; describe('LearningPathRepository', () => { let learningPathRepo: LearningPathRepository; @@ -24,10 +20,7 @@ describe('LearningPathRepository', () => { }); 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 - ); + const result = await learningPathRepo.findByHruidAndLanguage(testLearningPath01.hruid, testLearningPath01.language as Language); expect(result).toBeInstanceOf(LearningPath); expectToBeCorrectEntity(result!, examplePath); }); diff --git a/backend/tests/data/content/learning-paths.test.ts b/backend/tests/data/content/learning-paths.test.ts index c8620a31..32e25dde 100644 --- a/backend/tests/data/content/learning-paths.test.ts +++ b/backend/tests/data/content/learning-paths.test.ts @@ -3,7 +3,7 @@ import { getLearningPathRepository } from '../../../src/data/repositories'; import { LearningPathRepository } from '../../../src/data/content/learning-path-repository'; import { setupTestApp } from '../../setup-tests'; import { Language } from '@dwengo-1/common/util/language'; -import {testLearningPath01} from "../../test_assets/content/learning-paths.testdata"; +import { testLearningPath01 } from '../../test_assets/content/learning-paths.testdata'; describe('LearningPathRepository', () => { let learningPathRepository: LearningPathRepository; @@ -20,9 +20,7 @@ describe('LearningPathRepository', () => { }); it('should return requested learning path', async () => { - const learningPath = await learningPathRepository.findByHruidAndLanguage( - testLearningPath01.hruid, testLearningPath01.language as Language - ); + const learningPath = await learningPathRepository.findByHruidAndLanguage(testLearningPath01.hruid, testLearningPath01.language as Language); expect(learningPath).toBeTruthy(); expect(learningPath?.title).toBe(testLearningPath01.title); 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 5170ea0f..79d6a59c 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 @@ -4,18 +4,12 @@ import { LearningObject } from '../../../src/entities/content/learning-object.en import databaseLearningObjectProvider from '../../../src/services/learning-objects/database-learning-object-provider'; import { expectToBeCorrectFilteredLearningObject } from '../../test-utils/expectations'; 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 { 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"; +import { RequiredEntityData } from '@mikro-orm/core'; +import { getHtmlRenderingForTestLearningObject } from '../../test-utils/get-html-rendering'; const EXPECTED_TITLE_FROM_DWENGO_LEARNING_OBJECT = 'Notebook opslaan'; @@ -31,7 +25,7 @@ describe('DatabaseLearningObjectProvider', () => { exampleLearningPathId = { hruid: exampleLearningPath.hruid, - language: exampleLearningPath.language as Language + language: exampleLearningPath.language as Language, }; }); describe('getLearningObjectById', () => { @@ -75,9 +69,7 @@ describe('DatabaseLearningObjectProvider', () => { describe('getLearningObjectIdsFromPath', () => { it('should return all learning object IDs from a path', async () => { const result = await databaseLearningObjectProvider.getLearningObjectIdsFromPath(exampleLearningPathId); - expect(new Set(result)).toEqual( - new Set(exampleLearningPath.nodes.map((it: LearningObjectNode) => it.learningobject_hruid)) - ); + 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( diff --git a/backend/tests/services/learning-objects/learning-object-service.test.ts b/backend/tests/services/learning-objects/learning-object-service.test.ts index 2f793156..819e6470 100644 --- a/backend/tests/services/learning-objects/learning-object-service.test.ts +++ b/backend/tests/services/learning-objects/learning-object-service.test.ts @@ -3,18 +3,12 @@ import { setupTestApp } from '../../setup-tests'; import { LearningObject } from '../../../src/entities/content/learning-object.entity'; import learningObjectService from '../../../src/services/learning-objects/learning-object-service'; import { envVars, getEnvVar } from '../../../src/util/envVars'; -import { - LearningObjectIdentifierDTO, - LearningPath as LearningPathDTO, - LearningPathIdentifier -} from '@dwengo-1/common/interfaces/learning-content'; +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"; +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: LearningObjectIdentifierDTO = { @@ -41,8 +35,8 @@ describe('LearningObjectService', () => { exampleLearningPathId = { hruid: exampleLearningPath.hruid, - language: exampleLearningPath.language as Language - } + language: exampleLearningPath.language as Language, + }; }); describe('getLearningObjectById', () => { @@ -99,9 +93,7 @@ describe('LearningObjectService', () => { describe('getLearningObjectsFromPath', () => { it('returns all learning objects when a learning path in the database is queried', async () => { const result = await learningObjectService.getLearningObjectsFromPath(exampleLearningPathId); - expect(result.map(it=> it.key)).toEqual( - exampleLearningPath.nodes.map(it => it.learningobject_hruid) - ); + 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); @@ -119,7 +111,7 @@ describe('LearningObjectService', () => { describe('getLearningObjectIdsFromPath', () => { it('returns all learning objects when a learning path in the database is queried', async () => { const result = await learningObjectService.getLearningObjectIdsFromPath(exampleLearningPathId); - expect(result).toEqual(exampleLearningPath.nodes.map(it => it.learningobject_hruid)); + 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); diff --git a/backend/tests/services/learning-objects/processing/processing-service.test.ts b/backend/tests/services/learning-objects/processing/processing-service.test.ts index d41b8afa..1995ce4a 100644 --- a/backend/tests/services/learning-objects/processing/processing-service.test.ts +++ b/backend/tests/services/learning-objects/processing/processing-service.test.ts @@ -1,12 +1,13 @@ -import {beforeAll, describe, expect, it} from 'vitest'; +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"; + 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 () => { @@ -17,24 +18,18 @@ describe('ProcessingService', () => { const markdownLearningObject = getLearningObjectRepository().create(testLearningObjectPnNotebooks); const result = await processingService.render(markdownLearningObject); // Set newlines so your tests are platform-independent. - expect(result).toEqual( - getHtmlRenderingForTestLearningObject(markdownLearningObject).replace(/\r\n/g, '\n') - ); + expect(result).toEqual(getHtmlRenderingForTestLearningObject(markdownLearningObject).replace(/\r\n/g, '\n')); }); it('renders a multiple choice question correctly', async () => { const testLearningObject = getLearningObjectRepository().create(testLearningObjectMultipleChoice); const result = await processingService.render(testLearningObject); - expect(result).toEqual( - getHtmlRenderingForTestLearningObject(testLearningObjectMultipleChoice).replace(/\r\n/g, '\n') - ); + expect(result).toEqual(getHtmlRenderingForTestLearningObject(testLearningObjectMultipleChoice).replace(/\r\n/g, '\n')); }); it('renders an essay question correctly', async () => { const essayLearningObject = getLearningObjectRepository().create(testLearningObjectEssayQuestion); const result = await processingService.render(essayLearningObject); - expect(result).toEqual( - getHtmlRenderingForTestLearningObject(essayLearningObject).replace(/\r\n/g, '\n') - ); + expect(result).toEqual(getHtmlRenderingForTestLearningObject(essayLearningObject).replace(/\r\n/g, '\n')); }); }); diff --git a/backend/tests/services/learning-path/database-learning-path-provider.test.ts b/backend/tests/services/learning-path/database-learning-path-provider.test.ts index 69d88288..2cc594d1 100644 --- a/backend/tests/services/learning-path/database-learning-path-provider.test.ts +++ b/backend/tests/services/learning-path/database-learning-path-provider.test.ts @@ -8,26 +8,20 @@ import databaseLearningPathProvider from '../../../src/services/learning-paths/d import { expectToBeCorrectLearningPath } from '../../test-utils/expectations.js'; import { Language } from '@dwengo-1/common/util/language'; +import { LearningObjectNode, LearningPathResponse } from '@dwengo-1/common/interfaces/learning-content'; import { - LearningObjectNode, - LearningPathResponse -} from '@dwengo-1/common/interfaces/learning-content'; -import { - 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"; + 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"; +import { RequiredEntityData } from '@mikro-orm/core'; -function expectBranchingObjectNode( - result: LearningPathResponse -): LearningObjectNode { - const branchingObjectMatches = result.data![0].nodes.filter( - (it) => it.learningobject_hruid === testLearningObjectMultipleChoice.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]; } @@ -36,7 +30,7 @@ describe('DatabaseLearningPathProvider', () => { let testLearningPath: LearningPath; let branchingLearningObject: RequiredEntityData; let extraExerciseLearningObject: RequiredEntityData; - let finalLearningObject: RequiredEntityData; + let finalLearningObject: RequiredEntityData; let groupA: Group; let groupB: Group; @@ -55,10 +49,10 @@ describe('DatabaseLearningPathProvider', () => { learningObjectHruid: branchingLearningObject.hruid, learningObjectLanguage: branchingLearningObject.language, learningObjectVersion: branchingLearningObject.version, - content: "[0]", + content: '[0]', onBehalfOf: groupA, submissionTime: new Date(), - submitter: groupA.members[0] + submitter: groupA.members[0], }); await submissionRepo.save(submissionA); @@ -66,21 +60,17 @@ describe('DatabaseLearningPathProvider', () => { learningObjectHruid: branchingLearningObject.hruid, learningObjectLanguage: branchingLearningObject.language, learningObjectVersion: branchingLearningObject.version, - content: "[1]", + content: '[1]', onBehalfOf: groupB, submissionTime: new Date(), - submitter: groupB.members[0] + submitter: groupB.members[0], }); await submissionRepo.save(submissionB); }); describe('fetchLearningPaths', () => { it('returns the learning path correctly', async () => { - const result = await databaseLearningPathProvider.fetchLearningPaths( - [testLearningPath.hruid], - testLearningPath.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); @@ -100,24 +90,11 @@ describe('DatabaseLearningPathProvider', () => { // There should be exactly one branching object let branchingObject = expectBranchingObjectNode(result); - 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. + 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( - [testLearningPath.hruid], - testLearningPath.language, - 'the source', - groupB - ); + result = await databaseLearningPathProvider.fetchLearningPaths([testLearningPath.hruid], testLearningPath.language, 'the source', groupB); expect(result.success).toBeTruthy(); expect(result.data?.length).toBe(1); @@ -125,16 +102,8 @@ describe('DatabaseLearningPathProvider', () => { branchingObject = expectBranchingObjectNode(result); // However, now the student picks the other option. - 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. + 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( @@ -149,10 +118,7 @@ describe('DatabaseLearningPathProvider', () => { describe('searchLearningPaths', () => { it('returns the correct learning path when queried with a substring of its title', async () => { - const result = await databaseLearningPathProvider.searchLearningPaths( - testLearningPath.title.substring(2, 6), - testLearningPath.language - ); + const result = await databaseLearningPathProvider.searchLearningPaths(testLearningPath.title.substring(2, 6), testLearningPath.language); expect(result.length).toBe(1); expect(result[0].title).toBe(testLearningPath.title); expect(result[0].description).toBe(testLearningPath.description); diff --git a/backend/tests/services/learning-path/learning-path-service.test.ts b/backend/tests/services/learning-path/learning-path-service.test.ts index cb263d73..ae4d9e99 100644 --- a/backend/tests/services/learning-path/learning-path-service.test.ts +++ b/backend/tests/services/learning-path/learning-path-service.test.ts @@ -2,10 +2,8 @@ import { beforeAll, describe, expect, it } from 'vitest'; import { setupTestApp } from '../../setup-tests'; import learningPathService from '../../../src/services/learning-paths/learning-path-service'; 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"; +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'; @@ -16,7 +14,7 @@ describe('LearningPathService', () => { let testLearningPath: LearningPathDTO; beforeAll(async () => { await setupTestApp(); - testLearningPath = testPartiallyDatabaseAndPartiallyDwengoApiLearningPath + testLearningPath = testPartiallyDatabaseAndPartiallyDwengoApiLearningPath; }); describe('fetchLearningPaths', () => { it('should return learning paths both from the database and from the Dwengo API', async () => { diff --git a/backend/tests/setup-tests.ts b/backend/tests/setup-tests.ts index 0d71b434..23fc43ee 100644 --- a/backend/tests/setup-tests.ts +++ b/backend/tests/setup-tests.ts @@ -13,8 +13,8 @@ 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"; +import { Collection } from '@mikro-orm/core'; +import { Group } from '../src/entities/assignments/group.entity'; export async function setupTestApp(): Promise { dotenv.config({ path: '.env.test' }); diff --git a/backend/tests/test-utils/expectations.ts b/backend/tests/test-utils/expectations.ts index fc9da71d..6579be16 100644 --- a/backend/tests/test-utils/expectations.ts +++ b/backend/tests/test-utils/expectations.ts @@ -2,7 +2,7 @@ import { AssertionError } from 'node:assert'; import { LearningObject } from '../../src/entities/content/learning-object.entity'; import { expect } from 'vitest'; import { FilteredLearningObject, LearningPath } from '@dwengo-1/common/interfaces/learning-content'; -import {RequiredEntityData} from "@mikro-orm/core"; +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']; @@ -13,11 +13,7 @@ const IGNORE_PROPERTIES = ['parent']; * @param expected The (previously added) entity we would expect to retrieve * @param propertyPrefix Prefix to append to property in error messages. */ -export function expectToBeCorrectEntity( - actual: T, - expected: T, - propertyPrefix = "" -): void { +export function expectToBeCorrectEntity(actual: T, expected: T, propertyPrefix = ''): void { for (const property in expected) { if (Object.prototype.hasOwnProperty.call(expected, property)) { const prefixedProperty = propertyPrefix + property; @@ -41,16 +37,16 @@ export function expectToBeCorrectEntity( } } else if (typeof expected[property] !== typeof actual[property]) { throw new AssertionError({ - message: `${prefixedProperty} was expected to have type ${typeof expected[property]},` - + `but had type ${typeof actual[property]}.`, + 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]}.`, + message: `${prefixedProperty} was expected to be ${expected[property]}, ` + `but was ${actual[property]}.`, }); } } @@ -94,10 +90,7 @@ export function expectToBeCorrectFilteredLearningObject(filtered: FilteredLearni * @param learningPath The learning path returned by the retriever, service or endpoint * @param expected The learning path that should have been returned. */ -export function expectToBeCorrectLearningPath( - learningPath: LearningPath, - expected: LearningPath -): void { +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); @@ -113,17 +106,18 @@ export function expectToBeCorrectLearningPath( expect(learningPath.image ?? null).toEqual(expected.image ?? null); 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 + const correspondingNode = learningPath.nodes.find( + (it) => node.learningobject_hruid === it.learningobject_hruid && node.language === it.language && node.version === it.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 + 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(); } diff --git a/backend/tests/test-utils/get-html-rendering.ts b/backend/tests/test-utils/get-html-rendering.ts index 28d24ed2..23ea7f86 100644 --- a/backend/tests/test-utils/get-html-rendering.ts +++ b/backend/tests/test-utils/get-html-rendering.ts @@ -1,12 +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"; +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): string { const userPrefix = getEnvVar(envVars.UserContentPrefix); - const cleanedHruid = learningObject.hruid.startsWith(userPrefix) - ? learningObject.hruid.substring(userPrefix.length) - : learningObject.hruid; + const cleanedHruid = learningObject.hruid.startsWith(userPrefix) ? learningObject.hruid.substring(userPrefix.length) : learningObject.hruid; return loadTestAsset(`/content/learning-object-resources/${cleanedHruid}/rendering.txt`).toString(); } diff --git a/backend/tests/test-utils/load-test-asset.ts b/backend/tests/test-utils/load-test-asset.ts index b7107a76..2920afe0 100644 --- a/backend/tests/test-utils/load-test-asset.ts +++ b/backend/tests/test-utils/load-test-asset.ts @@ -1,6 +1,6 @@ import fs from 'fs'; import path from 'node:path'; -import {fileURLToPath} from "node:url"; +import { fileURLToPath } from 'node:url'; const fileName = fileURLToPath(import.meta.url); const dirName = path.dirname(fileName); diff --git a/backend/tests/test_assets/assignments/assignments.testdata.ts b/backend/tests/test_assets/assignments/assignments.testdata.ts index bcd98c44..efb20e60 100644 --- a/backend/tests/test_assets/assignments/assignments.testdata.ts +++ b/backend/tests/test_assets/assignments/assignments.testdata.ts @@ -2,8 +2,8 @@ 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 '@dwengo-1/common/util/language'; -import {testLearningPathWithConditions} from "../content/learning-paths.testdata"; -import {getClassWithTestleerlingAndTestleerkracht} from "../classes/classes.testdata"; +import { testLearningPathWithConditions } from '../content/learning-paths.testdata'; +import { getClassWithTestleerlingAndTestleerkracht } from '../classes/classes.testdata'; export function makeTestAssignemnts(em: EntityManager, classes: Class[]): Assignment[] { assignment01 = em.create(Assignment, { diff --git a/backend/tests/test_assets/assignments/groups.testdata.ts b/backend/tests/test_assets/assignments/groups.testdata.ts index 3240b8d0..3ace2be9 100644 --- a/backend/tests/test_assets/assignments/groups.testdata.ts +++ b/backend/tests/test_assets/assignments/groups.testdata.ts @@ -1,9 +1,9 @@ -import {EntityManager} 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"; +import { getConditionalPathAssignment } from './assignments.testdata'; +import { getTestleerling1 } from '../users/students.testdata'; export function makeTestGroups(em: EntityManager, students: Student[], assignments: Assignment[]): Group[] { /* @@ -62,8 +62,8 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen group1ConditionalLearningPath = em.create(Group, { assignment: getConditionalPathAssignment(), groupNumber: 1, - members: [getTestleerling1()] - }) + members: [getTestleerling1()], + }); return [group01, group02, group03, group04, group05, group1ConditionalLearningPath]; } diff --git a/backend/tests/test_assets/classes/classes.testdata.ts b/backend/tests/test_assets/classes/classes.testdata.ts index 218ab228..7b5f2976 100644 --- a/backend/tests/test_assets/classes/classes.testdata.ts +++ b/backend/tests/test_assets/classes/classes.testdata.ts @@ -2,8 +2,8 @@ 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"; +import { getTestleerkracht1 } from '../users/teachers.testdata'; +import { getTestleerling1 } from '../users/students.testdata'; export function makeTestClasses(em: EntityManager, students: Student[], teachers: Teacher[]): Class[] { const studentsClass01 = students.slice(0, 8); @@ -47,10 +47,10 @@ export function makeTestClasses(em: EntityManager, students: Student[], teachers }); classWithTestleerlingAndTestleerkracht = em.create(Class, { - classId: "a75298b5-18aa-471d-8eeb-5d77eb989393", + classId: 'a75298b5-18aa-471d-8eeb-5d77eb989393', displayName: 'Testklasse', teachers: [getTestleerkracht1()], - students: [getTestleerling1()] + students: [getTestleerling1()], }); return [class01, class02, class03, class04, classWithTestleerlingAndTestleerkracht]; diff --git a/backend/tests/test_assets/content/learning-objects.testdata.ts b/backend/tests/test_assets/content/learning-objects.testdata.ts index 35ff46bf..6ee3bccf 100644 --- a/backend/tests/test_assets/content/learning-objects.testdata.ts +++ b/backend/tests/test_assets/content/learning-objects.testdata.ts @@ -1,11 +1,11 @@ -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"; +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): LearningObject[] { const returnValue: ReturnValue = new ReturnValue(); @@ -19,13 +19,19 @@ export function makeTestLearningObjects(em: EntityManager): LearningObject[] { const learningObject05 = em.create(LearningObject, testLearningObject05); const learningObjectMultipleChoice = em.create(LearningObject, testLearningObjectMultipleChoice); - const learningObjectEssayQuestion= em.create(LearningObject, testLearningObjectEssayQuestion); + const learningObjectEssayQuestion = em.create(LearningObject, testLearningObjectEssayQuestion); const learningObjectPnNotebooks = em.create(LearningObject, testLearningObjectPnNotebooks); return [ - learningObject01, learningObject02, learningObject03, learningObject04, learningObject05, - learningObjectMultipleChoice, learningObjectEssayQuestion, learningObjectPnNotebooks + learningObject01, + learningObject02, + learningObject03, + learningObject04, + learningObject05, + learningObjectMultipleChoice, + learningObjectEssayQuestion, + learningObjectPnNotebooks, ]; } @@ -164,14 +170,14 @@ export const testLearningObjectMultipleChoice: RequiredEntityData = { hruid: `${getEnvVar(envVars.UserContentPrefix)}test_essay_question`, language: Language.English, version: 1, - title: "Reflection", - description: "Reflect on your learning progress.", - keywords: ["test"], + title: 'Reflection', + description: 'Reflect on your learning progress.', + keywords: ['test'], teacherExclusive: false, skosConcepts: [], educationalGoals: [], - copyright: "Groep 1 SEL-2 2025", - license: "CC0", + copyright: 'Groep 1 SEL-2 2025', + license: 'CC0', difficulty: 1, estimatedTime: 1, attachments: [], @@ -209,47 +215,47 @@ export const testLearningObjectEssayQuestion: RequiredEntityData returnValue: { callbackUrl: `%SUBMISSION%`, callbackSchema: '["antwoord vraag 1"]', - } + }, }; export const testLearningObjectPnNotebooks: RequiredEntityData = { 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"], + title: 'Werken met notebooks', + description: 'Leren werken met notebooks', + keywords: ['Python', 'KIKS', 'Wiskunde', 'STEM', 'AI'], targetAges: [14, 15, 16, 17, 18], admins: [], - copyright: "dwengo", + copyright: 'dwengo', educationalGoals: [], - license: "dwengo", + license: 'dwengo', contentType: DwengoContentType.TEXT_MARKDOWN, difficulty: 3, estimatedTime: 10, - uuid: "2adf9929-b424-4650-bf60-186f730d38ab", + 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", + '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: '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") - } + 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"), + content: loadTestAsset('/content/learning-object-resources/pn_werkingnotebooks/content.md'), returnValue: { - callbackUrl: "%SUBMISSION%", - callbackSchema: "[]" - } -} + callbackUrl: '%SUBMISSION%', + callbackSchema: '[]', + }, +}; diff --git a/backend/tests/test_assets/content/learning-paths.testdata.ts b/backend/tests/test_assets/content/learning-paths.testdata.ts index 4d9f09c8..2a0640f8 100644 --- a/backend/tests/test_assets/content/learning-paths.testdata.ts +++ b/backend/tests/test_assets/content/learning-paths.testdata.ts @@ -1,40 +1,39 @@ -import {EntityManager} from '@mikro-orm/core'; -import {LearningPath} from '../../../src/entities/content/learning-path.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 { EntityManager } from '@mikro-orm/core'; +import { LearningPath } from '../../../src/entities/content/learning-path.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, + testLearningObject01, + testLearningObject02, + testLearningObject03, + testLearningObject04, + testLearningObject05, testLearningObjectEssayQuestion, - testLearningObjectMultipleChoice, testLearningObjectPnNotebooks -} from "./learning-objects.testdata"; + testLearningObjectMultipleChoice, + testLearningObjectPnNotebooks, +} from './learning-objects.testdata'; export function makeTestLearningPaths(_em: EntityManager): LearningPath[] { const learningPath01 = mapToLearningPath(testLearningPath01, []); const learningPath02 = mapToLearningPath(testLearningPath02, []); - const partiallyDatabasePartiallyDwengoApiLearningPath - = mapToLearningPath(testPartiallyDatabaseAndPartiallyDwengoApiLearningPath, []) - const learningPathWithConditions = mapToLearningPath(testLearningPathWithConditions, []) + const partiallyDatabasePartiallyDwengoApiLearningPath = mapToLearningPath(testPartiallyDatabaseAndPartiallyDwengoApiLearningPath, []); + const learningPathWithConditions = mapToLearningPath(testLearningPathWithConditions, []); - return [ - learningPath01, - learningPath02, - partiallyDatabasePartiallyDwengoApiLearningPath, - learningPathWithConditions - ]; + return [learningPath01, learningPath02, partiallyDatabasePartiallyDwengoApiLearningPath, learningPathWithConditions]; } const nowString = new Date().toString(); export const testLearningPath01: LearningPathDTO = { - keywords: "test", + keywords: 'test', target_ages: [16, 17, 18], hruid: `${getEnvVar(envVars.UserContentPrefix)}id01`, language: Language.English, - title: "repertoire Tool", - description: "all about Tool", + title: 'repertoire Tool', + description: 'all about Tool', nodes: [ { learningobject_hruid: testLearningObject01.hruid, @@ -48,10 +47,10 @@ export const testLearningPath01: LearningPathDTO = { next: { hruid: testLearningObject02.hruid, language: testLearningObject02.language, - version: testLearningObject02.version - } - } - ] + version: testLearningObject02.version, + }, + }, + ], }, { learningobject_hruid: testLearningObject02.hruid, @@ -59,18 +58,18 @@ export const testLearningPath01: LearningPathDTO = { version: testLearningObject02.version, created_at: nowString, updatedAt: nowString, - transitions: [] - } - ] + transitions: [], + }, + ], }; export const testLearningPath02: LearningPathDTO = { - keywords: "test", + keywords: 'test', target_ages: [16, 17, 18], hruid: `${getEnvVar(envVars.UserContentPrefix)}id02`, language: Language.English, - title: "repertoire Dire Straits", - description: "all about Dire Straits", + title: 'repertoire Dire Straits', + description: 'all about Dire Straits', nodes: [ { learningobject_hruid: testLearningObject03.hruid, @@ -84,10 +83,10 @@ export const testLearningPath02: LearningPathDTO = { next: { hruid: testLearningObject04.hruid, language: testLearningObject04.language, - version: testLearningObject04.version - } - } - ] + version: testLearningObject04.version, + }, + }, + ], }, { learningobject_hruid: testLearningObject04.hruid, @@ -100,10 +99,10 @@ export const testLearningPath02: LearningPathDTO = { next: { hruid: testLearningObject05.hruid, language: testLearningObject05.language, - version: testLearningObject05.version - } - } - ] + version: testLearningObject05.version, + }, + }, + ], }, { learningobject_hruid: testLearningObject05.hruid, @@ -111,17 +110,17 @@ export const testLearningPath02: LearningPathDTO = { version: testLearningObject05.version, created_at: nowString, updatedAt: nowString, - transitions: [] - } - ] + transitions: [], + }, + ], }; export const testPartiallyDatabaseAndPartiallyDwengoApiLearningPath: LearningPathDTO = { hruid: `${getEnvVar(envVars.UserContentPrefix)}pn_werking`, - title: "Werken met notebooks", + 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", + keywords: 'Python KIKS Wiskunde STEM AI', target_ages: [14, 15, 16, 17, 18], nodes: [ { @@ -135,15 +134,15 @@ export const testPartiallyDatabaseAndPartiallyDwengoApiLearningPath: LearningPat { default: true, next: { - hruid: "pn_werkingnotebooks2", + hruid: 'pn_werkingnotebooks2', language: Language.Dutch, - version: 3 - } - } - ] + version: 3, + }, + }, + ], }, { - learningobject_hruid: "pn_werkingnotebooks2", + learningobject_hruid: 'pn_werkingnotebooks2', language: Language.Dutch, version: 3, created_at: nowString, @@ -152,30 +151,30 @@ export const testPartiallyDatabaseAndPartiallyDwengoApiLearningPath: LearningPat { default: true, next: { - hruid: "pn_werkingnotebooks3", + hruid: 'pn_werkingnotebooks3', language: Language.Dutch, - version: 3 - } - } - ] + version: 3, + }, + }, + ], }, { - learningobject_hruid: "pn_werkingnotebooks3", + learningobject_hruid: 'pn_werkingnotebooks3', language: Language.Dutch, version: 3, created_at: nowString, updatedAt: nowString, - transitions: [] - } - ] -} + 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", + keywords: 'test', target_ages: [10, 11, 12, 13, 14, 15, 16, 17, 18], nodes: [ { @@ -193,8 +192,8 @@ export const testLearningPathWithConditions: LearningPathDTO = { //... we let the student do an extra exercise. hruid: testLearningObject01.hruid, language: testLearningObject01.language, - version: testLearningObject01.version - } + version: testLearningObject01.version, + }, }, { // If the answer to the first question was the second one (I can follow along): @@ -203,10 +202,10 @@ export const testLearningPathWithConditions: LearningPathDTO = { //... we let the student right through to the final question. hruid: testLearningObjectEssayQuestion.hruid, language: testLearningObjectEssayQuestion.language, - version: testLearningObjectEssayQuestion.version - } - } - ] + version: testLearningObjectEssayQuestion.version, + }, + }, + ], }, { learningobject_hruid: testLearningObject01.hruid, @@ -220,10 +219,10 @@ export const testLearningPathWithConditions: LearningPathDTO = { next: { hruid: testLearningObjectEssayQuestion.hruid, language: testLearningObjectEssayQuestion.language, - version: testLearningObjectEssayQuestion.version - } - } - ] + version: testLearningObjectEssayQuestion.version, + }, + }, + ], }, { learningobject_hruid: testLearningObjectEssayQuestion.hruid, @@ -231,7 +230,7 @@ export const testLearningPathWithConditions: LearningPathDTO = { version: testLearningObjectEssayQuestion.version, created_at: nowString, updatedAt: nowString, - transitions: [] - } - ] -} + transitions: [], + }, + ], +}; diff --git a/backend/tests/test_assets/users/students.testdata.ts b/backend/tests/test_assets/users/students.testdata.ts index 4080766f..e596b388 100644 --- a/backend/tests/test_assets/users/students.testdata.ts +++ b/backend/tests/test_assets/users/students.testdata.ts @@ -24,5 +24,5 @@ export function makeTestStudents(em: EntityManager): Student[] { } export function getTestleerling1(): Student { - return testStudents.find(it => it.username === "testleerling1"); + return testStudents.find((it) => it.username === 'testleerling1'); } diff --git a/backend/tests/test_assets/users/teachers.testdata.ts b/backend/tests/test_assets/users/teachers.testdata.ts index 9494f9ea..03366c80 100644 --- a/backend/tests/test_assets/users/teachers.testdata.ts +++ b/backend/tests/test_assets/users/teachers.testdata.ts @@ -62,4 +62,3 @@ export function getTeacher04(): Teacher { export function getTestleerkracht1(): Teacher { return testleerkracht1; } - diff --git a/frontend/src/controllers/learning-paths.ts b/frontend/src/controllers/learning-paths.ts index 8c96d682..bef3ac44 100644 --- a/frontend/src/controllers/learning-paths.ts +++ b/frontend/src/controllers/learning-paths.ts @@ -15,14 +15,14 @@ export class LearningPathController extends BaseController { async getBy( hruid: string, language: Language, - forGroup?: { forGroup: number, assignmentNo: number, classId: string }, + forGroup?: { forGroup: number; assignmentNo: number; classId: string }, ): Promise { const dtos = await this.get("/", { hruid, language, forGroup: forGroup?.forGroup, assignmentNo: forGroup?.assignmentNo, - classId: forGroup?.classId + classId: forGroup?.classId, }); return LearningPath.fromDTO(single(dtos)); } diff --git a/frontend/src/controllers/submissions.ts b/frontend/src/controllers/submissions.ts index a0e310c1..0be1c122 100644 --- a/frontend/src/controllers/submissions.ts +++ b/frontend/src/controllers/submissions.ts @@ -1,6 +1,6 @@ import { BaseController } from "./base-controller"; import type { SubmissionDTO, SubmissionDTOId } from "@dwengo-1/common/interfaces/submission"; -import type {Language} from "@dwengo-1/common/util/language"; +import type { Language } from "@dwengo-1/common/util/language"; export interface SubmissionsResponse { submissions: SubmissionDTO[] | SubmissionDTOId[]; @@ -11,18 +11,19 @@ export interface SubmissionResponse { } export class SubmissionController extends BaseController { - constructor(hruid: string) { super(`learningObject/${hruid}/submissions`); } async getAll( - language: Language, version: number, classId: string, assignmentId: number, groupId?: number, full = true + language: Language, + version: number, + classId: string, + assignmentId: number, + groupId?: number, + full = true, ): Promise { - return this.get( - `/`, - { language, version, classId, assignmentId, groupId, full } - ); + return this.get(`/`, { language, version, classId, assignmentId, groupId, full }); } async getByNumber( @@ -31,12 +32,15 @@ export class SubmissionController extends BaseController { classId: string, assignmentId: number, groupId: number, - submissionNumber: number + submissionNumber: number, ): Promise { - return this.get( - `/${submissionNumber}`, - { language, version, classId, assignmentId, groupId }, - ); + return this.get(`/${submissionNumber}`, { + language, + version, + classId, + assignmentId, + groupId, + }); } async createSubmission(data: SubmissionDTO): Promise { diff --git a/frontend/src/queries/learning-paths.ts b/frontend/src/queries/learning-paths.ts index 69016a77..16eef965 100644 --- a/frontend/src/queries/learning-paths.ts +++ b/frontend/src/queries/learning-paths.ts @@ -10,7 +10,7 @@ const learningPathController = getLearningPathController(); export function useGetLearningPathQuery( hruid: MaybeRefOrGetter, language: MaybeRefOrGetter, - forGroup?: MaybeRefOrGetter<{forGroup: number, assignmentNo: number, classId: string} | undefined>, + forGroup?: MaybeRefOrGetter<{ forGroup: number; assignmentNo: number; classId: string } | undefined>, ): UseQueryReturnType { return useQuery({ queryKey: [LEARNING_PATH_KEY, "get", hruid, language, forGroup], @@ -34,7 +34,7 @@ export function useGetAllLearningPathsByThemeQuery( export function useSearchLearningPathQuery( query: MaybeRefOrGetter, - language: MaybeRefOrGetter + language: MaybeRefOrGetter, ): UseQueryReturnType { return useQuery({ queryKey: [LEARNING_PATH_KEY, "search", query, language], diff --git a/frontend/src/queries/submissions.ts b/frontend/src/queries/submissions.ts index d1c1a6a2..812e5fe5 100644 --- a/frontend/src/queries/submissions.ts +++ b/frontend/src/queries/submissions.ts @@ -9,9 +9,9 @@ import { type UseQueryReturnType, } from "@tanstack/vue-query"; import { computed, toValue, type MaybeRefOrGetter } from "vue"; -import {LEARNING_PATH_KEY} from "@/queries/learning-paths.ts"; -import {LEARNING_OBJECT_KEY} from "@/queries/learning-objects.ts"; -import type {Language} from "@dwengo-1/common/util/language"; +import { LEARNING_PATH_KEY } from "@/queries/learning-paths.ts"; +import { LEARNING_OBJECT_KEY } from "@/queries/learning-objects.ts"; +import type { Language } from "@dwengo-1/common/util/language"; export const SUBMISSION_KEY = "submissions"; @@ -22,7 +22,7 @@ function submissionQueryKey( classid: string, assignmentNumber: number, groupNumber: number, - submissionNumber: number + submissionNumber: number, ) { return ["submission", hruid, language, version, classid, assignmentNumber, groupNumber, submissionNumber]; } @@ -41,29 +41,37 @@ export async function invalidateAllSubmissionKeys( for (const key of keys) { const queryKey = [ - key, hruid, language, version, classid, assignmentNumber, groupNumber, submissionNumber - ].filter( - (arg) => arg !== undefined, - ); + key, + hruid, + language, + version, + classid, + assignmentNumber, + groupNumber, + submissionNumber, + ].filter((arg) => arg !== undefined); await queryClient.invalidateQueries({ queryKey: queryKey }); } await queryClient.invalidateQueries({ - queryKey: ["submissions", hruid, language, version, classid, assignmentNumber, groupNumber] - .filter((arg) => arg !== undefined), + queryKey: ["submissions", hruid, language, version, classid, assignmentNumber, groupNumber].filter( + (arg) => arg !== undefined, + ), }); await queryClient.invalidateQueries({ - queryKey: ["group-submissions", hruid, language, version, classid, assignmentNumber, groupNumber] - .filter((arg) => arg !== undefined), + queryKey: ["group-submissions", hruid, language, version, classid, assignmentNumber, groupNumber].filter( + (arg) => arg !== undefined, + ), }); await queryClient.invalidateQueries({ - queryKey: ["assignment-submissions", hruid, language, version,classid, assignmentNumber] - .filter((arg) => arg !== undefined), + queryKey: ["assignment-submissions", hruid, language, version, classid, assignmentNumber].filter( + (arg) => arg !== undefined, + ), }); } function checkEnabled(properties: MaybeRefOrGetter[]): boolean { - return properties.every(prop => Boolean(toValue(prop))); + return properties.every((prop) => Boolean(toValue(prop))); } export function useSubmissionsQuery( @@ -87,9 +95,14 @@ export function useSubmissionsQuery( const fullVal = toValue(full); const response = await new SubmissionController(hruidVal!).getAll( - languageVal, versionVal!, classIdVal!, assignmentNumberVal!, groupNumberVal, fullVal + languageVal, + versionVal!, + classIdVal!, + assignmentNumberVal!, + groupNumberVal, + fullVal, ); - return response ? response.submissions as SubmissionDTO[] : undefined; + return response ? (response.submissions as SubmissionDTO[]) : undefined; }, enabled: () => checkEnabled([hruid, language, version, classid, assignmentNumber]), }); @@ -113,13 +126,33 @@ export function useSubmissionQuery( const submissionNumberVal = toValue(submissionNumber); return useQuery({ - queryKey: computed(() => submissionQueryKey( - hruidVal!, languageVal, versionVal!, classIdVal!, assignmentNumberVal!, groupNumberVal!, submissionNumberVal! - )), - queryFn: async () => new SubmissionController(hruidVal!).getByNumber( - languageVal, versionVal!, classIdVal!, assignmentNumberVal!, groupNumberVal!, submissionNumberVal! + queryKey: computed(() => + submissionQueryKey( + hruidVal!, + languageVal, + versionVal!, + classIdVal!, + assignmentNumberVal!, + groupNumberVal!, + submissionNumberVal!, + ), ), - enabled: () => Boolean(hruidVal) && Boolean(languageVal) && Boolean(versionVal) && Boolean(classIdVal) && Boolean(assignmentNumberVal) && Boolean(submissionNumber), + queryFn: async () => + new SubmissionController(hruidVal!).getByNumber( + languageVal, + versionVal!, + classIdVal!, + assignmentNumberVal!, + groupNumberVal!, + submissionNumberVal!, + ), + enabled: () => + Boolean(hruidVal) && + Boolean(languageVal) && + Boolean(versionVal) && + Boolean(classIdVal) && + Boolean(assignmentNumberVal) && + Boolean(submissionNumber), }); } @@ -132,7 +165,8 @@ export function useCreateSubmissionMutation(): UseMutationReturnType< const queryClient = useQueryClient(); return useMutation({ - mutationFn: async ({ data }) => new SubmissionController(data.learningObjectIdentifier.hruid).createSubmission(data), + mutationFn: async ({ data }) => + new SubmissionController(data.learningObjectIdentifier.hruid).createSubmission(data), onSuccess: async (response) => { if (!response.submission.group) { await invalidateAllSubmissionKeys(queryClient); @@ -144,13 +178,13 @@ export function useCreateSubmissionMutation(): UseMutationReturnType< const an = typeof assignment === "number" ? assignment : assignment.id; const gn = response.submission.group.groupNumber; - const {hruid, language, version} = response.submission.learningObjectIdentifier; + const { hruid, language, version } = response.submission.learningObjectIdentifier; await invalidateAllSubmissionKeys(queryClient, hruid, language, version, cid, an, gn); - await queryClient.invalidateQueries({queryKey: [LEARNING_PATH_KEY, "get"]}); + await queryClient.invalidateQueries({ queryKey: [LEARNING_PATH_KEY, "get"] }); await queryClient.invalidateQueries({ - queryKey: [LEARNING_OBJECT_KEY, "metadata", hruid, language, version] + queryKey: [LEARNING_OBJECT_KEY, "metadata", hruid, language, version], }); } }, @@ -178,15 +212,9 @@ export function useDeleteSubmissionMutation(): UseMutationReturnType< const an = typeof assignment === "number" ? assignment : assignment.id; const gn = response.submission.group.groupNumber; - const {hruid, language, version} = response.submission.learningObjectIdentifier; + const { hruid, language, version } = response.submission.learningObjectIdentifier; - await invalidateAllSubmissionKeys( - queryClient, - hruid, - language, - version, - cid, an, gn - ); + await invalidateAllSubmissionKeys(queryClient, hruid, language, version, cid, an, gn); } }, }); diff --git a/frontend/src/utils/deep-equals.ts b/frontend/src/utils/deep-equals.ts index 94099dc1..2edc1be2 100644 --- a/frontend/src/utils/deep-equals.ts +++ b/frontend/src/utils/deep-equals.ts @@ -1,20 +1,29 @@ export function deepEquals(a: T, b: T): boolean { - if (a === b) {return true;} + if (a === b) { + return true; + } - if (typeof a !== 'object' || typeof b !== 'object' || a == null || b == null) - {return false;} + if (typeof a !== "object" || typeof b !== "object" || a == null || b == null) { + return false; + } - if (Array.isArray(a) !== Array.isArray(b)) {return false;} + if (Array.isArray(a) !== Array.isArray(b)) { + return false; + } if (Array.isArray(a) && Array.isArray(b)) { - if (a.length !== b.length) {return false;} + if (a.length !== b.length) { + return false; + } return a.every((val, i) => deepEquals(val, b[i])); } const keysA = Object.keys(a) as (keyof T)[]; const keysB = Object.keys(b) as (keyof T)[]; - if (keysA.length !== keysB.length) {return false;} + if (keysA.length !== keysB.length) { + return false; + } - return keysA.every(key => deepEquals(a[key], b[key])); + return keysA.every((key) => deepEquals(a[key], b[key])); } diff --git a/frontend/src/views/assignments/CreateAssignment.vue b/frontend/src/views/assignments/CreateAssignment.vue index 51a3fc15..fd2264f6 100644 --- a/frontend/src/views/assignments/CreateAssignment.vue +++ b/frontend/src/views/assignments/CreateAssignment.vue @@ -1,5 +1,5 @@ diff --git a/frontend/src/views/learning-paths/LearningPathGroupSelector.vue b/frontend/src/views/learning-paths/LearningPathGroupSelector.vue index dc3be31d..f6ae4027 100644 --- a/frontend/src/views/learning-paths/LearningPathGroupSelector.vue +++ b/frontend/src/views/learning-paths/LearningPathGroupSelector.vue @@ -1,24 +1,24 @@ diff --git a/frontend/src/views/learning-paths/LearningPathPage.vue b/frontend/src/views/learning-paths/LearningPathPage.vue index fb3a3c35..953e70d1 100644 --- a/frontend/src/views/learning-paths/LearningPathPage.vue +++ b/frontend/src/views/learning-paths/LearningPathPage.vue @@ -3,7 +3,7 @@ import type { LearningPath } from "@/data-objects/learning-paths/learning-path.ts"; import { computed, type ComputedRef, ref } from "vue"; import type { LearningObject } from "@/data-objects/learning-objects/learning-object.ts"; - import {useRoute, useRouter} from "vue-router"; + import { useRoute, useRouter } from "vue-router"; import LearningObjectView from "@/views/learning-paths/learning-object/LearningObjectView.vue"; import { useI18n } from "vue-i18n"; import LearningPathSearchField from "@/components/LearningPathSearchField.vue"; @@ -21,7 +21,7 @@ const props = defineProps<{ hruid: string; language: Language; - learningObjectHruid?: string, + learningObjectHruid?: string; }>(); interface LearningPathPageQuery { @@ -37,7 +37,7 @@ return { forGroup: parseInt(query.value.forGroup), assignmentNo: parseInt(query.value.assignmentNo), - classId: query.value.classId + classId: query.value.classId, }; } }); @@ -112,7 +112,7 @@ let query = structuredClone(route.query); query.forGroup = value; router.push({ query }); - } + }, }); function assign() { @@ -120,8 +120,8 @@ path: "/assignment/create", query: { hruid: props.hruid, - language: props.language - } + language: props.language, + }, }); } @@ -136,80 +136,86 @@ :width="350" >
- - - - - - - - - - - -
- - - + diff --git a/frontend/src/views/learning-paths/learning-object/submissions/LearningObjectSubmissionsView.vue b/frontend/src/views/learning-paths/learning-object/submissions/LearningObjectSubmissionsView.vue index 25d3ce6f..ee541eb2 100644 --- a/frontend/src/views/learning-paths/learning-object/submissions/LearningObjectSubmissionsView.vue +++ b/frontend/src/views/learning-paths/learning-object/submissions/LearningObjectSubmissionsView.vue @@ -1,26 +1,25 @@