1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-10 17:53:36 +02:00

fix: upgrade unleash-client to v5.3.0 (#5800)

This commit is contained in:
Tymoteusz Czech 2024-01-24 09:12:07 +01:00 committed by GitHub
parent 3957abf0f6
commit 68eb3dec07
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 230 additions and 81 deletions

View File

@ -23,6 +23,7 @@ test('should render environment table', async () => {
type: 'string', type: 'string',
value: 'variantValue', value: 'variantValue',
}, },
feature_enabled: true,
}, },
environment: 'dev', environment: 'dev',
context: { context: {

View File

@ -14,6 +14,8 @@ import type { AdvancedPlaygroundEnvironmentFeatureSchemaVariantPayload } from '.
export type AdvancedPlaygroundEnvironmentFeatureSchemaVariant = { export type AdvancedPlaygroundEnvironmentFeatureSchemaVariant = {
/** Whether the variant is enabled or not. If the feature is disabled or if it doesn't have variants, this property will be `false` */ /** Whether the variant is enabled or not. If the feature is disabled or if it doesn't have variants, this property will be `false` */
enabled: boolean; enabled: boolean;
/** Whether the feature is enabled or not. If the feature is disabled, this property will be `false` */
feature_enabled?: boolean;
/** The variant's name. If there is no variant or if the toggle is disabled, this will be `disabled` */ /** The variant's name. If there is no variant or if the toggle is disabled, this will be `disabled` */
name: string; name: string;
/** An optional payload attached to the variant. */ /** An optional payload attached to the variant. */

View File

@ -11,6 +11,8 @@ import type { ProxyFeatureSchemaVariantPayload } from './proxyFeatureSchemaVaria
export type ProxyFeatureSchemaVariant = { export type ProxyFeatureSchemaVariant = {
/** Whether the variant is enabled or not. */ /** Whether the variant is enabled or not. */
enabled: boolean; enabled: boolean;
/** Whether the feature is enabled or not. */
feature_enabled?: boolean;
/** The variants name. Is unique for this feature toggle */ /** The variants name. Is unique for this feature toggle */
name: string; name: string;
/** Extra data configured for this variant */ /** Extra data configured for this variant */

View File

@ -15,4 +15,5 @@ export const ProxyFeatureSchemaVariantPayloadType = {
json: 'json', json: 'json',
csv: 'csv', csv: 'csv',
string: 'string', string: 'string',
number: 'number',
} as const; } as const;

View File

@ -11,6 +11,8 @@ import type { VariantFlagSchemaPayload } from './variantFlagSchemaPayload';
export interface VariantFlagSchema { export interface VariantFlagSchema {
/** Whether the variant is enabled or not. */ /** Whether the variant is enabled or not. */
enabled?: boolean; enabled?: boolean;
/** Whether the feature is enabled or not. */
feature_enabled?: boolean;
/** The name of the variant. Will always be disabled if `enabled` is false. */ /** The name of the variant. Will always be disabled if `enabled` is false. */
name?: string; name?: string;
/** Additional data associated with this variant. */ /** Additional data associated with this variant. */

View File

@ -15,4 +15,5 @@ export const VariantFlagSchemaPayloadType = {
string: 'string', string: 'string',
json: 'json', json: 'json',
csv: 'csv', csv: 'csv',
number: 'number',
} as const; } as const;

View File

@ -145,7 +145,7 @@
"stoppable": "^1.1.0", "stoppable": "^1.1.0",
"ts-toolbelt": "^9.6.0", "ts-toolbelt": "^9.6.0",
"type-is": "^1.6.18", "type-is": "^1.6.18",
"unleash-client": "5.0.0", "unleash-client": "5.3.1",
"uuid": "^9.0.0" "uuid": "^9.0.0"
}, },
"devDependencies": { "devDependencies": {

View File

@ -120,6 +120,7 @@ test('advanced playground evaluation with parent dependency', async () => {
expect(child.variant).toEqual({ expect(child.variant).toEqual({
name: 'disabled', name: 'disabled',
enabled: false, enabled: false,
feature_enabled: false,
}); });
expect(parent.hasUnsatisfiedDependency).toBe(false); expect(parent.hasUnsatisfiedDependency).toBe(false);
expect(parent.isEnabled).toBe(false); expect(parent.isEnabled).toBe(false);
@ -298,8 +299,7 @@ test('advanced playground evaluation happy path', async () => {
}); });
}); });
test('show matching variant from variants selection only for enabled toggles', async () => { test('show matching variant from variants selection only for enabled toggles', async () => {
const variants = [ const variant = {
{
stickiness: 'random', stickiness: 'random',
name: 'a', name: 'a',
weight: 1000, weight: 1000,
@ -308,8 +308,8 @@ test('show matching variant from variants selection only for enabled toggles', a
value: 'aval', value: 'aval',
}, },
weightType: 'variable', weightType: 'variable',
}, };
];
await createFeatureToggleWithStrategy( await createFeatureToggleWithStrategy(
'test-playground-feature-with-variants', 'test-playground-feature-with-variants',
{ {
@ -320,7 +320,7 @@ test('show matching variant from variants selection only for enabled toggles', a
stickiness: 'random', stickiness: 'random',
groupId: 'test-playground-feature-with-variants', groupId: 'test-playground-feature-with-variants',
}, },
variants, variants: [variant],
}, },
); );
@ -347,7 +347,7 @@ test('show matching variant from variants selection only for enabled toggles', a
enabledFeatures.forEach((feature) => { enabledFeatures.forEach((feature) => {
expect(feature.variant?.name).toBe('a'); expect(feature.variant?.name).toBe('a');
expect(feature.variants).toMatchObject(variants); expect(feature.variants).toMatchObject([variant]);
}); });
disabledFeatures.forEach((feature) => { disabledFeatures.forEach((feature) => {
expect(feature.variant?.name).toBe('disabled'); expect(feature.variant?.name).toBe('disabled');

View File

@ -11,17 +11,18 @@ import { Context } from './context';
import { SegmentForEvaluation } from './strategy/strategy'; import { SegmentForEvaluation } from './strategy/strategy';
import { PlaygroundStrategySchema } from '../../../openapi/spec/playground-strategy-schema'; import { PlaygroundStrategySchema } from '../../../openapi/spec/playground-strategy-schema';
import { playgroundStrategyEvaluation } from '../../../openapi/spec/playground-strategy-schema'; import { playgroundStrategyEvaluation } from '../../../openapi/spec/playground-strategy-schema';
import { randomId } from '../../../util';
export type StrategyEvaluationResult = Pick<
PlaygroundStrategySchema,
'result' | 'segments' | 'constraints'
>;
export type EvaluatedPlaygroundStrategy = Omit< export type EvaluatedPlaygroundStrategy = Omit<
PlaygroundStrategySchema, PlaygroundStrategySchema,
'links' 'links'
>; >;
export type StrategyEvaluationResult = Pick<
EvaluatedPlaygroundStrategy,
'result' | 'segments' | 'constraints'
>;
export type FeatureStrategiesEvaluationResult = { export type FeatureStrategiesEvaluationResult = {
result: boolean | typeof playgroundStrategyEvaluation.unknownResult; result: boolean | typeof playgroundStrategyEvaluation.unknownResult;
variant?: Variant; variant?: Variant;
@ -144,26 +145,32 @@ export default class UnleashClient {
const strategies = feature.strategies.map( const strategies = feature.strategies.map(
(strategySelector): EvaluatedPlaygroundStrategy => { (strategySelector): EvaluatedPlaygroundStrategy => {
const getStrategy = () => { const getStrategy = (): Strategy => {
// assume that 'unknown' strategy is always present
const unknownStrategy = this.getStrategy(
'unknown',
) as Strategy;
// the application hostname strategy relies on external // the application hostname strategy relies on external
// variables to calculate its result. As such, we can't // variables to calculate its result. As such, we can't
// evaluate it in a way that makes sense. So we'll // evaluate it in a way that makes sense. So we'll
// use the 'unknown' strategy instead. // use the 'unknown' strategy instead.
if (strategySelector.name === 'applicationHostname') { if (strategySelector.name === 'applicationHostname') {
return this.getStrategy('unknown'); return unknownStrategy;
} }
return ( return (
this.getStrategy(strategySelector.name) ?? this.getStrategy(strategySelector.name) ??
this.getStrategy('unknown') unknownStrategy
); );
}; };
const strategy = getStrategy(); const strategy = getStrategy();
const segments = const segments =
strategySelector.segments (strategySelector.segments
?.map(this.getSegment(this.repository)) ?.map(this.getSegment(this.repository))
.filter(Boolean) ?? []; .filter(Boolean) as SegmentForEvaluation[]) ?? [];
const evaluationResult = strategy.isEnabledWithConstraints( const evaluationResult = strategy.isEnabledWithConstraints(
strategySelector.parameters, strategySelector.parameters,
@ -176,7 +183,7 @@ export default class UnleashClient {
return { return {
name: strategySelector.name, name: strategySelector.name,
id: strategySelector.id, id: strategySelector.id || randomId(),
title: strategySelector.title, title: strategySelector.title,
disabled: strategySelector.disabled || false, disabled: strategySelector.disabled || false,
parameters: strategySelector.parameters, parameters: strategySelector.parameters,
@ -189,7 +196,7 @@ export default class UnleashClient {
const overallStrategyResult = (): [ const overallStrategyResult = (): [
boolean | typeof playgroundStrategyEvaluation.unknownResult, boolean | typeof playgroundStrategyEvaluation.unknownResult,
VariantDefinition[] | undefined, VariantDefinition[] | undefined,
Variant | undefined | null, Variant | undefined,
] => { ] => {
// if at least one strategy is enabled, then the feature is enabled // if at least one strategy is enabled, then the feature is enabled
const enabledStrategy = strategies.find( const enabledStrategy = strategies.find(
@ -202,7 +209,7 @@ export default class UnleashClient {
return [ return [
true, true,
enabledStrategy.result.variants, enabledStrategy.result.variants,
enabledStrategy.result.variant, enabledStrategy.result.variant || undefined,
]; ];
} }
@ -284,7 +291,11 @@ export default class UnleashClient {
'result' | 'variant' 'result' | 'variant'
>, >,
): Variant { ): Variant {
const fallback = fallbackVariant || getDefaultVariant(); const fallback = {
feature_enabled: false,
featureEnabled: false,
...(fallbackVariant || getDefaultVariant()),
};
const feature = this.repository.getToggle(name); const feature = this.repository.getToggle(name);
if ( if (
@ -294,13 +305,14 @@ export default class UnleashClient {
return fallback; return fallback;
} }
let enabled = true;
const result = const result =
forcedResult ?? forcedResult ??
this.isFeatureEnabled(feature, context, () => this.isFeatureEnabled(feature, context, () =>
fallbackVariant ? fallbackVariant.enabled : false, fallbackVariant ? fallbackVariant.enabled : false,
); );
enabled = result.result === true; const enabled = result.result === true;
fallback.feature_enabled = fallbackVariant?.feature_enabled ?? enabled;
fallback.featureEnabled = fallback.feature_enabled;
const strategyVariant = result.variant; const strategyVariant = result.variant;
if (enabled && strategyVariant) { if (enabled && strategyVariant) {
return strategyVariant; return strategyVariant;
@ -330,6 +342,8 @@ export default class UnleashClient {
name: variant.name, name: variant.name,
payload: variant.payload, payload: variant.payload,
enabled, enabled,
feature_enabled: true,
featureEnabled: true,
}; };
} }
} }

View File

@ -11,6 +11,7 @@ import {
resolveBootstrapProvider, resolveBootstrapProvider,
} from './repository/bootstrap-provider'; } from './repository/bootstrap-provider';
import { StorageProvider } from './repository/storage-provider'; import { StorageProvider } from './repository/storage-provider';
import InMemStorageProvider from './repository/storage-provider-in-mem';
export { Strategy }; export { Strategy };
@ -41,7 +42,7 @@ export class FeatureEvaluator {
strategies = [], strategies = [],
repository, repository,
bootstrap = { data: [] }, bootstrap = { data: [] },
storageProvider, storageProvider = new InMemStorageProvider(),
}: FeatureEvaluatorConfig) { }: FeatureEvaluatorConfig) {
this.staticContext = { appName, environment }; this.staticContext = { appName, environment };
@ -52,7 +53,7 @@ export class FeatureEvaluator {
new Repository({ new Repository({
appName, appName,
bootstrapProvider, bootstrapProvider,
storageProvider: storageProvider, storageProvider,
}); });
// setup client // setup client

View File

@ -26,6 +26,11 @@ export interface Variant {
name: string; name: string;
enabled: boolean; enabled: boolean;
payload?: Payload; payload?: Payload;
featureEnabled?: boolean;
/**
* @deprecated use featureEnabled
*/
feature_enabled?: boolean;
} }
export function getDefaultVariant(): Variant { export function getDefaultVariant(): Variant {

View File

@ -27,7 +27,7 @@ export const offlineUnleashClientNode = async ({
storageProvider: new InMemStorageProviderNode(), storageProvider: new InMemStorageProviderNode(),
bootstrap: { bootstrap: {
data: mapFeaturesForClient(features), data: mapFeaturesForClient(features),
segments: mapSegmentsForClient(segments), segments: mapSegmentsForClient(segments || []),
}, },
}); });

View File

@ -5,8 +5,9 @@ import { Segment } from './feature-evaluator/strategy/strategy';
import { ISegment } from '../../types/model'; import { ISegment } from '../../types/model';
import { serializeDates } from '../../types/serialize-dates'; import { serializeDates } from '../../types/serialize-dates';
import { Operator } from './feature-evaluator/constraint'; import { Operator } from './feature-evaluator/constraint';
import { FeatureInterface } from 'unleash-client/lib/feature';
import { PayloadType } from 'unleash-client'; import { PayloadType } from 'unleash-client';
import { FeatureInterface } from 'unleash-client/lib/feature';
import { FeatureInterface as PlaygroundFeatureInterface } from './feature-evaluator/feature';
type NonEmptyList<T> = [T, ...T[]]; type NonEmptyList<T> = [T, ...T[]];
@ -28,6 +29,8 @@ export const mapFeaturesForClient = (
strategies: feature.strategies.map((strategy) => ({ strategies: feature.strategies.map((strategy) => ({
parameters: {}, parameters: {},
...strategy, ...strategy,
title: strategy.title ?? undefined,
disabled: strategy.disabled ?? false,
variants: (strategy.variants || []).map((variant) => ({ variants: (strategy.variants || []).map((variant) => ({
...variant, ...variant,
payload: variant.payload && { payload: variant.payload && {
@ -35,12 +38,13 @@ export const mapFeaturesForClient = (
type: variant.payload.type as PayloadType, type: variant.payload.type as PayloadType,
}, },
})), })),
constraints: strategy.constraints?.map((constraint) => ({ constraints:
strategy.constraints?.map((constraint) => ({
inverted: false, inverted: false,
values: [], values: [],
...constraint, ...constraint,
operator: constraint.operator as unknown as Operator, operator: constraint.operator as unknown as Operator,
})), })) || [],
})), })),
dependencies: feature.dependencies, dependencies: feature.dependencies,
})); }));
@ -65,8 +69,11 @@ export const offlineUnleashClient = async ({
appName: context.appName, appName: context.appName,
storageProvider: new InMemStorageProvider(), storageProvider: new InMemStorageProvider(),
bootstrap: { bootstrap: {
data: mapFeaturesForClient(features), // FIXME: mismatch between playground and proxy types
segments: mapSegmentsForClient(segments), data: mapFeaturesForClient(
features,
) as PlaygroundFeatureInterface[],
segments: mapSegmentsForClient(segments || []),
}, },
}); });

View File

@ -203,6 +203,17 @@ export class PlaygroundService {
feature.enabled && feature.enabled &&
!hasUnsatisfiedDependency; !hasUnsatisfiedDependency;
const variant = {
...(isEnabled
? client.forceGetVariant(
feature.name,
strategyEvaluationResult,
clientContext,
)
: getDefaultVariant()),
feature_enabled: isEnabled,
};
return { return {
isEnabled, isEnabled,
isEnabledInCurrentEnvironment: feature.enabled, isEnabledInCurrentEnvironment: feature.enabled,
@ -212,13 +223,7 @@ export class PlaygroundService {
data: strategyEvaluationResult.strategies, data: strategyEvaluationResult.strategies,
}, },
projectId: featureProject[feature.name], projectId: featureProject[feature.name],
variant: isEnabled variant,
? client.forceGetVariant(
feature.name,
strategyEvaluationResult,
clientContext,
)
: getDefaultVariant(),
name: feature.name, name: feature.name,
environment, environment,
context, context,

View File

@ -127,6 +127,11 @@ export const advancedPlaygroundEnvironmentFeatureSchema = {
}, },
}, },
}, },
feature_enabled: {
type: 'boolean',
description:
'Whether the feature is enabled or not. If the feature is disabled, this property will be `false`',
},
}, },
nullable: true, nullable: true,
example: { name: 'green', enabled: true }, example: { name: 'green', enabled: true },

View File

@ -121,6 +121,17 @@ export const playgroundFeatureSchema = {
}, },
}, },
}, },
feature_enabled: {
type: 'boolean',
description: 'Use `featureEnabled` instead.',
example: true,
},
featureEnabled: {
deprecated: true,
type: 'boolean',
description: 'Whether the feature is enabled or not.',
example: true,
},
}, },
nullable: true, nullable: true,
example: { name: 'green', enabled: true }, example: { name: 'green', enabled: true },

View File

@ -50,7 +50,7 @@ export const proxyFeatureSchema = {
type: { type: {
type: 'string', type: 'string',
description: 'The format of the payload.', description: 'The format of the payload.',
enum: ['json', 'csv', 'string'], enum: ['json', 'csv', 'string', 'number'],
}, },
value: { value: {
type: 'string', type: 'string',
@ -58,6 +58,17 @@ export const proxyFeatureSchema = {
}, },
}, },
}, },
feature_enabled: {
type: 'boolean',
description: 'Whether the feature is enabled or not.',
example: true,
},
featureEnabled: {
deprecated: true,
type: 'boolean',
description: 'Use `feature_enabled` instead.',
example: true,
},
}, },
}, },
}, },

