1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-11-10 01:19:53 +01:00

feat: warning when empty segment (#10868)

This commit is contained in:
Jaanus Sellin 2025-10-27 14:46:51 +02:00 committed by GitHub
parent 07758a4267
commit 8db708369d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 185 additions and 2 deletions

View File

@ -0,0 +1,70 @@
import { screen } from '@testing-library/react';
import { render } from 'utils/testRenderer';
import { FeatureStrategySegmentList } from './FeatureStrategySegmentList.tsx';
import type { ISegment } from 'interfaces/segment';
const createMockSegment = (
id: number,
name: string,
constraints: ISegment['constraints'] = [],
): ISegment => ({
id,
name,
description: `Description for ${name}`,
createdAt: '2023-01-01T00:00:00Z',
createdBy: 'test-user',
constraints,
});
describe('FeatureStrategySegmentList', () => {
test('should not show warning when segment has constraints', () => {
const segments: ISegment[] = [
createMockSegment(1, 'Segment with constraints', [
{
contextName: 'userId',
operator: 'IN',
values: ['user1', 'user2'],
},
]),
];
render(
<FeatureStrategySegmentList
segments={segments}
setSegments={() => {}}
/>,
);
expect(screen.getByText('Selected Segments')).toBeInTheDocument();
expect(
screen.getByText('Segment with constraints'),
).toBeInTheDocument();
expect(
screen.queryByText(/You are adding an empty segment/i),
).not.toBeInTheDocument();
});
test('should show warning when segment has no constraints', () => {
const segments: ISegment[] = [
createMockSegment(1, 'pre-access-demo-accounts', []),
];
render(
<FeatureStrategySegmentList
segments={segments}
setSegments={() => {}}
/>,
);
expect(screen.getByText('Selected Segments')).toBeInTheDocument();
expect(
screen.getByText('pre-access-demo-accounts'),
).toBeInTheDocument();
expect(
screen.getByText(/You are adding an empty segment/i),
).toBeInTheDocument();
expect(
screen.getByText(/This will activate this feature for ALL USERS/i),
).toBeInTheDocument();
});
});

View File

@ -3,7 +3,7 @@ import { Fragment, useId, useState } from 'react';
import type { ISegment } from 'interfaces/segment';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { FeatureStrategySegmentChip } from 'component/feature/FeatureStrategy/FeatureStrategySegment/FeatureStrategySegmentChip';
import { styled } from '@mui/material';
import { Alert, styled } from '@mui/material';
import { SegmentItem } from 'component/common/SegmentItem/SegmentItem';
interface IFeatureStrategySegmentListProps {
@ -38,6 +38,11 @@ const StyledPreviewContainer = styled('div')({
display: 'contents',
});
const StyledWarningAlert = styled(Alert)(({ theme }) => ({
marginTop: theme.spacing(1.5),
marginBottom: theme.spacing(0.5),
}));
export const FeatureStrategySegmentList = ({
segments,
setSegments,
@ -50,6 +55,11 @@ export const FeatureStrategySegmentList = ({
return null;
}
const emptySegments = segments.filter(
(segment) => !segment.constraints || segment.constraints.length === 0,
);
const hasEmptySegments = emptySegments.length > 0;
return (
<>
<ConditionallyRender
@ -60,6 +70,17 @@ export const FeatureStrategySegmentList = ({
</StyledSelectedSegmentsLabel>
}
/>
<ConditionallyRender
condition={hasEmptySegments}
show={
<StyledWarningAlert severity='warning'>
<strong>Warning!</strong> You are adding an empty
segment{emptySegments.length > 1 ? 's' : ''} (
{emptySegments.map((s) => s.name).join(', ')}). This
will activate this feature for ALL USERS.
</StyledWarningAlert>
}
/>
<StyledList>
{segments.map((segment, i) => (
<Fragment key={segment.id}>

View File

@ -0,0 +1,70 @@
import { screen } from '@testing-library/react';
import { render } from 'utils/testRenderer';
import { MilestoneStrategySegmentList } from './MilestoneStrategySegmentList.tsx';
import type { ISegment } from 'interfaces/segment';
const createMockSegment = (
id: number,
name: string,
constraints: ISegment['constraints'] = [],
): ISegment => ({
id,
name,
description: `Description for ${name}`,
createdAt: '2023-01-01T00:00:00Z',
createdBy: 'test-user',
constraints,
});
describe('MilestoneStrategySegmentList', () => {
test('should not show warning when segment has constraints', () => {
const segments: ISegment[] = [
createMockSegment(1, 'Segment with constraints', [
{
contextName: 'userId',
operator: 'IN',
values: ['user1', 'user2'],
},
]),
];
render(
<MilestoneStrategySegmentList
segments={segments}
setSegments={() => {}}
/>,
);
expect(screen.getByText('Selected Segments')).toBeInTheDocument();
expect(
screen.getByText('Segment with constraints'),
).toBeInTheDocument();
expect(
screen.queryByText(/You are adding an empty segment/i),
).not.toBeInTheDocument();
});
test('should show warning when segment has no constraints', () => {
const segments: ISegment[] = [
createMockSegment(1, 'pre-access-demo-accounts', []),
];
render(
<MilestoneStrategySegmentList
segments={segments}
setSegments={() => {}}
/>,
);
expect(screen.getByText('Selected Segments')).toBeInTheDocument();
expect(
screen.getByText('pre-access-demo-accounts'),
).toBeInTheDocument();
expect(
screen.getByText(/You are adding an empty segment/i),
).toBeInTheDocument();
expect(
screen.getByText(/This will activate this feature for ALL USERS/i),
).toBeInTheDocument();
});
});

View File

@ -1,8 +1,9 @@
import type React from 'react';
import { Fragment, useState } from 'react';
import type { ISegment } from 'interfaces/segment';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { FeatureStrategySegmentChip } from 'component/feature/FeatureStrategy/FeatureStrategySegment/FeatureStrategySegmentChip';
import { styled } from '@mui/material';
import { Alert, styled } from '@mui/material';
import { SegmentItem } from 'component/common/SegmentItem/SegmentItem';
const StyledList = styled('div')(({ theme }) => ({
@ -28,6 +29,11 @@ const StyledAnd = styled('p')(({ theme }) => ({
backgroundColor: theme.palette.background.elevation2,
}));
const StyledWarningAlert = styled(Alert)(({ theme }) => ({
marginTop: theme.spacing(1.5),
marginBottom: theme.spacing(1.5),
}));
type IMilestoneStrategySegmentListProps = {
segments: ISegment[];
setSegments: React.Dispatch<React.SetStateAction<ISegment[]>>;
@ -44,6 +50,11 @@ export const MilestoneStrategySegmentList = ({
return null;
}
const emptySegments = segments.filter(
(segment) => !segment.constraints || segment.constraints.length === 0,
);
const hasEmptySegments = emptySegments.length > 0;
return (
<>
<ConditionallyRender
@ -54,6 +65,17 @@ export const MilestoneStrategySegmentList = ({
</StyledSelectedSegmentsLabel>
}
/>
<ConditionallyRender
condition={hasEmptySegments}
show={
<StyledWarningAlert severity='warning'>
<strong>Warning!</strong> You are adding an empty
segment{emptySegments.length > 1 ? 's' : ''} (
{emptySegments.map((s) => s.name).join(', ')}). This
will activate this feature for ALL USERS.
</StyledWarningAlert>
}
/>
<StyledList>
{segments.map((segment, i) => (
<Fragment key={segment.id}>