Skip to content

Commit

Permalink
Bc 4572 rewrite courses to nest (#4358)
Browse files Browse the repository at this point in the history
* change name of lesson entity, add method in lesson repo and in lesson service

* modification in repos: lesson, course, coursegroup and add methon in lessonService

* add method for course service

* add service for courseGroup

* tests for services

* small changes

* change lesson into lesoonEntity in one test

* add method to course and courseGroup entity

* fixes after review

* fix tests in courseGroup entity

* changes in testcases after review
  • Loading branch information
WojciechGrancow authored Sep 20, 2023
1 parent f13eb0e commit cb7bf6d
Show file tree
Hide file tree
Showing 42 changed files with 675 additions and 168 deletions.
4 changes: 2 additions & 2 deletions apps/server/src/modules/copy-helper/mapper/copy.mapper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EntityId, Lesson, Task } from '@shared/domain';
import { EntityId, LessonEntity, Task } from '@shared/domain';
import { LessonCopyApiParams } from '@src/modules/learnroom/controller/dto/lesson/lesson-copy.params';
import { LessonCopyParentParams } from '@src/modules/lesson/types';
import { TaskCopyApiParams } from '@src/modules/task/controller/dto/task-copy.params';
Expand All @@ -15,7 +15,7 @@ export class CopyMapper {
});

if (copyStatus.copyEntity) {
const copyEntity = copyStatus.copyEntity as Lesson | Task;
const copyEntity = copyStatus.copyEntity as LessonEntity | Task;
dto.id = copyEntity.id;
dto.destinationCourseId = copyEntity.course?.id;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Lesson, Submission, Task } from '@shared/domain';
import { LessonEntity, Submission, Task } from '@shared/domain';

export type EntitiesWithFiles = Task | Lesson | Submission;
export type EntityWithEmbeddedFiles = Task | Lesson;
export type EntitiesWithFiles = Task | LessonEntity | Submission;
export type EntityWithEmbeddedFiles = Task | LessonEntity;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Lesson, Submission, Task } from '@shared/domain';
import { LessonEntity, Submission, Task } from '@shared/domain';
import { FileRecordParentType } from '@shared/infra/rabbitmq';
import { CopyFileDto, FileDto } from '../dto';
import { EntitiesWithFiles, ICopyFileDomainObjectProps, IFileDomainObjectProps } from '../interfaces';
Expand Down Expand Up @@ -60,7 +60,7 @@ export class FilesStorageClientMapper {
}

