mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-14 01:16:17 +02:00
feat: connect feature lifecycle to real API (#6921)
This commit is contained in:
parent
1b2f983974
commit
e6355f4676
@ -0,0 +1,76 @@
|
|||||||
|
import { populateCurrentStage } from './populateCurrentStage';
|
||||||
|
import type { IFeatureToggle } from '../../../../../interfaces/featureToggle';
|
||||||
|
|
||||||
|
describe('populateCurrentStage', () => {
|
||||||
|
it('should return undefined if lifecycle is not defined', () => {
|
||||||
|
const feature = {};
|
||||||
|
const result = populateCurrentStage(feature as IFeatureToggle);
|
||||||
|
expect(result).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return initial stage when lifecycle stage is initial', () => {
|
||||||
|
const feature = {
|
||||||
|
lifecycle: { stage: 'initial' },
|
||||||
|
};
|
||||||
|
const expected = { name: 'initial' };
|
||||||
|
const result = populateCurrentStage(feature as IFeatureToggle);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly populate pre-live stage with dev environments', () => {
|
||||||
|
const feature = {
|
||||||
|
lifecycle: { stage: 'pre-live' },
|
||||||
|
environments: [
|
||||||
|
{ name: 'test', type: 'development', lastSeenAt: null },
|
||||||
|
{ name: 'test1', type: 'production', lastSeenAt: '2022-08-01' },
|
||||||
|
{ name: 'dev', type: 'development', lastSeenAt: '2022-08-01' },
|
||||||
|
],
|
||||||
|
} as IFeatureToggle;
|
||||||
|
const expected = {
|
||||||
|
name: 'pre-live',
|
||||||
|
environments: [{ name: 'dev', lastSeenAt: '2022-08-01' }],
|
||||||
|
};
|
||||||
|
const result = populateCurrentStage(feature);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle live stage with production environments', () => {
|
||||||
|
const feature = {
|
||||||
|
lifecycle: { stage: 'live' },
|
||||||
|
environments: [
|
||||||
|
{ name: 'prod', type: 'production', lastSeenAt: '2022-08-01' },
|
||||||
|
],
|
||||||
|
} as IFeatureToggle;
|
||||||
|
const expected = {
|
||||||
|
name: 'live',
|
||||||
|
environments: [{ name: 'prod', lastSeenAt: '2022-08-01' }],
|
||||||
|
};
|
||||||
|
const result = populateCurrentStage(feature);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return completed stage with production environments', () => {
|
||||||
|
const feature = {
|
||||||
|
lifecycle: { stage: 'completed' },
|
||||||
|
environments: [
|
||||||
|
{ name: 'prod', type: 'production', lastSeenAt: '2022-08-01' },
|
||||||
|
],
|
||||||
|
} as IFeatureToggle;
|
||||||
|
const expected = {
|
||||||
|
name: 'completed',
|
||||||
|
status: 'kept',
|
||||||
|
environments: [{ name: 'prod', lastSeenAt: '2022-08-01' }],
|
||||||
|
};
|
||||||
|
const result = populateCurrentStage(feature);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return archived stage when lifecycle stage is archived', () => {
|
||||||
|
const feature = {
|
||||||
|
lifecycle: { stage: 'archived' },
|
||||||
|
} as IFeatureToggle;
|
||||||
|
const expected = { name: 'archived' };
|
||||||
|
const result = populateCurrentStage(feature);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,48 @@
|
|||||||
|
import type { IFeatureToggle } from 'interfaces/featureToggle';
|
||||||
|
import type { LifecycleStage } from './LifecycleStage';
|
||||||
|
|
||||||
|
export const populateCurrentStage = (
|
||||||
|
feature: Pick<IFeatureToggle, 'lifecycle' | 'environments'>,
|
||||||
|
): LifecycleStage | undefined => {
|
||||||
|
if (!feature.lifecycle) return undefined;
|
||||||
|
|
||||||
|
const getFilteredEnvironments = (condition: (type: string) => boolean) => {
|
||||||
|
return feature.environments
|
||||||
|
.filter((env) => condition(env.type) && Boolean(env.lastSeenAt))
|
||||||
|
.map((env) => ({
|
||||||
|
name: env.name,
|
||||||
|
lastSeenAt: env.lastSeenAt!,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (feature.lifecycle.stage) {
|
||||||
|
case 'initial':
|
||||||
|
return { name: 'initial' };
|
||||||
|
case 'pre-live':
|
||||||
|
return {
|
||||||
|
name: 'pre-live',
|
||||||
|
environments: getFilteredEnvironments(
|
||||||
|
(type) => type !== 'production',
|
||||||
|
),
|
||||||
|
};
|
||||||
|
case 'live':
|
||||||
|
return {
|
||||||
|
name: 'live',
|
||||||
|
environments: getFilteredEnvironments(
|
||||||
|
(type) => type === 'production',
|
||||||
|
),
|
||||||
|
};
|
||||||
|
case 'completed':
|
||||||
|
return {
|
||||||
|
name: 'completed',
|
||||||
|
status: 'kept',
|
||||||
|
environments: getFilteredEnvironments(
|
||||||
|
(type) => type === 'production',
|
||||||
|
),
|
||||||
|
};
|
||||||
|
case 'archived':
|
||||||
|
return { name: 'archived' };
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
};
|
@ -10,7 +10,7 @@ import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
|||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
import { useUiFlag } from 'hooks/useUiFlag';
|
||||||
import { FeatureLifecycleTooltip } from '../FeatureLifecycle/FeatureLifecycleTooltip';
|
import { FeatureLifecycleTooltip } from '../FeatureLifecycle/FeatureLifecycleTooltip';
|
||||||
import { FeatureLifecycleStageIcon } from '../FeatureLifecycle/FeatureLifecycleStageIcon';
|
import { FeatureLifecycleStageIcon } from '../FeatureLifecycle/FeatureLifecycleStageIcon';
|
||||||
import type { LifecycleStage } from '../FeatureLifecycle/LifecycleStage';
|
import { populateCurrentStage } from '../FeatureLifecycle/populateCurrentStage';
|
||||||
|
|
||||||
const StyledContainer = styled('div')(({ theme }) => ({
|
const StyledContainer = styled('div')(({ theme }) => ({
|
||||||
borderRadius: theme.shape.borderRadiusLarge,
|
borderRadius: theme.shape.borderRadiusLarge,
|
||||||
@ -82,17 +82,7 @@ const FeatureOverviewMetaData = () => {
|
|||||||
|
|
||||||
const IconComponent = getFeatureTypeIcons(type);
|
const IconComponent = getFeatureTypeIcons(type);
|
||||||
|
|
||||||
const currentStage: LifecycleStage = {
|
const currentStage = populateCurrentStage(feature);
|
||||||
name: 'completed',
|
|
||||||
status: 'kept',
|
|
||||||
environments: [
|
|
||||||
{ name: 'production', lastSeenAt: new Date().toISOString() },
|
|
||||||
{
|
|
||||||
name: 'staging',
|
|
||||||
lastSeenAt: new Date().toISOString(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
@ -122,11 +112,16 @@ const FeatureOverviewMetaData = () => {
|
|||||||
show={
|
show={
|
||||||
<StyledRow data-loading>
|
<StyledRow data-loading>
|
||||||
<StyledLabel>Lifecycle:</StyledLabel>
|
<StyledLabel>Lifecycle:</StyledLabel>
|
||||||
<FeatureLifecycleTooltip stage={currentStage}>
|
|
||||||
|
{currentStage && (
|
||||||
|
<FeatureLifecycleTooltip
|
||||||
|
stage={currentStage}
|
||||||
|
>
|
||||||
<FeatureLifecycleStageIcon
|
<FeatureLifecycleStageIcon
|
||||||
stage={currentStage}
|
stage={currentStage}
|
||||||
/>
|
/>
|
||||||
</FeatureLifecycleTooltip>
|
</FeatureLifecycleTooltip>
|
||||||
|
)}
|
||||||
</StyledRow>
|
</StyledRow>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -49,6 +49,10 @@ export interface IFeatureToggle {
|
|||||||
impressionData: boolean;
|
impressionData: boolean;
|
||||||
strategies?: IFeatureStrategy[];
|
strategies?: IFeatureStrategy[];
|
||||||
dependencies: Array<IDependency>;
|
dependencies: Array<IDependency>;
|
||||||
|
lifecycle?: {
|
||||||
|
stage: 'initial' | 'pre-live' | 'live' | 'completed' | 'archived';
|
||||||
|
enteredStageAt: string;
|
||||||
|
};
|
||||||
children: Array<string>;
|
children: Array<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user