View File

@ -25,7 +25,7 @@ export const variantFlagSchema = {
type: { type: {
description: 'The type of data contained.', description: 'The type of data contained.',
type: 'string', type: 'string',
enum: ['string', 'json', 'csv'], enum: ['string', 'json', 'csv', 'number'],
example: 'json', example: 'json',
}, },
value: { value: {
@ -35,6 +35,17 @@ export const variantFlagSchema = {
}, },
}, },
}, },
feature_enabled: {
type: 'boolean',
description: 'Whether the feature is enabled or not.',
example: true,
},
featureEnabled: {
deprecated: true,
type: 'boolean',
description: 'Use `feature_enabled` instead.',
example: true,
},
}, },
components: {}, components: {},
} as const; } as const;

View File

@ -449,13 +449,23 @@ test('should filter features by enabled/disabled', async () => {
name: 'enabledFeature1', name: 'enabledFeature1',
enabled: true, enabled: true,
impressionData: false, impressionData: false,
variant: { enabled: false, name: 'disabled' }, variant: {
enabled: false,
name: 'disabled',
feature_enabled: true,
featureEnabled: true,
},
}, },
{ {
name: 'enabledFeature2', name: 'enabledFeature2',
enabled: true, enabled: true,
impressionData: false, impressionData: false,
variant: { enabled: false, name: 'disabled' }, variant: {
enabled: false,
name: 'disabled',
feature_enabled: true,
featureEnabled: true,
},
}, },
], ],
}); });
@ -486,7 +496,12 @@ test('should filter features by strategies', async () => {
name: 'featureWithMultipleStrategies', name: 'featureWithMultipleStrategies',
enabled: true, enabled: true,
impressionData: false, impressionData: false,
variant: { enabled: false, name: 'disabled' }, variant: {
enabled: false,
name: 'disabled',
feature_enabled: true,
featureEnabled: true,
},
}, },
], ],
}); });
@ -629,7 +644,12 @@ test('should filter features by project', async () => {
name: 'featureInProjectDefault', name: 'featureInProjectDefault',
enabled: true, enabled: true,
impressionData: false, impressionData: false,
variant: { enabled: false, name: 'disabled' }, variant: {
enabled: false,
name: 'disabled',
feature_enabled: true,
featureEnabled: true,
},
}, },
], ],
}); });
@ -646,7 +666,12 @@ test('should filter features by project', async () => {
name: 'featureInProjectA', name: 'featureInProjectA',
enabled: true, enabled: true,
impressionData: false, impressionData: false,
variant: { enabled: false, name: 'disabled' }, variant: {
enabled: false,
name: 'disabled',
feature_enabled: true,
featureEnabled: true,
},
}, },
], ],
}); });
@ -663,13 +688,23 @@ test('should filter features by project', async () => {
name: 'featureInProjectA', name: 'featureInProjectA',
enabled: true, enabled: true,
impressionData: false, impressionData: false,
variant: { enabled: false, name: 'disabled' }, variant: {
enabled: false,
name: 'disabled',
feature_enabled: true,
featureEnabled: true,
},
}, },
{ {
name: 'featureInProjectB', name: 'featureInProjectB',
enabled: true, enabled: true,
impressionData: false, impressionData: false,
variant: { enabled: false, name: 'disabled' }, variant: {
enabled: false,
name: 'disabled',
feature_enabled: true,
featureEnabled: true,
},
}, },
], ],
}); });
@ -743,7 +778,12 @@ test('should filter features by environment', async () => {
name: 'featureInEnvironmentDefault', name: 'featureInEnvironmentDefault',
enabled: true, enabled: true,
impressionData: false, impressionData: false,
variant: { enabled: false, name: 'disabled' }, variant: {
enabled: false,
name: 'disabled',
feature_enabled: true,
featureEnabled: true,
},
}, },
], ],
}); });
@ -760,7 +800,12 @@ test('should filter features by environment', async () => {
name: 'featureInEnvironmentA', name: 'featureInEnvironmentA',
enabled: true, enabled: true,
impressionData: false, impressionData: false,
variant: { enabled: false, name: 'disabled' }, variant: {
enabled: false,
name: 'disabled',
feature_enabled: true,
featureEnabled: true,
},
}, },
], ],
}); });
@ -777,7 +822,12 @@ test('should filter features by environment', async () => {
name: 'featureInEnvironmentB', name: 'featureInEnvironmentB',
enabled: true, enabled: true,
impressionData: false, impressionData: false,
variant: { enabled: false, name: 'disabled' }, variant: {
enabled: false,
name: 'disabled',
feature_enabled: true,
featureEnabled: true,
},
}, },
], ],
}); });
@ -1040,7 +1090,12 @@ test('should evaluate strategies when returning toggles', async () => {
name: 'enabledFeature', name: 'enabledFeature',
enabled: true, enabled: true,
impressionData: false, impressionData: false,
variant: { enabled: false, name: 'disabled' }, variant: {
enabled: false,
name: 'disabled',
feature_enabled: true,
featureEnabled: true,
},
}, },
], ],
}); });
@ -1095,13 +1150,23 @@ test('should not return all features', async () => {
name: 'enabledFeature1', name: 'enabledFeature1',
enabled: true, enabled: true,
impressionData: false, impressionData: false,
variant: { enabled: false, name: 'disabled' }, variant: {
enabled: false,
name: 'disabled',
feature_enabled: true,
featureEnabled: true,
},
}, },
{ {
name: 'enabledFeature2', name: 'enabledFeature2',
enabled: true, enabled: true,
impressionData: false, impressionData: false,
variant: { enabled: false, name: 'disabled' }, variant: {
enabled: false,
name: 'disabled',
feature_enabled: true,
featureEnabled: true,
},
}, },
], ],
}); });
@ -1197,7 +1262,12 @@ test('should NOT evaluate disabled strategies when returning toggles', async ()
name: 'enabledFeature', name: 'enabledFeature',
enabled: true, enabled: true,
impressionData: false, impressionData: false,
variant: { enabled: false, name: 'disabled' }, variant: {
enabled: false,
name: 'disabled',
feature_enabled: true,
featureEnabled: true,
},
}, },
], ],
}); });

