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( } /> , { 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(); }); });