1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-12-09 20:04:11 +01:00
unleash.unleash/frontend/src/component/feature/FeatureStrategy/FeatureStrategyCreate/FeatureStrategyCreate.test.tsx
Jaanus Sellin 3acb3ad2c2
feat: upgrade from react v17 to v18 (#7265)
**Upgrade to React v18 for Unleash v6. Here's why I think it's a good
time to do it:**
- Command Bar project: We've begun work on the command bar project, and
there's a fantastic library we want to use. However, it requires React
v18 support.
- Straightforward Upgrade: I took a look at the upgrade guide
https://react.dev/blog/2022/03/08/react-18-upgrade-guide and it seems
fairly straightforward. In fact, I was able to get React v18 running
with minimal changes in just 10 minutes!
- Dropping IE Support: React v18 no longer supports Internet Explorer
(IE), which is no longer supported by Microsoft as of June 15, 2022.
Upgrading to v18 in v6 would be a good way to align with this change.

TS updates:
* FC children has to be explicit:
https://stackoverflow.com/questions/71788254/react-18-typescript-children-fc
* forcing version 18 types in resolutions:
https://sentry.io/answers/type-is-not-assignable-to-type-reactnode/

Test updates:
* fixing SWR issue that we have always had but it manifests more in new
React (https://github.com/vercel/swr/issues/2373)

---------

Co-authored-by: kwasniew <kwasniewski.mateusz@gmail.com>
2024-06-11 13:59:52 +03:00

449 lines
15 KiB
TypeScript

import { formatAddStrategyApiCode } from 'component/feature/FeatureStrategy/FeatureStrategyCreate/FeatureStrategyCreate';
import { screen, fireEvent, waitFor } from '@testing-library/react';
import { render } from 'utils/testRenderer';
import { Route, Routes } from 'react-router-dom';
import {
CREATE_FEATURE_STRATEGY,
UPDATE_FEATURE_ENVIRONMENT_VARIANTS,
UPDATE_FEATURE_STRATEGY,
} from 'component/providers/AccessProvider/permissions';
import { FeatureStrategyCreate } from './FeatureStrategyCreate';
import {
setupProjectEndpoint,
setupSegmentsEndpoint,
setupStrategyEndpoint,
setupFeaturesEndpoint,
setupUiConfigEndpoint,
setupContextEndpoint,
} from './featureStrategyFormTestSetup';
const featureName = 'my-new-feature';
const setupComponent = () => {
return {
wrapper: render(
<Routes>
<Route
path={
'/projects/:projectId/features/:featureId/strategies/create'
}
element={<FeatureStrategyCreate />}
/>
</Routes>,
{
route: `/projects/default/features/${featureName}/strategies/create?environmentId=development&strategyName=flexibleRollout&defaultStrategy=true`,
permissions: [
{
permission: CREATE_FEATURE_STRATEGY,
project: 'default',
environment: 'development',
},
{
permission: UPDATE_FEATURE_STRATEGY,
project: 'default',
environment: 'development',
},
{
permission: UPDATE_FEATURE_ENVIRONMENT_VARIANTS,
project: 'default',
environment: 'development',
},
],
},
),
expectedSegmentName: 'test',
expectedGroupId: 'newGroupId',
expectedVariantName: 'Blue',
expectedSliderValue: '50',
expectedConstraintValue: 'new value',
expectedMultipleValues: '1234,4141,51515',
};
};
beforeEach(() => {
setupProjectEndpoint();
setupSegmentsEndpoint();
setupStrategyEndpoint();
setupFeaturesEndpoint(featureName);
setupUiConfigEndpoint();
setupContextEndpoint();
});
describe('NewFeatureStrategyCreate', () => {
test('formatAddStrategyApiCode', () => {
expect(
formatAddStrategyApiCode(
'projectId',
'featureId',
'environmentId',
{ id: 'strategyId' },
'unleashUrl',
),
).toMatchInlineSnapshot(`
"curl --location --request POST 'unleashUrl/api/admin/projects/projectId/features/featureId/environments/environmentId/strategies' \\
--header 'Authorization: INSERT_API_KEY' \\
--header 'Content-Type: application/json' \\
--data-raw '{
"id": "strategyId"
}'"
`);
});
test('should navigate tabs', async () => {
setupComponent();
const titleEl = await screen.findByText('Gradual rollout');
expect(titleEl).toBeInTheDocument();
const slider = await screen.findByRole('slider', { name: /rollout/i });
expect(slider).toHaveValue('100');
const targetingEl = screen.getByText('Targeting');
fireEvent.click(targetingEl);
const segmentsEl = await screen.findByText('Segments');
expect(segmentsEl).toBeInTheDocument();
const variantEl = screen.getByText('Variants');
fireEvent.click(variantEl);
const addVariantEl = await screen.findByText('Add variant');
expect(addVariantEl).toBeInTheDocument();
});
test('should change general settings', async () => {
const { expectedGroupId, expectedSliderValue } = setupComponent();
const titleEl = await screen.findByText('Gradual rollout');
expect(titleEl).toBeInTheDocument();
const slider = await screen.findByRole('slider', { name: /rollout/i });
const groupIdInput = await screen.findByLabelText('groupId');
expect(slider).toHaveValue('100');
expect(groupIdInput).toHaveValue(featureName);
fireEvent.change(slider, { target: { value: expectedSliderValue } });
fireEvent.change(groupIdInput, { target: { value: expectedGroupId } });
expect(slider).toHaveValue(expectedSliderValue);
expect(groupIdInput).toHaveValue(expectedGroupId);
});
test('should change targeting settings', async () => {
const { expectedConstraintValue, expectedSegmentName } =
setupComponent();
const titleEl = await screen.findByText('Gradual rollout');
expect(titleEl).toBeInTheDocument();
const targetingEl = screen.getByText('Targeting');
fireEvent.click(targetingEl);
const addConstraintEl = await screen.findByText('Add constraint');
fireEvent.click(addConstraintEl);
const inputElement = screen.getByPlaceholderText(
'value1, value2, value3...',
);
fireEvent.change(inputElement, {
target: { value: expectedConstraintValue },
});
const addValueEl = screen.getByText('Add values');
fireEvent.click(addValueEl);
const doneEl = screen.getByText('Done');
fireEvent.click(doneEl);
const selectElement = screen.getByPlaceholderText('Select segments');
fireEvent.mouseDown(selectElement);
const optionElement = await screen.findByText(expectedSegmentName);
fireEvent.click(optionElement);
expect(screen.getByText(expectedSegmentName)).toBeInTheDocument();
expect(screen.getByText(expectedConstraintValue)).toBeInTheDocument();
});
test('should change variants settings', async () => {
const { expectedVariantName } = setupComponent();
const titleEl = await screen.findByText('Gradual rollout');
expect(titleEl).toBeInTheDocument();
const variantsEl = screen.getByText('Variants');
fireEvent.click(variantsEl);
const addVariantEl = await screen.findByText('Add variant');
fireEvent.click(addVariantEl);
const inputElement = screen.getAllByRole('textbox')[0];
fireEvent.change(inputElement, {
target: { value: expectedVariantName },
});
expect(screen.getByText(expectedVariantName)).toBeInTheDocument();
const generalSettingsEl = screen.getByText('General');
fireEvent.click(generalSettingsEl);
await waitFor(() => {
const codeSnippet = document.querySelector('pre')?.innerHTML;
const variantNameMatches = (
codeSnippet!.match(new RegExp(expectedVariantName, 'g')) || []
).length;
const metaDataMatches = (codeSnippet!.match(/isValid/g) || [])
.length;
expect(variantNameMatches).toBe(1);
expect(metaDataMatches).toBe(0);
});
});
test('should change variant name after changing tab', async () => {
const { expectedVariantName } = setupComponent();
const titleEl = await screen.findByText('Gradual rollout');
expect(titleEl).toBeInTheDocument();
const variantsEl = screen.getByText('Variants');
fireEvent.click(variantsEl);
const addVariantEl = await screen.findByText('Add variant');
fireEvent.click(addVariantEl);
const inputElement = screen.getAllByRole('textbox')[0];
fireEvent.change(inputElement, {
target: { value: expectedVariantName },
});
const targetingEl = await screen.findByText('Targeting');
fireEvent.click(targetingEl);
const addConstraintEl = await screen.findByText('Add constraint');
expect(addConstraintEl).toBeInTheDocument();
fireEvent.click(variantsEl);
const inputElement2 = screen.getAllByRole('textbox')[0];
expect(inputElement2).not.toBeDisabled();
});
test('should remove empty variants when changing tabs', async () => {
setupComponent();
const titleEl = await screen.findByText('Gradual rollout');
expect(titleEl).toBeInTheDocument();
const variantsEl = screen.getByText('Variants');
fireEvent.click(variantsEl);
const addVariantEl = await screen.findByText('Add variant');
fireEvent.click(addVariantEl);
const variants = screen.queryAllByTestId('VARIANT');
expect(variants.length).toBe(1);
const targetingEl = await screen.findByText('Targeting');
fireEvent.click(targetingEl);
const addConstraintEl = await screen.findByText('Add constraint');
expect(addConstraintEl).toBeInTheDocument();
fireEvent.click(variantsEl);
const variants2 = screen.queryAllByTestId('VARIANT');
expect(variants2.length).toBe(0);
});
test('Should autosave constraint settings when navigating between tabs', async () => {
const { expectedMultipleValues } = setupComponent();
const titleEl = await screen.findByText('Gradual rollout');
expect(titleEl).toBeInTheDocument();
const targetingEl = screen.getByText('Targeting');
fireEvent.click(targetingEl);
const addConstraintEl = await screen.findByText('Add constraint');
fireEvent.click(addConstraintEl);
const inputElement = screen.getByPlaceholderText(
'value1, value2, value3...',
);
fireEvent.change(inputElement, {
target: { value: expectedMultipleValues },
});
const addValueEl = await screen.findByText('Add values');
fireEvent.click(addValueEl);
const variantsEl = screen.getByText('Variants');
fireEvent.click(variantsEl);
fireEvent.click(targetingEl);
const values = expectedMultipleValues.split(',');
expect(screen.getByText(values[0])).toBeInTheDocument();
expect(screen.getByText(values[1])).toBeInTheDocument();
expect(screen.getByText(values[2])).toBeInTheDocument();
});
test('Should update multiple constraints correctly', async () => {
setupComponent();
const titleEl = await screen.findByText('Gradual rollout');
expect(titleEl).toBeInTheDocument();
const targetingEl = screen.getByText('Targeting');
fireEvent.click(targetingEl);
const addConstraintEl = await screen.findByText('Add constraint');
fireEvent.click(addConstraintEl);
fireEvent.click(addConstraintEl);
fireEvent.click(addConstraintEl);
const inputElements = screen.getAllByPlaceholderText(
'value1, value2, value3...',
);
fireEvent.change(inputElements[0], {
target: { value: '123' },
});
fireEvent.change(inputElements[1], {
target: { value: '456' },
});
fireEvent.change(inputElements[2], {
target: { value: '789' },
});
const addValueEls = await screen.findAllByText('Add values');
fireEvent.click(addValueEls[0]);
fireEvent.click(addValueEls[1]);
fireEvent.click(addValueEls[2]);
expect(screen.queryByText('123')).toBeInTheDocument();
const deleteBtns = await screen.findAllByTestId('CancelIcon');
fireEvent.click(deleteBtns[0]);
expect(screen.queryByText('123')).not.toBeInTheDocument();
expect(screen.queryByText('456')).toBeInTheDocument();
expect(screen.queryByText('789')).toBeInTheDocument();
});
test('Should update multiple constraints with the correct react key', async () => {
setupComponent();
const titleEl = await screen.findByText('Gradual rollout');
expect(titleEl).toBeInTheDocument();
const targetingEl = screen.getByText('Targeting');
fireEvent.click(targetingEl);
const addConstraintEl = await screen.findByText('Add constraint');
fireEvent.click(addConstraintEl);
fireEvent.click(addConstraintEl);
fireEvent.click(addConstraintEl);
const inputElements = screen.getAllByPlaceholderText(
'value1, value2, value3...',
);
fireEvent.change(inputElements[0], {
target: { value: '123' },
});
fireEvent.change(inputElements[1], {
target: { value: '456' },
});
fireEvent.change(inputElements[2], {
target: { value: '789' },
});
const addValueEls = await screen.findAllByText('Add values');
fireEvent.click(addValueEls[0]);
fireEvent.click(addValueEls[1]);
fireEvent.click(addValueEls[2]);
expect(screen.queryByText('123')).toBeInTheDocument();
const deleteBtns = screen.getAllByTestId('DELETE_CONSTRAINT_BUTTON');
fireEvent.click(deleteBtns[0]);
const inputElements2 = screen.getAllByPlaceholderText(
'value1, value2, value3...',
);
fireEvent.change(inputElements2[0], {
target: { value: '666' },
});
const addValueEls2 = screen.getAllByText('Add values');
fireEvent.click(addValueEls2[0]);
expect(screen.queryByText('123')).not.toBeInTheDocument();
expect(screen.queryByText('456')).toBeInTheDocument();
expect(screen.queryByText('789')).toBeInTheDocument();
});
test('Should undo changes made to constraints', async () => {
setupComponent();
const titleEl = await screen.findByText('Gradual rollout');
expect(titleEl).toBeInTheDocument();
const targetingEl = screen.getByText('Targeting');
fireEvent.click(targetingEl);
const addConstraintEl = await screen.findByText('Add constraint');
fireEvent.click(addConstraintEl);
const inputEl = screen.getByPlaceholderText(
'value1, value2, value3...',
);
fireEvent.change(inputEl, {
target: { value: '6, 7, 8' },
});
const addBtn = await screen.findByText('Add values');
fireEvent.click(addBtn);
expect(screen.queryByText('6')).toBeInTheDocument();
expect(screen.queryByText('7')).toBeInTheDocument();
expect(screen.queryByText('8')).toBeInTheDocument();
const undoBtn = await screen.findByTestId(
'UNDO_CONSTRAINT_CHANGE_BUTTON',
);
fireEvent.click(undoBtn);
expect(screen.queryByText('6')).not.toBeInTheDocument();
expect(screen.queryByText('7')).not.toBeInTheDocument();
expect(screen.queryByText('8')).not.toBeInTheDocument();
});
test('Should remove constraint when no valid values are set and moving between tabs', async () => {
setupComponent();
const titleEl = await screen.findByText('Gradual rollout');
expect(titleEl).toBeInTheDocument();
const targetingEl = screen.getByText('Targeting');
fireEvent.click(targetingEl);
const addConstraintEl = await screen.findByText('Add constraint');
fireEvent.click(addConstraintEl);
const variantsEl = screen.getByText('Variants');
fireEvent.click(variantsEl);
fireEvent.click(targetingEl);
const seconAddConstraintEl = await screen.findByText('Add constraint');
expect(seconAddConstraintEl).toBeInTheDocument();
expect(screen.queryByText('appName')).not.toBeInTheDocument();
});
});