static mapEntityToParentType(entity: EntitiesWithFiles): FileRecordParentType {
if (entity instanceof Lesson) return FileRecordParentType.Lesson;
if (entity instanceof LessonEntity) return FileRecordParentType.Lesson;

if (entity instanceof Task) return FileRecordParentType.Task;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
Course,
isLesson,
isTask,
Lesson,
LessonEntity,
LessonBoardElement,
Task,
TaskBoardElement,
Expand Down Expand Up @@ -92,7 +92,7 @@ export class BoardCopyService {
return statuses;
}

private async copyLesson(originalLesson: Lesson, user: User, destinationCourse: Course): Promise<CopyStatus> {
private async copyLesson(originalLesson: LessonEntity, user: User, destinationCourse: Course): Promise<CopyStatus> {
return this.lessonCopyService.copyLesson({
originalLessonId: originalLesson.id,
user,
Expand All @@ -115,7 +115,7 @@ export class BoardCopyService {
const taskElement = new TaskBoardElement({ target: status.copyEntity });
references.push(taskElement);
}
if (status.copyEntity instanceof Lesson) {
if (status.copyEntity instanceof LessonEntity) {
const lessonElement = new LessonBoardElement({ target: status.copyEntity });
references.push(lessonElement);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { Test, TestingModule } from '@nestjs/testing';
import { ComponentType, Course, IComponentProperties, IComponentTextProperties, Lesson, Task } from '@shared/domain';
import {
ComponentType,
Course,
IComponentProperties,
IComponentTextProperties,
LessonEntity,
Task,
} from '@shared/domain';
import { courseFactory, lessonFactory, setupEntities, taskFactory } from '@shared/testing';
import { CommonCartridgeExportService } from '@src/modules/learnroom/service/common-cartridge-export.service';
import { CourseService } from '@src/modules/learnroom/service';
Expand All @@ -17,7 +24,7 @@ describe('CommonCartridgeExportService', () => {
let taskServiceMock: DeepMocked<TaskService>;

let course: Course;
let lessons: Lesson[];
let lessons: LessonEntity[];
let tasks: Task[];

beforeAll(async () => {
Expand Down
43 changes: 40 additions & 3 deletions apps/server/src/modules/learnroom/service/course.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { Test, TestingModule } from '@nestjs/testing';
import { Course } from '@shared/domain';
import { CourseRepo } from '@shared/repo';
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { CourseRepo, UserRepo } from '@shared/repo';
import { courseFactory, setupEntities, userFactory } from '@shared/testing';
import { CourseService } from './course.service';

describe('CourseService', () => {
let module: TestingModule;
let courseRepo: DeepMocked<CourseRepo>;
let courseService: CourseService;
let userRepo: DeepMocked<UserRepo>;

beforeAll(async () => {
await setupEntities();
module = await Test.createTestingModule({
providers: [
CourseService,
{
provide: UserRepo,
useValue: createMock<UserRepo>(),
},
{
provide: CourseRepo,
useValue: createMock<CourseRepo>(),
Expand All @@ -21,14 +28,15 @@ describe('CourseService', () => {
}).compile();
courseRepo = module.get(CourseRepo);
courseService = module.get(CourseService);
userRepo = module.get(UserRepo);
});

afterAll(async () => {
await module.close();
});

beforeEach(() => {
courseRepo.findById.mockClear();
jest.clearAllMocks();
});

describe('findById', () => {
Expand All @@ -41,4 +49,33 @@ describe('CourseService', () => {
expect(courseRepo.findById).toBeCalledWith(courseId);
});
});

describe('when deleting by userId', () => {
const setup = () => {
const user = userFactory.buildWithId();
const course1 = courseFactory.buildWithId({ students: [user] });
const course2 = courseFactory.buildWithId({ teachers: [user] });
const course3 = courseFactory.buildWithId({ substitutionTeachers: [user] });
const allCourses = [course1, course2, course3];

userRepo.findById.mockResolvedValue(user);
courseRepo.findAllByUserId.mockResolvedValue([allCourses, allCourses.length]);

return {
user,
};
};

it('should call courseRepo.findAllByUserId', async () => {
const { user } = setup();
await courseService.deleteUserDataFromCourse(user.id);
expect(courseRepo.findAllByUserId).toBeCalledWith(user.id);
});

it('should update courses without deleted user', async () => {
const { user } = setup();
const result = await courseService.deleteUserDataFromCourse(user.id);
expect(result).toEqual(3);
});
});
});
10 changes: 10 additions & 0 deletions apps/server/src/modules/learnroom/service/course.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,14 @@ export class CourseService {
async findById(courseId: EntityId): Promise<Course> {
return this.repo.findById(courseId);
}

public async deleteUserDataFromCourse(userId: EntityId): Promise<number> {
const [courses, count] = await this.repo.findAllByUserId(userId);

courses.forEach((course: Course) => course.removeUser(userId));

await this.repo.save(courses);

return count;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { Test, TestingModule } from '@nestjs/testing';
import { CourseGroupRepo, UserRepo } from '@shared/repo';
import { courseGroupFactory, setupEntities, userFactory } from '@shared/testing';
import { CourseGroupService } from './coursegroup.service';

describe('CourseGroupService', () => {
let module: TestingModule;
let courseGroupRepo: DeepMocked<CourseGroupRepo>;
let courseGroupService: CourseGroupService;
let userRepo: DeepMocked<UserRepo>;

beforeAll(async () => {
await setupEntities();
module = await Test.createTestingModule({
providers: [
CourseGroupService,
{
provide: UserRepo,
useValue: createMock<UserRepo>(),
},
{
provide: CourseGroupRepo,
useValue: createMock<CourseGroupRepo>(),
},
],
}).compile();
courseGroupRepo = module.get(CourseGroupRepo);
courseGroupService = module.get(CourseGroupService);
userRepo = module.get(UserRepo);
});

afterAll(async () => {
await module.close();
});

beforeEach(() => {
jest.clearAllMocks();
});

describe('when deleting by userId', () => {
const setup = () => {
const user = userFactory.buildWithId();
const courseGroup1 = courseGroupFactory.buildWithId({ students: [user] });
const courseGroup2 = courseGroupFactory.buildWithId({ students: [user] });

userRepo.findById.mockResolvedValue(user);
courseGroupRepo.findByUserId.mockResolvedValue([[courseGroup1, courseGroup2], 2]);

return {
user,
};
};

it('should call courseGroupRepo.findByUserId', async () => {
const { user } = setup();

await courseGroupService.deleteUserDataFromCourseGroup(user.id);

expect(courseGroupRepo.findByUserId).toBeCalledWith(user.id);
});

it('should update courses without deleted user', async () => {
const { user } = setup();

const result = await courseGroupService.deleteUserDataFromCourseGroup(user.id);

expect(result).toEqual(2);
});
});
});
18 changes: 18 additions & 0 deletions apps/server/src/modules/learnroom/service/coursegroup.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Injectable } from '@nestjs/common';
import { EntityId } from '@shared/domain';
import { CourseGroupRepo } from '@shared/repo';

@Injectable()
export class CourseGroupService {
constructor(private readonly repo: CourseGroupRepo) {}

public async deleteUserDataFromCourseGroup(userId: EntityId): Promise<number> {
const [courseGroups, count] = await this.repo.findByUserId(userId);

courseGroups.forEach((courseGroup) => courseGroup.removeStudent(userId));

await this.repo.save(courseGroups);

return count;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { Configuration } from '@hpi-schul-cloud/commons/lib';
import { IConfig } from '@hpi-schul-cloud/commons/lib/interfaces/IConfig';
import { Test, TestingModule } from '@nestjs/testing';
import { Board, Course, Lesson, Task, TaskWithStatusVo, User } from '@shared/domain';
import { Board, Course, LessonEntity, Task, TaskWithStatusVo, User } from '@shared/domain';
import {
boardFactory,
columnboardBoardElementFactory,
Expand Down Expand Up @@ -44,7 +44,7 @@ describe(RoomBoardDTOFactory.name, () => {
throw new Error('Please write a mock for RoomsAuthorisationService.hasTaskReadPermission');
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
hasLessonReadPermission(user: User, lesson: Lesson): boolean {
hasLessonReadPermission(user: User, lesson: LessonEntity): boolean {
throw new Error('Please write a mock for RoomsAuthorisationService.hasLessonReadPermission');
},
},
Expand Down Expand Up @@ -204,7 +204,7 @@ describe(RoomBoardDTOFactory.name, () => {
let substitutionTeacher: User;
let board: Board;
let room: Course;
let lessons: Lesson[];
let lessons: LessonEntity[];

beforeEach(() => {
teacher = userFactory.buildWithId();
Expand Down Expand Up @@ -243,7 +243,7 @@ describe(RoomBoardDTOFactory.name, () => {
let substitutionTeacher: User;
let board: Board;
let room: Course;
let lesson: Lesson;
let lesson: LessonEntity;
const inOneDay = new Date(Date.now() + 8.64e7);

beforeEach(() => {
Expand Down Expand Up @@ -325,7 +325,7 @@ describe(RoomBoardDTOFactory.name, () => {
let substitutionTeacher: User;
let board: Board;
let room: Course;
let lessons: Lesson[];
let lessons: LessonEntity[];

beforeEach(() => {
teacher = userFactory.buildWithId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
ColumnBoardTarget,
Course,
ITaskStatus,
Lesson,
LessonEntity,
Permission,
Task,
TaskWithStatusVo,
Expand Down Expand Up @@ -73,7 +73,7 @@ class DtoCreator {
}

if (element.boardElementType === BoardElementType.Lesson) {
result = this.roomsAuthorisationService.hasLessonReadPermission(this.user, element.target as Lesson);
result = this.roomsAuthorisationService.hasLessonReadPermission(this.user, element.target as LessonEntity);
}

if (element instanceof ColumnboardBoardElement && this.isColumnBoardFeatureFlagActive()) {
Expand Down Expand Up @@ -139,7 +139,7 @@ class DtoCreator {

private mapLessonElement(element: BoardElement): RoomBoardElementDTO {
const type = RoomBoardElementTypes.LESSON;
const lesson = element.target as Lesson;
const lesson = element.target as LessonEntity;
const content: LessonMetaData = {
id: lesson.id,
name: lesson.name,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Injectable, NotImplementedException } from '@nestjs/common';
import { Course, Lesson, Task, User } from '@shared/domain';
import { Course, LessonEntity, Task, User } from '@shared/domain';

export enum TaskParentPermission {
read,
Expand Down Expand Up @@ -42,7 +42,7 @@ export class RoomsAuthorisationService {
return hasPermission;
}

hasLessonReadPermission(user: User, lesson: Lesson): boolean {
hasLessonReadPermission(user: User, lesson: LessonEntity): boolean {
let hasCoursePermission = false;
hasCoursePermission = this.hasCourseReadPermission(user, lesson.course);
if (lesson.hidden) {
Expand Down
Loading

0 comments on commit cb7bf6d

Please sign in to comment.