Skip to content

Commit

Permalink
POC: integration tests (#2422)
Browse files Browse the repository at this point in the history
  • Loading branch information
kwasniew committed Dec 6, 2022
1 parent b976fee commit c4f3ada
Show file tree
Hide file tree
Showing 13 changed files with 357 additions and 18 deletions.
Expand Up @@ -7,6 +7,7 @@ import {
IAddonMultiSelectorProps,
AddonMultiSelector,
} from './AddonMultiSelector';
import { testServerRoute, testServerSetup } from 'utils/testServer';

const onChange = vi.fn();
const onFocus = vi.fn();
Expand All @@ -24,10 +25,13 @@ const mockProps: IAddonMultiSelectorProps = {
entityName: 'project',
};

const server = testServerSetup();

describe('AddonMultiSelector', () => {
beforeEach(() => {
onChange.mockClear();
onFocus.mockClear();
testServerRoute(server, '/api/admin/ui-config', {});
});

it('renders with default state', () => {
Expand Down
Expand Up @@ -7,6 +7,7 @@ import {
ISelectProjectInputProps,
SelectProjectInput,
} from './SelectProjectInput';
import { testServerRoute, testServerSetup } from 'utils/testServer';

const onChange = vi.fn();
const onFocus = vi.fn();
Expand All @@ -22,10 +23,13 @@ const mockProps: ISelectProjectInputProps = {
onFocus,
};

const server = testServerSetup();

describe('SelectProjectInput', () => {
beforeEach(() => {
onChange.mockClear();
onFocus.mockClear();
testServerRoute(server, '/api/admin/ui-config', {});
});

it('renders with default state', () => {
Expand Down
288 changes: 288 additions & 0 deletions frontend/src/component/changeRequest/ChangeRequest.test.tsx
@@ -0,0 +1,288 @@
import {
render,
screen,
waitFor,
within,
getAllByRole,
fireEvent,
} from '@testing-library/react';
import { MemoryRouter, Routes, Route } from 'react-router-dom';
import { FeatureView } from '../feature/FeatureView/FeatureView';
import { ThemeProvider } from 'themes/ThemeProvider';
import { AccessProvider } from '../providers/AccessProvider/AccessProvider';
import { AnnouncerProvider } from '../common/Announcer/AnnouncerProvider/AnnouncerProvider';
import { testServerRoute, testServerSetup } from '../../utils/testServer';
import { UIProviderContainer } from '../providers/UIProvider/UIProviderContainer';
import { FC } from 'react';

const server = testServerSetup();

const pendingChangeRequest = (featureName: string) =>
testServerRoute(
server,
'api/admin/projects/default/change-requests/pending',
[
{
id: 156,
environment: 'production',
state: 'Draft',
minApprovals: 1,
project: 'default',
createdBy: {
id: 1,
username: 'admin',
imageUrl:
'https://gravatar.com/avatar/21232f297a57a5a743894a0e4a801fc3?size=42&default=retro',
},
createdAt: '2022-12-02T09:19:12.242Z',
features: [
{
name: featureName,
changes: [
{
id: 292,
action: 'addStrategy',
payload: {
name: 'default',
segments: [],
parameters: {},
constraints: [],
},
createdAt: '2022-12-02T09:19:12.245Z',
createdBy: {
id: 1,
username: 'admin',
imageUrl:
'https://gravatar.com/avatar/21232f297a57a5a743894a0e4a801fc3?size=42&default=retro',
},
},
],
},
],
approvals: [],
comments: [],
},
]
);

const changeRequestsEnabledIn = (env: string) =>
testServerRoute(
server,
'/api/admin/projects/default/change-requests/config',
[
{
environment: 'development',
type: 'development',
changeRequestEnabled: env === 'development',
},
{
environment: 'production',
type: 'production',
changeRequestEnabled: env === 'production',
},
]
);

const uiConfigForEnterprise = () =>
testServerRoute(server, '/api/admin/ui-config', {
environment: 'Open Source',
flags: {
changeRequests: true,
},
slogan: 'getunleash.io - All rights reserved',
name: 'Unleash enterprise',
links: [
{
value: 'Documentation',
icon: 'library_books',
href: 'https://docs.getunleash.io/docs',
title: 'User documentation',
},
{
value: 'GitHub',
icon: 'c_github',
href: 'https://github.com/Unleash/unleash',
title: 'Source code on GitHub',
},
],
version: '4.18.0-beta.5',
emailEnabled: false,
unleashUrl: 'http://localhost:4242',
baseUriPath: '',
authenticationType: 'enterprise',
segmentValuesLimit: 100,
strategySegmentsLimit: 5,
frontendApiOrigins: ['*'],
versionInfo: {
current: { oss: '4.18.0-beta.5', enterprise: '4.17.0-beta.1' },
latest: {},
isLatest: true,
instanceId: 'c7566052-15d7-4e09-9625-9c988e1f2be7',
},
disablePasswordAuth: false,
});

const featureList = (featureName: string) =>
testServerRoute(server, '/api/admin/projects/default', {
name: 'Default',
description: 'Default project',
health: 100,
updatedAt: '2022-11-14T10:15:59.228Z',
environments: ['development', 'production'],
features: [
{
type: 'release',
name: featureName,
createdAt: '2022-11-14T08:16:33.338Z',
lastSeenAt: null,
stale: false,
environments: [
{
name: 'development',
enabled: false,
type: 'development',
sortOrder: 100,
},
{
name: 'production',
enabled: false,
type: 'production',
sortOrder: 200,
},
],
},
],
members: 0,
version: 1,
});

const feature = ({ name, enabled }: { name: string; enabled: boolean }) =>
testServerRoute(server, `/api/admin/projects/default/features/${name}`, {
environments: [
{
name: 'development',
enabled: false,
type: 'development',
sortOrder: 100,
strategies: [],
},
{
name: 'production',
enabled,
type: 'production',
sortOrder: 200,
strategies: [],
},
],
name,
impressionData: false,
description: '',
project: 'default',
stale: false,
variants: [],
createdAt: '2022-11-14T08:16:33.338Z',
lastSeenAt: null,
type: 'release',
archived: false,
});

const otherRequests = (feature: string) => {
testServerRoute(server, `api/admin/client-metrics/features/${feature}`, {
version: 1,
maturity: 'stable',
featureName: feature,
lastHourUsage: [],
seenApplications: [],
});
testServerRoute(server, `api/admin/features/${feature}/tags`, {
version: 1,
tags: [],
});
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 UnleashUiSetup: FC<{ path: string; pathTemplate: string }> = ({
children,
path,
pathTemplate,
}) => (
<UIProviderContainer>
<AccessProvider>
<MemoryRouter initialEntries={[path]}>
<ThemeProvider>
<AnnouncerProvider>
<Routes>
<Route path={pathTemplate} element={children} />
</Routes>
</AnnouncerProvider>
</ThemeProvider>
</MemoryRouter>
</AccessProvider>
</UIProviderContainer>
);

const setupHttpRoutes = ({
featureName,
enabled,
}: {
featureName: string;
enabled: boolean;
}) => {
pendingChangeRequest(featureName);
changeRequestsEnabledIn('production');
uiConfigForEnterprise();
featureList(featureName);
feature({ name: featureName, enabled });
otherRequests(featureName);
};

const verifyBannerForPendingChangeRequest = async () => {
return screen.findByText('Change request mode', {}, { timeout: 5000 });
};

const changeToggle = async (environment: string) => {
const featureToggleStatusBox = screen.getByTestId('feature-toggle-status');
await within(featureToggleStatusBox).findByText(environment);
const toggle = screen.getAllByRole('checkbox')[1];
fireEvent.click(toggle);
};

const verifyChangeRequestDialog = async (bannerMainText: string) => {
await screen.findByText('Your suggestion:');
const message = screen.getByTestId('update-enabled-message').textContent;
expect(message).toBe(bannerMainText);
};

test('add toggle change to pending change request', async () => {
setupHttpRoutes({ featureName: 'test', enabled: false });

render(
<UnleashUiSetup
pathTemplate="/projects/:projectId/features/:featureId/*"
path="/projects/default/features/test"
>
<FeatureView />
</UnleashUiSetup>
);

await verifyBannerForPendingChangeRequest();

await changeToggle('production');

await verifyChangeRequestDialog('Enable feature toggle test in production');
});
Expand Up @@ -224,6 +224,7 @@ export const ChangeRequest: VFC<IChangeRequestProps> = ({
>
{feature.changes.map((change, index) => (
<Change
key={index}
onDiscard={onDiscard(change.id)}
index={index}
changeRequest={changeRequest}
Expand Down
Expand Up @@ -11,7 +11,7 @@ export const UpdateEnabledMessage = ({
featureName,
environment,
}: UpdateEnabledMsg) => (
<Typography>
<Typography data-testid="update-enabled-message">
<strong>{enabled ? 'Enable' : 'Disable'}</strong> feature toggle{' '}
<strong>{featureName}</strong> in <strong>{environment}</strong>
</Typography>
Expand Down
Expand Up @@ -5,6 +5,13 @@ import { screen } from '@testing-library/react';
import { addDays, subDays } from 'date-fns';
import { INSTANCE_STATUS_BAR_ID } from 'utils/testIds';
import { UNKNOWN_INSTANCE_STATUS } from 'hooks/api/getters/useInstanceStatus/useInstanceStatus';
import { testServerRoute, testServerSetup } from 'utils/testServer';

const server = testServerSetup();

beforeEach(() => {
testServerRoute(server, '/api/admin/ui-config', {});
});

test('InstanceStatusBar should be hidden by default', async () => {
render(<InstanceStatusBar instanceStatus={UNKNOWN_INSTANCE_STATUS} />);
Expand Down
Expand Up @@ -44,6 +44,7 @@ const PermissionSwitch = React.forwardRef<
<TooltipResolver title={formatAccessText(access, tooltip)} arrow>
<span data-loading>
<Switch
data-testid="toggle-switch"
onChange={onChange}
disabled={disabled || !access}
checked={checked}
Expand Down
Expand Up @@ -70,7 +70,7 @@ const FeatureOverviewEnvSwitches = () => {
};

return (
<StyledContainer>
<StyledContainer data-testid="feature-toggle-status">
<StyledHeader data-loading>
Feature toggle status
<HelpIcon
Expand Down
Expand Up @@ -9,6 +9,7 @@ import { render } from 'utils/testRenderer';
const server = testServerSetup();

test('should render password auth', async () => {
testServerRoute(server, '/api/admin/ui-config', {});
testServerRoute(server, '/api/admin/user', {});
testServerRoute(server, '/auth/reset/validate', {
name: INVALID_TOKEN_ERROR,
Expand Down

0 comments on commit c4f3ada

Please sign in to comment.