-
-
Notifications
You must be signed in to change notification settings - Fork 736
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add Changes Scheduled badge to feature variants (#5312)
Adds the Changes Scheduled badge to environment variant when appropriate Closes # [1-1625](https://linear.app/unleash/issue/1-1625/show-a-badge-when-variant-in-scheduled-request) <img width="1006" alt="Screenshot 2023-11-09 at 15 42 37" src="https://github.com/Unleash/unleash/assets/104830839/118a3f0b-9acf-4a49-92d2-49bbe49a4c91"> --------- Signed-off-by: andreas-unleash <[email protected]> Co-authored-by: Thomas Heartman <[email protected]>
- Loading branch information
1 parent
de638b5
commit 77db9f3
Showing
4 changed files
with
325 additions
and
1 deletion.
There are no files selected for viewing
263 changes: 263 additions & 0 deletions
263
...iants/FeatureEnvironmentVariants/EnvironmentVariantsCard/EnvironmentVariantsCard.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,263 @@ | ||
import { testServerRoute, testServerSetup } from 'utils/testServer'; | ||
import { render } from 'utils/testRenderer'; | ||
import { ADMIN } from 'component/providers/AccessProvider/permissions'; | ||
import { screen } from '@testing-library/dom'; | ||
import { Route, Routes } from 'react-router-dom'; | ||
import { | ||
ChangeRequestAction, | ||
IChangeRequest, | ||
} from 'component/changeRequest/changeRequest.types'; | ||
import { EnvironmentVariantsCard } from './EnvironmentVariantsCard'; | ||
import { IFeatureEnvironment } from 'interfaces/featureToggle'; | ||
|
||
const server = testServerSetup(); | ||
|
||
const strategy = { | ||
name: 'flexibleRollout', | ||
constraints: [], | ||
variants: [], | ||
parameters: { | ||
groupId: 'CR-toggle', | ||
rollout: '100', | ||
stickiness: 'default', | ||
}, | ||
sortOrder: 0, | ||
id: 'b6363cc8-ad8e-478a-b464-484bbd3b31f6', | ||
title: '', | ||
disabled: false, | ||
}; | ||
|
||
const scheduledRequest = ( | ||
action: Omit<ChangeRequestAction, 'updateSegment'> = 'updateStrategy', | ||
createdBy = 1, | ||
): IChangeRequest => { | ||
return { | ||
id: 71, | ||
title: 'Change request #71', | ||
environment: 'production', | ||
minApprovals: 1, | ||
project: 'dafault', | ||
createdBy: { | ||
id: createdBy, | ||
username: 'admin', | ||
imageUrl: | ||
'https://gravatar.com/avatar/8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918?s=42&d=retro&r=g', | ||
}, | ||
createdAt: new Date('2023-11-08T10:28:47.183Z'), | ||
features: [ | ||
{ | ||
name: 'feature1', | ||
changes: [ | ||
{ | ||
id: 84, | ||
action: action as any, | ||
payload: { | ||
id: 'b6363cc8-ad8e-478a-b464-484bbd3b31f6', | ||
name: 'flexibleRollout', | ||
title: '', | ||
disabled: false, | ||
segments: [], | ||
variants: [], | ||
parameters: { | ||
groupId: 'CR-toggle', | ||
rollout: '15', | ||
stickiness: 'default', | ||
}, | ||
constraints: [], | ||
}, | ||
createdAt: new Date('2023-11-08T10:28:47.183Z'), | ||
createdBy: { | ||
id: 1, | ||
username: 'admin', | ||
imageUrl: | ||
'https://gravatar.com/avatar/8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918?s=42&d=retro&r=g', | ||
}, | ||
}, | ||
], | ||
}, | ||
], | ||
segments: [], | ||
approvals: [], | ||
rejections: [], | ||
comments: [], | ||
state: 'Scheduled', | ||
schedule: { | ||
scheduledAt: new Date().toISOString(), | ||
status: 'pending', | ||
}, | ||
}; | ||
}; | ||
|
||
const uiConfig = () => { | ||
testServerRoute(server, '/api/admin/ui-config', { | ||
versionInfo: { | ||
current: { oss: 'version', enterprise: 'version' }, | ||
}, | ||
flags: { | ||
scheduledConfigurationChanges: true, | ||
}, | ||
}); | ||
}; | ||
|
||
const user = () => { | ||
testServerRoute(server, '/api/admin/user', { | ||
user: { | ||
isAPI: false, | ||
id: 1, | ||
name: 'Some User', | ||
email: '[email protected]', | ||
imageUrl: | ||
'https://gravatar.com/avatar/8aa1132e102345f8c79322340e15340?size=42&default=retro', | ||
seenAt: '2022-11-28T14:55:18.982Z', | ||
loginAttempts: 0, | ||
createdAt: '2022-11-23T13:31:17.061Z', | ||
}, | ||
permissions: [{ permission: ADMIN }], | ||
feedback: [], | ||
splash: {}, | ||
}); | ||
}; | ||
const changeRequestConfig = () => | ||
testServerRoute( | ||
server, | ||
'/api/admin/projects/default/change-requests/config', | ||
[ | ||
{ | ||
environment: 'development', | ||
type: 'development', | ||
changeRequestEnabled: false, | ||
}, | ||
{ | ||
environment: 'production', | ||
type: 'production', | ||
changeRequestEnabled: true, | ||
}, | ||
], | ||
'get', | ||
); | ||
|
||
const feature = () => { | ||
testServerRoute(server, '/api/admin/projects/default/features/feature1', { | ||
environments: [ | ||
{ | ||
name: 'development', | ||
lastSeenAt: null, | ||
variants: [], | ||
enabled: false, | ||
type: 'development', | ||
sortOrder: 2, | ||
strategies: [], | ||
}, | ||
{ | ||
name: 'production', | ||
lastSeenAt: null, | ||
variants: [], | ||
enabled: false, | ||
type: 'production', | ||
sortOrder: 3, | ||
strategies: [ | ||
{ | ||
name: 'flexibleRollout', | ||
constraints: [], | ||
variants: [], | ||
parameters: { | ||
groupId: 'CR-toggle', | ||
rollout: '100', | ||
stickiness: 'default', | ||
}, | ||
sortOrder: 0, | ||
id: 'b6363cc8-ad8e-478a-b464-484bbd3b31f6', | ||
title: '', | ||
disabled: false, | ||
}, | ||
], | ||
}, | ||
], | ||
name: 'feature1', | ||
favorite: false, | ||
impressionData: false, | ||
description: null, | ||
project: 'MyNewProject', | ||
stale: false, | ||
lastSeenAt: null, | ||
createdAt: '2023-11-01T10:11:58.505Z', | ||
type: 'release', | ||
variants: [], | ||
archived: false, | ||
dependencies: [], | ||
children: [], | ||
}); | ||
}; | ||
|
||
const setupOtherServerRoutes = () => { | ||
uiConfig(); | ||
changeRequestConfig(); | ||
user(); | ||
feature(); | ||
}; | ||
|
||
beforeEach(() => { | ||
setupOtherServerRoutes(); | ||
}); | ||
|
||
const Component = () => { | ||
return ( | ||
<> | ||
<Routes> | ||
<Route | ||
path={'/projects/:projectId/features/:featureId/variants'} | ||
element={ | ||
<EnvironmentVariantsCard | ||
environment={ | ||
{ | ||
name: 'production', | ||
} as unknown as IFeatureEnvironment | ||
} | ||
searchValue={''} | ||
/> | ||
} | ||
/> | ||
</Routes> | ||
</> | ||
); | ||
}; | ||
describe('Change request badges for variants', () => { | ||
test('should not render a badge if no changes', async () => { | ||
testServerRoute( | ||
server, | ||
'/api/admin/projects/default/change-requests/pending/feature1/variants', | ||
[], | ||
); | ||
|
||
render(<Component />, { | ||
route: '/projects/default/features/feature1/variants', | ||
permissions: [ | ||
{ | ||
permission: ADMIN, | ||
}, | ||
], | ||
}); | ||
|
||
expect(screen.queryByText('Changes Scheduled')).toBe(null); | ||
}); | ||
|
||
test('should render the badge when scheduled request with "patchVariant" action', async () => { | ||
const changeRequest = scheduledRequest('patchVariant', 1); | ||
|
||
testServerRoute( | ||
server, | ||
'/api/admin/projects/default/change-requests/pending/feature1', | ||
[changeRequest], | ||
); | ||
|
||
render(<Component />, { | ||
route: '/projects/default/features/feature1/variants', | ||
permissions: [ | ||
{ | ||
permission: ADMIN, | ||
}, | ||
], | ||
}); | ||
await screen.findByText('Changes Scheduled'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
...ts/FeatureEnvironmentVariants/EnvironmentVariantsCard/useVariantsFromScheduledRequests.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { usePendingChangeRequestsForFeature } from 'hooks/api/getters/usePendingChangeRequestsForFeature/usePendingChangeRequestsForFeature'; | ||
|
||
export const useVariantsFromScheduledRequests = ( | ||
projectId: string, | ||
featureId: string, | ||
environment: string, | ||
): number[] => { | ||
const { changeRequests } = usePendingChangeRequestsForFeature( | ||
projectId, | ||
featureId, | ||
); | ||
|
||
const scheduledEnvironmentRequests = | ||
changeRequests?.filter( | ||
(request) => | ||
request.environment === environment && | ||
request.state === 'Scheduled', | ||
) || []; | ||
|
||
const result: number[] = []; | ||
if (scheduledEnvironmentRequests.length === 0) { | ||
return result; | ||
} | ||
|
||
scheduledEnvironmentRequests.forEach((scheduledRequest) => { | ||
const feature = scheduledRequest?.features.find( | ||
(feature) => feature.name === featureId, | ||
); | ||
const change = feature?.changes.find((change) => { | ||
return change.action === 'patchVariant'; | ||
}); | ||
|
||
if (change) { | ||
result.push(scheduledRequest.id); | ||
} | ||
}); | ||
|
||
return result; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters