From 7b8b6bceafdd294adedb451266b525e441c0c802 Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Mon, 12 Jun 2023 11:01:52 +0200 Subject: [PATCH] feat: walking skeleton of the advanced playground (#3949) --- frontend/src/interfaces/uiConfig.ts | 1 + .../__snapshots__/create-config.test.ts.snap | 2 + .../features/playground/hardcodedReponse.ts | 142 ++++++++++++++++++ src/lib/features/playground/playground.ts | 26 +++- src/lib/types/experimental.ts | 7 +- src/server-dev.ts | 1 + 6 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 src/lib/features/playground/hardcodedReponse.ts diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts index b84e0d447c..f86e804b5b 100644 --- a/frontend/src/interfaces/uiConfig.ts +++ b/frontend/src/interfaces/uiConfig.ts @@ -53,6 +53,7 @@ export interface IFlags { disableBulkToggle?: boolean; segmentContextFieldUsage?: boolean; disableNotifications?: boolean; + advancedPlayground?: boolean; } export interface IVersionInfo { diff --git a/src/lib/__snapshots__/create-config.test.ts.snap b/src/lib/__snapshots__/create-config.test.ts.snap index aa00871ae9..2ea4fb73e6 100644 --- a/src/lib/__snapshots__/create-config.test.ts.snap +++ b/src/lib/__snapshots__/create-config.test.ts.snap @@ -67,6 +67,7 @@ exports[`should create default config 1`] = ` "isEnabled": [Function], }, "flags": { + "advancedPlayground": false, "anonymiseEventLog": false, "caseInsensitiveInOperators": false, "cleanClientApi": false, @@ -99,6 +100,7 @@ exports[`should create default config 1`] = ` }, "flagResolver": FlagResolver { "experiments": { + "advancedPlayground": false, "anonymiseEventLog": false, "caseInsensitiveInOperators": false, "cleanClientApi": false, diff --git a/src/lib/features/playground/hardcodedReponse.ts b/src/lib/features/playground/hardcodedReponse.ts new file mode 100644 index 0000000000..d7e6e1b268 --- /dev/null +++ b/src/lib/features/playground/hardcodedReponse.ts @@ -0,0 +1,142 @@ +const sharedDetails = { + isEnabled: true, + isEnabledInCurrentEnvironment: true, + strategies: { + result: true, + data: [ + { + name: 'flexibleRollout', + id: '9422b4bb-5f8a-4df5-863a-c2a4c4d83af7', + disabled: false, + parameters: { + groupId: 'test', + rollout: '100', + stickiness: 'default', + }, + result: { + enabled: true, + evaluationStatus: 'complete', + }, + constraints: [ + { + inverted: false, + values: ['2', '4', '6', '8', '10'], + operator: 'IN', + contextName: 'userId', + caseInsensitive: false, + result: true, + }, + ], + segments: [], + }, + ], + }, + variant: { + name: 'a', + payload: { + type: 'string', + value: 'a', + }, + enabled: true, + }, + variants: [ + { + name: 'a', + weight: 334, + payload: { + type: 'string', + value: 'a', + }, + overrides: [], + stickiness: 'default', + weightType: 'variable', + }, + { + name: 'b', + weight: 333, + payload: { + type: 'string', + value: 'b', + }, + overrides: [], + stickiness: 'default', + weightType: 'variable', + }, + { + name: 'c', + weight: 333, + payload: { + type: 'string', + value: 'c', + }, + overrides: [], + stickiness: 'default', + weightType: 'variable', + }, + ], +}; +const sharedEnv = [ + { + ...sharedDetails, + context: { + appName: 'playground', + userId: '1', + channel: 'web', + }, + }, + { + ...sharedDetails, + context: { + appName: 'playground', + userId: '2', + channel: 'web', + }, + }, + { + ...sharedDetails, + context: { + appName: 'playground', + userId: '1', + channel: 'mobile', + }, + }, + { + ...sharedDetails, + context: { + appName: 'playground', + userId: '2', + channel: 'mobile', + }, + }, +]; +export const fixedAdvancedPlaygroundResponse = { + input: { + environments: ['development', 'production'], + projects: ['default'], + context: { + appName: 'playground', + userId: '1,2', + channel: 'web,mobile', + }, + }, + features: [ + { + environments: { + development: sharedEnv, + production: sharedEnv, + }, + + projectId: 'default', + name: 'featureA', + }, + { + environments: { + development: sharedEnv, + production: sharedEnv, + }, + + projectId: 'default', + name: 'featureB', + }, + ], +}; diff --git a/src/lib/features/playground/playground.ts b/src/lib/features/playground/playground.ts index c0c9e0fc05..f3b387b6f4 100644 --- a/src/lib/features/playground/playground.ts +++ b/src/lib/features/playground/playground.ts @@ -14,12 +14,16 @@ import { } from '../../openapi/spec/playground-response-schema'; import { PlaygroundRequestSchema } from '../../openapi/spec/playground-request-schema'; import { PlaygroundService } from './playground-service'; +import { fixedAdvancedPlaygroundResponse } from './hardcodedReponse'; +import { IFlagResolver } from '../../types'; export default class PlaygroundController extends Controller { private openApiService: OpenApiService; private playgroundService: PlaygroundService; + private flagResolver: IFlagResolver; + constructor( config: IUnleashConfig, { @@ -30,6 +34,7 @@ export default class PlaygroundController extends Controller { super(config); this.openApiService = openApiService; this.playgroundService = playgroundService; + this.flagResolver = config.flagResolver; this.route({ method: 'post', @@ -49,6 +54,14 @@ export default class PlaygroundController extends Controller { }), ], }); + + this.route({ + method: 'post', + path: '/advanced', + handler: this.evaluateAdvancedContext, + permission: NONE, + middleware: [], + }); } async evaluateContext( @@ -58,7 +71,7 @@ export default class PlaygroundController extends Controller { const response = { input: req.body, features: await this.playgroundService.evaluateQuery( - req.body.projects, + req.body.projects || '*', req.body.environment, req.body.context, ), @@ -71,4 +84,15 @@ export default class PlaygroundController extends Controller { response, ); } + + async evaluateAdvancedContext( + req: Request, + res: Response, + ): Promise { + if (this.flagResolver.isEnabled('advancedPlayground')) { + res.json(fixedAdvancedPlaygroundResponse); + } else { + res.status(409).end(); + } + } } diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts index 3eeace5375..bb6950af69 100644 --- a/src/lib/types/experimental.ts +++ b/src/lib/types/experimental.ts @@ -23,7 +23,8 @@ export type IFlagKey = | 'variantMetrics' | 'disableBulkToggle' | 'segmentContextFieldUsage' - | 'disableNotifications'; + | 'disableNotifications' + | 'advancedPlayground'; export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>; @@ -108,6 +109,10 @@ const flags: IFlags = { process.env.DISABLE_NOTIFICATIONS, false, ), + advancedPlayground: parseEnvVarBoolean( + process.env.ADVANCED_PLAYGROUND, + false, + ), }; export const defaultExperimentalOptions: IExperimentalOptions = { diff --git a/src/server-dev.ts b/src/server-dev.ts index 20895a4019..4b0980a467 100644 --- a/src/server-dev.ts +++ b/src/server-dev.ts @@ -41,6 +41,7 @@ process.nextTick(async () => { variantMetrics: true, strategyImprovements: true, segmentContextFieldUsage: true, + advancedPlayground: true, }, }, authentication: {