diff --git a/src/lib/features/client-feature-toggles/tests/client-feature-toggles.e2e.test.ts b/src/lib/features/client-feature-toggles/tests/client-feature-toggles.e2e.test.ts index b88640e35cfa..18f6767935c8 100644 --- a/src/lib/features/client-feature-toggles/tests/client-feature-toggles.e2e.test.ts +++ b/src/lib/features/client-feature-toggles/tests/client-feature-toggles.e2e.test.ts @@ -11,6 +11,51 @@ let app: IUnleashTest; let db: ITestDb; let dummyAdmin; +const apiClientResponse = [ + { + name: 'test1', + type: 'release', + enabled: false, + project: 'default', + stale: false, + strategies: [ + { + name: 'flexibleRollout', + constraints: [], + parameters: { rollout: '100' }, + variants: [], + }, + ], + variants: [], + description: null, + impressionData: false, + }, + { + name: 'test2', + type: 'release', + enabled: false, + project: 'default', + stale: false, + strategies: [ + { + name: 'default', + constraints: [ + { + contextName: 'userId', + operator: 'IN', + values: ['123'], + }, + ], + parameters: {}, + variants: [], + }, + ], + variants: [], + description: null, + impressionData: false, + }, +]; + beforeAll(async () => { db = await dbInit('client_feature_toggles', getLogger); app = await setupAppWithCustomConfig( @@ -107,3 +152,88 @@ test('should support filtering on project', async () => { expect(res.body.features[0].name).toBe('ab_test1'); }); }); + +test('should return correct data structure from /api/client/features', async () => { + await db.rawDatabase.raw('DELETE FROM features'); + + await app.createFeature('test1', 'default'); + await app.createFeature('test2', 'default'); + + await app.addStrategyToFeatureEnv( + { + name: 'flexibleRollout', + constraints: [], + parameters: { rollout: '100' }, + }, + DEFAULT_ENV, + 'test1', + ); + await app.addStrategyToFeatureEnv( + { + name: 'default', + constraints: [ + { contextName: 'userId', operator: 'IN', values: ['123'] }, + ], + parameters: {}, + }, + DEFAULT_ENV, + 'test2', + ); + + const result = await app.request + .get('/api/client/features') + .expect('Content-Type', /json/) + .expect(200); + + expect(result.body.features).toEqual(apiClientResponse); +}); + +test('should return correct data structure from /api/client/features | separateAdminClientApi', async () => { + const appWithFeatureFlag = await setupAppWithCustomConfig( + db.stores, + { + experimental: { + flags: { + strictSchemaValidation: true, + dependentFeatures: true, + separateAdminClientApi: true, + }, + }, + }, + db.rawDatabase, + ); + + await db.rawDatabase.raw('DELETE FROM features'); + + await appWithFeatureFlag.createFeature('test1', 'default'); + await appWithFeatureFlag.createFeature('test2', 'default'); + + await appWithFeatureFlag.addStrategyToFeatureEnv( + { + name: 'flexibleRollout', + constraints: [], + parameters: { rollout: '100' }, + }, + DEFAULT_ENV, + 'test1', + ); + + await appWithFeatureFlag.addStrategyToFeatureEnv( + { + name: 'default', + constraints: [ + { contextName: 'userId', operator: 'IN', values: ['123'] }, + ], + parameters: {}, + }, + DEFAULT_ENV, + 'test2', + ); + + const result = await appWithFeatureFlag.request + .get('/api/client/features') + .expect('Content-Type', /json/) + .expect(200); + + expect(result.body.features).toEqual(apiClientResponse); +}); diff --git a/src/test/e2e/helpers/test-helper.ts b/src/test/e2e/helpers/test-helper.ts index a9a559c75f2b..038ab0ff230e 100644 --- a/src/test/e2e/helpers/test-helper.ts +++ b/src/test/e2e/helpers/test-helper.ts @@ -11,7 +11,11 @@ import { IUnleashServices } from '../../../lib/types/services'; import { Db } from '../../../lib/db/db'; import { IContextFieldDto } from 'lib/types/stores/context-field-store'; import { DEFAULT_ENV } from '../../../lib/util'; -import { CreateFeatureSchema, ImportTogglesSchema } from '../../../lib/openapi'; +import { + CreateFeatureSchema, + CreateFeatureStrategySchema, + ImportTogglesSchema, +} from '../../../lib/openapi'; process.env.NODE_ENV = 'test'; @@ -28,6 +32,14 @@ export interface IUnleashTest extends IUnleashHttpAPI { * All functions return a supertest.Test object, which can be used to compose more assertions on the response. */ export interface IUnleashHttpAPI { + addStrategyToFeatureEnv( + postData: CreateFeatureStrategySchema, + envName: string, + featureName: string, + project?: string, + expectStatusCode?: number, + ): supertest.Test; + createFeature( feature: string | CreateFeatureSchema, project?: string, @@ -74,6 +86,16 @@ function httpApis( const base = config.server.baseUriPath || ''; return { + addStrategyToFeatureEnv: ( + postData: CreateFeatureStrategySchema, + envName: string, + featureName: string, + project: string = DEFAULT_PROJECT, + expectStatusCode: number = 200, + ) => { + const url = `${base}/api/admin/projects/${project}/features/${featureName}/environments/${envName}/strategies`; + return request.post(url).send(postData).expect(expectStatusCode); + }, createFeature: ( feature: string | CreateFeatureSchema, project: string = DEFAULT_PROJECT,