diff --git a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyForm/FeatureStrategyForm.tsx b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyForm/FeatureStrategyForm.tsx
index cba83a9ece..87cbf7426e 100644
--- a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyForm/FeatureStrategyForm.tsx
+++ b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyForm/FeatureStrategyForm.tsx
@@ -248,7 +248,11 @@ export const FeatureStrategyForm = ({
/>
void;
removeVariant: (variantId: string) => void;
error?: string;
+ disableOverrides?: boolean;
}
export const VariantForm = ({
@@ -158,6 +159,7 @@ export const VariantForm = ({
updateVariant,
removeVariant,
error,
+ disableOverrides = false,
}: IVariantFormProps) => {
const [name, setName] = useState(variant.name);
const [customPercentage, setCustomPercentage] = useState(
@@ -168,8 +170,9 @@ export const VariantForm = ({
variant.payload || EMPTY_PAYLOAD
);
const [overrides, overridesDispatch] = useOverrides(
- variant.overrides || []
+ 'overrides' in variant ? variant.overrides || [] : []
);
+
const { context } = useUnleashContext();
const [errors, setErrors] = useState({});
@@ -269,7 +272,7 @@ export const VariantForm = ({
};
useEffect(() => {
- updateVariant({
+ const newVariant: IFeatureVariantEdit = {
...variant,
name,
weight: Number(customPercentage ? percentage : 100) * 10,
@@ -277,19 +280,22 @@ export const VariantForm = ({
stickiness:
variants?.length > 0 ? variants[0].stickiness : 'default',
payload: payload.value ? payload : undefined,
- overrides: overrides
- .map(o => ({
- contextName: o.contextName,
- values: o.values,
- }))
- .filter(o => o.values && o.values.length > 0),
isValid:
isNameNotEmpty(name) &&
isNameUnique(name, variant.id) &&
isValidPercentage(percentage) &&
isValidPayload(payload) &&
!error,
- });
+ };
+ if (!disableOverrides) {
+ newVariant['overrides'] = overrides
+ .map(o => ({
+ contextName: o.contextName,
+ values: o.values,
+ }))
+ .filter(o => o.values && o.values.length > 0);
+ }
+ updateVariant(newVariant);
}, [name, customPercentage, percentage, payload, overrides]);
useEffect(() => {
@@ -423,24 +429,28 @@ export const VariantForm = ({
/>
-
- Overrides
-
-
-
-
-
- Add override
-
-
+ {!disableOverrides ? (
+ <>
+
+ Overrides
+
+
+
+
+
+ Add override
+
+
+ >
+ ) : null}
);
};
diff --git a/frontend/src/component/feature/StrategyTypes/StrategyVariants.test.tsx b/frontend/src/component/feature/StrategyTypes/StrategyVariants.test.tsx
new file mode 100644
index 0000000000..57b2961226
--- /dev/null
+++ b/frontend/src/component/feature/StrategyTypes/StrategyVariants.test.tsx
@@ -0,0 +1,96 @@
+import { screen, waitFor } from '@testing-library/react';
+import { render } from 'utils/testRenderer';
+import { StrategyVariants } from './StrategyVariants';
+import { Route, Routes } from 'react-router-dom';
+import { UPDATE_FEATURE_ENVIRONMENT_VARIANTS } from '../../providers/AccessProvider/permissions';
+import { IFeatureStrategy } from '../../../interfaces/strategy';
+import React, { useState } from 'react';
+
+test('should render variants', async () => {
+ let currentStrategy: Partial = {};
+ const initialStrategy = {
+ name: '',
+ constraints: [],
+ parameters: { stickiness: 'clientId' },
+ variants: [
+ {
+ name: 'variantName',
+ stickiness: 'default',
+ weight: 1000,
+ weightType: 'variable',
+ payload: {
+ type: 'string',
+ value: 'variantValue',
+ },
+ },
+ ],
+ };
+ const Parent = () => {
+ const [strategy, setStrategy] =
+ useState>(initialStrategy);
+
+ currentStrategy = strategy;
+
+ return (
+
+ );
+ };
+ render(
+
+ }
+ />
+ ,
+ {
+ route: 'projects/default/features/colors/strategies/edit?environmentId=development&strategyId=2e4f0555-518b-45b3-b0cd-a32cca388a92',
+ permissions: [
+ {
+ permission: UPDATE_FEATURE_ENVIRONMENT_VARIANTS,
+ project: 'default',
+ environment: 'development',
+ },
+ ],
+ }
+ );
+
+ // static form info
+ await screen.findByText('Variants');
+ const button = await screen.findByText('Add variant');
+
+ // variant form populated
+ const variantInput = screen.getByDisplayValue('variantValue');
+ expect(variantInput).toBeInTheDocument();
+
+ // overrides disabled
+ expect(screen.queryByText('Overrides')).not.toBeInTheDocument();
+
+ // add second variant
+ button.click();
+
+ // UI allows to adjust percentages
+ const matchedElements = screen.getAllByText('Custom percentage');
+ expect(matchedElements.length).toBe(2);
+
+ // correct variants set on the parent
+ await waitFor(() => {
+ expect(currentStrategy).toMatchObject({
+ ...initialStrategy,
+ variants: [
+ {
+ name: 'variantName',
+ payload: { type: 'string', value: 'variantValue' },
+ stickiness: 'clientId',
+ weight: 500,
+ weightType: 'variable',
+ },
+ {
+ name: '',
+ stickiness: 'clientId',
+ weight: 500,
+ weightType: 'variable',
+ },
+ ],
+ });
+ });
+});
diff --git a/frontend/src/component/feature/StrategyTypes/StrategyVariants.tsx b/frontend/src/component/feature/StrategyTypes/StrategyVariants.tsx
index ff91c8d751..404bbd3253 100644
--- a/frontend/src/component/feature/StrategyTypes/StrategyVariants.tsx
+++ b/frontend/src/component/feature/StrategyTypes/StrategyVariants.tsx
@@ -7,8 +7,7 @@ import { UPDATE_FEATURE_ENVIRONMENT_VARIANTS } from '../../providers/AccessProvi
import { v4 as uuidv4 } from 'uuid';
import { WeightType } from '../../../constants/variantTypes';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
-import { useDefaultProjectSettings } from 'hooks/useDefaultProjectSettings';
-import { styled } from '@mui/material';
+import { styled, Typography } from '@mui/material';
import { useRequiredQueryParam } from 'hooks/useRequiredQueryParam';
import { IFeatureStrategy } from 'interfaces/strategy';
@@ -26,8 +25,10 @@ export const StrategyVariants: FC<{
const projectId = useRequiredPathParam('projectId');
const environment = useRequiredQueryParam('environmentId');
const [variantsEdit, setVariantsEdit] = useState([]);
- const [newVariant, setNewVariant] = useState();
- const { defaultStickiness, loading } = useDefaultProjectSettings(projectId);
+ const stickiness =
+ strategy?.parameters && 'stickiness' in strategy?.parameters
+ ? String(strategy.parameters.stickiness)
+ : 'default';
useEffect(() => {
setVariantsEdit(
@@ -41,19 +42,6 @@ export const StrategyVariants: FC<{
);
}, []);
- useEffect(() => {
- setStrategy(prev => ({
- ...prev,
- variants: variantsEdit.map(variant => ({
- name: variant.name,
- weight: variant.weight,
- stickiness: variant.stickiness,
- payload: variant.payload,
- weightType: variant.weightType,
- })),
- }));
- }, [JSON.stringify(variantsEdit)]);
-
const updateVariant = (updatedVariant: IFeatureVariantEdit, id: string) => {
setVariantsEdit(prevVariants =>
updateWeightEdit(
@@ -63,6 +51,16 @@ export const StrategyVariants: FC<{
1000
)
);
+ setStrategy(prev => ({
+ ...prev,
+ variants: variantsEdit.map(variant => ({
+ name: variant.name,
+ weight: variant.weight,
+ stickiness,
+ payload: variant.payload,
+ weightType: variant.weightType,
+ })),
+ }));
};
const addVariant = () => {
@@ -73,24 +71,23 @@ export const StrategyVariants: FC<{
name: '',
weightType: WeightType.VARIABLE,
weight: 0,
- overrides: [],
- stickiness:
- variantsEdit?.length > 0
- ? variantsEdit[0].stickiness
- : defaultStickiness,
+ stickiness,
new: true,
isValid: false,
id,
},
]);
- setNewVariant(id);
};
return (
<>
+
+ Variants
+
{variantsEdit.map(variant => (