fix: Test- en linting-errors opgelost
This commit is contained in:
parent
ce5c0ea629
commit
ba912c3ef0
20 changed files with 103 additions and 116 deletions
|
@ -19,8 +19,7 @@ export async function getSubmissionsHandler(req: Request, res: Response): Promis
|
|||
|
||||
const forGroup = req.query.forGroup as string | undefined;
|
||||
|
||||
let submissions: SubmissionDTO[]
|
||||
submissions = await getSubmissionsForLearningObjectAndAssignment(
|
||||
const submissions: SubmissionDTO[] = await getSubmissionsForLearningObjectAndAssignment(
|
||||
loHruid,
|
||||
lang,
|
||||
version,
|
||||
|
|
|
@ -61,28 +61,36 @@ export class SubmissionRepository extends DwengoEntityRepository<Submission> {
|
|||
|
||||
/**
|
||||
* Looks up all submissions for the given learning object which were submitted as part of the given assignment.
|
||||
* When forGroup is set, only the submissions of the given group are shown.
|
||||
*/
|
||||
public async findAllSubmissionsForLearningObjectAndAssignment(
|
||||
loId: LearningObjectIdentifier,
|
||||
assignment: Assignment,
|
||||
forGroup?: number
|
||||
): Promise<Submission[]> {
|
||||
const onBehalfOf = forGroup
|
||||
? {
|
||||
assignment,
|
||||
groupNumber: forGroup
|
||||
}
|
||||
: {
|
||||
assignment,
|
||||
};
|
||||
|
||||
return this.findAll({
|
||||
where: {
|
||||
learningObjectHruid: loId.hruid,
|
||||
learningObjectLanguage: loId.language,
|
||||
learningObjectVersion: loId.version,
|
||||
onBehalfOf,
|
||||
onBehalfOf: {
|
||||
assignment
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up all submissions for the given learning object which were submitted by the given group
|
||||
*/
|
||||
public async findAllSubmissionsForLearningObjectAndGroup(
|
||||
loId: LearningObjectIdentifier,
|
||||
group: Group,
|
||||
): Promise<Submission[]> {
|
||||
return this.findAll({
|
||||
where: {
|
||||
learningObjectHruid: loId.hruid,
|
||||
learningObjectLanguage: loId.language,
|
||||
learningObjectVersion: loId.version,
|
||||
onBehalfOf: group
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -29,13 +29,13 @@ export class LearningPathRepository extends DwengoEntityRepository<LearningPath>
|
|||
}
|
||||
|
||||
public createNode(
|
||||
nodeData: RequiredEntityData<LearningPathNode, never, false>
|
||||
nodeData: RequiredEntityData<LearningPathNode>
|
||||
): LearningPathNode {
|
||||
return this.em.create(LearningPathNode, nodeData);
|
||||
}
|
||||
|
||||
public createTransition(
|
||||
transitionData: RequiredEntityData<LearningPathTransition, never, false>
|
||||
transitionData: RequiredEntityData<LearningPathTransition>
|
||||
): LearningPathTransition {
|
||||
return this.em.create(LearningPathTransition, transitionData)
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ export class LearningPathRepository extends DwengoEntityRepository<LearningPath>
|
|||
}
|
||||
const em = this.getEntityManager();
|
||||
await em.persistAndFlush(path);
|
||||
await Promise.all(nodes.map(it => em.persistAndFlush(it)));
|
||||
await Promise.all(transitions.map(it => em.persistAndFlush(it)));
|
||||
await Promise.all(nodes.map(async it => em.persistAndFlush(it)));
|
||||
await Promise.all(transitions.map(async it => em.persistAndFlush(it)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ export class LearningObject {
|
|||
@Property({ type: 'array' })
|
||||
keywords: string[] = [];
|
||||
|
||||
@Property({ type: new ArrayType(i => +i), nullable: true })
|
||||
@Property({ type: new ArrayType(i => Number(i)), nullable: true })
|
||||
targetAges?: number[] = [];
|
||||
|
||||
@Property({ type: 'bool' })
|
||||
|
|
|
@ -61,9 +61,9 @@ export function mapToLearningPath(
|
|||
next: toNode,
|
||||
condition: transDto.condition ?? "true"
|
||||
});
|
||||
} else {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
}).filter(it => it).map(it => it!);
|
||||
|
||||
fromNode.transitions = new Collection<LearningPathTransition>(fromNode, transitions);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {getAssignmentRepository, 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';
|
||||
|
@ -37,11 +37,8 @@ export async function createSubmission(submissionDTO: SubmissionDTO): Promise<Su
|
|||
|
||||
const submissionRepository = getSubmissionRepository();
|
||||
const submission = mapToSubmission(submissionDTO, submitter, group);
|
||||
try {
|
||||
await submissionRepository.save(submission);
|
||||
} catch (e) {
|
||||
"test"
|
||||
}
|
||||
|
||||
await submissionRepository.save(submission);
|
||||
|
||||
return mapToSubmissionDTO(submission);
|
||||
}
|
||||
|
@ -69,7 +66,13 @@ export async function getSubmissionsForLearningObjectAndAssignment(
|
|||
const loId = new LearningObjectIdentifier(learningObjectHruid, language, version);
|
||||
const assignment = await getAssignmentRepository().findByClassIdAndAssignmentId(classId, assignmentId);
|
||||
|
||||
const submissions = await getSubmissionRepository().findAllSubmissionsForLearningObjectAndAssignment(loId, assignment!, groupId);
|
||||
let submissions: Submission[];
|
||||
if (groupId !== undefined) {
|
||||
const group = await getGroupRepository().findByAssignmentAndGroupNumber(assignment!, groupId);
|
||||
submissions = await getSubmissionRepository().findAllSubmissionsForLearningObjectAndGroup(loId, group!);
|
||||
} else {
|
||||
submissions = await getSubmissionRepository().findAllSubmissionsForLearningObjectAndAssignment(loId, assignment!);
|
||||
}
|
||||
|
||||
return submissions.map((s) => mapToSubmissionDTO(s));
|
||||
}
|
||||
|
|
|
@ -27,7 +27,10 @@ export class SqliteAutoincrementSubscriber implements EventSubscriber {
|
|||
|
||||
for (const prop of Object.values(args.meta.properties)) {
|
||||
const property = prop as EntityProperty<T>;
|
||||
if (property.primary && property.autoincrement && !(args.entity as Record<string, unknown>)[property.name]) {
|
||||
if (
|
||||
property.primary && property.autoincrement
|
||||
&& (args.entity as Record<string, unknown>)[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;
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
* Convert a Base64-encoded string into a buffer with the same data.
|
||||
* @param base64 The Base64 encoded string.
|
||||
*/
|
||||
export function base64ToArrayBuffer(base64: string) {
|
||||
var binaryString = atob(base64);
|
||||
var bytes = new Uint8Array(binaryString.length);
|
||||
for (var i = 0; i < binaryString.length; i++) {
|
||||
export function base64ToArrayBuffer(base64: string): ArrayBuffer {
|
||||
const binaryString = atob(base64);
|
||||
const bytes = new Uint8Array(binaryString.length);
|
||||
for (let i = 0; i < binaryString.length; i++) {
|
||||
bytes[i] = binaryString.charCodeAt(i);
|
||||
}
|
||||
return bytes.buffer;
|
||||
|
|
|
@ -33,9 +33,10 @@ 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, 3, 4]);
|
||||
expect(resultIds).toEqual([1, 1, 3, 4]);
|
||||
});
|
||||
|
||||
it('should not find removed assignment', async () => {
|
||||
|
|
|
@ -91,9 +91,11 @@ describe('SubmissionRepository', () => {
|
|||
expect(result[2].submissionNumber).toBe(3);
|
||||
});
|
||||
|
||||
it("should find only the submissions for a certain learning object and assignment made for the user's group", async () => {
|
||||
const result = await submissionRepository.findAllSubmissionsForLearningObjectAndAssignment(loId, assignment!, 'Tool');
|
||||
// (student Tool is in group #2)
|
||||
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!
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ describe('LearningObjectRepository', () => {
|
|||
let newerExample: LearningObject;
|
||||
|
||||
it('should allow a learning object with the same id except a different version to be added', async () => {
|
||||
let testLearningObject01Newer = structuredClone(testLearningObject01);
|
||||
const testLearningObject01Newer = structuredClone(testLearningObject01);
|
||||
testLearningObject01Newer.version = 10;
|
||||
testLearningObject01Newer.title += " (nieuw)";
|
||||
testLearningObject01Newer.uuid = v4();
|
||||
|
|
|
@ -3,6 +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";
|
||||
|
||||
describe('LearningPathRepository', () => {
|
||||
let learningPathRepository: LearningPathRepository;
|
||||
|
@ -19,10 +20,12 @@ describe('LearningPathRepository', () => {
|
|||
});
|
||||
|
||||
it('should return requested learning path', async () => {
|
||||
const learningPath = await learningPathRepository.findByHruidAndLanguage('id01', Language.English);
|
||||
const learningPath = await learningPathRepository.findByHruidAndLanguage(
|
||||
testLearningPath01.hruid, testLearningPath01.language as Language
|
||||
);
|
||||
|
||||
expect(learningPath).toBeTruthy();
|
||||
expect(learningPath?.title).toBe('repertoire Tool');
|
||||
expect(learningPath?.description).toBe('all about Tool');
|
||||
expect(learningPath?.title).toBe(testLearningPath01.title);
|
||||
expect(learningPath?.description).toBe(testLearningPath01.description);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,7 +6,6 @@ import { getSubmissionRepository } from '../../../src/data/repositories.js';
|
|||
|
||||
import databaseLearningPathProvider from '../../../src/services/learning-paths/database-learning-path-provider.js';
|
||||
import { expectToBeCorrectLearningPath } from '../../test-utils/expectations.js';
|
||||
import learningObjectService from '../../../src/services/learning-objects/learning-object-service.js';
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
|
||||
import {
|
||||
|
@ -79,29 +78,13 @@ describe('DatabaseLearningPathProvider', () => {
|
|||
it('returns the learning path correctly', async () => {
|
||||
const result = await databaseLearningPathProvider.fetchLearningPaths(
|
||||
[testLearningPath.hruid],
|
||||
testLearningPath.language as Language,
|
||||
testLearningPath.language,
|
||||
'the source'
|
||||
);
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data?.length).toBe(1);
|
||||
|
||||
const learningObjectsOnPath = (
|
||||
await Promise.all(
|
||||
testLearningPath.nodes.map(async (node) =>
|
||||
learningObjectService.getLearningObjectById({
|
||||
hruid: node.learningObjectHruid,
|
||||
version: node.version,
|
||||
language: node.language,
|
||||
})
|
||||
)
|
||||
)
|
||||
).filter((it) => it !== null);
|
||||
|
||||
expectToBeCorrectLearningPath(
|
||||
result.data![0],
|
||||
mapToLearningPath(testLearningPathWithConditions, []),
|
||||
learningObjectsOnPath
|
||||
);
|
||||
expectToBeCorrectLearningPath(result.data![0], testLearningPathWithConditions);
|
||||
});
|
||||
it('returns the correct personalized learning path', async () => {
|
||||
// For student A:
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { AssertionError } from 'node:assert';
|
||||
import { LearningObject } from '../../src/entities/content/learning-object.entity';
|
||||
import { LearningPath as LearningPathEntity } from '../../src/entities/content/learning-path.entity';
|
||||
import { expect } from 'vitest';
|
||||
import { FilteredLearningObject, LearningPath } from '@dwengo-1/common/interfaces/learning-content';
|
||||
import {RequiredEntityData} from "@mikro-orm/core";
|
||||
|
@ -17,7 +16,7 @@ const IGNORE_PROPERTIES = ['parent'];
|
|||
export function expectToBeCorrectEntity<T extends object>(
|
||||
actual: T,
|
||||
expected: T,
|
||||
propertyPrefix: string = ""
|
||||
propertyPrefix = ""
|
||||
): void {
|
||||
for (const property in expected) {
|
||||
const prefixedProperty = propertyPrefix + property;
|
||||
|
@ -91,55 +90,41 @@ export function expectToBeCorrectFilteredLearningObject(filtered: FilteredLearni
|
|||
* is a correct representation of the given learning path entity.
|
||||
*
|
||||
* @param learningPath The learning path returned by the retriever, service or endpoint
|
||||
* @param expectedEntity The expected entity
|
||||
* @param learningObjectsOnPath The learning objects on LearningPath. Necessary since some information in
|
||||
* the learning path returned from the API endpoint
|
||||
* @param expected The learning path that should have been returned.
|
||||
*/
|
||||
export function expectToBeCorrectLearningPath(
|
||||
learningPath: LearningPath,
|
||||
expectedEntity: LearningPathEntity,
|
||||
learningObjectsOnPath: FilteredLearningObject[]
|
||||
expected: LearningPath
|
||||
): void {
|
||||
expect(learningPath.hruid).toEqual(expectedEntity.hruid);
|
||||
expect(learningPath.language).toEqual(expectedEntity.language);
|
||||
expect(learningPath.description).toEqual(expectedEntity.description);
|
||||
expect(learningPath.title).toEqual(expectedEntity.title);
|
||||
expect(learningPath.hruid).toEqual(expected.hruid);
|
||||
expect(learningPath.language).toEqual(expected.language);
|
||||
expect(learningPath.description).toEqual(expected.description);
|
||||
expect(learningPath.title).toEqual(expected.title);
|
||||
|
||||
const keywords = new Set(learningObjectsOnPath.flatMap((it) => it.keywords || []));
|
||||
expect(new Set(learningPath.keywords.split(' '))).toEqual(keywords);
|
||||
expect(new Set(learningPath.keywords.split(' '))).toEqual(new Set(learningPath.keywords.split(' ')));
|
||||
|
||||
const targetAges = new Set(learningObjectsOnPath.flatMap((it) => it.targetAges || []));
|
||||
expect(new Set(learningPath.target_ages)).toEqual(targetAges);
|
||||
expect(learningPath.min_age).toEqual(Math.min(...targetAges));
|
||||
expect(learningPath.max_age).toEqual(Math.max(...targetAges));
|
||||
expect(new Set(learningPath.target_ages)).toEqual(new Set(expected.target_ages));
|
||||
expect(learningPath.min_age).toEqual(Math.min(...expected.target_ages));
|
||||
expect(learningPath.max_age).toEqual(Math.max(...expected.target_ages));
|
||||
|
||||
expect(learningPath.num_nodes).toEqual(expectedEntity.nodes.length);
|
||||
expect(learningPath.image || null).toEqual(expectedEntity.image);
|
||||
expect(learningPath.num_nodes).toEqual(expected.nodes.length);
|
||||
expect(learningPath.image ?? null).toEqual(expected.image ?? null);
|
||||
|
||||
const expectedLearningPathNodes = new Map(
|
||||
expectedEntity.nodes.map((node) => [
|
||||
{ learningObjectHruid: node.learningObjectHruid, language: node.language, version: node.version },
|
||||
{ startNode: node.startNode, transitions: node.transitions },
|
||||
])
|
||||
);
|
||||
|
||||
for (const node of learningPath.nodes) {
|
||||
const nodeKey = {
|
||||
learningObjectHruid: node.learningobject_hruid,
|
||||
language: node.language,
|
||||
version: node.version,
|
||||
};
|
||||
expect(expectedLearningPathNodes.keys()).toContainEqual(nodeKey);
|
||||
const expectedNode = [...expectedLearningPathNodes.entries()].find(
|
||||
([key, _]) => key.learningObjectHruid === nodeKey.learningObjectHruid && key.language === node.language && key.version === node.version
|
||||
)![1];
|
||||
expect(Boolean(node.start_node)).toEqual(Boolean(expectedNode.startNode));
|
||||
|
||||
expect(new Set(node.transitions.map((it) => it.next.hruid))).toEqual(
|
||||
new Set(expectedNode.transitions.map((it) => it.next.learningObjectHruid))
|
||||
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
|
||||
);
|
||||
expect(new Set(node.transitions.map((it) => it.next.language))).toEqual(new Set(expectedNode.transitions.map((it) => it.next.language)));
|
||||
expect(new Set(node.transitions.map((it) => it.next.version))).toEqual(new Set(expectedNode.transitions.map((it) => it.next.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
|
||||
);
|
||||
expect(correspondingTransition).toBeTruthy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,13 +2,13 @@ import fs from 'fs';
|
|||
import path from 'node:path';
|
||||
import {fileURLToPath} from "node:url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const fileName = fileURLToPath(import.meta.url);
|
||||
const dirName = path.dirname(fileName);
|
||||
|
||||
/**
|
||||
* Load the asset at the given path.
|
||||
* @param relPath Path of the asset relative to the test-assets folder.
|
||||
*/
|
||||
export function loadTestAsset(relPath: string): Buffer {
|
||||
return fs.readFileSync(path.resolve(__dirname, `../test_assets/${relPath}`));
|
||||
return fs.readFileSync(path.resolve(dirName, `../test_assets/${relPath}`));
|
||||
}
|
||||
|
|
|
@ -75,26 +75,26 @@ let group04: Group;
|
|||
let group05: Group;
|
||||
let group1ConditionalLearningPath: Group;
|
||||
|
||||
export function getTestGroup01() {
|
||||
export function getTestGroup01(): Group {
|
||||
return group01;
|
||||
}
|
||||
|
||||
export function getTestGroup02() {
|
||||
export function getTestGroup02(): Group {
|
||||
return group02;
|
||||
}
|
||||
|
||||
export function getTestGroup03() {
|
||||
export function getTestGroup03(): Group {
|
||||
return group03;
|
||||
}
|
||||
|
||||
export function getTestGroup04() {
|
||||
export function getTestGroup04(): Group {
|
||||
return group04;
|
||||
}
|
||||
|
||||
export function getTestGroup05() {
|
||||
export function getTestGroup05(): Group {
|
||||
return group05;
|
||||
}
|
||||
|
||||
export function getGroup1ConditionalLearningPath() {
|
||||
export function getGroup1ConditionalLearningPath(): Group {
|
||||
return group1ConditionalLearningPath;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="learning-object-gift">
|
||||
<div id="gift-q1" class="gift-question">
|
||||
<div id="gift-q1" class="gift-question gift-question-type-Essay">
|
||||
<h2 id="gift-q1-title" class="gift-title">Reflection</h2>
|
||||
<p id="gift-q1-stem" class="gift-stem">Reflect on this learning path. What have you learned today?</p>
|
||||
<textarea id="gift-q1-answer" class="gift-essay-answer"></textarea>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="learning-object-gift">
|
||||
<div id="gift-q1" class="gift-question">
|
||||
<div id="gift-q1" class="gift-question gift-question-type-MC">
|
||||
<h2 id="gift-q1-title" class="gift-title">Self-evaluation</h2>
|
||||
<p id="gift-q1-stem" class="gift-stem">Are you following along well?</p>
|
||||
<div class="gift-choice-div">
|
||||
|
|
|
@ -176,7 +176,7 @@ export const testLearningPathWithConditions: LearningPathDTO = {
|
|||
title: 'Example learning path with conditional transitions',
|
||||
description: 'This learning path was made for the purpose of testing conditional transitions',
|
||||
keywords: "test",
|
||||
target_ages: [18, 19, 20, 21],
|
||||
target_ages: [10, 11, 12, 13, 14, 15, 16, 17, 18],
|
||||
nodes: [
|
||||
{
|
||||
learningobject_hruid: testLearningObjectMultipleChoice.hruid,
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue