diff --git a/apps/server/src/modules/tool/common/service/common-tool-validation.service.spec.ts b/apps/server/src/modules/tool/common/service/common-tool-validation.service.spec.ts index d3ca547a854..1f76ec01a14 100644 --- a/apps/server/src/modules/tool/common/service/common-tool-validation.service.spec.ts +++ b/apps/server/src/modules/tool/common/service/common-tool-validation.service.spec.ts @@ -109,104 +109,93 @@ describe('CommonToolValidationService', () => { }); }); - describe('checkForDuplicateParameters', () => { - describe('when given parameters has a case sensitive duplicate', () => { - const setup = () => { - const schoolExternalTool: SchoolExternalTool = schoolExternalToolFactory.build({ - parameters: [ - { name: 'nameDuplicate', value: 'value' }, - { name: 'nameDuplicate', value: 'value' }, - ], - }); + describe('checkCustomParameterEntries', () => { + const createTools = ( + externalToolMock?: Partial, + schoolExternalToolMock?: Partial, + contextExternalToolMock?: Partial + ) => { + const externalTool: ExternalTool = new ExternalTool({ + ...externalToolFactory.buildWithId(), + ...externalToolMock, + }); + const schoolExternalTool: SchoolExternalTool = schoolExternalToolFactory.build({ + ...schoolExternalToolFactory.buildWithId(), + ...schoolExternalToolMock, + }); + const schoolExternalToolId = schoolExternalTool.id as string; + const contextExternalTool: ContextExternalTool = contextExternalToolFactory.build({ + ...contextExternalToolFactory.buildWithId(), + ...contextExternalToolMock, + }); - return { - schoolExternalTool, - }; + return { + externalTool, + schoolExternalTool, + schoolExternalToolId, + contextExternalTool, }; + }; - it('should throw error', () => { - const { schoolExternalTool } = setup(); - - const func = () => service.checkForDuplicateParameters(schoolExternalTool); - - expect(func).toThrow('tool_param_duplicate'); - }); - }); - - describe('when given parameters has case insensitive duplicate', () => { + describe('when a parameter is a duplicate', () => { const setup = () => { - const schoolExternalTool: SchoolExternalTool = schoolExternalToolFactory.build({ + const externalTool: ExternalTool = externalToolFactory.buildWithId({ parameters: [ - { name: 'nameDuplicate', value: 'value' }, - { name: 'nameduplicate', value: 'value' }, + customParameterFactory.build({ + name: 'duplicate', + scope: CustomParameterScope.SCHOOL, + type: CustomParameterType.STRING, + isOptional: true, + }), + ], + }); + const schoolExternalTool: SchoolExternalTool = schoolExternalToolFactory.buildWithId({ + toolId: externalTool.id, + parameters: [ + { name: 'duplicate', value: undefined }, + { name: 'duplicate', value: undefined }, ], }); return { + externalTool, schoolExternalTool, }; }; - it('should throw error when given parameters has case insensitive duplicate', () => { - const { schoolExternalTool } = setup(); + it('should throw error', () => { + const { externalTool, schoolExternalTool } = setup(); - const func = () => service.checkForDuplicateParameters(schoolExternalTool); + const func = () => service.checkCustomParameterEntries(externalTool, schoolExternalTool); expect(func).toThrowError('tool_param_duplicate'); }); }); - describe('when given parameters has no duplicates', () => { + describe('when a parameter is unknown', () => { const setup = () => { - const schoolExternalTool: SchoolExternalTool = schoolExternalToolFactory.build({ - parameters: [ - { name: 'nameNoDuplicate1', value: 'value' }, - { name: 'nameNoDuplicate2', value: 'value' }, - ], + const externalTool: ExternalTool = externalToolFactory.buildWithId({ + parameters: [], + }); + const schoolExternalTool: SchoolExternalTool = schoolExternalToolFactory.buildWithId({ + toolId: externalTool.id, + parameters: [{ name: 'unknownParameter', value: undefined }], }); return { + externalTool, schoolExternalTool, }; }; - it('when given parameters has no duplicates should return without error', () => { - const { schoolExternalTool } = setup(); + it('should throw error', () => { + const { externalTool, schoolExternalTool } = setup(); - const func = () => service.checkForDuplicateParameters(schoolExternalTool); + const func = () => service.checkCustomParameterEntries(externalTool, schoolExternalTool); - expect(func).not.toThrowError('tool_param_duplicate'); + expect(func).toThrowError('tool_param_unknown'); }); }); - }); - - describe('checkCustomParameterEntries', () => { - const createTools = ( - externalToolMock?: Partial, - schoolExternalToolMock?: Partial, - contextExternalToolMock?: Partial - ) => { - const externalTool: ExternalTool = new ExternalTool({ - ...externalToolFactory.buildWithId(), - ...externalToolMock, - }); - const schoolExternalTool: SchoolExternalTool = schoolExternalToolFactory.build({ - ...schoolExternalToolFactory.buildWithId(), - ...schoolExternalToolMock, - }); - const schoolExternalToolId = schoolExternalTool.id as string; - const contextExternalTool: ContextExternalTool = contextExternalToolFactory.build({ - ...contextExternalToolFactory.buildWithId(), - ...contextExternalToolMock, - }); - - return { - externalTool, - schoolExternalTool, - schoolExternalToolId, - contextExternalTool, - }; - }; describe('when checking parameter is required', () => { describe('and given parameter is not optional and parameter value is empty', () => { @@ -280,16 +269,23 @@ describe('CommonToolValidationService', () => { describe('when parameter is not school or context', () => { const setup = () => { - const notSchoolParam: CustomParameter = customParameterFactory.build({ - name: 'notSchoolParam', - scope: CustomParameterScope.GLOBAL, - type: CustomParameterType.BOOLEAN, - }); - const { externalTool, schoolExternalTool } = createTools( - { parameters: [notSchoolParam] }, { - parameters: [{ name: 'name', value: 'true' }], + parameters: [ + customParameterFactory.build({ + name: 'notSchoolParam', + scope: CustomParameterScope.GLOBAL, + type: CustomParameterType.BOOLEAN, + }), + customParameterFactory.build({ + name: 'schoolParam', + scope: CustomParameterScope.SCHOOL, + type: CustomParameterType.BOOLEAN, + }), + ], + }, + { + parameters: [{ name: 'schoolParam', value: 'true' }], } ); @@ -320,7 +316,7 @@ describe('CommonToolValidationService', () => { const { externalTool, schoolExternalTool } = createTools( { parameters: [missingParam] }, { - parameters: [{ name: 'anotherParam', value: 'value' }], + parameters: [], } ); @@ -339,18 +335,26 @@ describe('CommonToolValidationService', () => { }); }); - describe('when parameter is optional but is missing on params', () => { + describe('when parameter is optional and was not defined', () => { const setup = () => { - const param: CustomParameter = customParameterFactory.build({ - name: 'notChecked', - scope: CustomParameterScope.SCHOOL, - isOptional: true, - }); - const { externalTool, schoolExternalTool } = createTools( - { parameters: [param] }, { - parameters: [{ name: 'anotherParam', value: 'value' }], + parameters: [ + customParameterFactory.build({ + name: 'optionalParameter', + scope: CustomParameterScope.SCHOOL, + isOptional: true, + }), + customParameterFactory.build({ + name: 'requiredParameter', + scope: CustomParameterScope.SCHOOL, + type: CustomParameterType.STRING, + isOptional: false, + }), + ], + }, + { + parameters: [{ name: 'requiredParameter', value: 'value' }], } ); @@ -360,7 +364,7 @@ describe('CommonToolValidationService', () => { }; }; - it('should return without error ', () => { + it('should return without error', () => { const { externalTool, schoolExternalTool } = setup(); const func = () => service.checkCustomParameterEntries(externalTool, schoolExternalTool); @@ -385,7 +389,7 @@ describe('CommonToolValidationService', () => { }, undefined, { - parameters: [{ name: 'anotherParam', value: 'value' }], + parameters: [], } ); diff --git a/apps/server/src/modules/tool/common/service/common-tool-validation.service.ts b/apps/server/src/modules/tool/common/service/common-tool-validation.service.ts index 3ee9ee7d465..e6c3a31b288 100644 --- a/apps/server/src/modules/tool/common/service/common-tool-validation.service.ts +++ b/apps/server/src/modules/tool/common/service/common-tool-validation.service.ts @@ -29,12 +29,25 @@ export class CommonToolValidationService { return isValid; } - public checkForDuplicateParameters(validatableTool: ValidatableTool): void { - const caseInsensitiveNames: string[] = validatableTool.parameters.map(({ name }: CustomParameterEntry) => - name.toLowerCase() + public checkCustomParameterEntries(loadedExternalTool: ExternalTool, validatableTool: ValidatableTool): void { + this.checkForDuplicateParameters(validatableTool); + + const parametersForScope: CustomParameter[] = (loadedExternalTool.parameters ?? []).filter( + (param: CustomParameter) => + (validatableTool instanceof SchoolExternalTool && param.scope === CustomParameterScope.SCHOOL) || + (validatableTool instanceof ContextExternalTool && param.scope === CustomParameterScope.CONTEXT) ); + this.checkForUnknownParameters(validatableTool, parametersForScope); + + this.checkValidityOfParameters(validatableTool, parametersForScope); + } + + private checkForDuplicateParameters(validatableTool: ValidatableTool): void { + const caseInsensitiveNames: string[] = validatableTool.parameters.map(({ name }: CustomParameterEntry) => name); + const uniqueNames: Set = new Set(caseInsensitiveNames); + if (uniqueNames.size !== validatableTool.parameters.length) { throw new ValidationError( `tool_param_duplicate: The tool ${validatableTool.id ?? ''} contains multiple of the same custom parameters.` @@ -42,28 +55,33 @@ export class CommonToolValidationService { } } - public checkCustomParameterEntries(loadedExternalTool: ExternalTool, validatableTool: ValidatableTool): void { - if (loadedExternalTool.parameters) { - for (const param of loadedExternalTool.parameters) { - this.checkScopeAndValidateParameter(validatableTool, param); + private checkForUnknownParameters(validatableTool: ValidatableTool, parametersForScope: CustomParameter[]): void { + for (const entry of validatableTool.parameters) { + const foundParameter: CustomParameter | undefined = parametersForScope.find( + ({ name }: CustomParameter): boolean => name === entry.name + ); + + if (!foundParameter) { + throw new ValidationError( + `tool_param_unknown: The parameter with name ${entry.name} is not part of this tool.` + ); } } } - private checkScopeAndValidateParameter(validatableTool: ValidatableTool, param: CustomParameter): void { - const foundEntry: CustomParameterEntry | undefined = validatableTool.parameters.find( - ({ name }: CustomParameterEntry): boolean => name.toLowerCase() === param.name.toLowerCase() - ); + private checkValidityOfParameters(validatableTool: ValidatableTool, parametersForScope: CustomParameter[]): void { + for (const param of parametersForScope) { + const foundEntry: CustomParameterEntry | undefined = validatableTool.parameters.find( + ({ name }: CustomParameterEntry): boolean => name === param.name + ); - if (param.scope === CustomParameterScope.SCHOOL && validatableTool instanceof SchoolExternalTool) { - this.validateParameter(param, foundEntry); - } else if (param.scope === CustomParameterScope.CONTEXT && validatableTool instanceof ContextExternalTool) { this.validateParameter(param, foundEntry); } } private validateParameter(param: CustomParameter, foundEntry: CustomParameterEntry | undefined): void { this.checkOptionalParameter(param, foundEntry); + if (foundEntry) { this.checkParameterType(foundEntry, param); this.checkParameterRegex(foundEntry, param); diff --git a/apps/server/src/modules/tool/context-external-tool/controller/api-test/tool-context.api.spec.ts b/apps/server/src/modules/tool/context-external-tool/controller/api-test/tool-context.api.spec.ts index eb570130c4e..af14eb379f3 100644 --- a/apps/server/src/modules/tool/context-external-tool/controller/api-test/tool-context.api.spec.ts +++ b/apps/server/src/modules/tool/context-external-tool/controller/api-test/tool-context.api.spec.ts @@ -17,9 +17,8 @@ import { userFactory, } from '@shared/testing'; import { ObjectId } from 'bson'; -import { CustomParameterScope, ToolContextType } from '../../../common/enum'; +import { CustomParameterScope, CustomParameterType, ToolContextType } from '../../../common/enum'; import { ExternalToolEntity } from '../../../external-tool/entity'; -import { CustomParameterEntryResponse } from '../../../school-external-tool/controller/dto'; import { SchoolExternalToolEntity } from '../../../school-external-tool/entity'; import { ContextExternalToolEntity, ContextExternalToolType } from '../../entity'; import { @@ -66,10 +65,27 @@ describe('ToolContextController (API)', () => { const course: Course = courseFactory.buildWithId({ teachers: [teacherUser], school }); - const paramEntry: CustomParameterEntryResponse = { name: 'name', value: 'value' }; + 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, + }), + ], + version: 1, + }); const schoolExternalToolEntity: SchoolExternalToolEntity = schoolExternalToolEntityFactory.buildWithId({ + tool: externalToolEntity, school, - schoolParameters: [paramEntry], + schoolParameters: [], toolVersion: 1, }); @@ -78,7 +94,10 @@ describe('ToolContextController (API)', () => { contextId: course.id, displayName: course.name, contextType: ToolContextType.COURSE, - parameters: [paramEntry], + parameters: [ + { name: 'param1', value: 'value' }, + { name: 'param2', value: '' }, + ], toolVersion: 1, }; @@ -87,30 +106,30 @@ describe('ToolContextController (API)', () => { const loggedInClient: TestApiClient = await testApiClient.login(teacherAccount); - const expected: ContextExternalToolResponse = { - id: expect.any(String), - schoolToolId: postParams.schoolToolId, - contextId: postParams.contextId, - displayName: postParams.displayName, - contextType: postParams.contextType, - parameters: [paramEntry], - toolVersion: postParams.toolVersion, - }; - return { loggedInClient, postParams, - expected, }; }; it('should create a contextExternalTool', async () => { - const { postParams, loggedInClient, expected } = await setup(); + const { postParams, loggedInClient } = await setup(); const response = await loggedInClient.post().send(postParams); expect(response.statusCode).toEqual(HttpStatus.CREATED); - expect(response.body).toEqual(expect.objectContaining(expected)); + expect(response.body).toEqual({ + id: expect.any(String), + schoolToolId: postParams.schoolToolId, + contextId: postParams.contextId, + displayName: postParams.displayName, + contextType: postParams.contextType, + parameters: [ + { name: 'param1', value: 'value' }, + { name: 'param2', value: undefined }, + ], + toolVersion: postParams.toolVersion, + }); }); }); diff --git a/apps/server/src/modules/tool/context-external-tool/mapper/context-external-tool-request.mapper.ts b/apps/server/src/modules/tool/context-external-tool/mapper/context-external-tool-request.mapper.ts index 951559afbcc..8e72f5f540b 100644 --- a/apps/server/src/modules/tool/context-external-tool/mapper/context-external-tool-request.mapper.ts +++ b/apps/server/src/modules/tool/context-external-tool/mapper/context-external-tool-request.mapper.ts @@ -25,7 +25,7 @@ export class ContextExternalToolRequestMapper { return customParameterParams.map((customParameterParam: CustomParameterEntryParam) => { return { name: customParameterParam.name, - value: customParameterParam.value, + value: customParameterParam.value || undefined, }; }); } diff --git a/apps/server/src/modules/tool/context-external-tool/service/context-external-tool-validation.service.ts b/apps/server/src/modules/tool/context-external-tool/service/context-external-tool-validation.service.ts index 2cce83a08b2..b12193eadd5 100644 --- a/apps/server/src/modules/tool/context-external-tool/service/context-external-tool-validation.service.ts +++ b/apps/server/src/modules/tool/context-external-tool/service/context-external-tool-validation.service.ts @@ -18,7 +18,7 @@ export class ContextExternalToolValidationService { ) {} async validate(contextExternalTool: ContextExternalTool): Promise { - await this.checkDuplicateInContext(contextExternalTool); + await this.checkDuplicateUsesInContext(contextExternalTool); const loadedSchoolExternalTool: SchoolExternalTool = await this.schoolExternalToolService.findById( contextExternalTool.schoolToolRef.schoolToolId @@ -29,7 +29,7 @@ export class ContextExternalToolValidationService { this.commonToolValidationService.checkCustomParameterEntries(loadedExternalTool, contextExternalTool); } - private async checkDuplicateInContext(contextExternalTool: ContextExternalTool) { + private async checkDuplicateUsesInContext(contextExternalTool: ContextExternalTool) { let duplicate: ContextExternalTool[] = await this.contextExternalToolService.findContextExternalTools({ schoolToolRef: contextExternalTool.schoolToolRef, context: contextExternalTool.contextRef, diff --git a/apps/server/src/modules/tool/school-external-tool/controller/api-test/tool-school.api.spec.ts b/apps/server/src/modules/tool/school-external-tool/controller/api-test/tool-school.api.spec.ts index 3512e66038e..2cca9819b3a 100644 --- a/apps/server/src/modules/tool/school-external-tool/controller/api-test/tool-school.api.spec.ts +++ b/apps/server/src/modules/tool/school-external-tool/controller/api-test/tool-school.api.spec.ts @@ -1,9 +1,11 @@ import { EntityManager, MikroORM } from '@mikro-orm/core'; +import { ServerTestModule } from '@modules/server'; import { HttpStatus, INestApplication } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; import { Account, Permission, SchoolEntity, User } from '@shared/domain'; import { accountFactory, + customParameterEntityFactory, externalToolEntityFactory, schoolExternalToolEntityFactory, schoolFactory, @@ -11,9 +13,8 @@ import { UserAndAccountTestFactory, userFactory, } from '@shared/testing'; -import { ServerTestModule } from '@modules/server'; import { ToolConfigurationStatusResponse } from '../../../context-external-tool/controller/dto/tool-configuration-status.response'; -import { ExternalToolEntity } from '../../../external-tool/entity'; +import { CustomParameterScope, CustomParameterType, ExternalToolEntity } from '../../../external-tool/entity'; import { SchoolExternalToolEntity } from '../../entity'; import { CustomParameterEntryParam, @@ -66,31 +67,31 @@ describe('ToolSchoolController (API)', () => { const externalToolEntity: ExternalToolEntity = externalToolEntityFactory.buildWithId({ version: 1, - parameters: [], + parameters: [ + customParameterEntityFactory.build({ + name: 'param1', + scope: CustomParameterScope.SCHOOL, + type: CustomParameterType.STRING, + isOptional: false, + }), + customParameterEntityFactory.build({ + name: 'param2', + scope: CustomParameterScope.SCHOOL, + type: CustomParameterType.BOOLEAN, + isOptional: true, + }), + ], }); - const paramEntry: CustomParameterEntryParam = { name: 'name', value: 'value' }; const postParams: SchoolExternalToolPostParams = { toolId: externalToolEntity.id, schoolId: school.id, version: 1, - parameters: [paramEntry], - }; - - const schoolExternalToolResponse: SchoolExternalToolResponse = new SchoolExternalToolResponse({ - id: expect.any(String), - name: externalToolEntity.name, - schoolId: postParams.schoolId, - toolId: postParams.toolId, - status: ToolConfigurationStatusResponse.LATEST, - toolVersion: postParams.version, parameters: [ - { - name: paramEntry.name, - value: paramEntry.value, - }, + { name: 'param1', value: 'value' }, + { name: 'param2', value: '' }, ], - }); + }; em.persist([ school, @@ -112,7 +113,7 @@ describe('ToolSchoolController (API)', () => { loggedInClientWithMissingPermission, loggedInClient, postParams, - schoolExternalToolResponse, + externalToolEntity, }; }; @@ -125,12 +126,23 @@ describe('ToolSchoolController (API)', () => { }); it('should create an school external tool', async () => { - const { loggedInClient, postParams, schoolExternalToolResponse } = await setup(); + const { loggedInClient, postParams, externalToolEntity } = await setup(); const response = await loggedInClient.post().send(postParams); expect(response.statusCode).toEqual(HttpStatus.CREATED); - expect(response.body).toEqual(schoolExternalToolResponse); + expect(response.body).toEqual({ + id: expect.any(String), + name: externalToolEntity.name, + schoolId: postParams.schoolId, + toolId: postParams.toolId, + status: ToolConfigurationStatusResponse.LATEST, + toolVersion: postParams.version, + parameters: [ + { name: 'param1', value: 'value' }, + { name: 'param2', value: undefined }, + ], + }); const createdSchoolExternalTool: SchoolExternalToolEntity | null = await em.findOne(SchoolExternalToolEntity, { school: postParams.schoolId, @@ -391,7 +403,14 @@ describe('ToolSchoolController (API)', () => { const externalToolEntity: ExternalToolEntity = externalToolEntityFactory.buildWithId({ version: 1, - parameters: [], + parameters: [ + customParameterEntityFactory.build({ + name: 'param1', + scope: CustomParameterScope.SCHOOL, + type: CustomParameterType.STRING, + isOptional: false, + }), + ], }); const externalToolEntity2: ExternalToolEntity = externalToolEntityFactory.buildWithId({ version: 1, @@ -422,7 +441,7 @@ describe('ToolSchoolController (API)', () => { accountWithMissingPermission ); - const paramEntry: CustomParameterEntryParam = { name: 'name', value: 'value' }; + const paramEntry: CustomParameterEntryParam = { name: 'param1', value: 'value' }; const postParams: SchoolExternalToolPostParams = { toolId: externalToolEntity.id, schoolId: school.id, @@ -430,7 +449,7 @@ describe('ToolSchoolController (API)', () => { parameters: [paramEntry], }; - const updatedParamEntry: CustomParameterEntryParam = { name: 'name', value: 'updatedValue' }; + const updatedParamEntry: CustomParameterEntryParam = { name: 'param1', value: 'updatedValue' }; const postParamsUpdate: SchoolExternalToolPostParams = { toolId: externalToolEntity.id, schoolId: school.id, diff --git a/apps/server/src/modules/tool/school-external-tool/mapper/school-external-tool-request.mapper.ts b/apps/server/src/modules/tool/school-external-tool/mapper/school-external-tool-request.mapper.ts index 6617e4ec7fd..eff05c092cb 100644 --- a/apps/server/src/modules/tool/school-external-tool/mapper/school-external-tool-request.mapper.ts +++ b/apps/server/src/modules/tool/school-external-tool/mapper/school-external-tool-request.mapper.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; +import { CustomParameterEntry } from '../../common/domain'; import { CustomParameterEntryParam, SchoolExternalToolPostParams } from '../controller/dto'; import { SchoolExternalToolDto } from '../uc/dto/school-external-tool.types'; -import { CustomParameterEntry } from '../../common/domain'; @Injectable() export class SchoolExternalToolRequestMapper { @@ -20,7 +20,7 @@ export class SchoolExternalToolRequestMapper { return customParameterParams.map((customParameterParam: CustomParameterEntryParam) => { return { name: customParameterParam.name, - value: customParameterParam.value, + value: customParameterParam.value || undefined, }; }); } diff --git a/apps/server/src/modules/tool/school-external-tool/service/school-external-tool-validation.service.spec.ts b/apps/server/src/modules/tool/school-external-tool/service/school-external-tool-validation.service.spec.ts index 6b4f69d6686..1f2ba7f5eb9 100644 --- a/apps/server/src/modules/tool/school-external-tool/service/school-external-tool-validation.service.spec.ts +++ b/apps/server/src/modules/tool/school-external-tool/service/school-external-tool-validation.service.spec.ts @@ -4,9 +4,9 @@ import { externalToolFactory, schoolExternalToolFactory } from '@shared/testing/ import { CommonToolValidationService } from '../../common/service'; import { ExternalTool } from '../../external-tool/domain'; import { ExternalToolService } from '../../external-tool/service'; +import { IToolFeatures, ToolFeatures } from '../../tool-config'; import { SchoolExternalTool } from '../domain'; import { SchoolExternalToolValidationService } from './school-external-tool-validation.service'; -import { IToolFeatures, ToolFeatures } from '../../tool-config'; describe('SchoolExternalToolValidationService', () => { let module: TestingModule; @@ -82,14 +82,6 @@ describe('SchoolExternalToolValidationService', () => { expect(externalToolService.findById).toHaveBeenCalledWith(schoolExternalTool.toolId); }); - it('should call commonToolValidationService.checkForDuplicateParameters', async () => { - const { schoolExternalTool } = setup(); - - await service.validate(schoolExternalTool); - - expect(commonToolValidationService.checkForDuplicateParameters).toHaveBeenCalledWith(schoolExternalTool); - }); - it('should call commonToolValidationService.checkCustomParameterEntries', async () => { const { schoolExternalTool } = setup(); diff --git a/apps/server/src/modules/tool/school-external-tool/service/school-external-tool-validation.service.ts b/apps/server/src/modules/tool/school-external-tool/service/school-external-tool-validation.service.ts index 3474aa90f5e..899055e321f 100644 --- a/apps/server/src/modules/tool/school-external-tool/service/school-external-tool-validation.service.ts +++ b/apps/server/src/modules/tool/school-external-tool/service/school-external-tool-validation.service.ts @@ -3,8 +3,8 @@ import { ValidationError } from '@shared/common'; import { CommonToolValidationService } from '../../common/service'; import { ExternalTool } from '../../external-tool/domain'; import { ExternalToolService } from '../../external-tool/service'; -import { SchoolExternalTool } from '../domain'; import { IToolFeatures, ToolFeatures } from '../../tool-config'; +import { SchoolExternalTool } from '../domain'; @Injectable() export class SchoolExternalToolValidationService { @@ -15,13 +15,12 @@ export class SchoolExternalToolValidationService { ) {} async validate(schoolExternalTool: SchoolExternalTool): Promise { - this.commonToolValidationService.checkForDuplicateParameters(schoolExternalTool); - const loadedExternalTool: ExternalTool = await this.externalToolService.findById(schoolExternalTool.toolId); if (!this.toolFeatures.toolStatusWithoutVersions) { this.checkVersionMatch(schoolExternalTool.toolVersion, loadedExternalTool.version); } + this.commonToolValidationService.checkCustomParameterEntries(loadedExternalTool, schoolExternalTool); } diff --git a/apps/server/src/shared/testing/factory/external-tool-entity.factory.ts b/apps/server/src/shared/testing/factory/external-tool-entity.factory.ts index 32c077e2529..39ff2662cf7 100644 --- a/apps/server/src/shared/testing/factory/external-tool-entity.factory.ts +++ b/apps/server/src/shared/testing/factory/external-tool-entity.factory.ts @@ -82,8 +82,6 @@ export const customParameterEntityFactory = BaseFactory.define