diff --git a/apps/server/src/modules/learnroom/controller/rooms.controller.ts b/apps/server/src/modules/learnroom/controller/rooms.controller.ts
index fe8f8d67671..0e0b2f7c7a0 100644
--- a/apps/server/src/modules/learnroom/controller/rooms.controller.ts
+++ b/apps/server/src/modules/learnroom/controller/rooms.controller.ts
@@ -2,7 +2,7 @@ import { Body, Controller, Get, Param, Patch, Post } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { RequestTimeout } from '@shared/common';
import { ICurrentUser, Authenticate, CurrentUser } from '@modules/authentication';
-import { CopyApiResponse, CopyElementType, CopyMapper } from '@modules/copy-helper';
+import { CopyApiResponse, CopyMapper } from '@modules/copy-helper';
import { serverConfig } from '@modules/server/server.config';
import { RoomBoardResponseMapper } from '../mapper/room-board-response.mapper';
import { CourseCopyUC } from '../uc/course-copy.uc';
diff --git a/apps/server/src/modules/lesson/service/lesson-copy.service.spec.ts b/apps/server/src/modules/lesson/service/lesson-copy.service.spec.ts
index 91e20a54668..11432af777f 100644
--- a/apps/server/src/modules/lesson/service/lesson-copy.service.spec.ts
+++ b/apps/server/src/modules/lesson/service/lesson-copy.service.spec.ts
@@ -176,21 +176,105 @@ describe('lesson copy service', () => {
expect(lesson.hidden).toEqual(true);
});
- describe('the response', () => {
- it('should set status title to the name of the lesson', async () => {
- const { destinationCourse, originalLesson, user, copyName } = setup();
+ describe('the response', () => {
+ it('should set status title to the name of the lesson', async () => {
+ const { destinationCourse, originalLesson, user, copyName } = setup();
+
+ const status = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ copyName,
+ });
+
+ expect(status.title).toEqual(copyName);
+ });
+
+ it('should set status type to lesson', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
+
+ const status = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+
+ expect(status.type).toEqual(CopyElementType.LESSON);
+ });
+
+ it('should set status originalEntity to original lesson', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
+
+ const status = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+
+ expect(status.originalEntity).toEqual(originalLesson);
+ });
+
+ it('should set lesson status', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
+
+ const status = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+
+ expect(status.status).toEqual(CopyStatusEnum.SUCCESS);
+ });
+
+ it('should set status of metadata', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
+
+ const status = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+
+ const metadataStatus = status.elements?.find((el) => el.type === CopyElementType.METADATA);
+ expect(metadataStatus).toBeDefined();
+ expect(metadataStatus?.status).toEqual(CopyStatusEnum.SUCCESS);
+ });
+ });
+ });
+
+ describe('when copying into a different course', () => {
+ it('should set destination course as course of the copy', async () => {
+ const originalCourse = courseFactory.build({});
+ const destinationCourse = courseFactory.buildWithId();
+ const user = userFactory.build({});
+ const originalLesson = lessonFactory.build({ course: originalCourse });
+ lessonRepo.findById.mockResolvedValueOnce(originalLesson);
const status = await copyService.copyLesson({
originalLessonId: originalLesson.id,
destinationCourse,
user,
- copyName,
});
+ const lesson = status.copyEntity as LessonEntity;
- expect(status.title).toEqual(copyName);
+ expect(lesson.course).toEqual(destinationCourse);
});
+ });
+
+ describe('when lesson contains no content', () => {
+ const setup = () => {
+ const user = userFactory.build();
+ const originalCourse = courseFactory.build({ school: user.school });
+ const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const originalLesson = lessonFactory.build({
+ course: originalCourse,
+ });
+ lessonRepo.findById.mockResolvedValueOnce(originalLesson);
+
+ return { user, originalCourse, destinationCourse, originalLesson };
+ };
- it('should set status type to lesson', async () => {
+ it('contents array of copied lesson should be empty', async () => {
const { user, destinationCourse, originalLesson } = setup();
const status = await copyService.copyLesson({
@@ -199,10 +283,12 @@ describe('lesson copy service', () => {
user,
});
- expect(status.type).toEqual(CopyElementType.LESSON);
+ const lesson = status.copyEntity as LessonEntity;
+
+ expect(lesson.contents.length).toEqual(0);
});
- it('should set status originalEntity to original lesson', async () => {
+ it('should not set contents status group', async () => {
const { user, destinationCourse, originalLesson } = setup();
const status = await copyService.copyLesson({
@@ -210,11 +296,50 @@ describe('lesson copy service', () => {
destinationCourse,
user,
});
-
- expect(status.originalEntity).toEqual(originalLesson);
+ const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
+ expect(contentsStatus).not.toBeDefined();
});
+ });
+
+ describe('when lesson contains at least one content element', () => {
+ const setup = () => {
+ const contentOne: IComponentProperties = {
+ title: 'title component 1',
+ hidden: false,
+ component: ComponentType.TEXT,
+ content: {
+ text: 'this is a text content',
+ },
+ };
+ const contentTwo: IComponentProperties = {
+ title: 'title component 2',
+ hidden: false,
+ component: ComponentType.LERNSTORE,
+ content: {
+ resources: [
+ {
+ url: 'http://foo.bar',
+ title: 'foo',
+ description: 'bar',
+ client: 'client',
+ merlinReference: '',
+ },
+ ],
+ },
+ };
+ const user = userFactory.build();
+ const originalCourse = courseFactory.build({ school: user.school });
+ const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const originalLesson = lessonFactory.build({
+ course: originalCourse,
+ contents: [contentOne, contentTwo],
+ });
+ lessonRepo.findById.mockResolvedValueOnce(originalLesson);
+ copyHelperService.deriveStatusFromElements.mockReturnValue(CopyStatusEnum.SUCCESS);
+ return { user, originalCourse, destinationCourse, originalLesson };
+ };
- it('should set lesson status', async () => {
+ it('contents array of copied lesson should contain content elments of original lesson', async () => {
const { user, destinationCourse, originalLesson } = setup();
const status = await copyService.copyLesson({
@@ -223,11 +348,16 @@ describe('lesson copy service', () => {
user,
});
- expect(status.status).toEqual(CopyStatusEnum.SUCCESS);
+ const lesson = status.copyEntity as LessonEntity;
+
+ expect(lesson.contents.length).toEqual(2);
+ expect(lesson.contents).toEqual(originalLesson.contents);
});
- it('should set status of metadata', async () => {
+ it('copied content should persist the original hidden value', async () => {
const { user, destinationCourse, originalLesson } = setup();
+ originalLesson.contents[0].hidden = true;
+ originalLesson.contents[1].hidden = false;
const status = await copyService.copyLesson({
originalLessonId: originalLesson.id,
@@ -235,46 +365,66 @@ describe('lesson copy service', () => {
user,
});
- const metadataStatus = status.elements?.find((el) => el.type === CopyElementType.METADATA);
- expect(metadataStatus).toBeDefined();
- expect(metadataStatus?.status).toEqual(CopyStatusEnum.SUCCESS);
+ const lesson = status.copyEntity as LessonEntity;
+
+ expect(lesson.contents[0].hidden).toEqual(true);
+ expect(lesson.contents[1].hidden).toEqual(false);
});
- });
- });
- describe('when copying into a different course', () => {
- it('should set destination course as course of the copy', async () => {
- const originalCourse = courseFactory.build({});
- const destinationCourse = courseFactory.buildWithId();
- const user = userFactory.build({});
- const originalLesson = lessonFactory.build({ course: originalCourse });
- lessonRepo.findById.mockResolvedValueOnce(originalLesson);
+ it('should set contents status group with correct amount of children status elements', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
+ const status = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+ const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
+ expect(contentsStatus).toBeDefined();
+ expect(contentsStatus?.elements?.length).toEqual(2);
+ if (contentsStatus?.elements && contentsStatus?.elements[0]) {
+ expect(contentsStatus?.elements[0].status).toEqual(CopyStatusEnum.SUCCESS);
+ }
});
- const lesson = status.copyEntity as LessonEntity;
- expect(lesson.course).toEqual(destinationCourse);
+ it('should set contents status group with correct status', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
+
+ const status = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+ const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
+ expect(contentsStatus).toBeDefined();
+ expect(contentsStatus?.status).toEqual(CopyStatusEnum.SUCCESS);
+ });
});
});
- describe('when lesson contains no content', () => {
- const setup = () => {
+ describe('when lesson contains text content element', () => {
+ const setup = (text = 'this is a text content') => {
+ const textContent: IComponentProperties = {
+ title: 'text component 1',
+ hidden: false,
+ component: ComponentType.TEXT,
+ content: {
+ text,
+ },
+ };
const user = userFactory.build();
const originalCourse = courseFactory.build({ school: user.school });
const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
const originalLesson = lessonFactory.build({
course: originalCourse,
+ contents: [textContent],
});
lessonRepo.findById.mockResolvedValueOnce(originalLesson);
- return { user, originalCourse, destinationCourse, originalLesson };
+ return { user, originalCourse, destinationCourse, originalLesson, textContent };
};
- it('contents array of copied lesson should be empty', async () => {
+ it('should set content type to LESSON_CONTENT_TEXT', async () => {
const { user, destinationCourse, originalLesson } = setup();
const status = await copyService.copyLesson({
@@ -282,46 +432,57 @@ describe('lesson copy service', () => {
destinationCourse,
user,
});
-
- const lesson = status.copyEntity as LessonEntity;
-
- expect(lesson.contents.length).toEqual(0);
+ const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
+ expect(contentsStatus).toBeDefined();
+ if (contentsStatus?.elements) {
+ expect(contentsStatus.elements[0].type).toEqual(CopyElementType.LESSON_CONTENT_TEXT);
+ expect(contentsStatus.elements[0].status).toEqual(CopyStatusEnum.SUCCESS);
+ }
});
- it('should not set contents status group', async () => {
- const { user, destinationCourse, originalLesson } = setup();
+ it('should replace copied urls in lesson text', async () => {
+ const FILE_ID_TO_BE_REPLACED = '12837461287346091823z490812374098127340987123';
+ const NEW_FILE_ID = '19843275091827465871246598716239438';
+ const { user, destinationCourse, originalLesson } = setup(
+ `Here is a link to a file`
+ );
+
+ copyFilesService.copyFilesOfEntity.mockResolvedValue({
+ fileUrlReplacements: [
+ {
+ regex: new RegExp(FILE_ID_TO_BE_REPLACED),
+ replacement: NEW_FILE_ID,
+ },
+ ],
+ fileCopyStatus: { type: CopyElementType.FILE_GROUP, status: CopyStatusEnum.SUCCESS },
+ });
const status = await copyService.copyLesson({
originalLessonId: originalLesson.id,
destinationCourse,
user,
});
+
+ const lessonCopy = status.copyEntity as LessonEntity;
const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
- expect(contentsStatus).not.toBeDefined();
+ expect(contentsStatus).toBeDefined();
+ expect((lessonCopy.contents[0].content as IComponentTextProperties).text).not.toContain(FILE_ID_TO_BE_REPLACED);
});
});
- describe('when lesson contains at least one content element', () => {
+ describe('when lesson contains LernStore content element', () => {
const setup = () => {
- const contentOne: IComponentProperties = {
- title: 'title component 1',
- hidden: false,
- component: ComponentType.TEXT,
- content: {
- text: 'this is a text content',
- },
- };
- const contentTwo: IComponentProperties = {
- title: 'title component 2',
+ const lernStoreContent: IComponentProperties = {
+ title: 'text component 1',
hidden: false,
component: ComponentType.LERNSTORE,
content: {
resources: [
{
- url: 'http://foo.bar',
- title: 'foo',
- description: 'bar',
- client: 'client',
+ url: 'https://foo.bar/baz',
+ title: 'Test title',
+ description: 'description',
+ client: 'Schul-Cloud',
merlinReference: '',
},
],
@@ -332,15 +493,15 @@ describe('lesson copy service', () => {
const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
const originalLesson = lessonFactory.build({
course: originalCourse,
- contents: [contentOne, contentTwo],
+ contents: [lernStoreContent],
});
lessonRepo.findById.mockResolvedValueOnce(originalLesson);
- copyHelperService.deriveStatusFromElements.mockReturnValue(CopyStatusEnum.SUCCESS);
- return { user, originalCourse, destinationCourse, originalLesson };
+
+ return { user, originalCourse, destinationCourse, originalLesson, lernStoreContent };
};
- it('contents array of copied lesson should contain content elments of original lesson', async () => {
- const { user, destinationCourse, originalLesson } = setup();
+ it('the content should be fully copied', async () => {
+ const { user, destinationCourse, originalLesson, lernStoreContent } = setup();
const status = await copyService.copyLesson({
originalLessonId: originalLesson.id,
@@ -348,46 +509,60 @@ describe('lesson copy service', () => {
user,
});
- const lesson = status.copyEntity as LessonEntity;
-
- expect(lesson.contents.length).toEqual(2);
- expect(lesson.contents).toEqual(originalLesson.contents);
+ const copiedLessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
+ expect(copiedLessonContents[0]).toEqual(lernStoreContent);
});
- it('copied content should persist the original hidden value', async () => {
+ it('should set content type to LESSON_CONTENT_LERNSTORE', async () => {
const { user, destinationCourse, originalLesson } = setup();
- originalLesson.contents[0].hidden = true;
- originalLesson.contents[1].hidden = false;
const status = await copyService.copyLesson({
originalLessonId: originalLesson.id,
destinationCourse,
user,
});
+ const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
+ expect(contentsStatus).toBeDefined();
+ if (contentsStatus?.elements) {
+ expect(contentsStatus.elements[0].type).toEqual(CopyElementType.LESSON_CONTENT_LERNSTORE);
+ expect(contentsStatus.elements[0].status).toEqual(CopyStatusEnum.SUCCESS);
+ }
+ });
+ });
- const lesson = status.copyEntity as LessonEntity;
+ describe('when lesson contains LernStore content element without set resource', () => {
+ const setup = () => {
+ const lernStoreContent: IComponentProperties = {
+ title: 'text component 1',
+ hidden: false,
+ component: ComponentType.LERNSTORE,
+ };
+ const user = userFactory.build();
+ const originalCourse = courseFactory.build({ school: user.school });
+ const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const originalLesson = lessonFactory.build({
+ course: originalCourse,
+ contents: [lernStoreContent],
+ });
+ lessonRepo.findById.mockResolvedValueOnce(originalLesson);
- expect(lesson.contents[0].hidden).toEqual(true);
- expect(lesson.contents[1].hidden).toEqual(false);
- });
+ return { user, originalCourse, destinationCourse, originalLesson, lernStoreContent };
+ };
- it('should set contents status group with correct amount of children status elements', async () => {
- const { user, destinationCourse, originalLesson } = setup();
+ it('the content should be fully copied', async () => {
+ const { user, destinationCourse, originalLesson, lernStoreContent } = setup();
const status = await copyService.copyLesson({
originalLessonId: originalLesson.id,
destinationCourse,
user,
});
- const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
- expect(contentsStatus).toBeDefined();
- expect(contentsStatus?.elements?.length).toEqual(2);
- if (contentsStatus?.elements && contentsStatus?.elements[0]) {
- expect(contentsStatus?.elements[0].status).toEqual(CopyStatusEnum.SUCCESS);
- }
+
+ const copiedLessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
+ expect(copiedLessonContents[0]).toEqual(lernStoreContent);
});
- it('should set contents status group with correct status', async () => {
+ it('should set content type to LESSON_CONTENT_LERNSTORE', async () => {
const { user, destinationCourse, originalLesson } = setup();
const status = await copyService.copyLesson({
@@ -397,695 +572,385 @@ describe('lesson copy service', () => {
});
const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
expect(contentsStatus).toBeDefined();
- expect(contentsStatus?.status).toEqual(CopyStatusEnum.SUCCESS);
- });
- });
- });
-
- describe('when lesson contains text content element', () => {
- const setup = (text = 'this is a text content') => {
- const textContent: IComponentProperties = {
- title: 'text component 1',
- hidden: false,
- component: ComponentType.TEXT,
- content: {
- text,
- },
- };
- const user = userFactory.build();
- const originalCourse = courseFactory.build({ school: user.school });
- const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const originalLesson = lessonFactory.build({
- course: originalCourse,
- contents: [textContent],
- });
- lessonRepo.findById.mockResolvedValueOnce(originalLesson);
-
- return { user, originalCourse, destinationCourse, originalLesson, textContent };
- };
-
- it('should set content type to LESSON_CONTENT_TEXT', async () => {
- const { user, destinationCourse, originalLesson } = setup();
-
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
+ if (contentsStatus?.elements) {
+ expect(contentsStatus.elements[0].type).toEqual(CopyElementType.LESSON_CONTENT_LERNSTORE);
+ expect(contentsStatus.elements[0].status).toEqual(CopyStatusEnum.SUCCESS);
+ }
});
- const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
- expect(contentsStatus).toBeDefined();
- if (contentsStatus?.elements) {
- expect(contentsStatus.elements[0].type).toEqual(CopyElementType.LESSON_CONTENT_TEXT);
- expect(contentsStatus.elements[0].status).toEqual(CopyStatusEnum.SUCCESS);
- }
});
- it('should replace copied urls in lesson text', async () => {
- const FILE_ID_TO_BE_REPLACED = '12837461287346091823z490812374098127340987123';
- const NEW_FILE_ID = '19843275091827465871246598716239438';
- const { user, destinationCourse, originalLesson } = setup(
- `Here is a link to a file`
- );
-
- copyFilesService.copyFilesOfEntity.mockResolvedValue({
- fileUrlReplacements: [
- {
- regex: new RegExp(FILE_ID_TO_BE_REPLACED),
- replacement: NEW_FILE_ID,
+ describe('when lesson contains geoGebra content element', () => {
+ const setup = () => {
+ const geoGebraContent: IComponentProperties = {
+ title: 'text component 1',
+ hidden: false,
+ component: ComponentType.GEOGEBRA,
+ content: {
+ materialId: 'foo',
},
- ],
- fileCopyStatus: { type: CopyElementType.FILE_GROUP, status: CopyStatusEnum.SUCCESS },
- });
-
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
- });
-
- const lessonCopy = status.copyEntity as LessonEntity;
- const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
- expect(contentsStatus).toBeDefined();
- expect((lessonCopy.contents[0].content as IComponentTextProperties).text).not.toContain(FILE_ID_TO_BE_REPLACED);
- });
- });
+ };
+ const user = userFactory.build();
+ const originalCourse = courseFactory.build({ school: user.school });
+ const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const originalLesson = lessonFactory.build({
+ course: originalCourse,
+ contents: [geoGebraContent],
+ });
+ lessonRepo.findById.mockResolvedValueOnce(originalLesson);
- describe('when lesson contains LernStore content element', () => {
- const setup = () => {
- const lernStoreContent: IComponentProperties = {
- title: 'text component 1',
- hidden: false,
- component: ComponentType.LERNSTORE,
- content: {
- resources: [
- {
- url: 'https://foo.bar/baz',
- title: 'Test title',
- description: 'description',
- client: 'Schul-Cloud',
- merlinReference: '',
- },
- ],
- },
+ return { user, originalCourse, destinationCourse, originalLesson };
};
- const user = userFactory.build();
- const originalCourse = courseFactory.build({ school: user.school });
- const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const originalLesson = lessonFactory.build({
- course: originalCourse,
- contents: [lernStoreContent],
- });
- lessonRepo.findById.mockResolvedValueOnce(originalLesson);
- return { user, originalCourse, destinationCourse, originalLesson, lernStoreContent };
- };
+ it('geoGebra Material-ID should not be copied', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
+
+ const status = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
- it('the content should be fully copied', async () => {
- const { user, destinationCourse, originalLesson, lernStoreContent } = setup();
+ const lessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
+ const geoGebraContent = lessonContents[0].content as IComponentGeogebraProperties;
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
+ expect(geoGebraContent.materialId).toEqual('');
});
- const copiedLessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
- expect(copiedLessonContents[0]).toEqual(lernStoreContent);
- });
-
- it('should set content type to LESSON_CONTENT_LERNSTORE', async () => {
- const { user, destinationCourse, originalLesson } = setup();
+ it('element should be hidden', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
- });
- const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
- expect(contentsStatus).toBeDefined();
- if (contentsStatus?.elements) {
- expect(contentsStatus.elements[0].type).toEqual(CopyElementType.LESSON_CONTENT_LERNSTORE);
- expect(contentsStatus.elements[0].status).toEqual(CopyStatusEnum.SUCCESS);
- }
- });
- });
+ const status = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
- describe('when lesson contains LernStore content element without set resource', () => {
- const setup = () => {
- const lernStoreContent: IComponentProperties = {
- title: 'text component 1',
- hidden: false,
- component: ComponentType.LERNSTORE,
- };
- const user = userFactory.build();
- const originalCourse = courseFactory.build({ school: user.school });
- const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const originalLesson = lessonFactory.build({
- course: originalCourse,
- contents: [lernStoreContent],
+ const lessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
+ expect(lessonContents[0].hidden).toEqual(true);
});
- lessonRepo.findById.mockResolvedValueOnce(originalLesson);
- return { user, originalCourse, destinationCourse, originalLesson, lernStoreContent };
- };
+ it('content status should have correct status value', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
- it('the content should be fully copied', async () => {
- const { user, destinationCourse, originalLesson, lernStoreContent } = setup();
+ const status = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
+ const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
+ expect(contentsStatus).toBeDefined();
+ if (contentsStatus?.elements) {
+ expect(contentsStatus.elements[0].status).toEqual(CopyStatusEnum.PARTIAL);
+ }
});
- const copiedLessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
- expect(copiedLessonContents[0]).toEqual(lernStoreContent);
- });
-
- it('should set content type to LESSON_CONTENT_LERNSTORE', async () => {
- const { user, destinationCourse, originalLesson } = setup();
+ it('should set content type to LESSON_CONTENT_GEOGEBRA', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
+ const status = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+ const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
+ expect(contentsStatus).toBeDefined();
+ if (contentsStatus?.elements) {
+ expect(contentsStatus.elements[0].type).toEqual(CopyElementType.LESSON_CONTENT_GEOGEBRA);
+ }
});
- const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
- expect(contentsStatus).toBeDefined();
- if (contentsStatus?.elements) {
- expect(contentsStatus.elements[0].type).toEqual(CopyElementType.LESSON_CONTENT_LERNSTORE);
- expect(contentsStatus.elements[0].status).toEqual(CopyStatusEnum.SUCCESS);
- }
});
- });
- describe('when lesson contains geoGebra content element', () => {
- const setup = () => {
- const geoGebraContent: IComponentProperties = {
- title: 'text component 1',
- hidden: false,
- component: ComponentType.GEOGEBRA,
- content: {
- materialId: 'foo',
- },
- };
- const user = userFactory.build();
- const originalCourse = courseFactory.build({ school: user.school });
- const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const originalLesson = lessonFactory.build({
- course: originalCourse,
- contents: [geoGebraContent],
- });
- lessonRepo.findById.mockResolvedValueOnce(originalLesson);
+ describe('when lesson contains linked tasks', () => {
+ describe('when no tasks are linked to the original lesson', () => {
+ const setup = () => {
+ const user = userFactory.build();
+ const originalCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const originalLesson = lessonFactory.build({
+ course: originalCourse,
+ });
- return { user, originalCourse, destinationCourse, originalLesson };
- };
+ return {
+ user,
+ destinationCourse,
+ originalLesson,
+ };
+ };
- it('geoGebra Material-ID should not be copied', async () => {
- const { user, destinationCourse, originalLesson } = setup();
+ it('should not set task status', async () => {
+ const { originalLesson, destinationCourse, user } = setup();
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
+ const copyStatus = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+ const tasksGroupStatus = copyStatus.elements?.find((el) => el.type === CopyElementType.TASK_GROUP);
+ expect(tasksGroupStatus).not.toBeDefined();
+ });
});
- const lessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
- const geoGebraContent = lessonContents[0].content as IComponentGeogebraProperties;
-
- expect(geoGebraContent.materialId).toEqual('');
- });
+ describe('when a single task is linked to the original lesson', () => {
+ const setup = () => {
+ const user = userFactory.build();
+ const originalCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const originalLesson = lessonFactory.build({
+ course: originalCourse,
+ });
+ lessonRepo.findById.mockResolvedValueOnce(originalLesson);
+ const originalTask = taskFactory.build({
+ course: originalCourse,
+ lesson: originalLesson,
+ });
+ const taskCopy = taskFactory.build({ name: originalTask.name });
+ const mockedTaskStatus = {
+ title: taskCopy.name,
+ type: CopyElementType.TASK,
+ status: CopyStatusEnum.SUCCESS,
+ copyEntity: taskCopy,
+ };
+ const mockedTaskGroupStatus = {
+ type: CopyElementType.TASK_GROUP,
+ status: CopyStatusEnum.SUCCESS,
+ elements: [mockedTaskStatus],
+ };
+ taskCopyService.copyTask.mockResolvedValue(mockedTaskStatus);
- it('element should be hidden', async () => {
- const { user, destinationCourse, originalLesson } = setup();
+ return {
+ user,
+ destinationCourse,
+ originalLesson,
+ originalTask,
+ mockedTaskStatus,
+ mockedTaskGroupStatus,
+ };
+ };
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
- });
+ it('should put copy status tasks leaf', async () => {
+ const { originalLesson, destinationCourse, user, mockedTaskGroupStatus } = setup();
- const lessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
- expect(lessonContents[0].hidden).toEqual(true);
- });
+ const copyStatus = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+ const tasksGroupStatus = copyStatus.elements?.find((el) => el.type === CopyElementType.TASK_GROUP);
+ expect(tasksGroupStatus).toBeDefined();
+ expect(tasksGroupStatus).toEqual(mockedTaskGroupStatus);
+ });
- it('content status should have correct status value', async () => {
- const { user, destinationCourse, originalLesson } = setup();
+ it('should put copy status for the copied task', async () => {
+ const { originalLesson, originalTask, destinationCourse, user, mockedTaskStatus } = setup();
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
+ const copyStatus = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+ const tasksGroupStatus = copyStatus.elements?.find((el) => el.type === CopyElementType.TASK_GROUP);
+ expect(tasksGroupStatus).toBeDefined();
+ const tasksStatus = tasksGroupStatus?.elements?.find(
+ (el) => el.type === CopyElementType.TASK && el.title === originalTask.name
+ );
+ expect(tasksStatus).toBeDefined();
+ expect(tasksStatus).toEqual(mockedTaskStatus);
+ });
});
- const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
- expect(contentsStatus).toBeDefined();
- if (contentsStatus?.elements) {
- expect(contentsStatus.elements[0].status).toEqual(CopyStatusEnum.PARTIAL);
- }
- });
+ describe('when mupltiple tasks are linked to the original lesson', () => {
+ const setup = () => {
+ const user = userFactory.build();
+ const originalCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const originalLesson = lessonFactory.build({
+ course: originalCourse,
+ });
+ lessonRepo.findById.mockResolvedValueOnce(originalLesson);
+ const originalTasks = taskFactory.buildList(2, {
+ course: originalCourse,
+ lesson: originalLesson,
+ });
+ const taskCopyOne = taskFactory.build({ name: originalTasks[0].name });
+ const taskCopyTwo = taskFactory.build({ name: originalTasks[1].name });
+ const mockedTaskStatusOne = {
+ title: taskCopyOne.name,
+ type: CopyElementType.TASK,
+ status: CopyStatusEnum.SUCCESS,
+ copyEntity: taskCopyOne,
+ };
+ const mockedTaskStatusTwo = {
+ title: taskCopyTwo.name,
+ type: CopyElementType.TASK,
+ status: CopyStatusEnum.SUCCESS,
+ copyEntity: taskCopyTwo,
+ };
+ taskCopyService.copyTask
+ .mockResolvedValueOnce(mockedTaskStatusOne)
+ .mockResolvedValueOnce(mockedTaskStatusTwo);
+
+ return {
+ user,
+ destinationCourse,
+ originalLesson,
+ mockedTaskStatusOne,
+ mockedTaskStatusTwo,
+ };
+ };
- it('should set content type to LESSON_CONTENT_GEOGEBRA', async () => {
- const { user, destinationCourse, originalLesson } = setup();
+ it('should put copy status for each copied task under tasks', async () => {
+ const { originalLesson, destinationCourse, user, mockedTaskStatusOne, mockedTaskStatusTwo } = setup();
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
+ const copyStatus = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+ const tasksGroupStatus = copyStatus.elements?.find((el) => el.type === CopyElementType.TASK_GROUP);
+ expect(tasksGroupStatus).toBeDefined();
+ expect(tasksGroupStatus?.elements).toEqual([mockedTaskStatusOne, mockedTaskStatusTwo]);
+ });
});
- const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
- expect(contentsStatus).toBeDefined();
- if (contentsStatus?.elements) {
- expect(contentsStatus.elements[0].type).toEqual(CopyElementType.LESSON_CONTENT_GEOGEBRA);
- }
});
- });
- describe('when lesson contains linked tasks', () => {
- describe('when no tasks are linked to the original lesson', () => {
+ describe('when lesson contains Etherpad content element', () => {
const setup = () => {
+ const etherpadContent: IComponentProperties = {
+ title: 'text',
+ hidden: false,
+ component: ComponentType.ETHERPAD,
+ content: {
+ description: 'foo',
+ title: 'bar',
+ url: 'baz',
+ },
+ };
const user = userFactory.build();
- const originalCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const originalCourse = courseFactory.build({ school: user.school });
const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
const originalLesson = lessonFactory.build({
course: originalCourse,
+ contents: [etherpadContent],
});
+ lessonRepo.findById.mockResolvedValueOnce(originalLesson);
- return {
- user,
- destinationCourse,
- originalLesson,
- };
- };
+ etherpadService.createEtherpad.mockResolvedValue('abc');
- it('should not set task status', async () => {
- const { originalLesson, destinationCourse, user } = setup();
+ configurationSpy = jest.spyOn(Configuration, 'get').mockImplementation((config: string) => {
+ if (config === 'FEATURE_ETHERPAD_ENABLED') {
+ return true;
+ }
+ if (config === 'ETHERPAD__PAD_URI') {
+ return 'http://pad.uri';
+ }
+ return null;
+ });
- const copyStatus = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
- });
- const tasksGroupStatus = copyStatus.elements?.find((el) => el.type === CopyElementType.TASK_GROUP);
- expect(tasksGroupStatus).not.toBeDefined();
- });
- });
-
- describe('when a single task is linked to the original lesson', () => {
- const setup = () => {
- const user = userFactory.build();
- const originalCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const originalLesson = lessonFactory.build({
- course: originalCourse,
- });
- lessonRepo.findById.mockResolvedValueOnce(originalLesson);
- const originalTask = taskFactory.build({
- course: originalCourse,
- lesson: originalLesson,
- });
- const taskCopy = taskFactory.build({ name: originalTask.name });
- const mockedTaskStatus = {
- title: taskCopy.name,
- type: CopyElementType.TASK,
- status: CopyStatusEnum.SUCCESS,
- copyEntity: taskCopy,
- };
- const mockedTaskGroupStatus = {
- type: CopyElementType.TASK_GROUP,
- status: CopyStatusEnum.SUCCESS,
- elements: [mockedTaskStatus],
- };
- taskCopyService.copyTask.mockResolvedValue(mockedTaskStatus);
-
- return {
- user,
- destinationCourse,
- originalLesson,
- originalTask,
- mockedTaskStatus,
- mockedTaskGroupStatus,
- };
+ return { user, originalCourse, destinationCourse, originalLesson };
};
- it('should put copy status tasks leaf', async () => {
- const { originalLesson, destinationCourse, user, mockedTaskGroupStatus } = setup();
+ it('should not call etherpad service, if feature flag is false', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
+ configurationSpy = jest.spyOn(Configuration, 'get').mockReturnValue(false);
- const copyStatus = await copyService.copyLesson({
+ const status = await copyService.copyLesson({
originalLessonId: originalLesson.id,
destinationCourse,
user,
});
- const tasksGroupStatus = copyStatus.elements?.find((el) => el.type === CopyElementType.TASK_GROUP);
- expect(tasksGroupStatus).toBeDefined();
- expect(tasksGroupStatus).toEqual(mockedTaskGroupStatus);
+
+ const lessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
+ expect(configurationSpy).toHaveBeenCalledWith('FEATURE_ETHERPAD_ENABLED');
+ expect(etherpadService.createEtherpad).not.toHaveBeenCalled();
+ expect(lessonContents).toEqual([]);
+
+ configurationSpy = jest.spyOn(Configuration, 'get').mockReturnValue(true);
});
- it('should put copy status for the copied task', async () => {
- const { originalLesson, originalTask, destinationCourse, user, mockedTaskStatus } = setup();
+ it('should call etherpad service to create new etherpad', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
- const copyStatus = await copyService.copyLesson({
+ await copyService.copyLesson({
originalLessonId: originalLesson.id,
destinationCourse,
user,
});
- const tasksGroupStatus = copyStatus.elements?.find((el) => el.type === CopyElementType.TASK_GROUP);
- expect(tasksGroupStatus).toBeDefined();
- const tasksStatus = tasksGroupStatus?.elements?.find(
- (el) => el.type === CopyElementType.TASK && el.title === originalTask.name
- );
- expect(tasksStatus).toBeDefined();
- expect(tasksStatus).toEqual(mockedTaskStatus);
- });
- });
- describe('when mupltiple tasks are linked to the original lesson', () => {
- const setup = () => {
- const user = userFactory.build();
- const originalCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const originalLesson = lessonFactory.build({
- course: originalCourse,
- });
- lessonRepo.findById.mockResolvedValueOnce(originalLesson);
- const originalTasks = taskFactory.buildList(2, {
- course: originalCourse,
- lesson: originalLesson,
- });
- const taskCopyOne = taskFactory.build({ name: originalTasks[0].name });
- const taskCopyTwo = taskFactory.build({ name: originalTasks[1].name });
- const mockedTaskStatusOne = {
- title: taskCopyOne.name,
- type: CopyElementType.TASK,
- status: CopyStatusEnum.SUCCESS,
- copyEntity: taskCopyOne,
- };
- const mockedTaskStatusTwo = {
- title: taskCopyTwo.name,
- type: CopyElementType.TASK,
- status: CopyStatusEnum.SUCCESS,
- copyEntity: taskCopyTwo,
- };
- taskCopyService.copyTask.mockResolvedValueOnce(mockedTaskStatusOne).mockResolvedValueOnce(mockedTaskStatusTwo);
+ expect(etherpadService.createEtherpad).toHaveBeenCalled();
+ });
- return {
- user,
- destinationCourse,
- originalLesson,
- mockedTaskStatusOne,
- mockedTaskStatusTwo,
- };
- };
+ it('should not copy the etherpad content, if etherpad creation fails', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
- it('should put copy status for each copied task under tasks', async () => {
- const { originalLesson, destinationCourse, user, mockedTaskStatusOne, mockedTaskStatusTwo } = setup();
+ etherpadService.createEtherpad.mockResolvedValue(false);
- const copyStatus = await copyService.copyLesson({
+ const status = await copyService.copyLesson({
originalLessonId: originalLesson.id,
destinationCourse,
user,
});
- const tasksGroupStatus = copyStatus.elements?.find((el) => el.type === CopyElementType.TASK_GROUP);
- expect(tasksGroupStatus).toBeDefined();
- expect(tasksGroupStatus?.elements).toEqual([mockedTaskStatusOne, mockedTaskStatusTwo]);
- });
- });
- });
-
- describe('when lesson contains Etherpad content element', () => {
- const setup = () => {
- const etherpadContent: IComponentProperties = {
- title: 'text',
- hidden: false,
- component: ComponentType.ETHERPAD,
- content: {
- description: 'foo',
- title: 'bar',
- url: 'baz',
- },
- };
- const user = userFactory.build();
- const originalCourse = courseFactory.build({ school: user.school });
- const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const originalLesson = lessonFactory.build({
- course: originalCourse,
- contents: [etherpadContent],
- });
- lessonRepo.findById.mockResolvedValueOnce(originalLesson);
- etherpadService.createEtherpad.mockResolvedValue('abc');
-
- configurationSpy = jest.spyOn(Configuration, 'get').mockImplementation((config: string) => {
- if (config === 'FEATURE_ETHERPAD_ENABLED') {
- return true;
- }
- if (config === 'ETHERPAD__PAD_URI') {
- return 'http://pad.uri';
+ let contentStatus = CopyStatusEnum.SUCCESS;
+ const group = status.elements?.filter((element) => element.type === CopyElementType.LESSON_CONTENT_GROUP)[0];
+ if (group && group.elements) {
+ contentStatus = group.elements[0].status;
}
- return null;
- });
-
- return { user, originalCourse, destinationCourse, originalLesson };
- };
-
- it('should not call etherpad service, if feature flag is false', async () => {
- const { user, destinationCourse, originalLesson } = setup();
- configurationSpy = jest.spyOn(Configuration, 'get').mockReturnValue(false);
-
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
- });
-
- const lessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
- expect(configurationSpy).toHaveBeenCalledWith('FEATURE_ETHERPAD_ENABLED');
- expect(etherpadService.createEtherpad).not.toHaveBeenCalled();
- expect(lessonContents).toEqual([]);
-
- configurationSpy = jest.spyOn(Configuration, 'get').mockReturnValue(true);
- });
+ expect(contentStatus).toEqual(CopyStatusEnum.FAIL);
- it('should call etherpad service to create new etherpad', async () => {
- const { user, destinationCourse, originalLesson } = setup();
-
- await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
- });
-
- expect(etherpadService.createEtherpad).toHaveBeenCalled();
- });
-
- it('should not copy the etherpad content, if etherpad creation fails', async () => {
- const { user, destinationCourse, originalLesson } = setup();
-
- etherpadService.createEtherpad.mockResolvedValue(false);
-
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
- });
-
- let contentStatus = CopyStatusEnum.SUCCESS;
- const group = status.elements?.filter((element) => element.type === CopyElementType.LESSON_CONTENT_GROUP)[0];
- if (group && group.elements) {
- contentStatus = group.elements[0].status;
- }
- expect(contentStatus).toEqual(CopyStatusEnum.FAIL);
-
- const lessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
- expect(lessonContents.length).toEqual(0);
- });
-
- it('should copy etherpad correctly', async () => {
- const { user, destinationCourse, originalLesson } = setup();
-
- etherpadService.createEtherpad.mockResolvedValue('abc');
-
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
- });
- const copiedLessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
- const copiedEtherpad = copiedLessonContents[0].content as IComponentEtherpadProperties;
- expect(copiedEtherpad.url).toEqual('http://pad.uri/abc');
- });
-
- it('should set content type to LESSON_CONTENT_ETHERPAD', async () => {
- const { user, destinationCourse, originalLesson } = setup();
-
- etherpadService.createEtherpad.mockResolvedValue('abc');
-
- const status = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
- });
- const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
- expect(contentsStatus).toBeDefined();
- if (contentsStatus?.elements) {
- expect(contentsStatus.elements[0].type).toEqual(CopyElementType.LESSON_CONTENT_ETHERPAD);
- }
- });
- });
-
- describe('when lesson contains embedded task element', () => {
- const setup = () => {
- const user = userFactory.build();
- const originalCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const embeddedTaskContent: IComponentProperties = {
- title: 'title',
- hidden: false,
- component: ComponentType.INTERNAL,
- content: {
- url: 'http://somebasedomain.de/homework/someid',
- },
- };
- const originalLesson = lessonFactory.build({
- course: originalCourse,
- contents: [embeddedTaskContent],
- });
- lessonRepo.findById.mockResolvedValueOnce(originalLesson);
-
- return {
- user,
- destinationCourse,
- originalLesson,
- embeddedTaskContent,
- };
- };
-
- it('should add status for embedded task as SUCCESS', async () => {
- const { originalLesson, destinationCourse, user } = setup();
- const copyStatus = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
- });
-
- const contentsStatus = copyStatus.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
- if (!contentsStatus || !contentsStatus.elements || contentsStatus.elements.length < 1) {
- throw new Error('element not found');
- }
- const embeddedTaskStatus = contentsStatus.elements[0];
-
- expect(embeddedTaskStatus.status).toEqual(CopyStatusEnum.SUCCESS);
- });
-
- it('should add embedded task to copy', async () => {
- const { originalLesson, destinationCourse, user, embeddedTaskContent } = setup();
- const copyStatus = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
- });
- const lesson = copyStatus.copyEntity as LessonEntity;
- const embeddedTaskLink = lesson.contents.find((el) => el.component === ComponentType.INTERNAL);
-
- expect(embeddedTaskLink).toEqual(embeddedTaskContent);
- });
-
- it('should set content type to LESSON_CONTENT_TASK', async () => {
- const { user, destinationCourse, originalLesson } = setup();
- const copyStatus = await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
- });
- const contentsStatus = copyStatus.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
- expect(contentsStatus).toBeDefined();
- if (contentsStatus?.elements) {
- expect(contentsStatus.elements[0].type).toEqual(CopyElementType.LESSON_CONTENT_TASK);
- }
- });
- });
-
- describe('when lesson contains neXboard content element', () => {
- const setup = () => {
- const nexboardContent: IComponentProperties = {
- title: 'text',
- hidden: false,
- component: ComponentType.NEXBOARD,
- content: {
- board: '123',
- description: 'foo',
- title: 'bar',
- url: 'baz',
- },
- };
- const user = userFactory.build();
- const originalCourse = courseFactory.build({ school: user.school });
- const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const originalLesson = lessonFactory.build({
- course: originalCourse,
- contents: [nexboardContent],
+ const lessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
+ expect(lessonContents.length).toEqual(0);
});
- lessonRepo.findById.mockResolvedValueOnce(originalLesson);
- nexboardService.createNexboard.mockResolvedValue({ board: '123', url: 'abc' });
-
- configurationSpy = jest.spyOn(Configuration, 'get').mockImplementation((config: string) => {
- if (config === 'FEATURE_NEXBOARD_ENABLED') {
- return true;
- }
- return null;
- });
+ it('should copy etherpad correctly', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
- return { user, originalCourse, destinationCourse, originalLesson };
- };
+ etherpadService.createEtherpad.mockResolvedValue('abc');
- it('should not copy neXboard', async () => {
- const { user, destinationCourse, originalLesson } = setup();
- const status = await copyService.copyLesson({
+ const status = await copyService.copyLesson({
originalLessonId: originalLesson.id,
destinationCourse,
user,
+ });
+ const copiedLessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
+ const copiedEtherpad = copiedLessonContents[0].content as IComponentEtherpadProperties;
+ expect(copiedEtherpad.url).toEqual('http://pad.uri/abc');
});
- const copiedLessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
- const hasNexboard = copiedLessonContents.some(content => content.component === ComponentType.NEXBOARD);
- expect(hasNexboard).toBe(false);
- });
- it('should call neXboard service to create new neXboard', async () => {
- const { user, destinationCourse, originalLesson } = setup();
+ it('should set content type to LESSON_CONTENT_ETHERPAD', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
- await copyService.copyLesson({
- originalLessonId: originalLesson.id,
- destinationCourse,
- user,
- });
+ etherpadService.createEtherpad.mockResolvedValue('abc');
- expect(nexboardService.createNexboard).toHaveBeenCalled();
- });
-
- it('should not copy the neXboard content, if neXboard creation fails', async () => {
- const { user, destinationCourse, originalLesson } = setup();
- nexboardService.createNexboard.mockResolvedValue(false);
- const status = await copyService.copyLesson({
+ const status = await copyService.copyLesson({
originalLessonId: originalLesson.id,
destinationCourse,
user,
+ });
+ const contentsStatus = status.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
+ expect(contentsStatus).toBeDefined();
+ if (contentsStatus?.elements) {
+ expect(contentsStatus.elements[0].type).toEqual(CopyElementType.LESSON_CONTENT_ETHERPAD);
+ }
});
- const copiedLessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
- const hasNexboard = copiedLessonContents.some(content => content.component === ComponentType.NEXBOARD);
- expect(hasNexboard).toBe(false);
- });
-
- });
+ });
- describe('when lesson contains linked materials', () => {
- describe('when no materials are linked to the original lesson', () => {
+ describe('when lesson contains embedded task element', () => {
const setup = () => {
const user = userFactory.build();
const originalCourse = courseFactory.build({ school: user.school, teachers: [user] });
const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const embeddedTaskContent: IComponentProperties = {
+ title: 'title',
+ hidden: false,
+ component: ComponentType.INTERNAL,
+ content: {
+ url: 'http://somebasedomain.de/homework/someid',
+ },
+ };
const originalLesson = lessonFactory.build({
course: originalCourse,
+ contents: [embeddedTaskContent],
});
lessonRepo.findById.mockResolvedValueOnce(originalLesson);
@@ -1093,276 +958,412 @@ describe('lesson copy service', () => {
user,
destinationCourse,
originalLesson,
+ embeddedTaskContent,
};
};
- it('should not set materials status', async () => {
+ it('should add status for embedded task as SUCCESS', async () => {
const { originalLesson, destinationCourse, user } = setup();
-
const copyStatus = await copyService.copyLesson({
originalLessonId: originalLesson.id,
destinationCourse,
user,
});
- const materialsGroupStatus = copyStatus.elements?.find(
- (el) => el.type === CopyElementType.LERNSTORE_MATERIAL_GROUP
- );
- expect(materialsGroupStatus).not.toBeDefined();
- });
- });
-
- describe('when a single material is linked to the original lesson', () => {
- const setup = () => {
- const user = userFactory.build();
- const originalCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const originalMaterial = materialFactory.build();
- const originalLesson = lessonFactory.build({
- course: originalCourse,
- materials: [originalMaterial],
- });
- lessonRepo.findById.mockResolvedValueOnce(originalLesson);
- const materialCopy = materialFactory.build({ title: originalMaterial.title });
- const mockedMaterialStatus = {
- title: materialCopy.title,
- type: CopyElementType.LERNSTORE_MATERIAL,
- status: CopyStatusEnum.SUCCESS,
- copyEntity: materialCopy,
- };
- const mockedMaterialGroupStatus = {
- type: CopyElementType.LERNSTORE_MATERIAL_GROUP,
- status: CopyStatusEnum.SUCCESS,
- elements: [mockedMaterialStatus],
- };
- return {
- user,
- destinationCourse,
- originalLesson,
- originalMaterial,
- mockedMaterialStatus,
- mockedMaterialGroupStatus,
- };
- };
+ const contentsStatus = copyStatus.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
+ if (!contentsStatus || !contentsStatus.elements || contentsStatus.elements.length < 1) {
+ throw new Error('element not found');
+ }
+ const embeddedTaskStatus = contentsStatus.elements[0];
- it('should put copy status materials leaf', async () => {
- const { originalLesson, destinationCourse, user, mockedMaterialGroupStatus } = setup();
+ expect(embeddedTaskStatus.status).toEqual(CopyStatusEnum.SUCCESS);
+ });
+ it('should add embedded task to copy', async () => {
+ const { originalLesson, destinationCourse, user, embeddedTaskContent } = setup();
const copyStatus = await copyService.copyLesson({
originalLessonId: originalLesson.id,
destinationCourse,
user,
});
- const materialsGroupStatus = copyStatus.elements?.find(
- (el) => el.type === CopyElementType.LERNSTORE_MATERIAL_GROUP
- );
- expect(materialsGroupStatus).toBeDefined();
- expect(materialsGroupStatus).toEqual(mockedMaterialGroupStatus);
- });
+ const lesson = copyStatus.copyEntity as LessonEntity;
+ const embeddedTaskLink = lesson.contents.find((el) => el.component === ComponentType.INTERNAL);
- it('should put copy status for the copied material', async () => {
- const { originalLesson, originalMaterial, destinationCourse, user, mockedMaterialStatus } = setup();
+ expect(embeddedTaskLink).toEqual(embeddedTaskContent);
+ });
+ it('should set content type to LESSON_CONTENT_TASK', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
const copyStatus = await copyService.copyLesson({
originalLessonId: originalLesson.id,
destinationCourse,
user,
});
- const materialsGroupStatus = copyStatus.elements?.find(
- (el) => el.type === CopyElementType.LERNSTORE_MATERIAL_GROUP
- );
- expect(materialsGroupStatus).toBeDefined();
- const materialStatus = materialsGroupStatus?.elements?.find(
- (el) => el.type === CopyElementType.LERNSTORE_MATERIAL && el.title === originalMaterial.title
- );
- expect(materialStatus).toBeDefined();
- expect(materialStatus?.title).toEqual(mockedMaterialStatus.title);
- expect(materialStatus?.status).toEqual(mockedMaterialStatus.status);
- const material = materialStatus?.copyEntity as Material;
- expect(material?.description).toEqual(mockedMaterialStatus?.copyEntity?.description);
+ const contentsStatus = copyStatus.elements?.find((el) => el.type === CopyElementType.LESSON_CONTENT_GROUP);
+ expect(contentsStatus).toBeDefined();
+ if (contentsStatus?.elements) {
+ expect(contentsStatus.elements[0].type).toEqual(CopyElementType.LESSON_CONTENT_TASK);
+ }
});
});
- describe('when mupltiple materials are linked to the original lesson', () => {
+ describe('when lesson contains neXboard content element', () => {
const setup = () => {
+ const nexboardContent: IComponentProperties = {
+ title: 'text',
+ hidden: false,
+ component: ComponentType.NEXBOARD,
+ content: {
+ board: '123',
+ description: 'foo',
+ title: 'bar',
+ url: 'baz',
+ },
+ };
const user = userFactory.build();
- const originalCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const originalCourse = courseFactory.build({ school: user.school });
const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
- const originalMaterial = materialFactory.buildList(2);
const originalLesson = lessonFactory.build({
course: originalCourse,
- materials: originalMaterial,
+ contents: [nexboardContent],
});
lessonRepo.findById.mockResolvedValueOnce(originalLesson);
- const materialCopyOne = materialFactory.build({ title: originalMaterial[0].title });
- const materialCopyTwo = materialFactory.build({ title: originalMaterial[1].title });
- const mockedMaterialStatusOne = {
- title: materialCopyOne.title,
- type: CopyElementType.LERNSTORE_MATERIAL,
- status: CopyStatusEnum.SUCCESS,
- copyEntity: materialCopyOne,
- };
- const mockedMaterialStatusTwo = {
- title: materialCopyTwo.title,
- type: CopyElementType.LERNSTORE_MATERIAL,
- status: CopyStatusEnum.SUCCESS,
- copyEntity: materialCopyTwo,
- };
- return {
+ nexboardService.createNexboard.mockResolvedValue({ board: '123', url: 'abc' });
+
+ configurationSpy = jest.spyOn(Configuration, 'get').mockImplementation((config: string) => {
+ if (config === 'FEATURE_NEXBOARD_ENABLED') {
+ return true;
+ }
+ return null;
+ });
+
+ return { user, originalCourse, destinationCourse, originalLesson };
+ };
+
+ it('should not copy neXboard', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
+ const status = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
user,
+ });
+ const copiedLessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
+ const hasNexboard = copiedLessonContents.some((content) => content.component === ComponentType.NEXBOARD);
+ expect(hasNexboard).toBe(false);
+ });
+
+ it('should call neXboard service to create new neXboard', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
+
+ await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
destinationCourse,
- originalLesson,
- mockedMaterialStatusOne,
- mockedMaterialStatusTwo,
- };
- };
+ user,
+ });
- it('should put copy status for each copied material under materials', async () => {
- const { originalLesson, destinationCourse, user, mockedMaterialStatusOne, mockedMaterialStatusTwo } = setup();
+ expect(nexboardService.createNexboard).toHaveBeenCalled();
+ });
- const copyStatus = await copyService.copyLesson({
+ it('should not copy the neXboard content, if neXboard creation fails', async () => {
+ const { user, destinationCourse, originalLesson } = setup();
+ nexboardService.createNexboard.mockResolvedValue(false);
+ const status = await copyService.copyLesson({
originalLessonId: originalLesson.id,
destinationCourse,
user,
});
- const materialsGroupStatus = copyStatus.elements?.find(
- (el) => el.type === CopyElementType.LERNSTORE_MATERIAL_GROUP
- );
- expect(materialsGroupStatus).toBeDefined();
- expect(materialsGroupStatus?.elements?.map((el) => el.title)).toEqual([
- mockedMaterialStatusOne.title,
- mockedMaterialStatusTwo.title,
- ]);
+ const copiedLessonContents = (status.copyEntity as LessonEntity).contents as IComponentProperties[];
+ const hasNexboard = copiedLessonContents.some((content) => content.component === ComponentType.NEXBOARD);
+ expect(hasNexboard).toBe(false);
});
});
- });
- describe('updateCopiedEmbeddedTasks', () => {
- it('should leave non-lesson status as is', () => {
- const status = {
- type: CopyElementType.COURSE,
- status: CopyStatusEnum.SUCCESS,
- elements: [
- {
- type: CopyElementType.TASK,
- status: CopyStatusEnum.SUCCESS,
- },
- ],
- };
- const copyDict = copyHelperService.buildCopyEntityDict(status);
- const result = copyService.updateCopiedEmbeddedTasks(status, copyDict);
+ describe('when lesson contains linked materials', () => {
+ describe('when no materials are linked to the original lesson', () => {
+ const setup = () => {
+ const user = userFactory.build();
+ const originalCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const originalLesson = lessonFactory.build({
+ course: originalCourse,
+ });
+ lessonRepo.findById.mockResolvedValueOnce(originalLesson);
- expect(result).toEqual(status);
- });
+ return {
+ user,
+ destinationCourse,
+ originalLesson,
+ };
+ };
- describe('when status contains lesson with embedded tasks', () => {
- const setup = () => {
- const originalLesson = lessonFactory.buildWithId();
- const copiedLesson = lessonFactory.buildWithId();
- const originalTask = taskFactory.buildWithId({ lesson: originalLesson });
- const copiedTask = taskFactory.buildWithId({ lesson: copiedLesson });
- const embeddedTaskContent: IComponentProperties = {
- title: 'title',
- hidden: false,
- component: ComponentType.INTERNAL,
- content: {
- url: `http://somebasedomain.de/homeworks/${originalTask.id}`,
- },
+ it('should not set materials status', async () => {
+ const { originalLesson, destinationCourse, user } = setup();
+
+ const copyStatus = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+ const materialsGroupStatus = copyStatus.elements?.find(
+ (el) => el.type === CopyElementType.LERNSTORE_MATERIAL_GROUP
+ );
+ expect(materialsGroupStatus).not.toBeDefined();
+ });
+ });
+
+ describe('when a single material is linked to the original lesson', () => {
+ const setup = () => {
+ const user = userFactory.build();
+ const originalCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const originalMaterial = materialFactory.build();
+ const originalLesson = lessonFactory.build({
+ course: originalCourse,
+ materials: [originalMaterial],
+ });
+ lessonRepo.findById.mockResolvedValueOnce(originalLesson);
+ const materialCopy = materialFactory.build({ title: originalMaterial.title });
+ const mockedMaterialStatus = {
+ title: materialCopy.title,
+ type: CopyElementType.LERNSTORE_MATERIAL,
+ status: CopyStatusEnum.SUCCESS,
+ copyEntity: materialCopy,
+ };
+ const mockedMaterialGroupStatus = {
+ type: CopyElementType.LERNSTORE_MATERIAL_GROUP,
+ status: CopyStatusEnum.SUCCESS,
+ elements: [mockedMaterialStatus],
+ };
+
+ return {
+ user,
+ destinationCourse,
+ originalLesson,
+ originalMaterial,
+ mockedMaterialStatus,
+ mockedMaterialGroupStatus,
+ };
};
- const textContent: IComponentProperties = {
- title: 'title component',
- hidden: false,
- component: ComponentType.TEXT,
- content: {
- text: 'this is a text content',
- },
+
+ it('should put copy status materials leaf', async () => {
+ const { originalLesson, destinationCourse, user, mockedMaterialGroupStatus } = setup();
+
+ const copyStatus = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+ const materialsGroupStatus = copyStatus.elements?.find(
+ (el) => el.type === CopyElementType.LERNSTORE_MATERIAL_GROUP
+ );
+ expect(materialsGroupStatus).toBeDefined();
+ expect(materialsGroupStatus).toEqual(mockedMaterialGroupStatus);
+ });
+
+ it('should put copy status for the copied material', async () => {
+ const { originalLesson, originalMaterial, destinationCourse, user, mockedMaterialStatus } = setup();
+
+ const copyStatus = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+ const materialsGroupStatus = copyStatus.elements?.find(
+ (el) => el.type === CopyElementType.LERNSTORE_MATERIAL_GROUP
+ );
+ expect(materialsGroupStatus).toBeDefined();
+ const materialStatus = materialsGroupStatus?.elements?.find(
+ (el) => el.type === CopyElementType.LERNSTORE_MATERIAL && el.title === originalMaterial.title
+ );
+ expect(materialStatus).toBeDefined();
+ expect(materialStatus?.title).toEqual(mockedMaterialStatus.title);
+ expect(materialStatus?.status).toEqual(mockedMaterialStatus.status);
+ const material = materialStatus?.copyEntity as Material;
+ expect(material?.description).toEqual(mockedMaterialStatus?.copyEntity?.description);
+ });
+ });
+
+ describe('when mupltiple materials are linked to the original lesson', () => {
+ const setup = () => {
+ const user = userFactory.build();
+ const originalCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const destinationCourse = courseFactory.build({ school: user.school, teachers: [user] });
+ const originalMaterial = materialFactory.buildList(2);
+ const originalLesson = lessonFactory.build({
+ course: originalCourse,
+ materials: originalMaterial,
+ });
+ lessonRepo.findById.mockResolvedValueOnce(originalLesson);
+ const materialCopyOne = materialFactory.build({ title: originalMaterial[0].title });
+ const materialCopyTwo = materialFactory.build({ title: originalMaterial[1].title });
+ const mockedMaterialStatusOne = {
+ title: materialCopyOne.title,
+ type: CopyElementType.LERNSTORE_MATERIAL,
+ status: CopyStatusEnum.SUCCESS,
+ copyEntity: materialCopyOne,
+ };
+ const mockedMaterialStatusTwo = {
+ title: materialCopyTwo.title,
+ type: CopyElementType.LERNSTORE_MATERIAL,
+ status: CopyStatusEnum.SUCCESS,
+ copyEntity: materialCopyTwo,
+ };
+
+ return {
+ user,
+ destinationCourse,
+ originalLesson,
+ mockedMaterialStatusOne,
+ mockedMaterialStatusTwo,
+ };
};
- copiedLesson.contents = [{ ...textContent }, embeddedTaskContent, { ...textContent }];
- const copyStatus: CopyStatus = {
- type: CopyElementType.LESSON,
+
+ it('should put copy status for each copied material under materials', async () => {
+ const { originalLesson, destinationCourse, user, mockedMaterialStatusOne, mockedMaterialStatusTwo } = setup();
+
+ const copyStatus = await copyService.copyLesson({
+ originalLessonId: originalLesson.id,
+ destinationCourse,
+ user,
+ });
+ const materialsGroupStatus = copyStatus.elements?.find(
+ (el) => el.type === CopyElementType.LERNSTORE_MATERIAL_GROUP
+ );
+ expect(materialsGroupStatus).toBeDefined();
+ expect(materialsGroupStatus?.elements?.map((el) => el.title)).toEqual([
+ mockedMaterialStatusOne.title,
+ mockedMaterialStatusTwo.title,
+ ]);
+ });
+ });
+ });
+
+ describe('updateCopiedEmbeddedTasks', () => {
+ it('should leave non-lesson status as is', () => {
+ const status = {
+ type: CopyElementType.COURSE,
status: CopyStatusEnum.SUCCESS,
- originalEntity: originalLesson,
- copyEntity: copiedLesson,
elements: [
{
type: CopyElementType.TASK,
status: CopyStatusEnum.SUCCESS,
- originalEntity: originalTask,
- copyEntity: copiedTask,
- },
- {
- type: CopyElementType.LESSON_CONTENT_GROUP,
- status: CopyStatusEnum.PARTIAL,
- elements: [
- {
- type: CopyElementType.LESSON_CONTENT_TEXT,
- status: CopyStatusEnum.SUCCESS,
- },
- {
- type: CopyElementType.LESSON_CONTENT_TASK,
- status: CopyStatusEnum.SUCCESS,
- },
- {
- type: CopyElementType.LESSON_CONTENT_TEXT,
- status: CopyStatusEnum.SUCCESS,
- },
- ],
},
],
};
- const copyDict = new Map();
- copyDict.set(originalTask.id, copiedTask);
- copyHelperService.buildCopyEntityDict.mockReturnValue(copyDict);
- return { copyStatus, copiedTask, originalTask };
- };
+ const copyDict = copyHelperService.buildCopyEntityDict(status);
+ const result = copyService.updateCopiedEmbeddedTasks(status, copyDict);
- it('should update taskIds in lesson, if tasks were copied', () => {
- const { copyStatus, originalTask, copiedTask } = setup();
- const copyDict = copyHelperService.buildCopyEntityDict(copyStatus);
- const updatedCopyStatus = copyService.updateCopiedEmbeddedTasks(copyStatus, copyDict);
- const lesson = updatedCopyStatus?.copyEntity as LessonEntity;
- if (lesson === undefined || lesson.contents === undefined) {
- throw new Error('lesson should be part of the copy');
- }
- const content = lesson.contents.find((el) => el.component === ComponentType.INTERNAL);
- expect((content?.content as IComponentInternalProperties).url).not.toContain(originalTask.id);
- expect((content?.content as IComponentInternalProperties).url).toContain(copiedTask.id);
+ expect(result).toEqual(status);
});
- it('should maintain order of content elements', () => {
- const { copyStatus } = setup();
- const copyDict = copyHelperService.buildCopyEntityDict(copyStatus);
- const updatedCopyStatus = copyService.updateCopiedEmbeddedTasks(copyStatus, copyDict);
- const lesson = updatedCopyStatus?.copyEntity as LessonEntity;
- if (lesson === undefined || lesson.contents === undefined) {
- throw new Error('lesson should be part of the copy');
- }
- expect(lesson.contents[1].component).toEqual(ComponentType.INTERNAL);
- });
+ describe('when status contains lesson with embedded tasks', () => {
+ const setup = () => {
+ const originalLesson = lessonFactory.buildWithId();
+ const copiedLesson = lessonFactory.buildWithId();
+ const originalTask = taskFactory.buildWithId({ lesson: originalLesson });
+ const copiedTask = taskFactory.buildWithId({ lesson: copiedLesson });
+ const embeddedTaskContent: IComponentProperties = {
+ title: 'title',
+ hidden: false,
+ component: ComponentType.INTERNAL,
+ content: {
+ url: `http://somebasedomain.de/homeworks/${originalTask.id}`,
+ },
+ };
+ const textContent: IComponentProperties = {
+ title: 'title component',
+ hidden: false,
+ component: ComponentType.TEXT,
+ content: {
+ text: 'this is a text content',
+ },
+ };
+ copiedLesson.contents = [{ ...textContent }, embeddedTaskContent, { ...textContent }];
+ const copyStatus: CopyStatus = {
+ type: CopyElementType.LESSON,
+ status: CopyStatusEnum.SUCCESS,
+ originalEntity: originalLesson,
+ copyEntity: copiedLesson,
+ elements: [
+ {
+ type: CopyElementType.TASK,
+ status: CopyStatusEnum.SUCCESS,
+ originalEntity: originalTask,
+ copyEntity: copiedTask,
+ },
+ {
+ type: CopyElementType.LESSON_CONTENT_GROUP,
+ status: CopyStatusEnum.PARTIAL,
+ elements: [
+ {
+ type: CopyElementType.LESSON_CONTENT_TEXT,
+ status: CopyStatusEnum.SUCCESS,
+ },
+ {
+ type: CopyElementType.LESSON_CONTENT_TASK,
+ status: CopyStatusEnum.SUCCESS,
+ },
+ {
+ type: CopyElementType.LESSON_CONTENT_TEXT,
+ status: CopyStatusEnum.SUCCESS,
+ },
+ ],
+ },
+ ],
+ };
+ const copyDict = new Map();
+ copyDict.set(originalTask.id, copiedTask);
+ copyHelperService.buildCopyEntityDict.mockReturnValue(copyDict);
+ return { copyStatus, copiedTask, originalTask };
+ };
- it('should keep original url when task is not in dictionary (has not been copied)', () => {
- const { copyStatus, originalTask } = setup();
- copyHelperService.buildCopyEntityDict.mockReturnValue(new Map());
- const copyDict = copyHelperService.buildCopyEntityDict(copyStatus);
- const updatedCopyStatus = copyService.updateCopiedEmbeddedTasks(copyStatus, copyDict);
- const lesson = updatedCopyStatus?.copyEntity as LessonEntity;
- if (lesson === undefined || lesson.contents === undefined) {
- throw new Error('lesson should be part of the copy');
- }
- const content = lesson.contents.find((el) => el.component === ComponentType.INTERNAL);
- expect((content?.content as IComponentInternalProperties).url).toEqual(
- `http://somebasedomain.de/homeworks/${originalTask.id}`
- );
- });
+ it('should update taskIds in lesson, if tasks were copied', () => {
+ const { copyStatus, originalTask, copiedTask } = setup();
+ const copyDict = copyHelperService.buildCopyEntityDict(copyStatus);
+ const updatedCopyStatus = copyService.updateCopiedEmbeddedTasks(copyStatus, copyDict);
+ const lesson = updatedCopyStatus?.copyEntity as LessonEntity;
+ if (lesson === undefined || lesson.contents === undefined) {
+ throw new Error('lesson should be part of the copy');
+ }
+ const content = lesson.contents.find((el) => el.component === ComponentType.INTERNAL);
+ expect((content?.content as IComponentInternalProperties).url).not.toContain(originalTask.id);
+ expect((content?.content as IComponentInternalProperties).url).toContain(copiedTask.id);
+ });
+
+ it('should maintain order of content elements', () => {
+ const { copyStatus } = setup();
+ const copyDict = copyHelperService.buildCopyEntityDict(copyStatus);
+ const updatedCopyStatus = copyService.updateCopiedEmbeddedTasks(copyStatus, copyDict);
+ const lesson = updatedCopyStatus?.copyEntity as LessonEntity;
+ if (lesson === undefined || lesson.contents === undefined) {
+ throw new Error('lesson should be part of the copy');
+ }
+ expect(lesson.contents[1].component).toEqual(ComponentType.INTERNAL);
+ });
+
+ it('should keep original url when task is not in dictionary (has not been copied)', () => {
+ const { copyStatus, originalTask } = setup();
+ copyHelperService.buildCopyEntityDict.mockReturnValue(new Map());
+ const copyDict = copyHelperService.buildCopyEntityDict(copyStatus);
+ const updatedCopyStatus = copyService.updateCopiedEmbeddedTasks(copyStatus, copyDict);
+ const lesson = updatedCopyStatus?.copyEntity as LessonEntity;
+ if (lesson === undefined || lesson.contents === undefined) {
+ throw new Error('lesson should be part of the copy');
+ }
+ const content = lesson.contents.find((el) => el.component === ComponentType.INTERNAL);
+ expect((content?.content as IComponentInternalProperties).url).toEqual(
+ `http://somebasedomain.de/homeworks/${originalTask.id}`
+ );
+ });
- it('should use copyHelperService to build a dictionary', () => {
- const { copyStatus } = setup();
- const copyDict = copyHelperService.buildCopyEntityDict(copyStatus);
- copyService.updateCopiedEmbeddedTasks(copyStatus, copyDict);
- expect(copyHelperService.buildCopyEntityDict).toHaveBeenCalled();
+ it('should use copyHelperService to build a dictionary', () => {
+ const { copyStatus } = setup();
+ const copyDict = copyHelperService.buildCopyEntityDict(copyStatus);
+ copyService.updateCopiedEmbeddedTasks(copyStatus, copyDict);
+ expect(copyHelperService.buildCopyEntityDict).toHaveBeenCalled();
+ });
});
});
});
});
-});
diff --git a/apps/server/src/modules/lesson/service/lesson-copy.service.ts b/apps/server/src/modules/lesson/service/lesson-copy.service.ts
index abc81a84736..2e3dc7db872 100644
--- a/apps/server/src/modules/lesson/service/lesson-copy.service.ts
+++ b/apps/server/src/modules/lesson/service/lesson-copy.service.ts
@@ -227,15 +227,18 @@ export class LessonCopyService {
copiedContent.push(linkContent);
copiedContentStatus.push(embeddedTaskStatus);
}
- if (element.component === ComponentType.NEXBOARD) {
+ if (element.component === ComponentType.NEXBOARD && nexboardEnabled) {
// eslint-disable-next-line no-await-in-loop
const nexboardContent = await this.copyNexboard(element, params);
const nexboardStatus = {
title: element.title,
type: CopyElementType.LESSON_CONTENT_NEXBOARD,
- status: nexboardContent ? CopyStatusEnum.NOT_DOING : CopyStatusEnum.FAIL,
+ status: CopyStatusEnum.PARTIAL,
};
- copiedContentStatus.push(nexboardStatus);
+ if (nexboardContent) {
+ nexboardStatus.status = CopyStatusEnum.FAIL;
+ }
+ copiedContentStatus.push(nexboardStatus);
}
}
const contentStatus = this.lessonStatusContent(copiedContentStatus);