From 2028064305e34e4184acc86259d03d8169bfe20f Mon Sep 17 00:00:00 2001 From: Igor Richter Date: Thu, 9 Nov 2023 12:35:30 +0100 Subject: [PATCH] add feature flag to tool config and fix unit tests --- .../service/tool-reference.service.spec.ts | 19 ++++++---- apps/server/src/modules/tool/tool-config.ts | 2 ++ .../service/tool-launch.service.spec.ts | 36 +++++++++++++------ 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/apps/server/src/modules/tool/context-external-tool/service/tool-reference.service.spec.ts b/apps/server/src/modules/tool/context-external-tool/service/tool-reference.service.spec.ts index 9182a641f95..3de57e5531f 100644 --- a/apps/server/src/modules/tool/context-external-tool/service/tool-reference.service.spec.ts +++ b/apps/server/src/modules/tool/context-external-tool/service/tool-reference.service.spec.ts @@ -2,7 +2,6 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { ObjectId } from '@mikro-orm/mongodb'; import { Test, TestingModule } from '@nestjs/testing'; import { contextExternalToolFactory, externalToolFactory, schoolExternalToolFactory } from '@shared/testing'; -import { Configuration } from '@hpi-schul-cloud/commons'; import { ApiValidationError } from '@shared/common'; import { ToolConfigurationStatus } from '../../common/enum'; import { CommonToolService } from '../../common/service'; @@ -12,7 +11,7 @@ import { ToolReference } from '../domain'; import { ContextExternalToolService } from './context-external-tool.service'; import { ToolReferenceService } from './tool-reference.service'; import { ContextExternalToolValidationService } from './context-external-tool-validation.service'; -import objectContaining = jasmine.objectContaining; +import { IToolFeatures, ToolFeatures } from '../../tool-config'; describe('ToolReferenceService', () => { let module: TestingModule; @@ -25,6 +24,7 @@ describe('ToolReferenceService', () => { let externalToolLogoService: DeepMocked; let contextExternalToolValidationService: DeepMocked; let schoolExternalToolValidationService: DeepMocked; + let toolFeatures: DeepMocked; beforeAll(async () => { module = await Test.createTestingModule({ @@ -58,6 +58,12 @@ describe('ToolReferenceService', () => { provide: SchoolExternalToolValidationService, useValue: createMock(), }, + { + provide: ToolFeatures, + useValue: { + toolStatusWithoutVersions: false, + }, + }, ], }).compile(); @@ -69,6 +75,7 @@ describe('ToolReferenceService', () => { externalToolLogoService = module.get(ExternalToolLogoService); contextExternalToolValidationService = module.get(ContextExternalToolValidationService); schoolExternalToolValidationService = module.get(SchoolExternalToolValidationService); + toolFeatures = module.get(ToolFeatures); }); afterAll(async () => { @@ -98,7 +105,7 @@ describe('ToolReferenceService', () => { commonToolService.determineToolConfigurationStatus.mockReturnValue(ToolConfigurationStatus.OUTDATED); externalToolLogoService.buildLogoUrl.mockReturnValue(logoUrl); - Configuration.set('FEATURE_COMPUTE_TOOL_STATUS_WITHOUT_VERSIONS_ENABLED', false); + toolFeatures.toolStatusWithoutVersions = false; return { contextExternalToolId, @@ -166,7 +173,7 @@ describe('ToolReferenceService', () => { externalToolLogoService.buildLogoUrl.mockReturnValue(logoUrl); schoolExternalToolValidationService.validate.mockRejectedValueOnce(ApiValidationError); - Configuration.set('FEATURE_COMPUTE_TOOL_STATUS_WITHOUT_VERSIONS_ENABLED', true); + toolFeatures.toolStatusWithoutVersions = true; return { contextExternalToolId, @@ -176,12 +183,12 @@ describe('ToolReferenceService', () => { }; it('should determine the tool status through validation', async () => { - const { contextExternalToolId, schoolExternalTool, contextExternalTool } = setup(); + const { contextExternalToolId, schoolExternalTool } = setup(); await service.getToolReference(contextExternalToolId); expect(schoolExternalToolValidationService.validate).toHaveBeenCalledWith(schoolExternalTool); - expect(contextExternalToolValidationService.validate).toHaveBeenCalledWith(contextExternalTool); + expect(contextExternalToolValidationService.validate).not.toHaveBeenCalled(); }); it('should get the outdated status', async () => { diff --git a/apps/server/src/modules/tool/tool-config.ts b/apps/server/src/modules/tool/tool-config.ts index 2bd47089286..ea8641727ff 100644 --- a/apps/server/src/modules/tool/tool-config.ts +++ b/apps/server/src/modules/tool/tool-config.ts @@ -6,6 +6,7 @@ export interface IToolFeatures { ctlToolsTabEnabled: boolean; ltiToolsTabEnabled: boolean; contextConfigurationEnabled: boolean; + toolStatusWithoutVersions: boolean; maxExternalToolLogoSizeInBytes: number; backEndUrl: string; } @@ -15,6 +16,7 @@ export default class ToolConfiguration { ctlToolsTabEnabled: Configuration.get('FEATURE_CTL_TOOLS_TAB_ENABLED') as boolean, ltiToolsTabEnabled: Configuration.get('FEATURE_LTI_TOOLS_TAB_ENABLED') as boolean, contextConfigurationEnabled: Configuration.get('FEATURE_CTL_CONTEXT_CONFIGURATION_ENABLED') as boolean, + toolStatusWithoutVersions: Configuration.get('FEATURE_COMPUTE_TOOL_STATUS_WITHOUT_VERSIONS_ENABLED') as boolean, maxExternalToolLogoSizeInBytes: Configuration.get('CTL_TOOLS__EXTERNAL_TOOL_MAX_LOGO_SIZE_IN_BYTES') as number, backEndUrl: Configuration.get('PUBLIC_BACKEND_URL') as string, }; diff --git a/apps/server/src/modules/tool/tool-launch/service/tool-launch.service.spec.ts b/apps/server/src/modules/tool/tool-launch/service/tool-launch.service.spec.ts index 9f814aaacd8..30e87c2433a 100644 --- a/apps/server/src/modules/tool/tool-launch/service/tool-launch.service.spec.ts +++ b/apps/server/src/modules/tool/tool-launch/service/tool-launch.service.spec.ts @@ -7,7 +7,6 @@ import { externalToolFactory, schoolExternalToolFactory, } from '@shared/testing'; -import { Configuration } from '@hpi-schul-cloud/commons'; import { ApiValidationError } from '@shared/common'; import { ToolConfigType, ToolConfigurationStatus } from '../../common/enum'; import { CommonToolService } from '../../common/service'; @@ -26,6 +25,7 @@ import { } from './launch-strategy'; import { ToolLaunchService } from './tool-launch.service'; import { ContextExternalToolValidationService } from '../../context-external-tool/service'; +import { IToolFeatures, ToolFeatures } from '../../tool-config'; describe('ToolLaunchService', () => { let module: TestingModule; @@ -37,6 +37,7 @@ describe('ToolLaunchService', () => { let commonToolService: DeepMocked; let contextExternalToolValidationService: DeepMocked; let schoolExternalToolValidationService: DeepMocked; + let toolFeatures: DeepMocked; beforeEach(async () => { module = await Test.createTestingModule({ @@ -74,6 +75,12 @@ describe('ToolLaunchService', () => { provide: SchoolExternalToolValidationService, useValue: createMock(), }, + { + provide: ToolFeatures, + useValue: { + toolStatusWithoutVersions: false, + }, + }, ], }).compile(); @@ -84,6 +91,7 @@ describe('ToolLaunchService', () => { commonToolService = module.get(CommonToolService); contextExternalToolValidationService = module.get(ContextExternalToolValidationService); schoolExternalToolValidationService = module.get(SchoolExternalToolValidationService); + toolFeatures = module.get(ToolFeatures); }); afterAll(async () => { @@ -124,7 +132,7 @@ describe('ToolLaunchService', () => { basicToolLaunchStrategy.createLaunchData.mockResolvedValue(launchDataDO); commonToolService.determineToolConfigurationStatus.mockReturnValueOnce(ToolConfigurationStatus.LATEST); - Configuration.set('FEATURE_COMPUTE_TOOL_STATUS_WITHOUT_VERSIONS_ENABLED', false); + toolFeatures.toolStatusWithoutVersions = false; return { launchDataDO, @@ -192,6 +200,8 @@ describe('ToolLaunchService', () => { externalToolService.findById.mockResolvedValue(externalTool); commonToolService.determineToolConfigurationStatus.mockReturnValueOnce(ToolConfigurationStatus.LATEST); + toolFeatures.toolStatusWithoutVersions = false; + return { launchParams, }; @@ -237,6 +247,8 @@ describe('ToolLaunchService', () => { basicToolLaunchStrategy.createLaunchData.mockResolvedValue(launchDataDO); commonToolService.determineToolConfigurationStatus.mockReturnValueOnce(ToolConfigurationStatus.OUTDATED); + toolFeatures.toolStatusWithoutVersions = false; + return { launchParams, userId, @@ -283,9 +295,11 @@ describe('ToolLaunchService', () => { externalToolService.findById.mockResolvedValue(externalTool); basicToolLaunchStrategy.createLaunchData.mockResolvedValue(launchDataDO); commonToolService.determineToolConfigurationStatus.mockReturnValueOnce(ToolConfigurationStatus.OUTDATED); + commonToolService.determineToolConfigurationStatus.mockReturnValueOnce(ToolConfigurationStatus.LATEST); contextExternalToolValidationService.validate.mockRejectedValueOnce(ApiValidationError); - Configuration.set('FEATURE_COMPUTE_TOOL_STATUS_WITHOUT_VERSIONS_ENABLED', true); + contextExternalToolValidationService.validate.mockResolvedValueOnce(); + toolFeatures.toolStatusWithoutVersions = true; return { launchParams, @@ -294,6 +308,14 @@ describe('ToolLaunchService', () => { }; }; + it('should throw ToolStatusOutdatedLoggableException', async () => { + const { launchParams, userId, contextExternalToolId } = setup(); + + const func = () => service.getLaunchData(userId, launchParams.contextExternalTool); + + await expect(func).rejects.toThrow(new ToolStatusOutdatedLoggableException(userId, contextExternalToolId)); + }); + it('should should call validate', async () => { const { launchParams } = setup(); @@ -302,14 +324,6 @@ describe('ToolLaunchService', () => { expect(schoolExternalToolValidationService.validate).toHaveBeenCalled(); expect(contextExternalToolValidationService.validate).toHaveBeenCalled(); }); - - it('should throw ToolStatusOutdatedLoggableException', async () => { - const { launchParams, userId, contextExternalToolId } = setup(); - - const func = () => service.getLaunchData(userId, launchParams.contextExternalTool); - - await expect(func).rejects.toThrow(new ToolStatusOutdatedLoggableException(userId, contextExternalToolId)); - }); }); });