-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'BC-6871-board-refactor' of github.com:hpi-schul-cloud/s…
…chulcloud-server into BC-6871-board-refactor
- Loading branch information
Showing
9 changed files
with
700 additions
and
45 deletions.
There are no files selected for viewing
389 changes: 389 additions & 0 deletions
389
apps/server/src/modules/board/service/media-board/media-available-line.service.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,389 @@ | ||
import { createMock, DeepMocked } from '@golevelup/ts-jest'; | ||
import { ObjectId } from '@mikro-orm/mongodb'; | ||
import { ExternalToolService } from '@modules/tool'; | ||
import { CustomParameterScope, ToolContextType } from '@modules/tool/common/enum'; | ||
import { ContextExternalToolService } from '@modules/tool/context-external-tool'; | ||
import { ContextExternalTool } from '@modules/tool/context-external-tool/domain'; | ||
import { contextExternalToolFactory } from '@modules/tool/context-external-tool/testing'; | ||
import { ExternalTool } from '@modules/tool/external-tool/domain'; | ||
import { ExternalToolLogoService } from '@modules/tool/external-tool/service'; | ||
import { externalToolFactory } from '@modules/tool/external-tool/testing'; | ||
import { SchoolExternalToolService } from '@modules/tool/school-external-tool'; | ||
import { SchoolExternalTool } from '@modules/tool/school-external-tool/domain'; | ||
import { schoolExternalToolFactory } from '@modules/tool/school-external-tool/testing'; | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { User } from '@shared/domain/entity'; | ||
import { setupEntities, userFactory } from '@shared/testing'; | ||
import { mediaBoardFactory, mediaExternalToolElementFactory } from '@modules/board/testing'; | ||
import { Page } from '@shared/domain/domainobject'; | ||
import { MediaAvailableLine, MediaBoard, MediaExternalToolElement } from '../../domain'; | ||
import { MediaAvailableLineService } from './media-available-line.service'; | ||
import { MediaBoardService } from './media-board.service'; | ||
|
||
describe(MediaAvailableLineService.name, () => { | ||
let module: TestingModule; | ||
let service: MediaAvailableLineService; | ||
|
||
let externalToolService: DeepMocked<ExternalToolService>; | ||
let schoolExternalToolService: DeepMocked<SchoolExternalToolService>; | ||
let contextExternalToolService: DeepMocked<ContextExternalToolService>; | ||
let externalToolLogoService: DeepMocked<ExternalToolLogoService>; | ||
let mediaBoardService: DeepMocked<MediaBoardService>; | ||
|
||
beforeAll(async () => { | ||
module = await Test.createTestingModule({ | ||
providers: [ | ||
MediaAvailableLineService, | ||
{ | ||
provide: ExternalToolService, | ||
useValue: createMock<ExternalToolService>(), | ||
}, | ||
{ | ||
provide: SchoolExternalToolService, | ||
useValue: createMock<SchoolExternalToolService>(), | ||
}, | ||
{ | ||
provide: ContextExternalToolService, | ||
useValue: createMock<ContextExternalToolService>(), | ||
}, | ||
{ | ||
provide: ExternalToolLogoService, | ||
useValue: createMock<ExternalToolLogoService>(), | ||
}, | ||
{ | ||
provide: MediaBoardService, | ||
useValue: createMock<MediaBoardService>(), | ||
}, | ||
], | ||
}).compile(); | ||
|
||
service = module.get(MediaAvailableLineService); | ||
externalToolService = module.get(ExternalToolService); | ||
schoolExternalToolService = module.get(SchoolExternalToolService); | ||
contextExternalToolService = module.get(ContextExternalToolService); | ||
externalToolLogoService = module.get(ExternalToolLogoService); | ||
mediaBoardService = module.get(MediaBoardService); | ||
|
||
await setupEntities(); | ||
}); | ||
|
||
afterAll(async () => { | ||
await module.close(); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.resetAllMocks(); | ||
}); | ||
|
||
describe('getUnusedAvailableSchoolExternalTools', () => { | ||
describe('when there are unused tools', () => { | ||
const setup = () => { | ||
const user: User = userFactory.build(); | ||
|
||
const schoolExternalTool: SchoolExternalTool = schoolExternalToolFactory | ||
.withSchoolId(user.school.id) | ||
.buildWithId(); | ||
const usedSchoolExternalTool: SchoolExternalTool = schoolExternalToolFactory | ||
.withSchoolId(user.school.id) | ||
.buildWithId(); | ||
|
||
const usedContextExternalTool: ContextExternalTool = contextExternalToolFactory | ||
.withSchoolExternalToolRef(usedSchoolExternalTool.id, user.school.id) | ||
.buildWithId(); | ||
|
||
const mediaExternalToolElement: MediaExternalToolElement = mediaExternalToolElementFactory.build({ | ||
contextExternalToolId: usedContextExternalTool.id, | ||
}); | ||
const board: MediaBoard = mediaBoardFactory.build({ children: [mediaExternalToolElement] }); | ||
|
||
schoolExternalToolService.findSchoolExternalTools.mockResolvedValue([ | ||
schoolExternalTool, | ||
usedSchoolExternalTool, | ||
]); | ||
contextExternalToolService.findById.mockResolvedValueOnce(usedContextExternalTool); | ||
|
||
mediaBoardService.findMediaElements.mockReturnValueOnce([mediaExternalToolElement]); | ||
|
||
return { user, board, mediaExternalToolElement, schoolExternalTool }; | ||
}; | ||
|
||
it('should call the service to get school external tools for users school', async () => { | ||
const { user, board } = setup(); | ||
|
||
await service.getUnusedAvailableSchoolExternalTools(user, board); | ||
|
||
expect(schoolExternalToolService.findSchoolExternalTools).toHaveBeenCalledWith({ | ||
schoolId: user.school?.id, | ||
isDeactivated: false, | ||
}); | ||
}); | ||
|
||
it('should call the service to get context external tools by board', async () => { | ||
const { user, board, mediaExternalToolElement } = setup(); | ||
|
||
await service.getUnusedAvailableSchoolExternalTools(user, board); | ||
|
||
expect(contextExternalToolService.findById).toHaveBeenCalledWith( | ||
mediaExternalToolElement.contextExternalToolId | ||
); | ||
}); | ||
|
||
it('should return the available tools', async () => { | ||
const { user, board, schoolExternalTool } = setup(); | ||
|
||
const schoolExternalTools: SchoolExternalTool[] = await service.getUnusedAvailableSchoolExternalTools( | ||
user, | ||
board | ||
); | ||
|
||
expect(schoolExternalTools).toEqual([schoolExternalTool]); | ||
}); | ||
}); | ||
|
||
describe('when there are elements on board which has deleted context external tool', () => { | ||
const setup = () => { | ||
const user: User = userFactory.build(); | ||
|
||
const schoolExternalTool: SchoolExternalTool = schoolExternalToolFactory | ||
.withSchoolId(user.school.id) | ||
.buildWithId(); | ||
const usedSchoolExternalTool: SchoolExternalTool = schoolExternalToolFactory | ||
.withSchoolId(user.school.id) | ||
.buildWithId(); | ||
|
||
const usedContextExternalTool: ContextExternalTool = contextExternalToolFactory | ||
.withSchoolExternalToolRef(usedSchoolExternalTool.id, user.school.id) | ||
.buildWithId(); | ||
|
||
const mediaExternalToolElement: MediaExternalToolElement = mediaExternalToolElementFactory.build({ | ||
contextExternalToolId: usedContextExternalTool.id, | ||
}); | ||
const mediaExternalToolElementWithDeletedTool: MediaExternalToolElement = mediaExternalToolElementFactory.build( | ||
{ | ||
contextExternalToolId: new ObjectId().toHexString(), | ||
} | ||
); | ||
const board: MediaBoard = mediaBoardFactory.build({ | ||
children: [mediaExternalToolElement, mediaExternalToolElementWithDeletedTool], | ||
}); | ||
mediaBoardService.findMediaElements.mockReturnValueOnce([mediaExternalToolElement]); | ||
|
||
schoolExternalToolService.findSchoolExternalTools.mockResolvedValue([ | ||
schoolExternalTool, | ||
usedSchoolExternalTool, | ||
]); | ||
contextExternalToolService.findById.mockResolvedValueOnce(usedContextExternalTool); | ||
contextExternalToolService.findById.mockResolvedValueOnce(null); | ||
|
||
return { user, board, mediaExternalToolElement, schoolExternalTool }; | ||
}; | ||
|
||
it('should return the available tools', async () => { | ||
const { user, board, schoolExternalTool } = setup(); | ||
|
||
const schoolExternalTools: SchoolExternalTool[] = await service.getUnusedAvailableSchoolExternalTools( | ||
user, | ||
board | ||
); | ||
|
||
expect(schoolExternalTools).toEqual([schoolExternalTool]); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getAvailableExternalToolsForSchool', () => { | ||
describe('when there are available external tools', () => { | ||
const setup = () => { | ||
const user: User = userFactory.build(); | ||
|
||
const deactivatedExternalTool: ExternalTool = externalToolFactory.buildWithId({ isDeactivated: true }); | ||
const hiddenExternalTool: ExternalTool = externalToolFactory.buildWithId({ isHidden: true }); | ||
const contextParameterExternalTool: ExternalTool = externalToolFactory | ||
.withCustomParameters(1, { scope: CustomParameterScope.CONTEXT }) | ||
.buildWithId(); | ||
const invalidRestrictedExternalTool: ExternalTool = externalToolFactory.buildWithId({ | ||
restrictToContexts: [ToolContextType.COURSE], | ||
}); | ||
const validRestrictedExternalTool: ExternalTool = externalToolFactory.buildWithId({ | ||
restrictToContexts: [ToolContextType.MEDIA_BOARD, ToolContextType.COURSE], | ||
}); | ||
const validExternalToolNew: ExternalTool = externalToolFactory.buildWithId({ | ||
createdAt: new Date(2024, 1, 2), | ||
restrictToContexts: undefined, | ||
}); | ||
const validExternalToolOld: ExternalTool = externalToolFactory.buildWithId({ | ||
createdAt: new Date(2023, 1, 2), | ||
restrictToContexts: [], | ||
}); | ||
const validAndInvalidExternalTools: Page<ExternalTool> = new Page<ExternalTool>( | ||
[ | ||
validExternalToolOld, | ||
validExternalToolNew, | ||
validRestrictedExternalTool, | ||
deactivatedExternalTool, | ||
hiddenExternalTool, | ||
contextParameterExternalTool, | ||
invalidRestrictedExternalTool, | ||
], | ||
7 | ||
); | ||
const schoolExternalTool: SchoolExternalTool = schoolExternalToolFactory | ||
.withSchoolId(user.school.id) | ||
.buildWithId({ toolId: validExternalToolNew.id }); | ||
|
||
externalToolService.findExternalTools.mockResolvedValueOnce(validAndInvalidExternalTools); | ||
|
||
const board: MediaBoard = mediaBoardFactory.build(); | ||
|
||
const expectedExternalTools: ExternalTool[] = [ | ||
validExternalToolNew, | ||
validExternalToolOld, | ||
validRestrictedExternalTool, | ||
]; | ||
|
||
return { user, board, schoolExternalTool, expectedExternalTools }; | ||
}; | ||
|
||
it('should call the service to get external tools', async () => { | ||
const { schoolExternalTool } = setup(); | ||
|
||
await service.getAvailableExternalToolsForSchool([schoolExternalTool]); | ||
|
||
expect(externalToolService.findExternalTools).toHaveBeenCalledWith({ ids: [schoolExternalTool.toolId] }); | ||
}); | ||
|
||
it('should return all available external tools in correct order', async () => { | ||
const { schoolExternalTool, expectedExternalTools } = setup(); | ||
|
||
const externalTools: ExternalTool[] = await service.getAvailableExternalToolsForSchool([schoolExternalTool]); | ||
|
||
expect(externalTools).toEqual(expectedExternalTools); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('matchTools', () => { | ||
describe('when there are matches', () => { | ||
const setup = () => { | ||
const availableExternalTools: ExternalTool[] = [ | ||
externalToolFactory.buildWithId(), | ||
externalToolFactory.buildWithId(), | ||
]; | ||
const schoolExternalTools: SchoolExternalTool[] = [ | ||
schoolExternalToolFactory.buildWithId({ toolId: availableExternalTools[0].id }), | ||
schoolExternalToolFactory.buildWithId({ toolId: availableExternalTools[1].id }), | ||
]; | ||
|
||
return { availableExternalTools, schoolExternalTools }; | ||
}; | ||
|
||
it('should return the matches', () => { | ||
const { availableExternalTools, schoolExternalTools } = setup(); | ||
|
||
const matches: [ExternalTool, SchoolExternalTool][] = service.matchTools( | ||
availableExternalTools, | ||
schoolExternalTools | ||
); | ||
|
||
expect(matches.length).toBe(2); | ||
expect(matches[0]).toEqual([availableExternalTools[0], schoolExternalTools[0]]); | ||
expect(matches[1]).toEqual([availableExternalTools[1], schoolExternalTools[1]]); | ||
}); | ||
}); | ||
|
||
describe('when there are no matches', () => { | ||
const setup = () => { | ||
const availableExternalTools: ExternalTool[] = [ | ||
externalToolFactory.buildWithId(), | ||
externalToolFactory.buildWithId(), | ||
]; | ||
const schoolExternalTools: SchoolExternalTool[] = [ | ||
schoolExternalToolFactory.buildWithId(), | ||
schoolExternalToolFactory.buildWithId(), | ||
]; | ||
|
||
return { availableExternalTools, schoolExternalTools }; | ||
}; | ||
|
||
it('should return an empty array', () => { | ||
const { availableExternalTools, schoolExternalTools } = setup(); | ||
|
||
const matches: [ExternalTool, SchoolExternalTool][] = service.matchTools( | ||
availableExternalTools, | ||
schoolExternalTools | ||
); | ||
|
||
expect(matches).toEqual([]); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('createMediaAvailableLine', () => { | ||
const setup = () => { | ||
const mediaBoard = mediaBoardFactory.build(); | ||
const externalTool1: ExternalTool = externalToolFactory.buildWithId(); | ||
const schoolExternalTool1: SchoolExternalTool = schoolExternalToolFactory.buildWithId(); | ||
const externalTool2: ExternalTool = externalToolFactory.buildWithId(); | ||
const schoolExternalTool2: SchoolExternalTool = schoolExternalToolFactory.buildWithId(); | ||
const availableExternalTools: [ExternalTool, SchoolExternalTool][] = [ | ||
[externalTool1, schoolExternalTool1], | ||
[externalTool2, schoolExternalTool2], | ||
]; | ||
|
||
const logoUrl = 'https://logo.com'; | ||
externalToolLogoService.buildLogoUrl.mockReturnValueOnce(logoUrl); | ||
|
||
return { | ||
availableExternalTools, | ||
externalTool1, | ||
externalTool2, | ||
schoolExternalTool1, | ||
schoolExternalTool2, | ||
logoUrl, | ||
mediaBoard, | ||
}; | ||
}; | ||
|
||
it('should call the service to build the logo url', () => { | ||
const { availableExternalTools, externalTool1, externalTool2, mediaBoard } = setup(); | ||
|
||
service.createMediaAvailableLine(mediaBoard, availableExternalTools); | ||
|
||
expect(externalToolLogoService.buildLogoUrl).toHaveBeenCalledWith(externalTool1); | ||
expect(externalToolLogoService.buildLogoUrl).toHaveBeenCalledWith(externalTool2); | ||
}); | ||
|
||
it('should create a media available line with correct elements', () => { | ||
const { | ||
availableExternalTools, | ||
externalTool1, | ||
externalTool2, | ||
schoolExternalTool1, | ||
schoolExternalTool2, | ||
logoUrl, | ||
mediaBoard, | ||
} = setup(); | ||
|
||
const line: MediaAvailableLine = service.createMediaAvailableLine(mediaBoard, availableExternalTools); | ||
|
||
expect(line).toEqual({ | ||
elements: [ | ||
{ | ||
schoolExternalToolId: schoolExternalTool1.id, | ||
name: externalTool1.name, | ||
description: externalTool1.description, | ||
logoUrl, | ||
}, | ||
{ | ||
schoolExternalToolId: schoolExternalTool2.id, | ||
name: externalTool2.name, | ||
description: externalTool2.description, | ||
logoUrl: undefined, | ||
}, | ||
], | ||
backgroundColor: mediaBoard.backgroundColor, | ||
collapsed: mediaBoard.collapsed, | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.