TGD-30: FeatureFlags
This commit is contained in:
parent
dfd149103e
commit
0d26101948
4 changed files with 122 additions and 0 deletions
18
src/featureflag/featureflag.controller.spec.ts
Normal file
18
src/featureflag/featureflag.controller.spec.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { FeatureflagController } from './featureflag.controller';
|
||||||
|
|
||||||
|
describe('FeatureflagController', () => {
|
||||||
|
let controller: FeatureflagController;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
controllers: [FeatureflagController],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
controller = module.get<FeatureflagController>(FeatureflagController);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(controller).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
18
src/featureflag/featureflag.controller.ts
Normal file
18
src/featureflag/featureflag.controller.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import {Body, Controller, Get, Param, Post} from '@nestjs/common';
|
||||||
|
import {FeatureflagService} from "./featureflag.service";
|
||||||
|
|
||||||
|
@Controller('featureflag')
|
||||||
|
export class FeatureflagController {
|
||||||
|
constructor(private featureflagService: FeatureflagService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':ffname')
|
||||||
|
async getFeatureFlag(@Param() params: { ffname: string}) {
|
||||||
|
return await this.featureflagService.getFeatureFlag(params.ffname);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post(':ffname')
|
||||||
|
async setFeatureFlag(@Param() params: { ffname: string}, @Body() ffState: { name: string, state: boolean }) {
|
||||||
|
return await this.featureflagService.setFeatureFlag(params.ffname, ffState.state );
|
||||||
|
}
|
||||||
|
}
|
||||||
51
src/featureflag/featureflag.service.spec.ts
Normal file
51
src/featureflag/featureflag.service.spec.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { FeatureflagService } from './featureflag.service';
|
||||||
|
import {SharedService} from "../shared/shared.service";
|
||||||
|
import {SharedServiceMock} from "../mocks/shared-service.mock";
|
||||||
|
|
||||||
|
|
||||||
|
describe('FeatureflagService', () => {
|
||||||
|
let service: FeatureflagService;
|
||||||
|
let sharedService: SharedService;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [
|
||||||
|
FeatureflagService,
|
||||||
|
{ provide: SharedService,useValue: SharedServiceMock },
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
service = module.get<FeatureflagService>(FeatureflagService);
|
||||||
|
sharedService = module.get<SharedService>(SharedService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(service).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set feature flag state', async () => {
|
||||||
|
const testFeatureName = 'TestFeatureFlag';
|
||||||
|
const testFeatureState = true;
|
||||||
|
const setConfigMock = jest
|
||||||
|
.spyOn(sharedService,'setConfig')
|
||||||
|
.mockImplementation((name: string, value: string) => Promise.resolve({ key: name, value: value}));
|
||||||
|
await service.setFeatureFlag(testFeatureName, testFeatureState);
|
||||||
|
expect(setConfigMock).toHaveBeenCalledWith(`featureflag/${testFeatureName}`, testFeatureState.toString());
|
||||||
|
expect(setConfigMock).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return state of the feature flag', async () => {
|
||||||
|
const testFeatureName = 'TestFeatureFlag';
|
||||||
|
const testFeatureState = true;
|
||||||
|
const getConfigMock = jest
|
||||||
|
.spyOn(sharedService, 'getConfig')
|
||||||
|
.mockImplementation((key: string) => Promise.resolve({ key:key, value: testFeatureState.toString() }));
|
||||||
|
await service.getFeatureFlag(testFeatureName);
|
||||||
|
|
||||||
|
expect(getConfigMock).toHaveBeenCalledTimes(1);
|
||||||
|
expect(getConfigMock).toHaveBeenCalledWith(`featureflag/${testFeatureName}`);
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
35
src/featureflag/featureflag.service.ts
Normal file
35
src/featureflag/featureflag.service.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import {Injectable, Logger} from '@nestjs/common';
|
||||||
|
import {SharedService} from "../shared/shared.service";
|
||||||
|
|
||||||
|
export interface IFeatureFlagStatus {
|
||||||
|
name: string;
|
||||||
|
state: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FeatureflagService {
|
||||||
|
private logger = new Logger(FeatureflagService.name);
|
||||||
|
constructor(private sharedService: SharedService ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
async getFeatureFlag(id: string): Promise<IFeatureFlagStatus> {
|
||||||
|
this.logger.verbose(`Getting feature flag status for ${id}`);
|
||||||
|
const state = await this.sharedService.getConfig(`featureflag/${id}`);
|
||||||
|
return {
|
||||||
|
name: id,
|
||||||
|
state: state.value !== 'false',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async setFeatureFlag(id: string, status: boolean) : Promise<IFeatureFlagStatus> {
|
||||||
|
this.logger.verbose(`Setting feature flag status for ${id} to ${status} `);
|
||||||
|
const result = await this.sharedService.setConfig(`featureflag/${id}`, status.toString());
|
||||||
|
console.log(result.value);
|
||||||
|
console.log(!!result.value);
|
||||||
|
return {
|
||||||
|
name: id,
|
||||||
|
state: result.value !== 'false',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue