mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
parent
eb199825e8
commit
29e7c4035d
@ -25,6 +25,6 @@ test('should show the count of projects and features used in', async () => {
|
|||||||
|
|
||||||
render(<ContextList />);
|
render(<ContextList />);
|
||||||
|
|
||||||
await screen.findByText('2 feature toggles');
|
await screen.findByText('2 feature flags');
|
||||||
await screen.findByText('3 projects');
|
await screen.findByText('3 projects');
|
||||||
});
|
});
|
||||||
|
@ -10,7 +10,7 @@ interface IUsedInCellProps {
|
|||||||
|
|
||||||
export const UsedInCell: VFC<IUsedInCellProps> = ({ original }) => {
|
export const UsedInCell: VFC<IUsedInCellProps> = ({ original }) => {
|
||||||
const projectText = original.usedInProjects === 1 ? 'project' : 'projects';
|
const projectText = original.usedInProjects === 1 ? 'project' : 'projects';
|
||||||
const togglesText = original.usedInFeatures === 1 ? 'toggle' : 'toggles';
|
const flagsText = original.usedInFeatures === 1 ? 'flag' : 'flags';
|
||||||
return (
|
return (
|
||||||
<TextCell
|
<TextCell
|
||||||
sx={{
|
sx={{
|
||||||
@ -25,7 +25,7 @@ export const UsedInCell: VFC<IUsedInCellProps> = ({ original }) => {
|
|||||||
{original.usedInProjects} {projectText}
|
{original.usedInProjects} {projectText}
|
||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box>
|
||||||
{original.usedInFeatures} feature {togglesText}
|
{original.usedInFeatures} feature {flagsText}
|
||||||
</Box>
|
</Box>
|
||||||
</TextCell>
|
</TextCell>
|
||||||
);
|
);
|
||||||
|
@ -82,7 +82,7 @@ const CreateEnvironment = () => {
|
|||||||
feature flags are accessible in all your
|
feature flags are accessible in all your
|
||||||
environments, but they can take different
|
environments, but they can take different
|
||||||
configurations per environment. This means
|
configurations per environment. This means
|
||||||
that you can enable a feature toggle in a
|
that you can enable a feature flag in a
|
||||||
development or test environment without
|
development or test environment without
|
||||||
enabling the feature flag in the
|
enabling the feature flag in the
|
||||||
production environment.'
|
production environment.'
|
||||||
|
@ -22,7 +22,7 @@ const testCases = [
|
|||||||
hasUnsatisfiedDependency: true,
|
hasUnsatisfiedDependency: true,
|
||||||
} as PlaygroundFeatureSchema,
|
} as PlaygroundFeatureSchema,
|
||||||
expectedText:
|
expectedText:
|
||||||
'If environment was enabled and parent dependencies were satisfied, then this feature toggle would be TRUE with strategies evaluated like so:',
|
'If environment was enabled and parent dependencies were satisfied, then this feature flag would be TRUE with strategies evaluated like so:',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Environment enabled and parent dependency not satisfied',
|
name: 'Environment enabled and parent dependency not satisfied',
|
||||||
@ -41,7 +41,7 @@ const testCases = [
|
|||||||
hasUnsatisfiedDependency: true,
|
hasUnsatisfiedDependency: true,
|
||||||
} as PlaygroundFeatureSchema,
|
} as PlaygroundFeatureSchema,
|
||||||
expectedText:
|
expectedText:
|
||||||
'If parent dependencies were satisfied, then this feature toggle would be TRUE with strategies evaluated like so:',
|
'If parent dependencies were satisfied, then this feature flag would be TRUE with strategies evaluated like so:',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Environment not enabled and parent dependency satisfied',
|
name: 'Environment not enabled and parent dependency satisfied',
|
||||||
@ -60,7 +60,7 @@ const testCases = [
|
|||||||
hasUnsatisfiedDependency: false,
|
hasUnsatisfiedDependency: false,
|
||||||
} as PlaygroundFeatureSchema,
|
} as PlaygroundFeatureSchema,
|
||||||
expectedText:
|
expectedText:
|
||||||
'If environment was enabled, then this feature toggle would be TRUE with strategies evaluated like so:',
|
'If environment was enabled, then this feature flag would be TRUE with strategies evaluated like so:',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Has disabled strategies and is enabled in environment',
|
name: 'Has disabled strategies and is enabled in environment',
|
||||||
|
@ -121,7 +121,7 @@ export const WrappedPlaygroundResultStrategyList = ({
|
|||||||
return (
|
return (
|
||||||
<StyledAlertWrapper sx={{ pb: 1, mt: 2 }}>
|
<StyledAlertWrapper sx={{ pb: 1, mt: 2 }}>
|
||||||
<StyledAlert severity={'info'} color={'warning'}>
|
<StyledAlert severity={'info'} color={'warning'}>
|
||||||
{resolveHintText(feature)}, then this feature toggle would be{' '}
|
{resolveHintText(feature)}, then this feature flag would be{' '}
|
||||||
{feature.strategies?.result ? 'TRUE' : 'FALSE'} with strategies
|
{feature.strategies?.result ? 'TRUE' : 'FALSE'} with strategies
|
||||||
evaluated like so:{' '}
|
evaluated like so:{' '}
|
||||||
</StyledAlert>
|
</StyledAlert>
|
||||||
|
@ -59,7 +59,7 @@ export const MoreActions: VFC<IMoreActionsProps> = ({
|
|||||||
onChange?.();
|
onChange?.();
|
||||||
setToastData({
|
setToastData({
|
||||||
title: 'State updated',
|
title: 'State updated',
|
||||||
text: 'Feature toggles marked as stale',
|
text: 'Feature flags marked as stale',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
trackEvent('batch_operations', {
|
trackEvent('batch_operations', {
|
||||||
@ -79,7 +79,7 @@ export const MoreActions: VFC<IMoreActionsProps> = ({
|
|||||||
onChange?.();
|
onChange?.();
|
||||||
setToastData({
|
setToastData({
|
||||||
title: 'State updated',
|
title: 'State updated',
|
||||||
text: 'Feature toggles unmarked as stale',
|
text: 'Feature flags unmarked as stale',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
trackEvent('batch_operations', {
|
trackEvent('batch_operations', {
|
||||||
|
@ -32,6 +32,6 @@ test('should show the count of projects and features used in', async () => {
|
|||||||
|
|
||||||
render(<SegmentTable />);
|
render(<SegmentTable />);
|
||||||
|
|
||||||
await screen.findByText('2 feature toggles');
|
await screen.findByText('2 feature flags');
|
||||||
await screen.findByText('3 projects');
|
await screen.findByText('3 projects');
|
||||||
});
|
});
|
||||||
|
@ -87,7 +87,7 @@ class ExportImportController extends Controller {
|
|||||||
...getStandardResponses(404),
|
...getStandardResponses(404),
|
||||||
},
|
},
|
||||||
summary: 'Validate feature import data',
|
summary: 'Validate feature import data',
|
||||||
description: `Validates a feature toggle data set. Checks whether the data can be imported into the specified project and environment. The returned value is an object that contains errors, warnings, and permissions required to perform the import, as described in the [import documentation](https://docs.getunleash.io/reference/deploy/environment-import-export#import).`,
|
description: `Validates a feature flag data set. Checks whether the data can be imported into the specified project and environment. The returned value is an object that contains errors, warnings, and permissions required to perform the import, as described in the [import documentation](https://docs.getunleash.io/reference/deploy/environment-import-export#import).`,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@ -105,8 +105,8 @@ class ExportImportController extends Controller {
|
|||||||
200: emptyResponse,
|
200: emptyResponse,
|
||||||
...getStandardResponses(404),
|
...getStandardResponses(404),
|
||||||
},
|
},
|
||||||
summary: 'Import feature toggles',
|
summary: 'Import feature flags',
|
||||||
description: `[Import feature toggles](https://docs.getunleash.io/reference/deploy/environment-import-export#import) into a specific project and environment.`,
|
description: `[Import feature flags](https://docs.getunleash.io/reference/deploy/environment-import-export#import) into a specific project and environment.`,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
@ -56,8 +56,8 @@ const defaultContext: ContextFieldSchema = {
|
|||||||
|
|
||||||
const defaultFeatureName = 'first_feature';
|
const defaultFeatureName = 'first_feature';
|
||||||
|
|
||||||
const createToggle = async (
|
const createFlag = async (
|
||||||
toggle: FeatureToggleDTO,
|
flag: FeatureToggleDTO,
|
||||||
strategy: Omit<IStrategyConfig, 'id'> = defaultStrategy,
|
strategy: Omit<IStrategyConfig, 'id'> = defaultStrategy,
|
||||||
tags: string[] = [],
|
tags: string[] = [],
|
||||||
projectId: string = 'default',
|
projectId: string = 'default',
|
||||||
@ -66,7 +66,7 @@ const createToggle = async (
|
|||||||
) => {
|
) => {
|
||||||
await app.services.featureToggleServiceV2.createFeatureToggle(
|
await app.services.featureToggleServiceV2.createFeatureToggle(
|
||||||
projectId,
|
projectId,
|
||||||
toggle,
|
flag,
|
||||||
TEST_AUDIT_USER,
|
TEST_AUDIT_USER,
|
||||||
);
|
);
|
||||||
if (strategy) {
|
if (strategy) {
|
||||||
@ -74,7 +74,7 @@ const createToggle = async (
|
|||||||
strategy,
|
strategy,
|
||||||
{
|
{
|
||||||
projectId,
|
projectId,
|
||||||
featureName: toggle.name,
|
featureName: flag.name,
|
||||||
environment: DEFAULT_ENV,
|
environment: DEFAULT_ENV,
|
||||||
},
|
},
|
||||||
TEST_AUDIT_USER,
|
TEST_AUDIT_USER,
|
||||||
@ -83,7 +83,7 @@ const createToggle = async (
|
|||||||
await Promise.all(
|
await Promise.all(
|
||||||
tags.map(async (tag) => {
|
tags.map(async (tag) => {
|
||||||
return app.services.featureTagService.addTag(
|
return app.services.featureTagService.addTag(
|
||||||
toggle.name,
|
flag.name,
|
||||||
{
|
{
|
||||||
type: 'simple',
|
type: 'simple',
|
||||||
value: tag,
|
value: tag,
|
||||||
@ -211,7 +211,7 @@ describe('import-export for project-specific segments', () => {
|
|||||||
],
|
],
|
||||||
segments: [segment.id],
|
segments: [segment.id],
|
||||||
};
|
};
|
||||||
await createToggle(
|
await createFlag(
|
||||||
{
|
{
|
||||||
name: defaultFeatureName,
|
name: defaultFeatureName,
|
||||||
description: 'the #1 feature',
|
description: 'the #1 feature',
|
||||||
@ -276,14 +276,14 @@ test('exports features', async () => {
|
|||||||
],
|
],
|
||||||
segments: [segment.id],
|
segments: [segment.id],
|
||||||
};
|
};
|
||||||
await createToggle(
|
await createFlag(
|
||||||
{
|
{
|
||||||
name: defaultFeatureName,
|
name: defaultFeatureName,
|
||||||
description: 'the #1 feature',
|
description: 'the #1 feature',
|
||||||
},
|
},
|
||||||
strategy,
|
strategy,
|
||||||
);
|
);
|
||||||
await createToggle(
|
await createFlag(
|
||||||
{
|
{
|
||||||
name: 'second_feature',
|
name: 'second_feature',
|
||||||
description: 'the #1 feature',
|
description: 'the #1 feature',
|
||||||
@ -352,7 +352,7 @@ test('exports features by tag', async () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
await createToggle(
|
await createFlag(
|
||||||
{
|
{
|
||||||
name: defaultFeatureName,
|
name: defaultFeatureName,
|
||||||
description: 'the #1 feature',
|
description: 'the #1 feature',
|
||||||
@ -360,7 +360,7 @@ test('exports features by tag', async () => {
|
|||||||
strategy,
|
strategy,
|
||||||
['mytag'],
|
['mytag'],
|
||||||
);
|
);
|
||||||
await createToggle(
|
await createFlag(
|
||||||
{
|
{
|
||||||
name: 'second_feature',
|
name: 'second_feature',
|
||||||
description: 'the #1 feature',
|
description: 'the #1 feature',
|
||||||
@ -428,7 +428,7 @@ test('should export custom context fields from strategies and variants', async (
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
await createToggle(
|
await createFlag(
|
||||||
{
|
{
|
||||||
name: defaultFeatureName,
|
name: defaultFeatureName,
|
||||||
description: 'the #1 feature',
|
description: 'the #1 feature',
|
||||||
@ -502,7 +502,7 @@ test('should export custom context fields from strategies and variants', async (
|
|||||||
test('should export tags', async () => {
|
test('should export tags', async () => {
|
||||||
const featureName = defaultFeatureName;
|
const featureName = defaultFeatureName;
|
||||||
await createProjects();
|
await createProjects();
|
||||||
await createToggle(
|
await createFlag(
|
||||||
{
|
{
|
||||||
name: featureName,
|
name: featureName,
|
||||||
description: 'the #1 feature',
|
description: 'the #1 feature',
|
||||||
@ -546,11 +546,11 @@ test('should export tags', async () => {
|
|||||||
|
|
||||||
test('returns all features, when no explicit feature was requested', async () => {
|
test('returns all features, when no explicit feature was requested', async () => {
|
||||||
await createProjects();
|
await createProjects();
|
||||||
await createToggle({
|
await createFlag({
|
||||||
name: defaultFeatureName,
|
name: defaultFeatureName,
|
||||||
description: 'the #1 feature',
|
description: 'the #1 feature',
|
||||||
});
|
});
|
||||||
await createToggle({
|
await createFlag({
|
||||||
name: 'second_feature',
|
name: 'second_feature',
|
||||||
description: 'the #1 feature',
|
description: 'the #1 feature',
|
||||||
});
|
});
|
||||||
@ -568,11 +568,11 @@ test('returns all features, when no explicit feature was requested', async () =>
|
|||||||
|
|
||||||
test('returns all project features', async () => {
|
test('returns all project features', async () => {
|
||||||
await createProjects();
|
await createProjects();
|
||||||
await createToggle({
|
await createFlag({
|
||||||
name: defaultFeatureName,
|
name: defaultFeatureName,
|
||||||
description: 'the #1 feature',
|
description: 'the #1 feature',
|
||||||
});
|
});
|
||||||
await createToggle({
|
await createFlag({
|
||||||
name: 'second_feature',
|
name: 'second_feature',
|
||||||
description: 'the #1 feature',
|
description: 'the #1 feature',
|
||||||
});
|
});
|
||||||
@ -1008,7 +1008,7 @@ test('reject import with duplicate features', async () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(body.details[0].description).toBe(
|
expect(body.details[0].description).toBe(
|
||||||
'A toggle with that name already exists',
|
'A flag with that name already exists',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ export default class ArchiveController extends Controller {
|
|||||||
tags: ['Archive'],
|
tags: ['Archive'],
|
||||||
summary: 'Get archived features',
|
summary: 'Get archived features',
|
||||||
description:
|
description:
|
||||||
'Retrieve a list of all [archived feature toggles](https://docs.getunleash.io/reference/archived-toggles).',
|
'Retrieve a list of all [archived feature flags](https://docs.getunleash.io/reference/archived-toggles).',
|
||||||
operationId: 'getArchivedFeatures',
|
operationId: 'getArchivedFeatures',
|
||||||
responses: {
|
responses: {
|
||||||
200: createResponseSchema('featuresSchema'),
|
200: createResponseSchema('featuresSchema'),
|
||||||
|
@ -29,7 +29,7 @@ export default class FakeFeatureToggleStore implements IFeatureToggleStore {
|
|||||||
return feature;
|
return feature;
|
||||||
}
|
}
|
||||||
throw new NotFoundError(
|
throw new NotFoundError(
|
||||||
`Could not find feature toggle with name ${featureName}`,
|
`Could not find feature flag with name ${featureName}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
summary: 'Get a feature environment',
|
summary: 'Get a feature environment',
|
||||||
description:
|
description:
|
||||||
'Information about the enablement status and strategies for a feature toggle in specified environment.',
|
'Information about the enablement status and strategies for a feature flag in specified environment.',
|
||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
operationId: 'getFeatureEnvironment',
|
operationId: 'getFeatureEnvironment',
|
||||||
responses: {
|
responses: {
|
||||||
@ -173,9 +173,9 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
permission: UPDATE_FEATURE_ENVIRONMENT,
|
permission: UPDATE_FEATURE_ENVIRONMENT,
|
||||||
middleware: [
|
middleware: [
|
||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
summary: 'Disable a feature toggle',
|
summary: 'Disable a feature flag',
|
||||||
description:
|
description:
|
||||||
'Disable a feature toggle in the specified environment.',
|
'Disable a feature flag in the specified environment.',
|
||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
operationId: 'toggleFeatureEnvironmentOff',
|
operationId: 'toggleFeatureEnvironmentOff',
|
||||||
responses: {
|
responses: {
|
||||||
@ -194,9 +194,9 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
permission: UPDATE_FEATURE_ENVIRONMENT,
|
permission: UPDATE_FEATURE_ENVIRONMENT,
|
||||||
middleware: [
|
middleware: [
|
||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
summary: 'Enable a feature toggle',
|
summary: 'Enable a feature flag',
|
||||||
description:
|
description:
|
||||||
'Enable a feature toggle in the specified environment.',
|
'Enable a feature flag in the specified environment.',
|
||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
operationId: 'toggleFeatureEnvironmentOn',
|
operationId: 'toggleFeatureEnvironmentOn',
|
||||||
responses: {
|
responses: {
|
||||||
@ -217,7 +217,7 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
summary: 'Bulk enable a list of features',
|
summary: 'Bulk enable a list of features',
|
||||||
description:
|
description:
|
||||||
'This endpoint enables multiple feature toggles.',
|
'This endpoint enables multiple feature flags.',
|
||||||
operationId: 'bulkToggleFeaturesEnvironmentOn',
|
operationId: 'bulkToggleFeaturesEnvironmentOn',
|
||||||
requestBody: createRequestSchema(
|
requestBody: createRequestSchema(
|
||||||
'bulkToggleFeaturesSchema',
|
'bulkToggleFeaturesSchema',
|
||||||
@ -240,7 +240,7 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
summary: 'Bulk disable a list of features',
|
summary: 'Bulk disable a list of features',
|
||||||
description:
|
description:
|
||||||
'This endpoint disables multiple feature toggles.',
|
'This endpoint disables multiple feature flags.',
|
||||||
operationId: 'bulkToggleFeaturesEnvironmentOff',
|
operationId: 'bulkToggleFeaturesEnvironmentOff',
|
||||||
requestBody: createRequestSchema(
|
requestBody: createRequestSchema(
|
||||||
'bulkToggleFeaturesSchema',
|
'bulkToggleFeaturesSchema',
|
||||||
@ -261,10 +261,10 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
middleware: [
|
middleware: [
|
||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
summary: 'Get feature toggle strategies',
|
summary: 'Get feature flag strategies',
|
||||||
operationId: 'getFeatureStrategies',
|
operationId: 'getFeatureStrategies',
|
||||||
description:
|
description:
|
||||||
'Get strategies defined for a feature toggle in the specified environment.',
|
'Get strategies defined for a feature flag in the specified environment.',
|
||||||
responses: {
|
responses: {
|
||||||
200: createResponseSchema('featureStrategySchema'),
|
200: createResponseSchema('featureStrategySchema'),
|
||||||
...getStandardResponses(401, 403, 404),
|
...getStandardResponses(401, 403, 404),
|
||||||
@ -281,9 +281,9 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
middleware: [
|
middleware: [
|
||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
summary: 'Add a strategy to a feature toggle',
|
summary: 'Add a strategy to a feature flag',
|
||||||
description:
|
description:
|
||||||
'Add a strategy to a feature toggle in the specified environment.',
|
'Add a strategy to a feature flag in the specified environment.',
|
||||||
operationId: 'addFeatureStrategy',
|
operationId: 'addFeatureStrategy',
|
||||||
requestBody: createRequestSchema(
|
requestBody: createRequestSchema(
|
||||||
'createFeatureStrategySchema',
|
'createFeatureStrategySchema',
|
||||||
@ -306,7 +306,7 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
summary: 'Get a strategy configuration',
|
summary: 'Get a strategy configuration',
|
||||||
description:
|
description:
|
||||||
'Get a strategy configuration for an environment in a feature toggle.',
|
'Get a strategy configuration for an environment in a feature flag.',
|
||||||
operationId: 'getFeatureStrategy',
|
operationId: 'getFeatureStrategy',
|
||||||
responses: {
|
responses: {
|
||||||
200: createResponseSchema('featureStrategySchema'),
|
200: createResponseSchema('featureStrategySchema'),
|
||||||
@ -349,7 +349,7 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
summary: 'Update a strategy',
|
summary: 'Update a strategy',
|
||||||
description:
|
description:
|
||||||
'Replace strategy configuration for a feature toggle in the specified environment.',
|
'Replace strategy configuration for a feature flag in the specified environment.',
|
||||||
operationId: 'updateFeatureStrategy',
|
operationId: 'updateFeatureStrategy',
|
||||||
requestBody: createRequestSchema(
|
requestBody: createRequestSchema(
|
||||||
'updateFeatureStrategySchema',
|
'updateFeatureStrategySchema',
|
||||||
@ -372,7 +372,7 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
summary: 'Change specific properties of a strategy',
|
summary: 'Change specific properties of a strategy',
|
||||||
description:
|
description:
|
||||||
'Change specific properties of a strategy configuration in a feature toggle.',
|
'Change specific properties of a strategy configuration in a feature flag.',
|
||||||
operationId: 'patchFeatureStrategy',
|
operationId: 'patchFeatureStrategy',
|
||||||
requestBody: createRequestSchema('patchesSchema'),
|
requestBody: createRequestSchema('patchesSchema'),
|
||||||
responses: {
|
responses: {
|
||||||
@ -392,9 +392,9 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
middleware: [
|
middleware: [
|
||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
summary: 'Delete a strategy from a feature toggle',
|
summary: 'Delete a strategy from a feature flag',
|
||||||
description:
|
description:
|
||||||
'Delete a strategy configuration from a feature toggle in the specified environment.',
|
'Delete a strategy configuration from a feature flag in the specified environment.',
|
||||||
operationId: 'deleteFeatureStrategy',
|
operationId: 'deleteFeatureStrategy',
|
||||||
responses: {
|
responses: {
|
||||||
200: emptyResponse,
|
200: emptyResponse,
|
||||||
@ -431,9 +431,9 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
permission: CREATE_FEATURE,
|
permission: CREATE_FEATURE,
|
||||||
middleware: [
|
middleware: [
|
||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
summary: 'Add a new feature toggle',
|
summary: 'Add a new feature flag',
|
||||||
description:
|
description:
|
||||||
'Create a new feature toggle in a specified project.',
|
'Create a new feature flag in a specified project.',
|
||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
operationId: 'createFeature',
|
operationId: 'createFeature',
|
||||||
requestBody: createRequestSchema('createFeatureSchema'),
|
requestBody: createRequestSchema('createFeatureSchema'),
|
||||||
@ -453,9 +453,9 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
permission: CREATE_FEATURE,
|
permission: CREATE_FEATURE,
|
||||||
middleware: [
|
middleware: [
|
||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
summary: 'Clone a feature toggle',
|
summary: 'Clone a feature flag',
|
||||||
description:
|
description:
|
||||||
'Creates a copy of the specified feature toggle. The copy can be created in any project.',
|
'Creates a copy of the specified feature flag. The copy can be created in any project.',
|
||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
operationId: 'cloneFeature',
|
operationId: 'cloneFeature',
|
||||||
requestBody: createRequestSchema('cloneFeatureSchema'),
|
requestBody: createRequestSchema('cloneFeatureSchema'),
|
||||||
@ -500,7 +500,7 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
operationId: 'updateFeature',
|
operationId: 'updateFeature',
|
||||||
summary: 'Update a feature toggle',
|
summary: 'Update a feature flag',
|
||||||
description:
|
description:
|
||||||
'Updates the specified feature if the feature belongs to the specified project. Only the provided properties are updated; any feature properties left out of the request body are left untouched.',
|
'Updates the specified feature if the feature belongs to the specified project. Only the provided properties are updated; any feature properties left out of the request body are left untouched.',
|
||||||
requestBody: createRequestSchema('updateFeatureSchema'),
|
requestBody: createRequestSchema('updateFeatureSchema'),
|
||||||
@ -521,9 +521,9 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
operationId: 'patchFeature',
|
operationId: 'patchFeature',
|
||||||
summary: 'Modify a feature toggle',
|
summary: 'Modify a feature flag',
|
||||||
description:
|
description:
|
||||||
'Change specific properties of a feature toggle.',
|
'Change specific properties of a feature flag.',
|
||||||
requestBody: createRequestSchema('patchesSchema'),
|
requestBody: createRequestSchema('patchesSchema'),
|
||||||
responses: {
|
responses: {
|
||||||
200: createResponseSchema('featureSchema'),
|
200: createResponseSchema('featureSchema'),
|
||||||
@ -543,7 +543,7 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
operationId: 'archiveFeature',
|
operationId: 'archiveFeature',
|
||||||
summary: 'Archive a feature toggle',
|
summary: 'Archive a feature flag',
|
||||||
description:
|
description:
|
||||||
'This endpoint archives the specified feature if the feature belongs to the specified project.',
|
'This endpoint archives the specified feature if the feature belongs to the specified project.',
|
||||||
responses: {
|
responses: {
|
||||||
@ -722,7 +722,7 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
const { projectId, featureName } = req.params;
|
const { projectId, featureName } = req.params;
|
||||||
const { createdAt, ...data } = req.body;
|
const { createdAt, ...data } = req.body;
|
||||||
if (data.name && data.name !== featureName) {
|
if (data.name && data.name !== featureName) {
|
||||||
throw new BadDataError('Cannot change name of feature toggle');
|
throw new BadDataError('Cannot change name of feature flag');
|
||||||
}
|
}
|
||||||
const created = await this.featureService.updateFeatureToggle(
|
const created = await this.featureService.updateFeatureToggle(
|
||||||
projectId,
|
projectId,
|
||||||
|
@ -1161,7 +1161,7 @@ class FeatureToggleService {
|
|||||||
isValidated: boolean = false,
|
isValidated: boolean = false,
|
||||||
): Promise<FeatureToggle> {
|
): Promise<FeatureToggle> {
|
||||||
this.logger.info(
|
this.logger.info(
|
||||||
`${auditUser.username} creates feature toggle ${value.name}`,
|
`${auditUser.username} creates feature flag ${value.name}`,
|
||||||
);
|
);
|
||||||
await this.validateName(value.name);
|
await this.validateName(value.name);
|
||||||
await this.validateFeatureFlagNameAgainstPattern(value.name, projectId);
|
await this.validateFeatureFlagNameAgainstPattern(value.name, projectId);
|
||||||
@ -1170,7 +1170,7 @@ class FeatureToggleService {
|
|||||||
|
|
||||||
if (await this.projectStore.isFeatureLimitReached(projectId)) {
|
if (await this.projectStore.isFeatureLimitReached(projectId)) {
|
||||||
throw new InvalidOperationError(
|
throw new InvalidOperationError(
|
||||||
'You have reached the maximum number of feature toggles for this project.',
|
'You have reached the maximum number of feature flags for this project.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (exists) {
|
if (exists) {
|
||||||
@ -1306,7 +1306,7 @@ class FeatureToggleService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.logger.info(
|
this.logger.info(
|
||||||
`${auditUser.username} clones feature toggle ${featureName} to ${newFeatureName}`,
|
`${auditUser.username} clones feature flag ${featureName} to ${newFeatureName}`,
|
||||||
);
|
);
|
||||||
await this.validateName(newFeatureName);
|
await this.validateName(newFeatureName);
|
||||||
|
|
||||||
@ -1384,7 +1384,7 @@ class FeatureToggleService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.logger.info(
|
this.logger.info(
|
||||||
`${auditUser.username} updates feature toggle ${featureName}`,
|
`${auditUser.username} updates feature flag ${featureName}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const featureData =
|
const featureData =
|
||||||
@ -1508,8 +1508,8 @@ class FeatureToggleService {
|
|||||||
try {
|
try {
|
||||||
const feature = await this.featureToggleStore.get(name);
|
const feature = await this.featureToggleStore.get(name);
|
||||||
msg = feature.archived
|
msg = feature.archived
|
||||||
? 'An archived toggle with that name already exists'
|
? 'An archived flag with that name already exists'
|
||||||
: 'A toggle with that name already exists';
|
: 'A flag with that name already exists';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -441,7 +441,7 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
|
|||||||
|
|
||||||
rowToFeature(row: FeaturesTable): FeatureToggle {
|
rowToFeature(row: FeaturesTable): FeatureToggle {
|
||||||
if (!row) {
|
if (!row) {
|
||||||
throw new NotFoundError('No feature toggle found');
|
throw new NotFoundError('No feature flag found');
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
name: row.name,
|
name: row.name,
|
||||||
@ -571,7 +571,7 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
|
|||||||
|
|
||||||
async delete(name: string): Promise<void> {
|
async delete(name: string): Promise<void> {
|
||||||
await this.db(TABLE)
|
await this.db(TABLE)
|
||||||
.where({ name }) // Feature toggle must be archived to allow deletion
|
.where({ name }) // Feature flag must be archived to allow deletion
|
||||||
.whereNotNull('archived_at')
|
.whereNotNull('archived_at')
|
||||||
.del();
|
.del();
|
||||||
}
|
}
|
||||||
@ -609,7 +609,7 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
|
|||||||
|
|
||||||
async getVariants(featureName: string): Promise<IVariant[]> {
|
async getVariants(featureName: string): Promise<IVariant[]> {
|
||||||
if (!(await this.exists(featureName))) {
|
if (!(await this.exists(featureName))) {
|
||||||
throw new NotFoundError('No feature toggle found');
|
throw new NotFoundError('No feature flag found');
|
||||||
}
|
}
|
||||||
const row = await this.db(`${TABLE} as f`)
|
const row = await this.db(`${TABLE} as f`)
|
||||||
.select('fe.variants')
|
.select('fe.variants')
|
||||||
@ -656,10 +656,10 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
|
|||||||
name: featureName,
|
name: featureName,
|
||||||
});
|
});
|
||||||
|
|
||||||
const toggle = this.rowToFeature(row[0]);
|
const flag = this.rowToFeature(row[0]);
|
||||||
toggle.variants = newVariants;
|
flag.variants = newVariants;
|
||||||
|
|
||||||
return toggle;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
async updatePotentiallyStaleFeatures(currentTime?: string): Promise<
|
async updatePotentiallyStaleFeatures(currentTime?: string): Promise<
|
||||||
|
@ -532,7 +532,7 @@ class FeatureStrategiesStore implements IFeatureStrategiesStore {
|
|||||||
return featureToggle;
|
return featureToggle;
|
||||||
}
|
}
|
||||||
throw new NotFoundError(
|
throw new NotFoundError(
|
||||||
`Could not find feature toggle with name ${featureName}`,
|
`Could not find feature flag with name ${featureName}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,9 +68,9 @@ class FeatureController extends Controller {
|
|||||||
200: createResponseSchema('featuresSchema'),
|
200: createResponseSchema('featuresSchema'),
|
||||||
...getStandardResponses(401, 403),
|
...getStandardResponses(401, 403),
|
||||||
},
|
},
|
||||||
summary: 'Get all feature toggles (deprecated)',
|
summary: 'Get all feature flags (deprecated)',
|
||||||
description:
|
description:
|
||||||
'Gets all feature toggles with their full configuration. This endpoint is **deprecated**. You should use the project-based endpoint instead (`/api/admin/projects/<project-id>/features`).',
|
'Gets all feature flags with their full configuration. This endpoint is **deprecated**. You should use the project-based endpoint instead (`/api/admin/projects/<project-id>/features`).',
|
||||||
deprecated: true,
|
deprecated: true,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
@ -85,10 +85,10 @@ class FeatureController extends Controller {
|
|||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
tags: ['Features'],
|
tags: ['Features'],
|
||||||
operationId: 'validateFeature',
|
operationId: 'validateFeature',
|
||||||
summary: 'Validate a feature toggle name.',
|
summary: 'Validate a feature flag name.',
|
||||||
requestBody: createRequestSchema('validateFeatureSchema'),
|
requestBody: createRequestSchema('validateFeatureSchema'),
|
||||||
description:
|
description:
|
||||||
'Validates a feature toggle name: checks whether the name is URL-friendly and whether a feature with the given name already exists. Returns 200 if the feature name is compliant and unused.',
|
'Validates a feature flag name: checks whether the name is URL-friendly and whether a feature with the given name already exists. Returns 200 if the feature name is compliant and unused.',
|
||||||
responses: {
|
responses: {
|
||||||
200: emptyResponse,
|
200: emptyResponse,
|
||||||
...getStandardResponses(400, 401, 409, 415),
|
...getStandardResponses(400, 401, 409, 415),
|
||||||
|
@ -67,9 +67,9 @@ afterAll(async () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await db.rawDatabase('change_request_settings').del();
|
await db.rawDatabase('change_request_settings').del();
|
||||||
});
|
});
|
||||||
test('Should create feature toggle strategy configuration', async () => {
|
test('Should create feature flag strategy configuration', async () => {
|
||||||
const projectId = 'default';
|
const projectId = 'default';
|
||||||
const username = 'feature-toggle';
|
const username = 'feature-flag';
|
||||||
const config: Omit<FeatureStrategySchema, 'id'> = {
|
const config: Omit<FeatureStrategySchema, 'id'> = {
|
||||||
name: 'default',
|
name: 'default',
|
||||||
constraints: [],
|
constraints: [],
|
||||||
@ -157,7 +157,7 @@ test('Should be able to get strategy by id', async () => {
|
|||||||
expect(fetchedConfig).toEqual(createdConfig);
|
expect(fetchedConfig).toEqual(createdConfig);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should ignore name in the body when updating feature toggle', async () => {
|
test('should ignore name in the body when updating feature flag', async () => {
|
||||||
const featureName = 'body-name-update';
|
const featureName = 'body-name-update';
|
||||||
const projectId = 'default';
|
const projectId = 'default';
|
||||||
|
|
||||||
@ -168,7 +168,7 @@ test('should ignore name in the body when updating feature toggle', async () =>
|
|||||||
projectId,
|
projectId,
|
||||||
{
|
{
|
||||||
name: featureName,
|
name: featureName,
|
||||||
description: 'First toggle',
|
description: 'First flag',
|
||||||
},
|
},
|
||||||
TEST_AUDIT_USER,
|
TEST_AUDIT_USER,
|
||||||
);
|
);
|
||||||
@ -177,7 +177,7 @@ test('should ignore name in the body when updating feature toggle', async () =>
|
|||||||
projectId,
|
projectId,
|
||||||
{
|
{
|
||||||
name: secondFeatureName,
|
name: secondFeatureName,
|
||||||
description: 'Second toggle',
|
description: 'Second flag',
|
||||||
},
|
},
|
||||||
TEST_AUDIT_USER,
|
TEST_AUDIT_USER,
|
||||||
);
|
);
|
||||||
@ -199,7 +199,7 @@ test('should ignore name in the body when updating feature toggle', async () =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(featureOne.description).toBe(`I'm changed`);
|
expect(featureOne.description).toBe(`I'm changed`);
|
||||||
expect(featureTwo.description).toBe('Second toggle');
|
expect(featureTwo.description).toBe('Second flag');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should not get empty rows as features', async () => {
|
test('should not get empty rows as features', async () => {
|
||||||
@ -211,7 +211,7 @@ test('should not get empty rows as features', async () => {
|
|||||||
projectId,
|
projectId,
|
||||||
{
|
{
|
||||||
name: 'linked-with-segment',
|
name: 'linked-with-segment',
|
||||||
description: 'First toggle',
|
description: 'First flag',
|
||||||
},
|
},
|
||||||
TEST_AUDIT_USER,
|
TEST_AUDIT_USER,
|
||||||
);
|
);
|
||||||
@ -220,7 +220,7 @@ test('should not get empty rows as features', async () => {
|
|||||||
projectId,
|
projectId,
|
||||||
{
|
{
|
||||||
name: 'not-linked-with-segment',
|
name: 'not-linked-with-segment',
|
||||||
description: 'Second toggle',
|
description: 'Second flag',
|
||||||
},
|
},
|
||||||
TEST_AUDIT_USER,
|
TEST_AUDIT_USER,
|
||||||
);
|
);
|
||||||
@ -252,7 +252,7 @@ test('adding and removing an environment preserves variants when variants per en
|
|||||||
'default',
|
'default',
|
||||||
{
|
{
|
||||||
name: featureName,
|
name: featureName,
|
||||||
description: 'Second toggle',
|
description: 'Second flag',
|
||||||
variants: [
|
variants: [
|
||||||
{
|
{
|
||||||
name: 'variant1',
|
name: 'variant1',
|
||||||
@ -273,7 +273,7 @@ test('adding and removing an environment preserves variants when variants per en
|
|||||||
// @ts-expect-error - incomplete flag resolver definition
|
// @ts-expect-error - incomplete flag resolver definition
|
||||||
flagResolver: {
|
flagResolver: {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
isEnabled: (toggleName: string) => false,
|
isEnabled: (flagName: string) => false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
eventService,
|
eventService,
|
||||||
@ -295,23 +295,23 @@ test('adding and removing an environment preserves variants when variants per en
|
|||||||
SYSTEM_USER_AUDIT,
|
SYSTEM_USER_AUDIT,
|
||||||
);
|
);
|
||||||
|
|
||||||
const toggle = await service.getFeature({
|
const flag = await service.getFeature({
|
||||||
featureName,
|
featureName,
|
||||||
projectId: undefined,
|
projectId: undefined,
|
||||||
environmentVariants: false,
|
environmentVariants: false,
|
||||||
});
|
});
|
||||||
expect(toggle.variants).toHaveLength(1);
|
expect(flag.variants).toHaveLength(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('cloning a feature toggle copies variant environments correctly', async () => {
|
test('cloning a feature flag copies variant environments correctly', async () => {
|
||||||
const newToggleName = 'Molly';
|
const newFlagName = 'Molly';
|
||||||
const clonedToggleName = 'Dolly';
|
const clonedFlagName = 'Dolly';
|
||||||
const targetEnv = 'gene-lab';
|
const targetEnv = 'gene-lab';
|
||||||
|
|
||||||
await service.createFeatureToggle(
|
await service.createFeatureToggle(
|
||||||
'default',
|
'default',
|
||||||
{
|
{
|
||||||
name: newToggleName,
|
name: newFlagName,
|
||||||
},
|
},
|
||||||
TEST_AUDIT_USER,
|
TEST_AUDIT_USER,
|
||||||
);
|
);
|
||||||
@ -322,12 +322,12 @@ test('cloning a feature toggle copies variant environments correctly', async ()
|
|||||||
});
|
});
|
||||||
|
|
||||||
await stores.featureEnvironmentStore.connectFeatureToEnvironmentsForProject(
|
await stores.featureEnvironmentStore.connectFeatureToEnvironmentsForProject(
|
||||||
newToggleName,
|
newFlagName,
|
||||||
'default',
|
'default',
|
||||||
);
|
);
|
||||||
|
|
||||||
await stores.featureEnvironmentStore.addVariantsToFeatureEnvironment(
|
await stores.featureEnvironmentStore.addVariantsToFeatureEnvironment(
|
||||||
newToggleName,
|
newFlagName,
|
||||||
targetEnv,
|
targetEnv,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -340,37 +340,37 @@ test('cloning a feature toggle copies variant environments correctly', async ()
|
|||||||
);
|
);
|
||||||
|
|
||||||
await service.cloneFeatureToggle(
|
await service.cloneFeatureToggle(
|
||||||
newToggleName,
|
newFlagName,
|
||||||
'default',
|
'default',
|
||||||
clonedToggleName,
|
clonedFlagName,
|
||||||
SYSTEM_USER_AUDIT,
|
SYSTEM_USER_AUDIT,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
const clonedToggle =
|
const clonedFlag =
|
||||||
await stores.featureStrategiesStore.getFeatureToggleWithVariantEnvs(
|
await stores.featureStrategiesStore.getFeatureToggleWithVariantEnvs(
|
||||||
clonedToggleName,
|
clonedFlagName,
|
||||||
);
|
);
|
||||||
|
|
||||||
const defaultEnv = clonedToggle.environments.find(
|
const defaultEnv = clonedFlag.environments.find(
|
||||||
(x) => x.name === 'default',
|
(x) => x.name === 'default',
|
||||||
);
|
);
|
||||||
const newEnv = clonedToggle.environments.find((x) => x.name === targetEnv);
|
const newEnv = clonedFlag.environments.find((x) => x.name === targetEnv);
|
||||||
|
|
||||||
expect(defaultEnv!!.variants).toHaveLength(0);
|
expect(defaultEnv!!.variants).toHaveLength(0);
|
||||||
expect(newEnv!!.variants).toHaveLength(1);
|
expect(newEnv!!.variants).toHaveLength(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('cloning a feature toggle not allowed for change requests enabled', async () => {
|
test('cloning a feature flag not allowed for change requests enabled', async () => {
|
||||||
await db.rawDatabase('change_request_settings').insert({
|
await db.rawDatabase('change_request_settings').insert({
|
||||||
project: 'default',
|
project: 'default',
|
||||||
environment: 'default',
|
environment: 'default',
|
||||||
});
|
});
|
||||||
await expect(
|
await expect(
|
||||||
service.cloneFeatureToggle(
|
service.cloneFeatureToggle(
|
||||||
'newToggleName',
|
'newFlagName',
|
||||||
'default',
|
'default',
|
||||||
'clonedToggleName',
|
'clonedFlagName',
|
||||||
SYSTEM_USER_AUDIT,
|
SYSTEM_USER_AUDIT,
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
@ -387,7 +387,7 @@ test('changing to a project with change requests enabled should not be allowed',
|
|||||||
environment: 'default',
|
environment: 'default',
|
||||||
});
|
});
|
||||||
await expect(
|
await expect(
|
||||||
service.changeProject('newToggleName', 'default', TEST_AUDIT_USER),
|
service.changeProject('newFlagName', 'default', TEST_AUDIT_USER),
|
||||||
).rejects.toEqual(
|
).rejects.toEqual(
|
||||||
new ForbiddenError(
|
new ForbiddenError(
|
||||||
`Changing project not allowed. Project default has change requests enabled.`,
|
`Changing project not allowed. Project default has change requests enabled.`,
|
||||||
@ -395,9 +395,9 @@ test('changing to a project with change requests enabled should not be allowed',
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Cloning a feature toggle also clones segments correctly', async () => {
|
test('Cloning a feature flag also clones segments correctly', async () => {
|
||||||
const featureName = 'ToggleWithSegments';
|
const featureName = 'FlagWithSegments';
|
||||||
const clonedFeatureName = 'AWholeNewFeatureToggle';
|
const clonedFeatureName = 'AWholeNewFeatureFlag';
|
||||||
|
|
||||||
const segment = await segmentService.create(
|
const segment = await segmentService.create(
|
||||||
{
|
{
|
||||||
@ -529,9 +529,9 @@ test('If CRs are protected for any environment in the project stops bulk update
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const toggle = await service.createFeatureToggle(
|
const flag = await service.createFeatureToggle(
|
||||||
project.id,
|
project.id,
|
||||||
{ name: 'crOnVariantToggle' },
|
{ name: 'crOnVariantFlag' },
|
||||||
TEST_AUDIT_USER,
|
TEST_AUDIT_USER,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -548,7 +548,7 @@ test('If CRs are protected for any environment in the project stops bulk update
|
|||||||
|
|
||||||
await customFeatureService.setVariantsOnEnvs(
|
await customFeatureService.setVariantsOnEnvs(
|
||||||
project.id,
|
project.id,
|
||||||
toggle.name,
|
flag.name,
|
||||||
[enabledEnv.name, disabledEnv.name],
|
[enabledEnv.name, disabledEnv.name],
|
||||||
[variant],
|
[variant],
|
||||||
TEST_AUDIT_USER,
|
TEST_AUDIT_USER,
|
||||||
@ -566,7 +566,7 @@ test('If CRs are protected for any environment in the project stops bulk update
|
|||||||
return expect(async () =>
|
return expect(async () =>
|
||||||
customFeatureService.crProtectedSetVariantsOnEnvs(
|
customFeatureService.crProtectedSetVariantsOnEnvs(
|
||||||
project.id,
|
project.id,
|
||||||
toggle.name,
|
flag.name,
|
||||||
[enabledEnv.name, disabledEnv.name],
|
[enabledEnv.name, disabledEnv.name],
|
||||||
newVariants,
|
newVariants,
|
||||||
{
|
{
|
||||||
|
@ -41,10 +41,10 @@ afterAll(async () => {
|
|||||||
await db.destroy();
|
await db.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Should not be possible to update feature toggle without permission', async () => {
|
test('Should not be possible to update feature flag without permission', async () => {
|
||||||
const email = 'user@mail.com';
|
const email = 'user@mail.com';
|
||||||
const url = '/api/admin/projects/default/features';
|
const url = '/api/admin/projects/default/features';
|
||||||
const name = 'auth.toggle.update';
|
const name = 'auth.flag.update';
|
||||||
|
|
||||||
await db.stores.featureToggleStore.create('default', {
|
await db.stores.featureToggleStore.create('default', {
|
||||||
name,
|
name,
|
||||||
@ -69,10 +69,10 @@ test('Should not be possible to update feature toggle without permission', async
|
|||||||
.expect(403);
|
.expect(403);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Should be possible to update feature toggle with permission', async () => {
|
test('Should be possible to update feature flag with permission', async () => {
|
||||||
const email = 'user2@mail.com';
|
const email = 'user2@mail.com';
|
||||||
const url = '/api/admin/projects/default/features';
|
const url = '/api/admin/projects/default/features';
|
||||||
const name = 'auth.toggle.update2';
|
const name = 'auth.flag.update2';
|
||||||
|
|
||||||
await db.stores.featureToggleStore.create('default', {
|
await db.stores.featureToggleStore.create('default', {
|
||||||
name,
|
name,
|
||||||
@ -97,10 +97,10 @@ test('Should be possible to update feature toggle with permission', async () =>
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Should not be possible auto-enable feature toggle without CREATE_FEATURE_STRATEGY permission', async () => {
|
test('Should not be possible auto-enable feature flag without CREATE_FEATURE_STRATEGY permission', async () => {
|
||||||
const email = 'user33@mail.com';
|
const email = 'user33@mail.com';
|
||||||
const url = '/api/admin/projects/default/features';
|
const url = '/api/admin/projects/default/features';
|
||||||
const name = 'auth.toggle.enable';
|
const name = 'auth.flag.enable';
|
||||||
|
|
||||||
await app.services.featureToggleServiceV2.createFeatureToggle(
|
await app.services.featureToggleServiceV2.createFeatureToggle(
|
||||||
'default',
|
'default',
|
||||||
|
@ -172,7 +172,7 @@ async function addStrategies(featureName: string, envName: string) {
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
test('Trying to add a strategy configuration to environment not connected to toggle should fail', async () => {
|
test('Trying to add a strategy configuration to environment not connected to flag should fail', async () => {
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({
|
.send({
|
||||||
@ -603,11 +603,11 @@ test('Trying to get features for non-existing project also yields 404', async ()
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can use new project feature toggle endpoint to create feature toggle without strategies', async () => {
|
test('Can use new project feature flag endpoint to create feature flag without strategies', async () => {
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({
|
.send({
|
||||||
name: 'new.toggle.without.strategy',
|
name: 'new.flag.without.strategy',
|
||||||
})
|
})
|
||||||
.expect(201)
|
.expect(201)
|
||||||
.expect((res) => {
|
.expect((res) => {
|
||||||
@ -615,19 +615,19 @@ test('Can use new project feature toggle endpoint to create feature toggle witho
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can create feature toggle without strategies', async () => {
|
test('Can create feature flag without strategies', async () => {
|
||||||
const name = 'new.toggle.without.strategy.2';
|
const name = 'new.flag.without.strategy.2';
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({ name });
|
.send({ name });
|
||||||
const { body: toggle } = await app.request.get(
|
const { body: flag } = await app.request.get(
|
||||||
`/api/admin/projects/default/features/${name}`,
|
`/api/admin/projects/default/features/${name}`,
|
||||||
);
|
);
|
||||||
expect(toggle.environments).toHaveLength(1);
|
expect(flag.environments).toHaveLength(1);
|
||||||
expect(toggle.environments[0].strategies).toHaveLength(0);
|
expect(flag.environments[0].strategies).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Still validates feature toggle input when creating', async () => {
|
test('Still validates feature flag input when creating', async () => {
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({
|
.send({
|
||||||
@ -636,7 +636,7 @@ test('Still validates feature toggle input when creating', async () => {
|
|||||||
.expect(400);
|
.expect(400);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Trying to create toggle that already exists yield 409 error', async () => {
|
test('Trying to create flag that already exists yield 409 error', async () => {
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({
|
.send({
|
||||||
@ -654,7 +654,7 @@ test('Trying to create toggle that already exists yield 409 error', async () =>
|
|||||||
.expect(409);
|
.expect(409);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Trying to create toggle under project that does not exist should fail', async () => {
|
test('Trying to create flag under project that does not exist should fail', async () => {
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/non-existing-secondary/features')
|
.post('/api/admin/projects/non-existing-secondary/features')
|
||||||
.send({
|
.send({
|
||||||
@ -663,7 +663,7 @@ test('Trying to create toggle under project that does not exist should fail', as
|
|||||||
.expect(404);
|
.expect(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can get environment info for feature toggle', async () => {
|
test('Can get environment info for feature flag', async () => {
|
||||||
const envName = 'environment-info';
|
const envName = 'environment-info';
|
||||||
// Create environment
|
// Create environment
|
||||||
await db.stores.environmentStore.create({
|
await db.stores.environmentStore.create({
|
||||||
@ -706,20 +706,20 @@ test('Getting environment info for environment that does not exist yields 404',
|
|||||||
.expect(404);
|
.expect(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Trying to toggle environment that does not exist yields 404', async () => {
|
test('Trying to flag environment that does not exist yields 404', async () => {
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({ name: 'toggle.env' })
|
.send({ name: 'flag.env' })
|
||||||
.expect(201);
|
.expect(201);
|
||||||
await app.request
|
await app.request
|
||||||
.post(
|
.post(
|
||||||
'/api/admin/projects/default/features/toggle.env/environments/does-not-exist/on',
|
'/api/admin/projects/default/features/flag.env/environments/does-not-exist/on',
|
||||||
)
|
)
|
||||||
.send({})
|
.send({})
|
||||||
.expect(404);
|
.expect(404);
|
||||||
await app.request
|
await app.request
|
||||||
.post(
|
.post(
|
||||||
'/api/admin/projects/default/features/toggle.env/environments/does-not-exist/off',
|
'/api/admin/projects/default/features/flag.env/environments/does-not-exist/off',
|
||||||
)
|
)
|
||||||
.send({})
|
.send({})
|
||||||
.expect(404);
|
.expect(404);
|
||||||
@ -733,7 +733,7 @@ test('Getting feature that does not exist should yield 404', async () => {
|
|||||||
|
|
||||||
describe('Interacting with features using project IDs that belong to other projects', () => {
|
describe('Interacting with features using project IDs that belong to other projects', () => {
|
||||||
const otherProject = 'project2';
|
const otherProject = 'project2';
|
||||||
const featureName = 'new-toggle';
|
const featureName = 'new-flag';
|
||||||
const nonExistingProject = 'this-is-not-a-project';
|
const nonExistingProject = 'this-is-not-a-project';
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
@ -761,7 +761,7 @@ describe('Interacting with features using project IDs that belong to other proje
|
|||||||
.get(`/api/admin/projects/${otherProject}`)
|
.get(`/api/admin/projects/${otherProject}`)
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
// create toggle in default project
|
// create flag in default project
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({ name: featureName })
|
.send({ name: featureName })
|
||||||
@ -823,9 +823,9 @@ describe('Interacting with features using project IDs that belong to other proje
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Should update feature toggle', async () => {
|
test('Should update feature flag', async () => {
|
||||||
const url = '/api/admin/projects/default/features';
|
const url = '/api/admin/projects/default/features';
|
||||||
const name = 'new.toggle.update';
|
const name = 'new.flag.update';
|
||||||
await app.request
|
await app.request
|
||||||
.post(url)
|
.post(url)
|
||||||
.send({ name, description: 'some', type: 'release' })
|
.send({ name, description: 'some', type: 'release' })
|
||||||
@ -835,17 +835,17 @@ test('Should update feature toggle', async () => {
|
|||||||
.send({ name, description: 'updated', type: 'kill-switch' })
|
.send({ name, description: 'updated', type: 'kill-switch' })
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const { body: toggle } = await app.request.get(`${url}/${name}`);
|
const { body: flag } = await app.request.get(`${url}/${name}`);
|
||||||
|
|
||||||
expect(toggle.name).toBe(name);
|
expect(flag.name).toBe(name);
|
||||||
expect(toggle.description).toBe('updated');
|
expect(flag.description).toBe('updated');
|
||||||
expect(toggle.type).toBe('kill-switch');
|
expect(flag.type).toBe('kill-switch');
|
||||||
expect(toggle.archived).toBeFalsy();
|
expect(flag.archived).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Should not change name of feature toggle', async () => {
|
test('Should not change name of feature flag', async () => {
|
||||||
const url = '/api/admin/projects/default/features';
|
const url = '/api/admin/projects/default/features';
|
||||||
const name = 'new.toggle.update.2';
|
const name = 'new.flag.update.2';
|
||||||
await app.request
|
await app.request
|
||||||
.post(url)
|
.post(url)
|
||||||
.send({ name, description: 'some', type: 'release' })
|
.send({ name, description: 'some', type: 'release' })
|
||||||
@ -856,9 +856,9 @@ test('Should not change name of feature toggle', async () => {
|
|||||||
.expect(400);
|
.expect(400);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Should not change project of feature toggle even if it is part of body', async () => {
|
test('Should not change project of feature flag even if it is part of body', async () => {
|
||||||
const url = '/api/admin/projects/default/features';
|
const url = '/api/admin/projects/default/features';
|
||||||
const name = 'new.toggle.update.3';
|
const name = 'new.flag.update.3';
|
||||||
await app.request
|
await app.request
|
||||||
.post(url)
|
.post(url)
|
||||||
.send({ name, description: 'some', type: 'release' })
|
.send({ name, description: 'some', type: 'release' })
|
||||||
@ -876,9 +876,9 @@ test('Should not change project of feature toggle even if it is part of body', a
|
|||||||
expect(body.project).toBe('default');
|
expect(body.project).toBe('default');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Should patch feature toggle', async () => {
|
test('Should patch feature flag', async () => {
|
||||||
const url = '/api/admin/projects/default/features';
|
const url = '/api/admin/projects/default/features';
|
||||||
const name = 'new.toggle.patch';
|
const name = 'new.flag.patch';
|
||||||
await app.request
|
await app.request
|
||||||
.post(url)
|
.post(url)
|
||||||
.send({
|
.send({
|
||||||
@ -897,25 +897,25 @@ test('Should patch feature toggle', async () => {
|
|||||||
])
|
])
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const { body: toggle } = await app.request.get(`${url}/${name}`);
|
const { body: flag } = await app.request.get(`${url}/${name}`);
|
||||||
|
|
||||||
expect(toggle.name).toBe(name);
|
expect(flag.name).toBe(name);
|
||||||
expect(toggle.description).toBe('New desc');
|
expect(flag.description).toBe('New desc');
|
||||||
expect(toggle.type).toBe('kill-switch');
|
expect(flag.type).toBe('kill-switch');
|
||||||
expect(toggle.impressionData).toBe(false);
|
expect(flag.impressionData).toBe(false);
|
||||||
expect(toggle.archived).toBeFalsy();
|
expect(flag.archived).toBeFalsy();
|
||||||
const events = await db.stores.eventStore.getAll({
|
const events = await db.stores.eventStore.getAll({
|
||||||
type: FEATURE_METADATA_UPDATED,
|
type: FEATURE_METADATA_UPDATED,
|
||||||
});
|
});
|
||||||
const updateForOurToggle = events.find((e) => e.data.name === name);
|
const updateForOurFlag = events.find((e) => e.data.name === name);
|
||||||
expect(updateForOurToggle).toBeTruthy();
|
expect(updateForOurFlag).toBeTruthy();
|
||||||
expect(updateForOurToggle?.data.description).toBe('New desc');
|
expect(updateForOurFlag?.data.description).toBe('New desc');
|
||||||
expect(updateForOurToggle?.data.type).toBe('kill-switch');
|
expect(updateForOurFlag?.data.type).toBe('kill-switch');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Should patch feature toggle and not remove variants', async () => {
|
test('Should patch feature flag and not remove variants', async () => {
|
||||||
const url = '/api/admin/projects/default/features';
|
const url = '/api/admin/projects/default/features';
|
||||||
const name = 'new.toggle.variants';
|
const name = 'new.flag.variants';
|
||||||
await app.request
|
await app.request
|
||||||
.post(url)
|
.post(url)
|
||||||
.send({ name, description: 'some', type: 'release' })
|
.send({ name, description: 'some', type: 'release' })
|
||||||
@ -945,17 +945,17 @@ test('Should patch feature toggle and not remove variants', async () => {
|
|||||||
])
|
])
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const { body: toggle } = await app.request.get(`${url}/${name}`);
|
const { body: flag } = await app.request.get(`${url}/${name}`);
|
||||||
|
|
||||||
expect(toggle.name).toBe(name);
|
expect(flag.name).toBe(name);
|
||||||
expect(toggle.description).toBe('New desc');
|
expect(flag.description).toBe('New desc');
|
||||||
expect(toggle.type).toBe('kill-switch');
|
expect(flag.type).toBe('kill-switch');
|
||||||
expect(toggle.variants).toHaveLength(2);
|
expect(flag.variants).toHaveLength(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Patching feature toggles to stale should trigger FEATURE_STALE_ON event', async () => {
|
test('Patching feature flags to stale should trigger FEATURE_STALE_ON event', async () => {
|
||||||
const url = '/api/admin/projects/default/features';
|
const url = '/api/admin/projects/default/features';
|
||||||
const name = 'toggle.stale.on.patch';
|
const name = 'flag.stale.on.patch';
|
||||||
await app.request
|
await app.request
|
||||||
.post(url)
|
.post(url)
|
||||||
.send({ name, description: 'some', type: 'release', stale: false })
|
.send({ name, description: 'some', type: 'release', stale: false })
|
||||||
@ -965,21 +965,21 @@ test('Patching feature toggles to stale should trigger FEATURE_STALE_ON event',
|
|||||||
.send([{ op: 'replace', path: '/stale', value: true }])
|
.send([{ op: 'replace', path: '/stale', value: true }])
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const { body: toggle } = await app.request.get(`${url}/${name}`);
|
const { body: flag } = await app.request.get(`${url}/${name}`);
|
||||||
|
|
||||||
expect(toggle.name).toBe(name);
|
expect(flag.name).toBe(name);
|
||||||
expect(toggle.archived).toBeFalsy();
|
expect(flag.archived).toBeFalsy();
|
||||||
expect(toggle.stale).toBeTruthy();
|
expect(flag.stale).toBeTruthy();
|
||||||
const events = await db.stores.eventStore.getAll({
|
const events = await db.stores.eventStore.getAll({
|
||||||
type: FEATURE_STALE_ON,
|
type: FEATURE_STALE_ON,
|
||||||
});
|
});
|
||||||
const updateForOurToggle = events.find((e) => e.featureName === name);
|
const updateForOurFlag = events.find((e) => e.featureName === name);
|
||||||
expect(updateForOurToggle).toBeTruthy();
|
expect(updateForOurFlag).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Trying to patch variants on a feature toggle should trigger an OperationDeniedError', async () => {
|
test('Trying to patch variants on a feature flag should trigger an OperationDeniedError', async () => {
|
||||||
const url = '/api/admin/projects/default/features';
|
const url = '/api/admin/projects/default/features';
|
||||||
const name = 'toggle.variants.on.patch';
|
const name = 'flag.variants.on.patch';
|
||||||
await app.request
|
await app.request
|
||||||
.post(url)
|
.post(url)
|
||||||
.send({ name, description: 'some', type: 'release', stale: false });
|
.send({ name, description: 'some', type: 'release', stale: false });
|
||||||
@ -1008,9 +1008,9 @@ test('Trying to patch variants on a feature toggle should trigger an OperationDe
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Patching feature toggles to active (turning stale to false) should trigger FEATURE_STALE_OFF event', async () => {
|
test('Patching feature flags to active (turning stale to false) should trigger FEATURE_STALE_OFF event', async () => {
|
||||||
const url = '/api/admin/projects/default/features';
|
const url = '/api/admin/projects/default/features';
|
||||||
const name = 'toggle.stale.off.patch';
|
const name = 'flag.stale.off.patch';
|
||||||
await app.request
|
await app.request
|
||||||
.post(url)
|
.post(url)
|
||||||
.send({ name, description: 'some', type: 'release', stale: true })
|
.send({ name, description: 'some', type: 'release', stale: true })
|
||||||
@ -1020,21 +1020,21 @@ test('Patching feature toggles to active (turning stale to false) should trigger
|
|||||||
.send([{ op: 'replace', path: '/stale', value: false }])
|
.send([{ op: 'replace', path: '/stale', value: false }])
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const { body: toggle } = await app.request.get(`${url}/${name}`);
|
const { body: flag } = await app.request.get(`${url}/${name}`);
|
||||||
|
|
||||||
expect(toggle.name).toBe(name);
|
expect(flag.name).toBe(name);
|
||||||
expect(toggle.archived).toBeFalsy();
|
expect(flag.archived).toBeFalsy();
|
||||||
expect(toggle.stale).toBe(false);
|
expect(flag.stale).toBe(false);
|
||||||
const events = await db.stores.eventStore.getAll({
|
const events = await db.stores.eventStore.getAll({
|
||||||
type: FEATURE_STALE_OFF,
|
type: FEATURE_STALE_OFF,
|
||||||
});
|
});
|
||||||
const updateForOurToggle = events.find((e) => e.featureName === name);
|
const updateForOurFlag = events.find((e) => e.featureName === name);
|
||||||
expect(updateForOurToggle).toBeTruthy();
|
expect(updateForOurFlag).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Should archive feature toggle', async () => {
|
test('Should archive feature flag', async () => {
|
||||||
const url = '/api/admin/projects/default/features';
|
const url = '/api/admin/projects/default/features';
|
||||||
const name = 'new.toggle.archive';
|
const name = 'new.flag.archive';
|
||||||
await app.request
|
await app.request
|
||||||
.post(url)
|
.post(url)
|
||||||
.send({ name, description: 'some', type: 'release' })
|
.send({ name, description: 'some', type: 'release' })
|
||||||
@ -1046,13 +1046,13 @@ test('Should archive feature toggle', async () => {
|
|||||||
.get(`/api/admin/archive/features`)
|
.get(`/api/admin/archive/features`)
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const toggle = body.features.find((f) => f.name === name);
|
const flag = body.features.find((f) => f.name === name);
|
||||||
expect(toggle).toBeDefined();
|
expect(flag).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can add strategy to feature toggle to a "some-env-2"', async () => {
|
test('Can add strategy to feature flag to a "some-env-2"', async () => {
|
||||||
const envName = 'some-env-2';
|
const envName = 'some-env-2';
|
||||||
const featureName = 'feature.strategy.toggle';
|
const featureName = 'feature.strategy.flag';
|
||||||
// Create environment
|
// Create environment
|
||||||
await db.stores.environmentStore.create({
|
await db.stores.environmentStore.create({
|
||||||
name: envName,
|
name: envName,
|
||||||
@ -1084,13 +1084,13 @@ test('Can add strategy to feature toggle to a "some-env-2"', async () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can update strategy on feature toggle', async () => {
|
test('Can update strategy on feature flag', async () => {
|
||||||
const envName = 'default';
|
const envName = 'default';
|
||||||
const featureName = 'feature.strategy.update.strat';
|
const featureName = 'feature.strategy.update.strat';
|
||||||
const projectPath = '/api/admin/projects/default';
|
const projectPath = '/api/admin/projects/default';
|
||||||
const featurePath = `${projectPath}/features/${featureName}`;
|
const featurePath = `${projectPath}/features/${featureName}`;
|
||||||
|
|
||||||
// create feature toggle
|
// create feature flag
|
||||||
await app.request
|
await app.request
|
||||||
.post(`${projectPath}/features`)
|
.post(`${projectPath}/features`)
|
||||||
.send({ name: featureName })
|
.send({ name: featureName })
|
||||||
@ -1166,7 +1166,7 @@ test('Can NOT delete strategy with wrong projectId', async () => {
|
|||||||
const projectPath = '/api/admin/projects/default';
|
const projectPath = '/api/admin/projects/default';
|
||||||
const featurePath = `${projectPath}/features/${featureName}`;
|
const featurePath = `${projectPath}/features/${featureName}`;
|
||||||
|
|
||||||
// create feature toggle
|
// create feature flag
|
||||||
await app.request
|
await app.request
|
||||||
.post(`${projectPath}/features`)
|
.post(`${projectPath}/features`)
|
||||||
.send({ name: featureName })
|
.send({ name: featureName })
|
||||||
@ -1195,7 +1195,7 @@ test('add strategy cannot use wrong projectId', async () => {
|
|||||||
const envName = 'default';
|
const envName = 'default';
|
||||||
const featureName = 'feature.strategy.add.strat.wrong.projectId';
|
const featureName = 'feature.strategy.add.strat.wrong.projectId';
|
||||||
|
|
||||||
// create feature toggle
|
// create feature flag
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({ name: featureName })
|
.send({ name: featureName })
|
||||||
@ -1215,14 +1215,14 @@ test('add strategy cannot use wrong projectId', async () => {
|
|||||||
.expect(404);
|
.expect(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('update strategy on feature toggle cannot use wrong projectId', async () => {
|
test('update strategy on feature flag cannot use wrong projectId', async () => {
|
||||||
const envName = 'default';
|
const envName = 'default';
|
||||||
const featureName = 'feature.strategy.update.strat.wrong.projectId';
|
const featureName = 'feature.strategy.update.strat.wrong.projectId';
|
||||||
|
|
||||||
const projectPath = '/api/admin/projects/default';
|
const projectPath = '/api/admin/projects/default';
|
||||||
const featurePath = `${projectPath}/features/${featureName}`;
|
const featurePath = `${projectPath}/features/${featureName}`;
|
||||||
|
|
||||||
// create feature toggle
|
// create feature flag
|
||||||
await app.request
|
await app.request
|
||||||
.post(`${projectPath}/features`)
|
.post(`${projectPath}/features`)
|
||||||
.send({ name: featureName })
|
.send({ name: featureName })
|
||||||
@ -1256,7 +1256,7 @@ test('update strategy on feature toggle cannot use wrong projectId', async () =>
|
|||||||
test('Environments are returned in sortOrder', async () => {
|
test('Environments are returned in sortOrder', async () => {
|
||||||
const sortedSecond = 'sortedSecond';
|
const sortedSecond = 'sortedSecond';
|
||||||
const sortedLast = 'sortedLast';
|
const sortedLast = 'sortedLast';
|
||||||
const featureName = 'feature.strategy.toggle.sortOrder';
|
const featureName = 'feature.strategy.flag.sortOrder';
|
||||||
// Create environments
|
// Create environments
|
||||||
await db.stores.environmentStore.create({
|
await db.stores.environmentStore.create({
|
||||||
name: sortedLast,
|
name: sortedLast,
|
||||||
@ -1282,12 +1282,12 @@ test('Environments are returned in sortOrder', async () => {
|
|||||||
environment: sortedLast,
|
environment: sortedLast,
|
||||||
})
|
})
|
||||||
.expect(200);
|
.expect(200);
|
||||||
/* Create feature toggle */
|
/* Create feature flag */
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({ name: featureName })
|
.send({ name: featureName })
|
||||||
.expect(201);
|
.expect(201);
|
||||||
/* create strategies connected to feature toggle */
|
/* create strategies connected to feature flag */
|
||||||
await app.request
|
await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${featureName}/environments/${sortedSecond}/strategies`,
|
`/api/admin/projects/default/features/${featureName}/environments/${sortedSecond}/strategies`,
|
||||||
@ -1767,9 +1767,9 @@ test('Returns 400 when toggling environment of archived feature', async () => {
|
|||||||
.expect(400);
|
.expect(400);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can delete strategy from feature toggle', async () => {
|
test('Can delete strategy from feature flag', async () => {
|
||||||
const envName = 'del-strategy';
|
const envName = 'del-strategy';
|
||||||
const featureName = 'feature.strategy.toggle.delete.strategy';
|
const featureName = 'feature.strategy.flag.delete.strategy';
|
||||||
// Create environment
|
// Create environment
|
||||||
await db.stores.environmentStore.create({
|
await db.stores.environmentStore.create({
|
||||||
name: envName,
|
name: envName,
|
||||||
@ -2025,10 +2025,10 @@ test('Deleting strategy for feature environment should not disable that environm
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should clone feature toggle without strategies', async () => {
|
test('should clone feature flag without strategies', async () => {
|
||||||
const envName = 'some-env-3';
|
const envName = 'some-env-3';
|
||||||
const featureName = 'feature.toggle.base';
|
const featureName = 'feature.flag.base';
|
||||||
const cloneName = 'feature.toggle.clone';
|
const cloneName = 'feature.flag.clone';
|
||||||
const type = 'eExperiment';
|
const type = 'eExperiment';
|
||||||
const description = 'Lorem ipsum...';
|
const description = 'Lorem ipsum...';
|
||||||
|
|
||||||
@ -2064,10 +2064,10 @@ test('should clone feature toggle without strategies', async () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should clone feature toggle WITH strategies', async () => {
|
test('should clone feature flag WITH strategies', async () => {
|
||||||
const envName = 'some-env-4';
|
const envName = 'some-env-4';
|
||||||
const featureName = 'feature.toggle.base.2';
|
const featureName = 'feature.flag.base.2';
|
||||||
const cloneName = 'feature.toggle.clone.2';
|
const cloneName = 'feature.flag.clone.2';
|
||||||
const type = 'eExperiment';
|
const type = 'eExperiment';
|
||||||
const description = 'Lorem ipsum...';
|
const description = 'Lorem ipsum...';
|
||||||
|
|
||||||
@ -2119,10 +2119,10 @@ test('should clone feature toggle WITH strategies', async () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should clone feature toggle WITH variants', async () => {
|
test('should clone feature flag WITH variants', async () => {
|
||||||
const envName = 'some-env-5';
|
const envName = 'some-env-5';
|
||||||
const featureName = 'feature.toggle.base.3';
|
const featureName = 'feature.flag.base.3';
|
||||||
const cloneName = 'feature.toggle.clone.3';
|
const cloneName = 'feature.flag.clone.3';
|
||||||
const type = 'eExperiment';
|
const type = 'eExperiment';
|
||||||
const description = 'Lorem ipsum...';
|
const description = 'Lorem ipsum...';
|
||||||
const variants = [
|
const variants = [
|
||||||
@ -2172,10 +2172,10 @@ test('should clone feature toggle WITH variants', async () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should clone feature toggle without replacing groupId', async () => {
|
test('should clone feature flag without replacing groupId', async () => {
|
||||||
const envName = 'default';
|
const envName = 'default';
|
||||||
const featureName = 'feature.toggle.base.4';
|
const featureName = 'feature.flag.base.4';
|
||||||
const cloneName = 'feature.toggle.clone.4';
|
const cloneName = 'feature.flag.clone.4';
|
||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
@ -2207,9 +2207,9 @@ test('should clone feature toggle without replacing groupId', async () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should clone feature toggle WITHOUT createdAt field', async () => {
|
test('should clone feature flag WITHOUT createdAt field', async () => {
|
||||||
const featureName = 'feature.toggle.base.5';
|
const featureName = 'feature.flag.base.5';
|
||||||
const cloneName = 'feature.toggle.clone.5';
|
const cloneName = 'feature.flag.clone.5';
|
||||||
const type = 'eExperiment';
|
const type = 'eExperiment';
|
||||||
const description = 'Lorem ipsum...';
|
const description = 'Lorem ipsum...';
|
||||||
const originalCreatedAt = new Date(2011, 11, 11);
|
const originalCreatedAt = new Date(2011, 11, 11);
|
||||||
@ -2449,7 +2449,7 @@ test(`a feature's variants should be sorted by name in increasing order`, async
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should validate context when calling update with PUT', async () => {
|
test('should validate context when calling update with PUT', async () => {
|
||||||
const name = 'new.toggle.validate.context';
|
const name = 'new.flag.validate.context';
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({ name, description: 'some', type: 'release' })
|
.send({ name, description: 'some', type: 'release' })
|
||||||
@ -2465,7 +2465,7 @@ test('should validate context when calling update with PUT', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should validate context when calling update with PATCH', async () => {
|
test('should validate context when calling update with PATCH', async () => {
|
||||||
const name = 'new.toggle.validate.context2';
|
const name = 'new.flag.validate.context2';
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({ name, description: 'some', type: 'release' })
|
.send({ name, description: 'some', type: 'release' })
|
||||||
@ -2481,7 +2481,7 @@ test('should validate context when calling update with PATCH', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should not update project with PUT', async () => {
|
test('should not update project with PUT', async () => {
|
||||||
const name = 'new.toggle.validate.update.project.put';
|
const name = 'new.flag.validate.update.project.put';
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({ name, description: 'some', type: 'release' })
|
.send({ name, description: 'some', type: 'release' })
|
||||||
@ -2502,7 +2502,7 @@ test('should not update project with PUT', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should not update project with PATCH', async () => {
|
test('should not update project with PATCH', async () => {
|
||||||
const name = 'new.toggle.validate.update.project.patch';
|
const name = 'new.flag.validate.update.project.patch';
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({ name, description: 'some', type: 'release' })
|
.send({ name, description: 'some', type: 'release' })
|
||||||
@ -2521,7 +2521,7 @@ test('Can create a feature with impression data', async () => {
|
|||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({
|
.send({
|
||||||
name: 'new.toggle.with.impressionData',
|
name: 'new.flag.with.impressionData',
|
||||||
impressionData: true,
|
impressionData: true,
|
||||||
})
|
})
|
||||||
.expect(201)
|
.expect(201)
|
||||||
@ -2534,7 +2534,7 @@ test('Can create a feature without impression data', async () => {
|
|||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({
|
.send({
|
||||||
name: 'new.toggle.without.impressionData',
|
name: 'new.flag.without.impressionData',
|
||||||
})
|
})
|
||||||
.expect(201)
|
.expect(201)
|
||||||
.expect((res) => {
|
.expect((res) => {
|
||||||
@ -2543,28 +2543,28 @@ test('Can create a feature without impression data', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Can update impression data with PUT', async () => {
|
test('Can update impression data with PUT', async () => {
|
||||||
const toggle = {
|
const flag = {
|
||||||
name: 'update.toggle.with.impressionData',
|
name: 'update.flag.with.impressionData',
|
||||||
impressionData: true,
|
impressionData: true,
|
||||||
};
|
};
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send(toggle)
|
.send(flag)
|
||||||
.expect(201)
|
.expect(201)
|
||||||
.expect((res) => {
|
.expect((res) => {
|
||||||
expect(res.body.impressionData).toBe(true);
|
expect(res.body.impressionData).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.put(`/api/admin/projects/default/features/${toggle.name}`)
|
.put(`/api/admin/projects/default/features/${flag.name}`)
|
||||||
.send({ ...toggle, impressionData: false })
|
.send({ ...flag, impressionData: false })
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.expect((res) => {
|
.expect((res) => {
|
||||||
expect(res.body.impressionData).toBe(false);
|
expect(res.body.impressionData).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can create toggle with impression data on different project', async () => {
|
test('Can create flag with impression data on different project', async () => {
|
||||||
await db.stores.projectStore.create({
|
await db.stores.projectStore.create({
|
||||||
id: 'impression-data',
|
id: 'impression-data',
|
||||||
name: 'ImpressionData',
|
name: 'ImpressionData',
|
||||||
@ -2572,22 +2572,22 @@ test('Can create toggle with impression data on different project', async () =>
|
|||||||
mode: 'open',
|
mode: 'open',
|
||||||
});
|
});
|
||||||
|
|
||||||
const toggle = {
|
const flag = {
|
||||||
name: 'project.impression.data',
|
name: 'project.impression.data',
|
||||||
impressionData: true,
|
impressionData: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/impression-data/features')
|
.post('/api/admin/projects/impression-data/features')
|
||||||
.send(toggle)
|
.send(flag)
|
||||||
.expect(201)
|
.expect(201)
|
||||||
.expect((res) => {
|
.expect((res) => {
|
||||||
expect(res.body.impressionData).toBe(true);
|
expect(res.body.impressionData).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.put(`/api/admin/projects/impression-data/features/${toggle.name}`)
|
.put(`/api/admin/projects/impression-data/features/${flag.name}`)
|
||||||
.send({ ...toggle, impressionData: false })
|
.send({ ...flag, impressionData: false })
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.expect((res) => {
|
.expect((res) => {
|
||||||
expect(res.body.impressionData).toBe(false);
|
expect(res.body.impressionData).toBe(false);
|
||||||
@ -2676,7 +2676,7 @@ test('should reject invalid constraint values for multi-valued constraints', asy
|
|||||||
mode: 'open',
|
mode: 'open',
|
||||||
});
|
});
|
||||||
|
|
||||||
const toggle = await db.stores.featureToggleStore.create(project.id, {
|
const flag = await db.stores.featureToggleStore.create(project.id, {
|
||||||
name: uuidv4(),
|
name: uuidv4(),
|
||||||
impressionData: true,
|
impressionData: true,
|
||||||
createdByUserId: 9999,
|
createdByUserId: 9999,
|
||||||
@ -2687,7 +2687,7 @@ test('should reject invalid constraint values for multi-valued constraints', asy
|
|||||||
constraints: [{ contextName: 'userId', operator: 'IN', values }],
|
constraints: [{ contextName: 'userId', operator: 'IN', values }],
|
||||||
});
|
});
|
||||||
|
|
||||||
const featureStrategiesPath = `/api/admin/projects/${project.id}/features/${toggle.name}/environments/default/strategies`;
|
const featureStrategiesPath = `/api/admin/projects/${project.id}/features/${flag.name}/environments/default/strategies`;
|
||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.post(featureStrategiesPath)
|
.post(featureStrategiesPath)
|
||||||
@ -2724,7 +2724,7 @@ test('should add default constraint values for single-valued constraints', async
|
|||||||
mode: 'open',
|
mode: 'open',
|
||||||
});
|
});
|
||||||
|
|
||||||
const toggle = await db.stores.featureToggleStore.create(project.id, {
|
const flag = await db.stores.featureToggleStore.create(project.id, {
|
||||||
name: uuidv4(),
|
name: uuidv4(),
|
||||||
impressionData: true,
|
impressionData: true,
|
||||||
createdByUserId: 9999,
|
createdByUserId: 9999,
|
||||||
@ -2752,7 +2752,7 @@ test('should add default constraint values for single-valued constraints', async
|
|||||||
expect(res.body.constraints[0].values).toEqual(values);
|
expect(res.body.constraints[0].values).toEqual(values);
|
||||||
};
|
};
|
||||||
|
|
||||||
const featureStrategiesPath = `/api/admin/projects/${project.id}/features/${toggle.name}/environments/default/strategies`;
|
const featureStrategiesPath = `/api/admin/projects/${project.id}/features/${flag.name}/environments/default/strategies`;
|
||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.post(featureStrategiesPath)
|
.post(featureStrategiesPath)
|
||||||
@ -2785,7 +2785,7 @@ test('should allow long parameter values', async () => {
|
|||||||
mode: 'open',
|
mode: 'open',
|
||||||
});
|
});
|
||||||
|
|
||||||
const toggle = await db.stores.featureToggleStore.create(project.id, {
|
const flag = await db.stores.featureToggleStore.create(project.id, {
|
||||||
name: uuidv4(),
|
name: uuidv4(),
|
||||||
createdByUserId: 9999,
|
createdByUserId: 9999,
|
||||||
});
|
});
|
||||||
@ -2797,24 +2797,24 @@ test('should allow long parameter values', async () => {
|
|||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/${project.id}/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/${project.id}/features/${flag.name}/environments/default/strategies`,
|
||||||
)
|
)
|
||||||
.send(strategy)
|
.send(strategy)
|
||||||
.expect(200);
|
.expect(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should change strategy sort order when payload is valid', async () => {
|
test('should change strategy sort order when payload is valid', async () => {
|
||||||
const toggle = { name: uuidv4(), impressionData: false };
|
const flag = { name: uuidv4(), impressionData: false };
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({
|
.send({
|
||||||
name: toggle.name,
|
name: flag.name,
|
||||||
})
|
})
|
||||||
.expect(201);
|
.expect(201);
|
||||||
|
|
||||||
const { body: strategyOne } = await app.request
|
const { body: strategyOne } = await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
)
|
)
|
||||||
.send({
|
.send({
|
||||||
name: 'default',
|
name: 'default',
|
||||||
@ -2826,7 +2826,7 @@ test('should change strategy sort order when payload is valid', async () => {
|
|||||||
|
|
||||||
const { body: strategyTwo } = await app.request
|
const { body: strategyTwo } = await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
)
|
)
|
||||||
.send({
|
.send({
|
||||||
name: 'flexibleRollout',
|
name: 'flexibleRollout',
|
||||||
@ -2837,7 +2837,7 @@ test('should change strategy sort order when payload is valid', async () => {
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const { body: strategies } = await app.request.get(
|
const { body: strategies } = await app.request.get(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(strategies[0].sortOrder).toBe(0);
|
expect(strategies[0].sortOrder).toBe(0);
|
||||||
@ -2847,7 +2847,7 @@ test('should change strategy sort order when payload is valid', async () => {
|
|||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies/set-sort-order`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies/set-sort-order`,
|
||||||
)
|
)
|
||||||
.send([
|
.send([
|
||||||
{
|
{
|
||||||
@ -2862,7 +2862,7 @@ test('should change strategy sort order when payload is valid', async () => {
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const { body: strategiesOrdered } = await app.request.get(
|
const { body: strategiesOrdered } = await app.request.get(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(strategiesOrdered[0].sortOrder).toBe(1);
|
expect(strategiesOrdered[0].sortOrder).toBe(1);
|
||||||
@ -2872,11 +2872,11 @@ test('should change strategy sort order when payload is valid', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should reject set sort order request when payload is invalid', async () => {
|
test('should reject set sort order request when payload is invalid', async () => {
|
||||||
const toggle = { name: uuidv4(), impressionData: false };
|
const flag = { name: uuidv4(), impressionData: false };
|
||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies/set-sort-order`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies/set-sort-order`,
|
||||||
)
|
)
|
||||||
.send([
|
.send([
|
||||||
{
|
{
|
||||||
@ -2890,17 +2890,17 @@ test('should reject set sort order request when payload is invalid', async () =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should return strategies in correct order when new strategies are added', async () => {
|
test('should return strategies in correct order when new strategies are added', async () => {
|
||||||
const toggle = { name: uuidv4(), impressionData: false };
|
const flag = { name: uuidv4(), impressionData: false };
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({
|
.send({
|
||||||
name: toggle.name,
|
name: flag.name,
|
||||||
})
|
})
|
||||||
.expect(201);
|
.expect(201);
|
||||||
|
|
||||||
const { body: strategyOne } = await app.request
|
const { body: strategyOne } = await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
)
|
)
|
||||||
.send({
|
.send({
|
||||||
name: 'default',
|
name: 'default',
|
||||||
@ -2912,7 +2912,7 @@ test('should return strategies in correct order when new strategies are added',
|
|||||||
|
|
||||||
const { body: strategyTwo } = await app.request
|
const { body: strategyTwo } = await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
)
|
)
|
||||||
.send({
|
.send({
|
||||||
name: 'flexibleRollout',
|
name: 'flexibleRollout',
|
||||||
@ -2923,7 +2923,7 @@ test('should return strategies in correct order when new strategies are added',
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const { body: strategies } = await app.request.get(
|
const { body: strategies } = await app.request.get(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(strategies[0].sortOrder).toBe(0);
|
expect(strategies[0].sortOrder).toBe(0);
|
||||||
@ -2933,7 +2933,7 @@ test('should return strategies in correct order when new strategies are added',
|
|||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies/set-sort-order`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies/set-sort-order`,
|
||||||
)
|
)
|
||||||
.send([
|
.send([
|
||||||
{
|
{
|
||||||
@ -2949,7 +2949,7 @@ test('should return strategies in correct order when new strategies are added',
|
|||||||
|
|
||||||
const { body: strategyThree } = await app.request
|
const { body: strategyThree } = await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
)
|
)
|
||||||
.send({
|
.send({
|
||||||
name: 'flexibleRollout',
|
name: 'flexibleRollout',
|
||||||
@ -2961,7 +2961,7 @@ test('should return strategies in correct order when new strategies are added',
|
|||||||
|
|
||||||
const { body: strategyFour } = await app.request
|
const { body: strategyFour } = await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
)
|
)
|
||||||
.send({
|
.send({
|
||||||
name: 'flexibleRollout',
|
name: 'flexibleRollout',
|
||||||
@ -2972,7 +2972,7 @@ test('should return strategies in correct order when new strategies are added',
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const { body: strategiesOrdered } = await app.request.get(
|
const { body: strategiesOrdered } = await app.request.get(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(strategiesOrdered[0].sortOrder).toBe(1);
|
expect(strategiesOrdered[0].sortOrder).toBe(1);
|
||||||
@ -2984,7 +2984,7 @@ test('should return strategies in correct order when new strategies are added',
|
|||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies/set-sort-order`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies/set-sort-order`,
|
||||||
)
|
)
|
||||||
.send([
|
.send([
|
||||||
{
|
{
|
||||||
@ -2995,7 +2995,7 @@ test('should return strategies in correct order when new strategies are added',
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const { body: strategiesReOrdered } = await app.request.get(
|
const { body: strategiesReOrdered } = await app.request.get(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
);
|
);
|
||||||
|
|
||||||
// This block checks the order of the strategies retrieved from the endpoint. After partial update, the order should
|
// This block checks the order of the strategies retrieved from the endpoint. After partial update, the order should
|
||||||
@ -3239,17 +3239,17 @@ test('Should batch stale features', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should return disabled strategies', async () => {
|
test('should return disabled strategies', async () => {
|
||||||
const toggle = { name: uuidv4(), impressionData: false };
|
const flag = { name: uuidv4(), impressionData: false };
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({
|
.send({
|
||||||
name: toggle.name,
|
name: flag.name,
|
||||||
})
|
})
|
||||||
.expect(201);
|
.expect(201);
|
||||||
|
|
||||||
const { body: strategyOne } = await app.request
|
const { body: strategyOne } = await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
)
|
)
|
||||||
.send({
|
.send({
|
||||||
name: 'default',
|
name: 'default',
|
||||||
@ -3262,7 +3262,7 @@ test('should return disabled strategies', async () => {
|
|||||||
|
|
||||||
const { body: strategyTwo } = await app.request
|
const { body: strategyTwo } = await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
)
|
)
|
||||||
.send({
|
.send({
|
||||||
name: 'flexibleRollout',
|
name: 'flexibleRollout',
|
||||||
@ -3273,7 +3273,7 @@ test('should return disabled strategies', async () => {
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const { body: strategies } = await app.request.get(
|
const { body: strategies } = await app.request.get(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(strategies[0].id).toBe(strategyOne.id);
|
expect(strategies[0].id).toBe(strategyOne.id);
|
||||||
@ -3283,17 +3283,17 @@ test('should return disabled strategies', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should disable strategies in place', async () => {
|
test('should disable strategies in place', async () => {
|
||||||
const toggle = { name: uuidv4(), impressionData: false };
|
const flag = { name: uuidv4(), impressionData: false };
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/features')
|
.post('/api/admin/projects/default/features')
|
||||||
.send({
|
.send({
|
||||||
name: toggle.name,
|
name: flag.name,
|
||||||
})
|
})
|
||||||
.expect(201);
|
.expect(201);
|
||||||
|
|
||||||
const { body: strategyOne } = await app.request
|
const { body: strategyOne } = await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
)
|
)
|
||||||
.send({
|
.send({
|
||||||
name: 'flexibleRollout',
|
name: 'flexibleRollout',
|
||||||
@ -3307,7 +3307,7 @@ test('should disable strategies in place', async () => {
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const { body: strategies } = await app.request.get(
|
const { body: strategies } = await app.request.get(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(strategies[0].id).toBe(strategyOne.id);
|
expect(strategies[0].id).toBe(strategyOne.id);
|
||||||
@ -3315,7 +3315,7 @@ test('should disable strategies in place', async () => {
|
|||||||
|
|
||||||
const { body: updatedStrategyOne } = await app.request
|
const { body: updatedStrategyOne } = await app.request
|
||||||
.put(
|
.put(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies/${strategyOne.id}`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies/${strategyOne.id}`,
|
||||||
)
|
)
|
||||||
.send({
|
.send({
|
||||||
name: 'flexibleRollout',
|
name: 'flexibleRollout',
|
||||||
@ -3330,7 +3330,7 @@ test('should disable strategies in place', async () => {
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const { body: updatedStrategies } = await app.request.get(
|
const { body: updatedStrategies } = await app.request.get(
|
||||||
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
`/api/admin/projects/default/features/${flag.name}/environments/default/strategies`,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(updatedStrategies[0].id).toBe(updatedStrategyOne.id);
|
expect(updatedStrategies[0].id).toBe(updatedStrategyOne.id);
|
||||||
|
Loading…
Reference in New Issue
Block a user