Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

N21-1507 copy ctl tools #4674

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5d08e79
copy ctl tools in tab when course copy
IgorCapCoder Jan 2, 2024
fbed27a
copy ctl tools in board when course copy
IgorCapCoder Jan 3, 2024
7d39bd4
change validation of context and school external tools
MarvinOehlerkingCap Jan 3, 2024
2a539ab
Merge remote-tracking branch 'origin/N21-1507-copy-ctl-tools' into N2…
MarvinOehlerkingCap Jan 3, 2024
dde2507
add tests
MarvinOehlerkingCap Jan 4, 2024
6941217
course copy unit tests
IgorCapCoder Jan 4, 2024
69b718a
Merge remote-tracking branch 'origin/N21-1507-copy-ctl-tools' into N2…
IgorCapCoder Jan 4, 2024
48d60fb
tools copy unit tests
IgorCapCoder Jan 4, 2024
fcb1820
Merge branch 'main' into N21-1507-copy-ctl-tools
IgorCapCoder Jan 4, 2024
d2f1444
linter fix
IgorCapCoder Jan 4, 2024
81a4f61
add migration
MarvinOehlerkingCap Jan 4, 2024
c2db774
test fix
IgorCapCoder Jan 4, 2024
dd92574
Merge remote-tracking branch 'origin/N21-1507-copy-ctl-tools' into N2…
IgorCapCoder Jan 4, 2024
f9efbca
improve tests for validation rules
MarvinOehlerkingCap Jan 4, 2024
299f25c
Merge remote-tracking branch 'origin/N21-1507-copy-ctl-tools' into N2…
MarvinOehlerkingCap Jan 4, 2024
d2c6fe0
requested changes
IgorCapCoder Jan 4, 2024
9605f02
Merge remote-tracking branch 'origin/N21-1507-copy-ctl-tools' into N2…
IgorCapCoder Jan 4, 2024
7d769b2
requested changes - use tool features
IgorCapCoder Jan 4, 2024
ea90cdb
Merge branch 'main' into N21-1507-copy-ctl-tools
IgorCapCoder Jan 5, 2024
2bd840e
requested changes - use tool features - unit tests
IgorCapCoder Jan 5, 2024
57bf1d1
fix tests
IgorCapCoder Jan 5, 2024
ecea339
change order of cunstructor injections
IgorCapCoder Jan 5, 2024
59efca6
N21-1507 fixes injection
arnegns Jan 5, 2024
7245bf1
fix tests
IgorCapCoder Jan 5, 2024
dc74ce0
Merge branch 'main' into N21-1507-copy-ctl-tools
IgorCapCoder Jan 5, 2024
7057498
fix tests
IgorCapCoder Jan 5, 2024
79ba460
Merge branch 'main' into N21-1507-copy-ctl-tools
IgorCapCoder Jan 5, 2024
b94cb3f
coverage up
IgorCapCoder Jan 5, 2024
33aae67
requested changes
IgorCapCoder Jan 8, 2024
fff685c
fix import
IgorCapCoder Jan 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { createMock } from '@golevelup/ts-jest';
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { Configuration } from '@hpi-schul-cloud/commons/lib';
import { FileRecordParentType } from '@infra/rabbitmq';
import { CopyElementType, CopyStatus, CopyStatusEnum } from '@modules/copy-helper';
import { ContextExternalTool } from '@modules/tool/context-external-tool/domain';
import { ContextExternalToolService } from '@modules/tool/context-external-tool/service';
import { Test, TestingModule } from '@nestjs/testing';
import {
Card,
Expand All @@ -9,9 +12,6 @@ import {
DrawingElement,
ExternalToolElement,
FileElement,
LinkElement,
RichTextElement,
SubmissionContainerElement,
isCard,
isColumn,
isColumnBoard,
Expand All @@ -21,11 +21,15 @@ import {
isLinkElement,
isRichTextElement,
isSubmissionContainerElement,
LinkElement,
RichTextElement,
SubmissionContainerElement,
} from '@shared/domain/domainobject';
import {
cardFactory,
columnBoardFactory,
columnFactory,
contextExternalToolFactory,
drawingElementFactory,
externalToolElementFactory,
fileElementFactory,
Expand All @@ -43,12 +47,21 @@ describe('recursive board copy visitor', () => {
let module: TestingModule;
let service: BoardDoCopyService;

let contextExternalToolService: DeepMocked<ContextExternalToolService>;

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

service = module.get(BoardDoCopyService);
contextExternalToolService = module.get(ContextExternalToolService);

await setupEntities();
});
Expand Down Expand Up @@ -711,61 +724,196 @@ describe('recursive board copy visitor', () => {
});
});

describe('when copying a external tool element', () => {
const setup = () => {
const original = externalToolElementFactory.build();
describe('when copying an external tool element', () => {
describe('when the element has no linked tool', () => {
const setup = () => {
const original = externalToolElementFactory.build();

return { original, ...setupfileCopyService() };
};
return { original, ...setupfileCopyService() };
};

const getExternalToolElementFromStatus = (status: CopyStatus): ExternalToolElement => {
const copy = status.copyEntity;
const getExternalToolElementFromStatus = (status: CopyStatus): ExternalToolElement => {
const copy = status.copyEntity;

expect(isExternalToolElement(copy)).toEqual(true);
expect(isExternalToolElement(copy)).toEqual(true);

return copy as ExternalToolElement;
};
return copy as ExternalToolElement;
};

it('should return a external tool element as copy', async () => {
const { original, fileCopyService } = setup();
it('should return a external tool element as copy', async () => {
const { original, fileCopyService } = setup();

const result = await service.copy({ original, fileCopyService });
const result = await service.copy({ original, fileCopyService });

expect(isExternalToolElement(result.copyEntity)).toEqual(true);
});
expect(isExternalToolElement(result.copyEntity)).toEqual(true);
});

it('should not copy tool', async () => {
const { original, fileCopyService } = setup();
it('should not copy tool', async () => {
const { original, fileCopyService } = setup();

const result = await service.copy({ original, fileCopyService });
const copy = getExternalToolElementFromStatus(result);
const result = await service.copy({ original, fileCopyService });
const copy = getExternalToolElementFromStatus(result);

expect(copy.contextExternalToolId).toBeUndefined();
});
expect(copy.contextExternalToolId).toBeUndefined();
});

it('should create new id', async () => {
const { original, fileCopyService } = setup();
it('should create new id', async () => {
const { original, fileCopyService } = setup();

const result = await service.copy({ original, fileCopyService });
const copy = getExternalToolElementFromStatus(result);
const result = await service.copy({ original, fileCopyService });
const copy = getExternalToolElementFromStatus(result);

expect(copy.id).not.toEqual(original.id);
});
expect(copy.id).not.toEqual(original.id);
});

it('should show status successful', async () => {
const { original, fileCopyService } = setup();
it('should show status successful', async () => {
const { original, fileCopyService } = setup();

const result = await service.copy({ original, fileCopyService });
const result = await service.copy({ original, fileCopyService });

expect(result.status).toEqual(CopyStatusEnum.SUCCESS);
expect(result.status).toEqual(CopyStatusEnum.SUCCESS);
});

it('should show type ExternalToolElement', async () => {
const { original, fileCopyService } = setup();

const result = await service.copy({ original, fileCopyService });

expect(result.type).toEqual(CopyElementType.EXTERNAL_TOOL_ELEMENT);
});
});

it('should show type RichTextElement', async () => {
const { original, fileCopyService } = setup();
describe('when the element has a linked tool and the feature is active', () => {
describe('when the linked tool exists', () => {
const setup = () => {
const originalTool: ContextExternalTool = contextExternalToolFactory.buildWithId();
const copiedTool: ContextExternalTool = contextExternalToolFactory.buildWithId();

const result = await service.copy({ original, fileCopyService });
const original: ExternalToolElement = externalToolElementFactory.build({
contextExternalToolId: originalTool.id,
});

contextExternalToolService.findById.mockResolvedValueOnce(originalTool);
contextExternalToolService.copyContextExternalTool.mockResolvedValueOnce(copiedTool);

Configuration.set('FEATURE_CTL_TOOLS_COPY_ENABLED', true);

return { original, ...setupfileCopyService(), copiedTool };
};

const getExternalToolElementFromStatus = (status: CopyStatus): ExternalToolElement => {
const copy = status.copyEntity;

expect(isExternalToolElement(copy)).toEqual(true);

return copy as ExternalToolElement;
};

it('should return a external tool element as copy', async () => {
const { original, fileCopyService } = setup();

const result = await service.copy({ original, fileCopyService });

expect(isExternalToolElement(result.copyEntity)).toEqual(true);
});

it('should copy tool', async () => {
const { original, fileCopyService, copiedTool } = setup();

const result = await service.copy({ original, fileCopyService });
const copy = getExternalToolElementFromStatus(result);

expect(copy.contextExternalToolId).toEqual(copiedTool.id);
});

it('should create new id', async () => {
const { original, fileCopyService } = setup();

const result = await service.copy({ original, fileCopyService });
const copy = getExternalToolElementFromStatus(result);

expect(copy.id).not.toEqual(original.id);
});

it('should show status successful', async () => {
const { original, fileCopyService } = setup();

const result = await service.copy({ original, fileCopyService });

expect(result.status).toEqual(CopyStatusEnum.SUCCESS);
});

it('should show type ExternalToolElement', async () => {
const { original, fileCopyService } = setup();

const result = await service.copy({ original, fileCopyService });

expect(result.type).toEqual(CopyElementType.EXTERNAL_TOOL_ELEMENT);
});
});

expect(result.type).toEqual(CopyElementType.EXTERNAL_TOOL_ELEMENT);
describe('when the linked tool does not exist anymore', () => {
const setup = () => {
const original: ExternalToolElement = externalToolElementFactory.build({
contextExternalToolId: new ObjectId().toHexString(),
});

contextExternalToolService.findById.mockResolvedValueOnce(null);

Configuration.set('FEATURE_CTL_TOOLS_COPY_ENABLED', true);

return { original, ...setupfileCopyService() };
};

const getExternalToolElementFromStatus = (status: CopyStatus): ExternalToolElement => {
const copy = status.copyEntity;

expect(isExternalToolElement(copy)).toEqual(true);

return copy as ExternalToolElement;
};

it('should return a external tool element as copy', async () => {
const { original, fileCopyService } = setup();

const result = await service.copy({ original, fileCopyService });

expect(isExternalToolElement(result.copyEntity)).toEqual(true);
});

it('should not try to copy the tool', async () => {
const { original, fileCopyService } = setup();

await service.copy({ original, fileCopyService });

expect(contextExternalToolService.copyContextExternalTool).not.toHaveBeenCalled();
});

it('should create new id', async () => {
const { original, fileCopyService } = setup();

const result = await service.copy({ original, fileCopyService });
const copy = getExternalToolElementFromStatus(result);

expect(copy.id).not.toEqual(original.id);
});

it('should show status fail', async () => {
const { original, fileCopyService } = setup();

const result = await service.copy({ original, fileCopyService });

expect(result.status).toEqual(CopyStatusEnum.FAIL);
});

it('should show type ExternalToolElement', async () => {
const { original, fileCopyService } = setup();

const result = await service.copy({ original, fileCopyService });

expect(result.type).toEqual(CopyElementType.EXTERNAL_TOOL_ELEMENT);
});
});
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ContextExternalToolService } from '@modules//tool/context-external-tool/service';
IgorCapCoder marked this conversation as resolved.
Show resolved Hide resolved
import { CopyStatus } from '@modules/copy-helper';
import { Injectable } from '@nestjs/common';
import { AnyBoardDo } from '@shared/domain/domainobject';
Expand All @@ -11,8 +12,10 @@ export type BoardDoCopyParams = {

@Injectable()
export class BoardDoCopyService {
constructor(private readonly contextExternalToolService: ContextExternalToolService) {}

public async copy(params: BoardDoCopyParams): Promise<CopyStatus> {
const visitor = new RecursiveCopyVisitor(params.fileCopyService);
const visitor = new RecursiveCopyVisitor(params.fileCopyService, this.contextExternalToolService);

const result = await visitor.copy(params.original);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,35 @@ import { Test, TestingModule } from '@nestjs/testing';
import { LinkElement } from '@shared/domain/domainobject';
import { linkElementFactory, setupEntities } from '@shared/testing';
import { CopyFileDto } from '@src/modules/files-storage-client/dto';
import { ContextExternalToolService } from '../../../tool/context-external-tool/service';
IgorCapCoder marked this conversation as resolved.
Show resolved Hide resolved

import { RecursiveCopyVisitor } from './recursive-copy.visitor';
import { SchoolSpecificFileCopyServiceFactory } from './school-specific-file-copy-service.factory';
import { SchoolSpecificFileCopyService } from './school-specific-file-copy.interface';

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

let fileCopyServiceFactory: DeepMocked<SchoolSpecificFileCopyServiceFactory>;
let contextExternalToolService: DeepMocked<ContextExternalToolService>;

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

fileCopyServiceFactory = module.get(SchoolSpecificFileCopyServiceFactory);
contextExternalToolService = module.get(ContextExternalToolService);

await setupEntities();
});
Expand Down Expand Up @@ -57,7 +65,7 @@ describe(RecursiveCopyVisitor.name, () => {
const { fileCopyServiceMock } = setup();

const linkElement = linkElementFactory.build();
const visitor = new RecursiveCopyVisitor(fileCopyServiceMock);
const visitor = new RecursiveCopyVisitor(fileCopyServiceMock, contextExternalToolService);

await visitor.visitLinkElementAsync(linkElement);

Expand All @@ -70,7 +78,7 @@ describe(RecursiveCopyVisitor.name, () => {
const { fileCopyServiceMock, imageUrl } = setup({ withFileCopy: true });

const linkElement = linkElementFactory.build({ imageUrl });
const visitor = new RecursiveCopyVisitor(fileCopyServiceMock);
const visitor = new RecursiveCopyVisitor(fileCopyServiceMock, contextExternalToolService);

await visitor.visitLinkElementAsync(linkElement);

Expand All @@ -83,7 +91,7 @@ describe(RecursiveCopyVisitor.name, () => {
const { fileCopyServiceMock, imageUrl, newFileId } = setup({ withFileCopy: true });

const linkElement = linkElementFactory.build({ imageUrl });
const visitor = new RecursiveCopyVisitor(fileCopyServiceMock);
const visitor = new RecursiveCopyVisitor(fileCopyServiceMock, contextExternalToolService);

await visitor.visitLinkElementAsync(linkElement);
const copy = visitor.copyMap.get(linkElement.id) as LinkElement;
Expand All @@ -97,7 +105,7 @@ describe(RecursiveCopyVisitor.name, () => {
const { fileCopyServiceMock } = setup({ withFileCopy: true });

const linkElement = linkElementFactory.build({ imageUrl: `https://abc.de/file/unknown-file-id` });
const visitor = new RecursiveCopyVisitor(fileCopyServiceMock);
const visitor = new RecursiveCopyVisitor(fileCopyServiceMock, contextExternalToolService);

await visitor.visitLinkElementAsync(linkElement);
const copy = visitor.copyMap.get(linkElement.id) as LinkElement;
Expand Down
Loading
Loading