TGD-30: FeatureFlags

This commit is contained in:
Kirill Ivlev 2024-11-11 13:56:04 +04:00
parent dfd149103e
commit 0d26101948
4 changed files with 122 additions and 0 deletions

View 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();
});
});

View 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 );
}
}

View 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}`);
});
});

View 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',
}
}
}