-
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.
- Loading branch information
1 parent
8c4646e
commit 4c7de71
Showing
20 changed files
with
817 additions
and
1 deletion.
There are no files selected for viewing
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
31 changes: 31 additions & 0 deletions
31
...dules/tool/context-external-tool/controller/admin-api-context-external-tool.controller.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,31 @@ | ||
import { Body, Controller, Post, UseGuards } from '@nestjs/common'; | ||
import { AuthGuard } from '@nestjs/passport'; | ||
import { ApiOperation, ApiTags } from '@nestjs/swagger'; | ||
import { ContextExternalTool } from '../domain'; | ||
import { ContextExternalToolRequestMapper, ContextExternalToolResponseMapper } from '../mapper'; | ||
import { AdminApiContextExternalToolUc } from '../uc'; | ||
import { ContextExternalToolDto } from '../uc/dto/context-external-tool.types'; | ||
import { ContextExternalToolPostParams, ContextExternalToolResponse } from './dto'; | ||
|
||
@ApiTags('AdminApi: Context External Tool') | ||
@UseGuards(AuthGuard('api-key')) | ||
@Controller('admin/tools/context-external-tools') | ||
export class AdminApiContextExternalToolController { | ||
constructor(private readonly adminApiContextExternalToolUc: AdminApiContextExternalToolUc) {} | ||
|
||
@Post() | ||
@ApiOperation({ summary: 'Creates a ContextExternalTool' }) | ||
async createContextExternalTool(@Body() body: ContextExternalToolPostParams): Promise<ContextExternalToolResponse> { | ||
const contextExternalToolProps: ContextExternalToolDto = | ||
ContextExternalToolRequestMapper.mapContextExternalToolRequest(body); | ||
|
||
const contextExternalTool: ContextExternalTool = await this.adminApiContextExternalToolUc.createContextExternalTool( | ||
contextExternalToolProps | ||
); | ||
|
||
const response: ContextExternalToolResponse = | ||
ContextExternalToolResponseMapper.mapContextExternalToolResponse(contextExternalTool); | ||
|
||
return response; | ||
} | ||
} |
142 changes: 142 additions & 0 deletions
142
...ool/context-external-tool/controller/api-test/admin-api-context-external-tool.api.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,142 @@ | ||
import { EntityManager, MikroORM } from '@mikro-orm/core'; | ||
import { serverConfig } from '@modules/server'; | ||
import { AdminApiServerTestModule } from '@modules/server/admin-api.server.module'; | ||
import { HttpStatus, INestApplication } from '@nestjs/common'; | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { Course, SchoolEntity } from '@shared/domain/entity'; | ||
import { courseFactory, schoolEntityFactory, TestApiClient } from '@shared/testing'; | ||
import { ToolContextType } from '../../../common/enum'; | ||
import { ExternalToolResponse } from '../../../external-tool/controller/dto'; | ||
import { CustomParameterScope, CustomParameterType, ExternalToolEntity } from '../../../external-tool/entity'; | ||
import { customParameterEntityFactory, externalToolEntityFactory } from '../../../external-tool/testing'; | ||
import { SchoolExternalToolEntity } from '../../../school-external-tool/entity'; | ||
import { schoolExternalToolEntityFactory } from '../../../school-external-tool/testing'; | ||
import { ContextExternalToolEntity } from '../../entity'; | ||
import { ContextExternalToolPostParams, ContextExternalToolResponse } from '../dto'; | ||
|
||
describe('AdminApiContextExternalTool (API)', () => { | ||
let app: INestApplication; | ||
let em: EntityManager; | ||
let orm: MikroORM; | ||
let testApiClient: TestApiClient; | ||
|
||
const apiKey = 'validApiKey'; | ||
|
||
const basePath = 'admin/tools/context-external-tools'; | ||
|
||
beforeAll(async () => { | ||
serverConfig().ADMIN_API__ALLOWED_API_KEYS = [apiKey]; | ||
|
||
const module: TestingModule = await Test.createTestingModule({ | ||
imports: [AdminApiServerTestModule], | ||
}).compile(); | ||
|
||
app = module.createNestApplication(); | ||
await app.init(); | ||
em = module.get(EntityManager); | ||
orm = app.get(MikroORM); | ||
testApiClient = new TestApiClient(app, basePath, apiKey, true); | ||
}); | ||
|
||
afterAll(async () => { | ||
await app.close(); | ||
}); | ||
|
||
afterEach(async () => { | ||
await orm.getSchemaGenerator().clearDatabase(); | ||
}); | ||
|
||
describe('[POST] admin/tools/context-external-tools', () => { | ||
describe('when authenticating without an api token', () => { | ||
it('should return unauthorized', async () => { | ||
const client = new TestApiClient(app, basePath); | ||
|
||
const response = await client.post(); | ||
|
||
expect(response.status).toEqual(HttpStatus.UNAUTHORIZED); | ||
}); | ||
}); | ||
|
||
describe('when authenticating with an invalid api token', () => { | ||
it('should return unauthorized', async () => { | ||
const client = new TestApiClient(app, basePath, 'invalidApiKey', true); | ||
|
||
const response = await client.post(); | ||
|
||
expect(response.status).toEqual(HttpStatus.UNAUTHORIZED); | ||
}); | ||
}); | ||
|
||
describe('when authenticating with a valid api token', () => { | ||
const setup = async () => { | ||
const school: SchoolEntity = schoolEntityFactory.buildWithId(); | ||
const course: Course = courseFactory.buildWithId({ school }); | ||
const externalToolEntity: ExternalToolEntity = externalToolEntityFactory.buildWithId({ | ||
parameters: [ | ||
customParameterEntityFactory.build({ | ||
name: 'param1', | ||
scope: CustomParameterScope.CONTEXT, | ||
type: CustomParameterType.STRING, | ||
isOptional: false, | ||
}), | ||
customParameterEntityFactory.build({ | ||
name: 'param2', | ||
scope: CustomParameterScope.CONTEXT, | ||
type: CustomParameterType.BOOLEAN, | ||
isOptional: true, | ||
}), | ||
], | ||
}); | ||
const schoolExternalToolEntity: SchoolExternalToolEntity = schoolExternalToolEntityFactory.buildWithId({ | ||
tool: externalToolEntity, | ||
school, | ||
schoolParameters: [], | ||
}); | ||
|
||
const postParams: ContextExternalToolPostParams = { | ||
schoolToolId: schoolExternalToolEntity.id, | ||
contextId: course.id, | ||
displayName: course.name, | ||
contextType: ToolContextType.COURSE, | ||
parameters: [ | ||
{ name: 'param1', value: 'value' }, | ||
{ name: 'param2', value: 'true' }, | ||
], | ||
}; | ||
|
||
await em.persistAndFlush([school, externalToolEntity]); | ||
em.clear(); | ||
|
||
return { | ||
postParams, | ||
}; | ||
}; | ||
|
||
it('should create a context external tool', async () => { | ||
const { postParams } = await setup(); | ||
|
||
const response = await testApiClient.post().send(postParams); | ||
|
||
const body: ExternalToolResponse = response.body as ExternalToolResponse; | ||
|
||
expect(response.statusCode).toEqual(HttpStatus.CREATED); | ||
expect(body).toEqual<ContextExternalToolResponse>({ | ||
id: expect.any(String), | ||
schoolToolId: postParams.schoolToolId, | ||
contextId: postParams.contextId, | ||
displayName: postParams.displayName, | ||
contextType: postParams.contextType, | ||
parameters: [ | ||
{ name: 'param1', value: 'value' }, | ||
{ name: 'param2', value: 'true' }, | ||
], | ||
}); | ||
|
||
const contextExternalTool: ContextExternalToolEntity | null = await em.findOne(ContextExternalToolEntity, { | ||
id: body.id, | ||
}); | ||
expect(contextExternalTool).toBeDefined(); | ||
}); | ||
}); | ||
}); | ||
}); |
1 change: 1 addition & 0 deletions
1
apps/server/src/modules/tool/context-external-tool/controller/index.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 |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from './tool-context.controller'; | ||
export { AdminApiContextExternalToolController } from './admin-api-context-external-tool.controller'; |
65 changes: 65 additions & 0 deletions
65
...rver/src/modules/tool/context-external-tool/uc/admin-api-context-external-tool.uc.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,65 @@ | ||
import { createMock, DeepMocked } from '@golevelup/ts-jest'; | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { ContextExternalToolService } from '../service'; | ||
import { contextExternalToolFactory } from '../testing'; | ||
import { AdminApiContextExternalToolUc } from './admin-api-context-external-tool.uc'; | ||
|
||
describe(AdminApiContextExternalToolUc.name, () => { | ||
let module: TestingModule; | ||
let uc: AdminApiContextExternalToolUc; | ||
|
||
let contextExternalToolService: DeepMocked<ContextExternalToolService>; | ||
|
||
beforeAll(async () => { | ||
module = await Test.createTestingModule({ | ||
providers: [ | ||
AdminApiContextExternalToolUc, | ||
{ | ||
provide: ContextExternalToolService, | ||
useValue: createMock<ContextExternalToolService>(), | ||
}, | ||
], | ||
}).compile(); | ||
|
||
uc = module.get(AdminApiContextExternalToolUc); | ||
contextExternalToolService = module.get(ContextExternalToolService); | ||
}); | ||
|
||
afterAll(async () => { | ||
await module.close(); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.resetAllMocks(); | ||
}); | ||
|
||
describe('createExternalTool', () => { | ||
describe('when creating a tool', () => { | ||
const setup = () => { | ||
const contextExternalTool = contextExternalToolFactory.build(); | ||
|
||
contextExternalToolService.saveContextExternalTool.mockResolvedValueOnce(contextExternalTool); | ||
|
||
return { | ||
contextExternalTool, | ||
}; | ||
}; | ||
|
||
it('should save the tool', async () => { | ||
const { contextExternalTool } = setup(); | ||
|
||
await uc.createContextExternalTool(contextExternalTool.getProps()); | ||
|
||
expect(contextExternalToolService.saveContextExternalTool).toHaveBeenCalledWith(contextExternalTool); | ||
}); | ||
|
||
it('should return the tool', async () => { | ||
const { contextExternalTool } = setup(); | ||
|
||
const result = await uc.createContextExternalTool(contextExternalTool.getProps()); | ||
|
||
expect(result).toEqual(contextExternalTool); | ||
}); | ||
}); | ||
}); | ||
}); |
19 changes: 19 additions & 0 deletions
19
apps/server/src/modules/tool/context-external-tool/uc/admin-api-context-external-tool.uc.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,19 @@ | ||
import { Injectable } from '@nestjs/common'; | ||
import { ContextExternalTool } from '../domain'; | ||
import { ContextExternalToolService } from '../service'; | ||
import { ContextExternalToolDto } from './dto/context-external-tool.types'; | ||
|
||
@Injectable() | ||
export class AdminApiContextExternalToolUc { | ||
constructor(private readonly contextExternalToolService: ContextExternalToolService) {} | ||
|
||
async createContextExternalTool(contextExternalToolProps: ContextExternalToolDto): Promise<ContextExternalTool> { | ||
const contextExternalTool: ContextExternalTool = new ContextExternalTool(contextExternalToolProps); | ||
|
||
const createdTool: ContextExternalTool = await this.contextExternalToolService.saveContextExternalTool( | ||
contextExternalTool | ||
); | ||
|
||
return createdTool; | ||
} | ||
} |
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 |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export { AdminApiContextExternalToolUc } from './admin-api-context-external-tool.uc'; | ||
export * from './context-external-tool.uc'; | ||
export * from './tool-reference.uc'; |
30 changes: 30 additions & 0 deletions
30
apps/server/src/modules/tool/external-tool/controller/admin-api-external-tool.controller.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,30 @@ | ||
import { Body, Controller, Post, UseGuards } from '@nestjs/common'; | ||
import { AuthGuard } from '@nestjs/passport'; | ||
import { ApiOperation, ApiTags } from '@nestjs/swagger'; | ||
import { ExternalTool } from '../domain'; | ||
|
||
import { ExternalToolRequestMapper, ExternalToolResponseMapper } from '../mapper'; | ||
import { AdminApiExternalToolUc, ExternalToolCreate } from '../uc'; | ||
import { ExternalToolCreateParams, ExternalToolResponse } from './dto'; | ||
|
||
@ApiTags('AdminApi: External Tools') | ||
@UseGuards(AuthGuard('api-key')) | ||
@Controller('admin/tools/external-tools') | ||
export class AdminApiExternalToolController { | ||
constructor( | ||
private readonly adminApiExternalToolUc: AdminApiExternalToolUc, | ||
private readonly externalToolDOMapper: ExternalToolRequestMapper | ||
) {} | ||
|
||
@Post() | ||
@ApiOperation({ summary: 'Creates an ExternalTool' }) | ||
async createExternalTool(@Body() externalToolParams: ExternalToolCreateParams): Promise<ExternalToolResponse> { | ||
const externalTool: ExternalToolCreate = this.externalToolDOMapper.mapCreateRequest(externalToolParams); | ||
|
||
const created: ExternalTool = await this.adminApiExternalToolUc.createExternalTool(externalTool); | ||
|
||
const mapped: ExternalToolResponse = ExternalToolResponseMapper.mapToExternalToolResponse(created); | ||
|
||
return mapped; | ||
} | ||
} |
Oops, something went wrong.