Skip to content

Commit

Permalink
Merge branch 'main' into BC-4256-Integration-tldraw
Browse files Browse the repository at this point in the history
  • Loading branch information
wiaderwek authored Nov 3, 2023
2 parents def15ff + f38c0be commit 188c151
Show file tree
Hide file tree
Showing 55 changed files with 1,513 additions and 426 deletions.
10 changes: 5 additions & 5 deletions apps/server/src/modules/board/board.module.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { FilesStorageClientModule } from '@modules/files-storage-client';
import { ContextExternalToolModule } from '@modules/tool/context-external-tool';
import { UserModule } from '@modules/user';
import { Module } from '@nestjs/common';
import { ContentElementFactory } from '@shared/domain';
import { ConsoleWriterModule } from '@shared/infra/console';
import { CourseRepo } from '@shared/repo';
import { LoggerModule } from '@src/core/logger';
import { FilesStorageClientModule } from '../files-storage-client';
import { UserModule } from '../user';
import { BoardDoRepo, BoardNodeRepo } from './repo';
import { RecursiveDeleteVisitor } from './repo/recursive-delete.vistor';
import { BoardDoRepo, BoardNodeRepo, RecursiveDeleteVisitor } from './repo';
import {
BoardDoAuthorizableService,
BoardDoService,
Expand All @@ -21,7 +21,7 @@ import { BoardDoCopyService, SchoolSpecificFileCopyServiceFactory } from './serv
import { ColumnBoardCopyService } from './service/column-board-copy.service';

@Module({
imports: [ConsoleWriterModule, FilesStorageClientModule, LoggerModule, UserModule],
imports: [ConsoleWriterModule, FilesStorageClientModule, LoggerModule, UserModule, ContextExternalToolModule],
providers: [
BoardDoAuthorizableService,
BoardDoRepo,
Expand Down
4 changes: 3 additions & 1 deletion apps/server/src/modules/board/repo/board-do.repo.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { createMock } from '@golevelup/ts-jest';
import { NotFoundError } from '@mikro-orm/core';
import { EntityManager } from '@mikro-orm/mongodb';
import { FilesStorageClientAdapterService } from '@modules/files-storage-client';
import { ContextExternalToolService } from '@modules/tool/context-external-tool/service';
import { NotFoundException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import {
Expand All @@ -26,7 +28,6 @@ import {
richTextElementFactory,
richTextElementNodeFactory,
} from '@shared/testing';
import { FilesStorageClientAdapterService } from '@modules/files-storage-client';
import { BoardDoRepo } from './board-do.repo';
import { BoardNodeRepo } from './board-node.repo';
import { RecursiveDeleteVisitor } from './recursive-delete.vistor';
Expand All @@ -46,6 +47,7 @@ describe(BoardDoRepo.name, () => {
BoardNodeRepo,
RecursiveDeleteVisitor,
{ provide: FilesStorageClientAdapterService, useValue: createMock<FilesStorageClientAdapterService>() },
{ provide: ContextExternalToolService, useValue: createMock<ContextExternalToolService>() },
],
}).compile();
repo = module.get(BoardDoRepo);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,45 @@
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { EntityManager } from '@mikro-orm/mongodb';
import { FileDto, FilesStorageClientAdapterService } from '@modules/files-storage-client';
import { ContextExternalToolService } from '@modules/tool/context-external-tool/service';
import { Test, TestingModule } from '@nestjs/testing';
import { FileRecordParentType } from '@shared/infra/rabbitmq';
import {
columnBoardFactory,
columnFactory,
contextExternalToolFactory,
externalToolElementFactory,
fileElementFactory,
linkElementFactory,
setupEntities,
submissionContainerElementFactory,
submissionItemFactory,
} from '@shared/testing';
import { FileDto, FilesStorageClientAdapterService } from '@modules/files-storage-client';
import { RecursiveDeleteVisitor } from './recursive-delete.vistor';

describe(RecursiveDeleteVisitor.name, () => {
let module: TestingModule;
let service: RecursiveDeleteVisitor;

let em: DeepMocked<EntityManager>;
let filesStorageClientAdapterService: DeepMocked<FilesStorageClientAdapterService>;
let service: RecursiveDeleteVisitor;
let contextExternalToolService: DeepMocked<ContextExternalToolService>;

beforeAll(async () => {
module = await Test.createTestingModule({
providers: [
RecursiveDeleteVisitor,
{ provide: EntityManager, useValue: createMock<EntityManager>() },
{ provide: FilesStorageClientAdapterService, useValue: createMock<FilesStorageClientAdapterService>() },
{ provide: ContextExternalToolService, useValue: createMock<ContextExternalToolService>() },
],
}).compile();

service = module.get(RecursiveDeleteVisitor);
em = module.get(EntityManager);
filesStorageClientAdapterService = module.get(FilesStorageClientAdapterService);
service = module.get(RecursiveDeleteVisitor);
contextExternalToolService = module.get(ContextExternalToolService);

await setupEntities();
});

Expand Down Expand Up @@ -212,14 +219,30 @@ describe(RecursiveDeleteVisitor.name, () => {

describe('visitExternalToolElementAsync', () => {
const setup = () => {
const contextExternalTool = contextExternalToolFactory.buildWithId();
const childExternalToolElement = externalToolElementFactory.build();
const externalToolElement = externalToolElementFactory.build({
children: [childExternalToolElement],
contextExternalToolId: contextExternalTool.id,
});

return { externalToolElement, childExternalToolElement };
contextExternalToolService.findById.mockResolvedValue(contextExternalTool);

return {
externalToolElement,
childExternalToolElement,
contextExternalTool,
};
};

it('should delete the context external tool that is linked to the element', async () => {
const { externalToolElement, contextExternalTool } = setup();

await service.visitExternalToolElementAsync(externalToolElement);

expect(contextExternalToolService.deleteContextExternalTool).toHaveBeenCalledWith(contextExternalTool);
});

it('should call entity remove', async () => {
const { externalToolElement, childExternalToolElement } = setup();

Expand Down
16 changes: 13 additions & 3 deletions apps/server/src/modules/board/repo/recursive-delete.vistor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { EntityManager } from '@mikro-orm/mongodb';
import { FilesStorageClientAdapterService } from '@modules/files-storage-client';
import { ContextExternalTool } from '@modules/tool/context-external-tool/domain';
import { ContextExternalToolService } from '@modules/tool/context-external-tool/service';
import { Injectable } from '@nestjs/common';
import {
AnyBoardDo,
Expand All @@ -14,13 +17,13 @@ import {
SubmissionItem,
} from '@shared/domain';
import { LinkElement } from '@shared/domain/domainobject/board/link-element.do';
import { FilesStorageClientAdapterService } from '@modules/files-storage-client';

@Injectable()
export class RecursiveDeleteVisitor implements BoardCompositeVisitorAsync {
constructor(
private readonly em: EntityManager,
private readonly filesStorageClientAdapterService: FilesStorageClientAdapterService
private readonly filesStorageClientAdapterService: FilesStorageClientAdapterService,
private readonly contextExternalToolService: ContextExternalToolService
) {}

async visitColumnBoardAsync(columnBoard: ColumnBoard): Promise<void> {
Expand Down Expand Up @@ -67,7 +70,14 @@ export class RecursiveDeleteVisitor implements BoardCompositeVisitorAsync {
}

async visitExternalToolElementAsync(externalToolElement: ExternalToolElement): Promise<void> {
// TODO N21-1296: Delete linked ContextExternalTool
if (externalToolElement.contextExternalToolId) {
const linkedTool: ContextExternalTool = await this.contextExternalToolService.findById(
externalToolElement.contextExternalToolId
);

await this.contextExternalToolService.deleteContextExternalTool(linkedTool);
}

this.deleteNode(externalToolElement);

await this.visitChildrenAsync(externalToolElement);
Expand Down
82 changes: 82 additions & 0 deletions apps/server/src/modules/board/service/column-board.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +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 { NotFoundLoggableException } from '@shared/common/loggable-exception';
import {
BoardExternalReference,
BoardExternalReferenceType,
Expand Down Expand Up @@ -106,6 +107,87 @@ describe(ColumnBoardService.name, () => {
});
});

describe('findByDescendant', () => {
describe('when searching a board for an element', () => {
const setup2 = () => {
const element = richTextElementFactory.build();
const board: ColumnBoard = columnBoardFactory.build({ children: [element] });

boardDoRepo.getAncestorIds.mockResolvedValue([board.id]);
boardDoRepo.findById.mockResolvedValue(board);

return {
element,
board,
};
};

it('should search by the root id', async () => {
const { element, board } = setup2();

await service.findByDescendant(element);

expect(boardDoRepo.findById).toHaveBeenCalledWith(board.id, 1);
});

it('should return the board', async () => {
const { element, board } = setup2();

const result = await service.findByDescendant(element);

expect(result).toEqual(board);
});
});

describe('when searching a board by itself', () => {
const setup2 = () => {
const board: ColumnBoard = columnBoardFactory.build({ children: [] });

boardDoRepo.getAncestorIds.mockResolvedValue([]);
boardDoRepo.findById.mockResolvedValue(board);

return {
board,
};
};

it('should search by the root id', async () => {
const { board } = setup2();

await service.findByDescendant(board);

expect(boardDoRepo.findById).toHaveBeenCalledWith(board.id, 1);
});

it('should return the board', async () => {
const { board } = setup2();

const result = await service.findByDescendant(board);

expect(result).toEqual(board);
});
});

describe('when the root node is not a board', () => {
const setup2 = () => {
const element = richTextElementFactory.build();

boardDoRepo.getAncestorIds.mockResolvedValue([]);
boardDoRepo.findById.mockResolvedValue(element);

return {
element,
};
};

it('should throw a NotFoundLoggableException', async () => {
const { element } = setup2();

await expect(service.findByDescendant(element)).rejects.toThrow(NotFoundLoggableException);
});
});
});

describe('getBoardObjectTitlesById', () => {
describe('when asking for a list of boardObject-ids', () => {
const setupBoards = () => {
Expand Down
15 changes: 15 additions & 0 deletions apps/server/src/modules/board/service/column-board.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Configuration } from '@hpi-schul-cloud/commons/lib';
import { Injectable } from '@nestjs/common';
import { NotFoundLoggableException } from '@shared/common/loggable-exception';
import {
AnyBoardDo,
BoardExternalReference,
Card,
Column,
Expand Down Expand Up @@ -34,6 +36,19 @@ export class ColumnBoardService {
return ids;
}

async findByDescendant(boardDo: AnyBoardDo): Promise<ColumnBoard> {
const ancestorIds: EntityId[] = await this.boardDoRepo.getAncestorIds(boardDo);
const idHierarchy: EntityId[] = [...ancestorIds, boardDo.id];
const rootId: EntityId = idHierarchy[0];
const rootBoardDo: AnyBoardDo = await this.boardDoRepo.findById(rootId, 1);

if (rootBoardDo instanceof ColumnBoard) {
return rootBoardDo;
}

throw new NotFoundLoggableException(ColumnBoard.name, 'id', rootId);
}

async getBoardObjectTitlesById(boardIds: EntityId[]): Promise<Record<EntityId, string>> {
const titleMap = this.boardDoRepo.getTitlesByIds(boardIds);
return titleMap;
Expand Down
1 change: 1 addition & 0 deletions apps/server/src/modules/class/domain/testing/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './factory/class.factory';
1 change: 1 addition & 0 deletions apps/server/src/modules/class/entity/testing/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './factory/class.entity.factory';
38 changes: 35 additions & 3 deletions apps/server/src/modules/class/repo/classes.repo.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { EntityManager, ObjectId } from '@mikro-orm/mongodb';
import { classEntityFactory } from '@modules/class/entity/testing/factory/class.entity.factory';
import { Test } from '@nestjs/testing';
import { TestingModule } from '@nestjs/testing/testing-module';
import { NotFoundLoggableException } from '@shared/common/loggable-exception';
import { SchoolEntity } from '@shared/domain';
import { MongoMemoryDatabaseModule } from '@shared/infra/database';
import { cleanupCollections, schoolFactory } from '@shared/testing';
import { classEntityFactory } from '@modules/class/entity/testing/factory/class.entity.factory';
import { Class } from '../domain';
import { ClassEntity } from '../entity';
import { ClassesRepo } from './classes.repo';
Expand Down Expand Up @@ -48,6 +49,7 @@ describe(ClassesRepo.name, () => {
const classes: ClassEntity[] = classEntityFactory.buildListWithId(3, { schoolId: school.id });

await em.persistAndFlush(classes);
em.clear();

return {
school,
Expand Down Expand Up @@ -78,9 +80,13 @@ describe(ClassesRepo.name, () => {
const setup = async () => {
const testUser = new ObjectId();
const class1: ClassEntity = classEntityFactory.withUserIds([testUser, new ObjectId()]).buildWithId();
const class2: ClassEntity = classEntityFactory.withUserIds([testUser, new ObjectId()]).buildWithId();
const class2: ClassEntity = classEntityFactory
.withUserIds([new ObjectId()])
.buildWithId({ teacherIds: [testUser] });
const class3: ClassEntity = classEntityFactory.withUserIds([new ObjectId(), new ObjectId()]).buildWithId();

await em.persistAndFlush([class1, class2, class3]);
em.clear();

return {
class1,
Expand All @@ -104,15 +110,17 @@ describe(ClassesRepo.name, () => {
});

describe('updateMany', () => {
describe('When deleting user data from classes', () => {
describe('when deleting user data from classes', () => {
const setup = async () => {
const testUser1 = new ObjectId();
const testUser2 = new ObjectId();
const testUser3 = new ObjectId();
const class1: ClassEntity = classEntityFactory.withUserIds([testUser1, testUser2]).buildWithId();
const class2: ClassEntity = classEntityFactory.withUserIds([testUser1, testUser3]).buildWithId();
const class3: ClassEntity = classEntityFactory.withUserIds([testUser2, testUser3]).buildWithId();

await em.persistAndFlush([class1, class2, class3]);
em.clear();

return {
class1,
Expand Down Expand Up @@ -144,5 +152,29 @@ describe(ClassesRepo.name, () => {
expect(result3).toHaveLength(2);
});
});

describe('when updating a class that does not exist', () => {
const setup = async () => {
const class1: ClassEntity = classEntityFactory.buildWithId();
const class2: ClassEntity = classEntityFactory.buildWithId();

await em.persistAndFlush([class1]);
em.clear();

return {
class1,
class2,
};
};

it('should throw an error', async () => {
const { class1, class2 } = await setup();

const updatedArray: ClassEntity[] = [class1, class2];
const domainObjectsArray: Class[] = ClassMapper.mapToDOs(updatedArray);

await expect(repo.updateMany(domainObjectsArray)).rejects.toThrow(NotFoundLoggableException);
});
});
});
});
Loading

0 comments on commit 188c151

Please sign in to comment.