mirror of
https://github.com/Unleash/unleash.git
synced 2024-12-22 19:07:54 +01:00
Feat/scheduled cr UI tests (#5296)
Ui tests scheduled change requests Closes # [1-1598](https://linear.app/unleash/issue/1-1598/e2e-ui-tests) --------- Signed-off-by: andreas-unleash <andreas@getunleash.ai> Co-authored-by: Thomas Heartman <thomas@getunleash.io>
This commit is contained in:
parent
24f9fa3058
commit
3e9d88f789
@ -0,0 +1,289 @@
|
||||
import { fireEvent, screen, waitFor, within } from '@testing-library/react';
|
||||
import { testServerRoute, testServerSetup } from 'utils/testServer';
|
||||
import { ChangeRequestState, IChangeRequest } from '../changeRequest.types';
|
||||
import { render } from 'utils/testRenderer';
|
||||
import { ChangeRequestOverview } from './ChangeRequestOverview';
|
||||
import {
|
||||
ADMIN,
|
||||
APPLY_CHANGE_REQUEST,
|
||||
} from 'component/providers/AccessProvider/permissions';
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
|
||||
const server = testServerSetup();
|
||||
const mockChangeRequest = (
|
||||
featureName: string,
|
||||
state: ChangeRequestState,
|
||||
): IChangeRequest => {
|
||||
const result: IChangeRequest = {
|
||||
id: 1,
|
||||
environment: 'production',
|
||||
state: state,
|
||||
minApprovals: 1,
|
||||
project: 'default',
|
||||
createdBy: {
|
||||
id: 1,
|
||||
username: 'admin',
|
||||
imageUrl:
|
||||
'https://gravatar.com/avatar/21232f297a57a5a743894a0e4a801fc3?size=42&default=retro',
|
||||
},
|
||||
createdAt: new Date('2022-12-02T09:19:12.242Z'),
|
||||
segments: [],
|
||||
title: '',
|
||||
features: [
|
||||
{
|
||||
name: featureName,
|
||||
changes: [
|
||||
{
|
||||
id: 292,
|
||||
action: 'addStrategy',
|
||||
payload: {
|
||||
name: 'default',
|
||||
segments: [],
|
||||
parameters: {},
|
||||
constraints: [],
|
||||
},
|
||||
createdAt: new Date('2022-12-02T09:19:12.245Z'),
|
||||
createdBy: {
|
||||
id: 1,
|
||||
username: 'admin',
|
||||
imageUrl:
|
||||
'https://gravatar.com/avatar/21232f297a57a5a743894a0e4a801fc3?size=42&default=retro',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
approvals: [],
|
||||
rejections: [],
|
||||
comments: [],
|
||||
};
|
||||
|
||||
if (state === 'Scheduled') {
|
||||
result.schedule = {
|
||||
scheduledAt: '2022-12-02T09:19:12.242Z',
|
||||
status: 'pending',
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
const pendingChangeRequest = (changeRequest: IChangeRequest) =>
|
||||
testServerRoute(
|
||||
server,
|
||||
'/api/admin/projects/default/change-requests/pending',
|
||||
[changeRequest],
|
||||
);
|
||||
|
||||
const changeRequest = (changeRequest: IChangeRequest) =>
|
||||
testServerRoute(
|
||||
server,
|
||||
'/api/admin/projects/default/change-requests/1',
|
||||
changeRequest,
|
||||
'get',
|
||||
);
|
||||
|
||||
const updateChangeRequestState = () =>
|
||||
testServerRoute(
|
||||
server,
|
||||
'/api/admin/projects/default/change-requests/1/state',
|
||||
{},
|
||||
'post',
|
||||
);
|
||||
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 setupChangeRequest = (featureName: string, state: ChangeRequestState) => {
|
||||
pendingChangeRequest(mockChangeRequest(featureName, state));
|
||||
changeRequest(mockChangeRequest(featureName, state));
|
||||
};
|
||||
|
||||
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: 17,
|
||||
name: 'Some User',
|
||||
email: 'user@example.com',
|
||||
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 setupHttpRoutes = () => {
|
||||
uiConfig();
|
||||
changeRequestConfig();
|
||||
user();
|
||||
updateChangeRequestState();
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
setupHttpRoutes();
|
||||
});
|
||||
|
||||
const Component = () => {
|
||||
return (
|
||||
<>
|
||||
<Routes>
|
||||
<Route
|
||||
path={'/projects/:projectId/change-requests/:id'}
|
||||
element={<ChangeRequestOverview />}
|
||||
/>
|
||||
</Routes>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const featureName = 'feature1';
|
||||
|
||||
test('should allow scheduling of approved change request and show the schedule dialog', async () => {
|
||||
setupChangeRequest(featureName, 'Approved');
|
||||
|
||||
render(<Component />, {
|
||||
route: '/projects/default/change-requests/1',
|
||||
permissions: [
|
||||
{
|
||||
permission: APPLY_CHANGE_REQUEST,
|
||||
project: 'default',
|
||||
environment: 'production',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const applyOrScheduleButton = await screen.findByText(
|
||||
'Apply or schedule changes',
|
||||
);
|
||||
await waitFor(() => expect(applyOrScheduleButton).toBeEnabled(), {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
fireEvent.click(applyOrScheduleButton);
|
||||
|
||||
const scheduleChangesButton = await screen.findByRole('menuitem', {
|
||||
name: 'Schedule changes',
|
||||
});
|
||||
|
||||
fireEvent.click(scheduleChangesButton);
|
||||
|
||||
await screen.findByRole('dialog', { name: 'Schedule changes' });
|
||||
});
|
||||
|
||||
test('should show a reschedule dialog when change request is scheduled and update schedule is selected', async () => {
|
||||
setupChangeRequest(featureName, 'Scheduled');
|
||||
render(<Component />, {
|
||||
route: '/projects/default/change-requests/1',
|
||||
permissions: [
|
||||
{
|
||||
permission: APPLY_CHANGE_REQUEST,
|
||||
project: 'default',
|
||||
environment: 'production',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const applyOrScheduleButton = await screen.findByText(
|
||||
'Apply or schedule changes',
|
||||
);
|
||||
await waitFor(() => expect(applyOrScheduleButton).toBeEnabled(), {
|
||||
timeout: 3000,
|
||||
});
|
||||
fireEvent.click(applyOrScheduleButton);
|
||||
|
||||
const scheduleChangesButton = await screen.findByRole('menuitem', {
|
||||
name: 'Update schedule',
|
||||
});
|
||||
|
||||
fireEvent.click(scheduleChangesButton);
|
||||
|
||||
await screen.findByRole('dialog', { name: 'Update schedule' });
|
||||
});
|
||||
|
||||
test('should show an apply dialog when change request is scheduled and apply is selected', async () => {
|
||||
setupChangeRequest(featureName, 'Scheduled');
|
||||
|
||||
render(<Component />, {
|
||||
route: '/projects/default/change-requests/1',
|
||||
permissions: [
|
||||
{
|
||||
permission: APPLY_CHANGE_REQUEST,
|
||||
project: 'default',
|
||||
environment: 'production',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const applyOrScheduleButton = await screen.findByText(
|
||||
'Apply or schedule changes',
|
||||
);
|
||||
await waitFor(() => expect(applyOrScheduleButton).toBeEnabled(), {
|
||||
timeout: 3000,
|
||||
});
|
||||
fireEvent.click(applyOrScheduleButton);
|
||||
|
||||
const applyChangesButton = await screen.findByRole('menuitem', {
|
||||
name: 'Apply changes',
|
||||
});
|
||||
fireEvent.click(applyChangesButton);
|
||||
|
||||
await screen.findByRole('dialog', { name: 'Apply changes' });
|
||||
});
|
||||
|
||||
test('should show a reject dialog when change request is scheduled and Reject Changes button is clicked', async () => {
|
||||
setupChangeRequest(featureName, 'Scheduled');
|
||||
|
||||
render(<Component />, {
|
||||
route: '/projects/default/change-requests/1',
|
||||
permissions: [{ permission: ADMIN }],
|
||||
});
|
||||
|
||||
const applyOrScheduleButton = await screen.findByText(
|
||||
'Apply or schedule changes',
|
||||
);
|
||||
await waitFor(() => expect(applyOrScheduleButton).toBeEnabled(), {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
const buttons = await screen.findAllByRole('button');
|
||||
const rejectChangesButton = buttons[buttons.length - 1];
|
||||
expect(
|
||||
within(rejectChangesButton).getByText('Reject changes'),
|
||||
).toBeInTheDocument();
|
||||
fireEvent.click(rejectChangesButton);
|
||||
|
||||
await screen.findByRole('dialog', {
|
||||
name: 'Reject changes',
|
||||
});
|
||||
});
|
@ -186,13 +186,13 @@ export const ChangeRequestOverview: FC = () => {
|
||||
comment,
|
||||
});
|
||||
setShowRejectDialog(false);
|
||||
refetchChangeRequest();
|
||||
refetchChangeRequestOpen();
|
||||
setToastData({
|
||||
type: 'success',
|
||||
title: 'Success',
|
||||
text: 'Changes rejected',
|
||||
});
|
||||
refetchChangeRequest();
|
||||
refetchChangeRequestOpen();
|
||||
} catch (error: unknown) {
|
||||
setToastApiError(formatUnknownError(error));
|
||||
}
|
||||
|
@ -102,7 +102,10 @@ export const MultiActionButton: FC<{
|
||||
>
|
||||
{actions.map(
|
||||
({ label, onSelect, icon }) => (
|
||||
<MenuItem onClick={onSelect}>
|
||||
<MenuItem
|
||||
onClick={onSelect}
|
||||
key={`MenuItem-${label}`}
|
||||
>
|
||||
<ListItemIcon>
|
||||
{icon}
|
||||
</ListItemIcon>
|
||||
|
@ -6,7 +6,7 @@ export const UpdateCount: FC<{
|
||||
featuresCount: number;
|
||||
segmentsCount: number;
|
||||
}> = ({ featuresCount, segmentsCount }) => (
|
||||
<Box sx={{ display: 'inline', pl: 0.5 }}>
|
||||
<Box component={'span'} sx={{ display: 'inline', pl: 0.5 }}>
|
||||
<Typography
|
||||
component='span'
|
||||
variant='body2'
|
||||
|
@ -14,7 +14,6 @@ export const useChangeRequestConfig = (projectId: string) => {
|
||||
formatApiPath(`api/admin/projects/${projectId}/change-requests/config`),
|
||||
fetcher,
|
||||
);
|
||||
|
||||
return {
|
||||
data: data || [],
|
||||
loading: !error && !data,
|
||||
|
Loading…
Reference in New Issue
Block a user