Skip to content

Commit

Permalink
Feat/scheduled cr UI tests (#5296)
Browse files Browse the repository at this point in the history
Ui tests scheduled change requests

Closes # [1-1598](https://linear.app/unleash/issue/1-1598/e2e-ui-tests)

---------

Signed-off-by: andreas-unleash <[email protected]>
Co-authored-by: Thomas Heartman <[email protected]>
  • Loading branch information
andreas-unleash and thomasheartman authored Nov 8, 2023
1 parent 24f9fa3 commit 3e9d88f
Show file tree
Hide file tree
Showing 5 changed files with 296 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -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: '[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 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',
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/component/changeRequest/UpdateCount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export const useChangeRequestConfig = (projectId: string) => {
formatApiPath(`api/admin/projects/${projectId}/change-requests/config`),
fetcher,
);

return {
data: data || [],
loading: !error && !data,
Expand Down

0 comments on commit 3e9d88f

Please sign in to comment.