1
0
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:
andreas-unleash 2023-11-08 14:28:16 +02:00 committed by GitHub
parent 24f9fa3058
commit 3e9d88f789
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 296 additions and 5 deletions

View File

@ -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',
});
});

View File

@ -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));
}

View File

@ -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>

View File

@ -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'

View File

@ -14,7 +14,6 @@ export const useChangeRequestConfig = (projectId: string) => {
formatApiPath(`api/admin/projects/${projectId}/change-requests/config`),
fetcher,
);
return {
data: data || [],
loading: !error && !data,