1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-19 01:17:18 +02:00

chore: remove playgroundImprovements flag (#5384)

Closes #:

[1-1647](https://linear.app/unleash/issue/1-1647/clean-playgroundimprovements-flag-for-release)

[1-1665](https://linear.app/unleash/issue/1-1665/flaky-test-playgroundconnectionfieldsettesttsx)

---------

Signed-off-by: andreas-unleash <andreas@getunleash.ai>
This commit is contained in:
andreas-unleash 2023-11-23 10:50:19 +02:00 committed by GitHub
parent 3e12c2b5b6
commit 1dafc85eaa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 116 additions and 130 deletions

View File

@ -7,26 +7,43 @@ import { useState } from 'react';
const server = testServerSetup(); const server = testServerSetup();
beforeEach(() => { beforeEach(() => {
testServerRoute(server, '/API/admin/ui-config', { testServerRoute(server, '/api/admin/ui-config', {
versionInfo: { versionInfo: {
current: { oss: 'version', enterprise: 'version' }, current: { oss: 'version', enterprise: 'version' },
}, },
flags: {
playgroundImprovements: true,
},
}); });
testServerRoute( testServerRoute(
server, server,
'/API/admin/projects', '/api/admin/projects',
{ {
version: 1,
projects: [ projects: [
{ {
id: 'default',
name: 'Default', name: 'Default',
id: 'default',
description: 'Default project',
health: 100,
favorite: false,
featureCount: 0,
memberCount: 0,
updatedAt: '2023-11-21T15:50:57.035Z',
createdAt: '2023-11-10T09:52:14.898Z',
mode: 'open',
defaultStickiness: 'default',
}, },
{ {
id: 'MyProject',
name: 'MyProject', name: 'MyProject',
id: 'MyProject',
description: '',
health: 100,
favorite: false,
featureCount: 1,
memberCount: 1,
updatedAt: '2023-11-21T15:50:57.037Z',
createdAt: '2023-11-10T09:52:52.169Z',
mode: 'open',
defaultStickiness: 'sessionId',
}, },
], ],
}, },
@ -35,7 +52,7 @@ beforeEach(() => {
); );
testServerRoute( testServerRoute(
server, server,
'/API/admin/API-tokens', '/api/admin/api-tokens',
{ {
tokens: [ tokens: [
{ {
@ -69,8 +86,18 @@ const Component = () => {
); );
}; };
test('should parse project and environment from token input', async () => { const timeoutInMilliseconds = 10000;
render(<Component />);
test(
'should parse project and environment from token input',
async () => {
const { container } = render(<Component />);
const projectAutocomplete = await screen.findByTestId(
'PLAYGROUND_PROJECT_SELECT',
);
const button = await within(projectAutocomplete).findByRole('button');
fireEvent.click(button);
await within(container).findByText('Default');
const tokenInput = await screen.findByLabelText('API token'); const tokenInput = await screen.findByLabelText('API token');
fireEvent.change(tokenInput, { fireEvent.change(tokenInput, {
@ -79,9 +106,6 @@ test('should parse project and environment from token input', async () => {
}, },
}); });
const projectAutocomplete = await screen.findByTestId(
'PLAYGROUND_PROJECT_SELECT',
);
const projectInput = within(projectAutocomplete).getByRole('combobox'); const projectInput = within(projectAutocomplete).getByRole('combobox');
const environmentAutocomplete = await screen.findByTestId( const environmentAutocomplete = await screen.findByTestId(
@ -95,19 +119,24 @@ test('should parse project and environment from token input', async () => {
expect(environmentInput).toBeDisabled(); expect(environmentInput).toBeDisabled();
await within(projectAutocomplete).findByText('Default'); await within(projectAutocomplete).findByText('Default');
await within(environmentAutocomplete).findByText('development'); await within(environmentAutocomplete).findByText('development');
}); },
timeoutInMilliseconds,
);
test('should load projects from token definition if project is []', async () => { test('should load projects from token definition if project is []', async () => {
render(<Component />); const { container } = render(<Component />);
const projectAutocomplete = await screen.findByTestId(
'PLAYGROUND_PROJECT_SELECT',
);
const button = await within(projectAutocomplete).findByRole('button');
fireEvent.click(button);
await within(container).findByText('Default');
const tokenInput = await screen.findByLabelText('API token'); const tokenInput = await screen.findByLabelText('API token');
fireEvent.change(tokenInput, { fireEvent.change(tokenInput, {
target: { value: '[]:development.964a287e1b728cb5f4f3e0120df92cb5' }, target: { value: '[]:development.964a287e1b728cb5f4f3e0120df92cb5' },
}); });
const projectAutocomplete = await screen.findByTestId(
'PLAYGROUND_PROJECT_SELECT',
);
const projectInput = within(projectAutocomplete).getByRole('combobox'); const projectInput = within(projectAutocomplete).getByRole('combobox');
const environmentAutocomplete = await screen.findByTestId( const environmentAutocomplete = await screen.findByTestId(
@ -125,16 +154,19 @@ test('should load projects from token definition if project is []', async () =>
}); });
test('should show an error when admin token', async () => { test('should show an error when admin token', async () => {
render(<Component />); const { container } = render(<Component />);
const projectAutocomplete = await screen.findByTestId(
'PLAYGROUND_PROJECT_SELECT',
);
const button = await within(projectAutocomplete).findByRole('button');
fireEvent.click(button);
await within(container).findByText('Default');
const tokenInput = await screen.findByLabelText('API token'); const tokenInput = await screen.findByLabelText('API token');
fireEvent.change(tokenInput, { fireEvent.change(tokenInput, {
target: { value: '*:*.964a287e1b728cb5f4f3e0120df92cb5' }, target: { value: '*:*.964a287e1b728cb5f4f3e0120df92cb5' },
}); });
const projectAutocomplete = await screen.findByTestId(
'PLAYGROUND_PROJECT_SELECT',
);
const projectInput = within(projectAutocomplete).getByRole('combobox'); const projectInput = within(projectAutocomplete).getByRole('combobox');
const environmentAutocomplete = await screen.findByTestId( const environmentAutocomplete = await screen.findByTestId(
@ -150,7 +182,13 @@ test('should show an error when admin token', async () => {
}); });
test('should have a working clear button when token is filled', async () => { test('should have a working clear button when token is filled', async () => {
render(<Component />); const { container } = render(<Component />);
const projectAutocomplete = await screen.findByTestId(
'PLAYGROUND_PROJECT_SELECT',
);
const button = await within(projectAutocomplete).findByRole('button');
fireEvent.click(button);
await within(container).findByText('Default');
const tokenInput = await screen.findByLabelText('API token'); const tokenInput = await screen.findByLabelText('API token');
fireEvent.change(tokenInput, { fireEvent.change(tokenInput, {
@ -160,8 +198,8 @@ test('should have a working clear button when token is filled', async () => {
}); });
const clear = await screen.findByTestId('TOKEN_INPUT_CLEAR_BTN'); const clear = await screen.findByTestId('TOKEN_INPUT_CLEAR_BTN');
const button = within(clear).getByRole('button'); const clearButton = within(clear).getByRole('button');
fireEvent.click(button); fireEvent.click(clearButton);
expect(tokenInput).toHaveValue(''); expect(tokenInput).toHaveValue('');
}); });

View File

@ -58,11 +58,11 @@ export const PlaygroundConnectionFieldset: VFC<
availableEnvironments, availableEnvironments,
}) => { }) => {
const theme = useTheme(); const theme = useTheme();
const playgroundImprovements = useUiFlag('playgroundImprovements');
const { tokens } = useApiTokens(); const { tokens } = useApiTokens();
const [tokenError, setTokenError] = useState<string | undefined>(); const [tokenError, setTokenError] = useState<string | undefined>();
const { projects: availableProjects = [] } = useProjects(); const { projects: availableProjects } = useProjects();
const projectsOptions = [ const projectsOptions = [
allOption, allOption,
...availableProjects.map(({ name: label, id }) => ({ ...availableProjects.map(({ name: label, id }) => ({
@ -155,7 +155,6 @@ export const PlaygroundConnectionFieldset: VFC<
const [tokenProject, tokenEnvironment] = const [tokenProject, tokenEnvironment] =
extractProjectEnvironmentFromToken(tempToken); extractProjectEnvironmentFromToken(tempToken);
setEnvironments([tokenEnvironment]); setEnvironments([tokenEnvironment]);
switch (tokenProject) { switch (tokenProject) {
case '[]': case '[]':
handleTokenWithSomeProjects(tempToken); handleTokenWithSomeProjects(tempToken);
@ -301,9 +300,6 @@ export const PlaygroundConnectionFieldset: VFC<
/> />
</Tooltip> </Tooltip>
</Box> </Box>
<ConditionallyRender
condition={Boolean(playgroundImprovements)}
show={
<Input <Input
sx={{ mt: 2, width: '50%', pr: 1 }} sx={{ mt: 2, width: '50%', pr: 1 }}
label='API token' label='API token'
@ -318,8 +314,6 @@ export const PlaygroundConnectionFieldset: VFC<
endAdornment: token ? renderClearButton() : null, endAdornment: token ? renderClearButton() : null,
}} }}
/> />
}
/>
</Box> </Box>
); );
}; };

View File

@ -16,7 +16,6 @@ export const PlaygroundResultFeatureStrategyList = ({
feature, feature,
input, input,
}: PlaygroundResultFeatureStrategyListProps) => { }: PlaygroundResultFeatureStrategyListProps) => {
const playgroundImprovements = useUiFlag('playgroundImprovements');
const enabledStrategies = feature.strategies?.data?.filter( const enabledStrategies = feature.strategies?.data?.filter(
(strategy) => !strategy.disabled, (strategy) => !strategy.disabled,
); );
@ -24,8 +23,7 @@ export const PlaygroundResultFeatureStrategyList = ({
(strategy) => strategy.disabled, (strategy) => strategy.disabled,
); );
const showDisabledStrategies = const showDisabledStrategies = disabledStrategies?.length > 0;
playgroundImprovements && disabledStrategies?.length > 0;
return ( return (
<> <>

View File

@ -110,7 +110,6 @@ export const WrappedPlaygroundResultStrategyList = ({
feature, feature,
input, input,
}: IWrappedPlaygroundResultStrategyListProps) => { }: IWrappedPlaygroundResultStrategyListProps) => {
const playgroundImprovements = useUiFlag('playgroundImprovements');
const enabledStrategies = feature.strategies?.data?.filter( const enabledStrategies = feature.strategies?.data?.filter(
(strategy) => !strategy.disabled, (strategy) => !strategy.disabled,
); );
@ -118,8 +117,7 @@ export const WrappedPlaygroundResultStrategyList = ({
(strategy) => strategy.disabled, (strategy) => strategy.disabled,
); );
const showDisabledStrategies = const showDisabledStrategies = disabledStrategies?.length > 0;
playgroundImprovements && disabledStrategies?.length > 0;
return ( return (
<StyledAlertWrapper sx={{ pb: 1, mt: 2 }}> <StyledAlertWrapper sx={{ pb: 1, mt: 2 }}>

View File

@ -65,7 +65,6 @@ export type UiFlags = {
privateProjects?: boolean; privateProjects?: boolean;
dependentFeatures?: boolean; dependentFeatures?: boolean;
banners?: boolean; banners?: boolean;
playgroundImprovements?: boolean;
scheduledConfigurationChanges?: boolean; scheduledConfigurationChanges?: boolean;
featureSearchAPI?: boolean; featureSearchAPI?: boolean;
featureSearchFrontend?: boolean; featureSearchFrontend?: boolean;

View File

@ -23,7 +23,9 @@ export const render = (
const Wrapper: FC = ({ children }) => ( const Wrapper: FC = ({ children }) => (
<UIProviderContainer> <UIProviderContainer>
<SWRConfig value={{ provider: () => new Map() }}> <SWRConfig
value={{ provider: () => new Map(), dedupingInterval: 0 }}
>
<AccessProviderMock permissions={permissions}> <AccessProviderMock permissions={permissions}>
<ThemeProvider> <ThemeProvider>
<AnnouncerProvider> <AnnouncerProvider>

View File

@ -98,7 +98,6 @@ exports[`should create default config 1`] = `
}, },
"migrationLock": true, "migrationLock": true,
"personalAccessTokensKillSwitch": false, "personalAccessTokensKillSwitch": false,
"playgroundImprovements": false,
"privateProjects": false, "privateProjects": false,
"proPlanAutoCharge": false, "proPlanAutoCharge": false,
"responseTimeWithAppNameKillSwitch": false, "responseTimeWithAppNameKillSwitch": false,

View File

@ -99,9 +99,7 @@ export class FeatureToggleRowConverter {
}; };
rowToStrategy = (row: Record<string, any>): IStrategyConfig => { rowToStrategy = (row: Record<string, any>): IStrategyConfig => {
let strategy: IStrategyConfig; return {
if (this.flagResolver.isEnabled('playgroundImprovements')) {
strategy = {
id: row.strategy_id, id: row.strategy_id,
name: row.strategy_name, name: row.strategy_name,
title: row.strategy_title, title: row.strategy_title,
@ -109,19 +107,8 @@ export class FeatureToggleRowConverter {
parameters: mapValues(row.parameters || {}, ensureStringValue), parameters: mapValues(row.parameters || {}, ensureStringValue),
sortOrder: row.sort_order, sortOrder: row.sort_order,
disabled: row.strategy_disabled, disabled: row.strategy_disabled,
variants: row.strategy_variants || [],
}; };
} else {
strategy = {
id: row.strategy_id,
name: row.strategy_name,
constraints: row.constraints || [],
parameters: mapValues(row.parameters || {}, ensureStringValue),
sortOrder: row.sort_order,
};
}
strategy.variants = row.strategy_variants || [];
return strategy;
}; };
addTag = (feature: Record<string, any>, row: Record<string, any>): void => { addTag = (feature: Record<string, any>, row: Record<string, any>): void => {
@ -160,7 +147,6 @@ export class FeatureToggleRowConverter {
row: any, row: any,
feature: PartialDeep<IFeatureToggleClient>, feature: PartialDeep<IFeatureToggleClient>,
featureQuery?: IFeatureToggleQuery, featureQuery?: IFeatureToggleQuery,
includeDisabledStrategies?: boolean,
) => { ) => {
feature.impressionData = row.impression_data; feature.impressionData = row.impression_data;
feature.enabled = !!row.enabled; feature.enabled = !!row.enabled;
@ -173,10 +159,7 @@ export class FeatureToggleRowConverter {
feature.variants = row.variants || []; feature.variants = row.variants || [];
feature.project = row.project; feature.project = row.project;
if ( if (this.isUnseenStrategyRow(feature, row)) {
this.isUnseenStrategyRow(feature, row) &&
(includeDisabledStrategies ? true : !row.strategy_disabled)
) {
feature.strategies?.push(this.rowToStrategy(row)); feature.strategies?.push(this.rowToStrategy(row));
} }
if (this.isNewTag(feature, row)) { if (this.isNewTag(feature, row)) {
@ -201,12 +184,7 @@ export class FeatureToggleRowConverter {
strategies: [], strategies: [],
}; };
feature = this.createBaseFeature( feature = this.createBaseFeature(r, feature, featureQuery);
r,
feature,
featureQuery,
includeDisabledStrategies,
);
feature.createdAt = r.created_at; feature.createdAt = r.created_at;
feature.favorite = r.favorite; feature.favorite = r.favorite;
@ -225,7 +203,6 @@ export class FeatureToggleRowConverter {
buildPlaygroundFeaturesFromRows = ( buildPlaygroundFeaturesFromRows = (
rows: any[], rows: any[],
dependentFeaturesEnabled: boolean, dependentFeaturesEnabled: boolean,
includeDisabledStrategies: boolean,
featureQuery?: IFeatureToggleQuery, featureQuery?: IFeatureToggleQuery,
): FeatureConfigurationClient[] => { ): FeatureConfigurationClient[] => {
const result = rows.reduce((acc, r) => { const result = rows.reduce((acc, r) => {
@ -233,12 +210,7 @@ export class FeatureToggleRowConverter {
strategies: [], strategies: [],
}; };
feature = this.createBaseFeature( feature = this.createBaseFeature(r, feature, featureQuery);
r,
feature,
featureQuery,
includeDisabledStrategies,
);
if (r.parent && dependentFeaturesEnabled) { if (r.parent && dependentFeaturesEnabled) {
feature.dependencies = feature.dependencies || []; feature.dependencies = feature.dependencies || [];

View File

@ -211,9 +211,6 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
const dependentFeaturesEnabled = const dependentFeaturesEnabled =
this.flagResolver.isEnabled('dependentFeatures'); this.flagResolver.isEnabled('dependentFeatures');
const includeDisabledStrategies = this.flagResolver.isEnabled(
'playgroundImprovements',
);
if (dependentFeaturesEnabled) { if (dependentFeaturesEnabled) {
builder.withDependentFeatureToggles(); builder.withDependentFeatureToggles();
@ -234,7 +231,6 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
return this.featureToggleRowConverter.buildPlaygroundFeaturesFromRows( return this.featureToggleRowConverter.buildPlaygroundFeaturesFromRows(
rows, rows,
dependentFeaturesEnabled, dependentFeaturesEnabled,
includeDisabledStrategies,
featureQuery, featureQuery,
); );
} }

View File

@ -37,11 +37,7 @@ const mockConstraints = (): IConstraint[] => {
const irrelevantDate = new Date(); const irrelevantDate = new Date();
beforeAll(async () => { beforeAll(async () => {
const config = createTestConfig({ const config = createTestConfig();
experimental: {
flags: { playgroundImprovements: true },
},
});
db = await dbInit( db = await dbInit(
'feature_toggle_service_v2_service_serial', 'feature_toggle_service_v2_service_serial',
config.getLogger, config.getLogger,

View File

@ -12,7 +12,7 @@ let db: ITestDb;
beforeAll(async () => { beforeAll(async () => {
db = await dbInit('advanced_playground', getLogger, { db = await dbInit('advanced_playground', getLogger, {
experimental: { experimental: {
flags: { dependentFeatures: true, playgroundImprovements: true }, flags: { dependentFeatures: true },
}, },
}); });
app = await setupAppWithCustomConfig( app = await setupAppWithCustomConfig(
@ -25,7 +25,6 @@ beforeAll(async () => {
strategyVariant: true, strategyVariant: true,
privateProjects: true, privateProjects: true,
dependentFeatures: true, dependentFeatures: true,
playgroundImprovements: true,
useLastSeenRefactor: true, useLastSeenRefactor: true,
}, },
}, },

View File

@ -28,7 +28,6 @@ export type IFlagKey =
| 'disableMetrics' | 'disableMetrics'
| 'useLastSeenRefactor' | 'useLastSeenRefactor'
| 'banners' | 'banners'
| 'playgroundImprovements'
| 'featureSearchAPI' | 'featureSearchAPI'
| 'featureSearchFrontend' | 'featureSearchFrontend'
| 'scheduledConfigurationChanges' | 'scheduledConfigurationChanges'
@ -128,10 +127,6 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_USE_LAST_SEEN_REFACTOR, process.env.UNLEASH_EXPERIMENTAL_USE_LAST_SEEN_REFACTOR,
false, false,
), ),
playgroundImprovements: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_PLAYGROUND_IMPROVEMENTS,
false,
),
featureSearchAPI: parseEnvVarBoolean( featureSearchAPI: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_FEATURE_SEARCH_API, process.env.UNLEASH_EXPERIMENTAL_FEATURE_SEARCH_API,
false, false,