View File

@ -177,13 +177,12 @@ export const seedDatabaseForPlaygroundTest = async (
}; };
describe('the playground service (e2e)', () => { describe('the playground service (e2e)', () => {
const isDisabledVariant = ({ const isDisabledVariant = (
name, variant?: {
enabled,
}: {
name: string; name: string;
enabled: boolean; enabled: boolean;
}) => name === 'disabled' && !enabled; } | null,
) => variant?.name === 'disabled' && !variant?.enabled;
const insertAndEvaluateFeatures = async ({ const insertAndEvaluateFeatures = async ({
features, features,
@ -290,12 +289,12 @@ describe('the playground service (e2e)', () => {
ctx.log(JSON.stringify(enabledStateMatches)); ctx.log(JSON.stringify(enabledStateMatches));
ctx.log( ctx.log(
JSON.stringify( JSON.stringify(
feature.variant.name === 'disabled', feature.variant?.name === 'disabled',
), ),
); );
ctx.log( ctx.log(
JSON.stringify( JSON.stringify(
feature.variant.enabled === false, feature.variant?.enabled === false,
), ),
); );
return ( return (
@ -704,7 +703,7 @@ describe('the playground service (e2e)', () => {
}, },
); );
feature.strategies.forEach( feature.strategies?.forEach(
({ segments, ...strategy }) => { ({ segments, ...strategy }) => {
expect(cleanedReceivedStrategies).toEqual( expect(cleanedReceivedStrategies).toEqual(
expect.arrayContaining([ expect.arrayContaining([
@ -845,7 +844,7 @@ describe('the playground service (e2e)', () => {
features: features.map((feature) => ({ features: features.map((feature) => ({
...feature, ...feature,
// remove any constraints and use a name that doesn't exist // remove any constraints and use a name that doesn't exist
strategies: feature.strategies.map( strategies: feature.strategies?.map(
(strategy) => ({ (strategy) => ({
...strategy, ...strategy,
name: 'bogus-strategy', name: 'bogus-strategy',
@ -907,7 +906,7 @@ describe('the playground service (e2e)', () => {
features: features.map((feature) => ({ features: features.map((feature) => ({
...feature, ...feature,
// use a constraint that will never be true // use a constraint that will never be true
strategies: feature.strategies.map( strategies: feature.strategies?.map(
(strategy) => ({ (strategy) => ({
...strategy, ...strategy,
name: 'bogusStrategy', name: 'bogusStrategy',
@ -1223,6 +1222,7 @@ describe('the playground service (e2e)', () => {
expect(feature.variant).toEqual({ expect(feature.variant).toEqual({
name: 'disabled', name: 'disabled',
enabled: false, enabled: false,
feature_enabled: false,
}); });
} }
}); });

View File

@ -7134,10 +7134,10 @@ universalify@^0.2.0:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==
unleash-client@5.0.0: unleash-client@5.3.1:
version "5.0.0" version "5.3.1"
resolved "https://registry.yarnpkg.com/unleash-client/-/unleash-client-5.0.0.tgz#b6725723b38f5572b4b1c5261c1bb2254148ec58" resolved "https://registry.yarnpkg.com/unleash-client/-/unleash-client-5.3.1.tgz#8647ea5f8905f21e5fdcb87a79ce91c27a92b605"
integrity sha512-9x3SOpHTnMDY0CosKwy/0Hi9gIjw65+i2fsC76bvYaUIVTlqDoPdCfosBokNIZ/IjCF0TjEgSZefSWNGY5SC9A== integrity sha512-S5WtDNJa9j/JC+tXB/LoBNDMwhtuQ5CxFWge8igoVSspyyypcrKtyd98TSODBeyfzKW0daCyLmE7Pr+jDfROLQ==
dependencies: dependencies:
ip "^1.1.8" ip "^1.1.8"
make-fetch-happen "^10.2.1" make-fetch-happen "^10.2.1"