Merge pull request #10614 from keithjgrant/test-cleanup

Test cleanup

SUMMARY

Makes a unit test fail if any errors or warnings are logged (see setupTest.js)
Updates/fixes all tests that were logging errors
Fixes a key cause of test flake caused by Jobs.test.jsx (I have still seen a rogue "Network error" cause a flaky failure once; which I will hopefully take care of in a subsequent PR)
Removes all unnecessary calls to wrapper.unmount() (this also surfaced several instances of tests leaving asynchronous code running after test completion, which are now fixed)

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

Reviewed-by: Kersom <None>
Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
This commit is contained in:
softwarefactory-project-zuul[bot] 2021-07-14 19:33:32 +00:00 committed by GitHub
commit 0e75193e3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
194 changed files with 688 additions and 1032 deletions

View File

@ -31,6 +31,5 @@ describe('<App />', () => {
});
expect(wrapper.length).toBe(1);
jest.clearAllMocks();
wrapper.unmount();
});
});

View File

@ -1,22 +1,23 @@
import React from 'react';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import { shallow } from 'enzyme';
import About from './About';
describe('<About />', () => {
let aboutWrapper;
let closeButton;
const onClose = jest.fn();
test('initially renders without crashing', () => {
aboutWrapper = mountWithContexts(<About isOpen onClose={onClose} />);
expect(aboutWrapper.length).toBe(1);
aboutWrapper.unmount();
});
jest.mock('../../util/useBrandName', () => ({
__esModule: true,
default: () => ({
current: 'AWX',
}),
}));
test('close button calls onClose handler', () => {
aboutWrapper = mountWithContexts(<About isOpen onClose={onClose} />);
closeButton = aboutWrapper.find('AboutModalBoxCloseButton Button');
closeButton.simulate('click');
expect(onClose).toBeCalled();
aboutWrapper.unmount();
describe('<About />', () => {
test('should render AboutModal', () => {
const onClose = jest.fn();
const wrapper = shallow(<About isOpen onClose={onClose} />);
const modal = wrapper.find('AboutModal');
expect(modal).toHaveLength(1);
expect(modal.prop('onClose')).toEqual(onClose);
expect(modal.prop('productName')).toEqual('AWX');
expect(modal.prop('isOpen')).toEqual(true);
});
});

View File

@ -76,8 +76,8 @@ describe('<AdHocCommands />', () => {
});
});
let wrapper;
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});

View File

@ -54,7 +54,6 @@ describe('<AdHocCommandsWizard/>', () => {
});
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should mount properly', async () => {

View File

@ -36,7 +36,6 @@ describe('<AdHocCredentialStep />', () => {
});
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should mount properly', async () => {

View File

@ -33,9 +33,9 @@ describe('<AdHocExecutionEnvironmentStep />', () => {
);
});
});
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should mount properly', async () => {

View File

@ -16,7 +16,6 @@ jest.mock('../../api/models/Users');
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useHistory: () => ({ push: jest.fn(), location: { pathname: {} } }),
}));
// TODO: Once error handling is functional in

View File

@ -34,6 +34,7 @@ describe('<SelectRoleStep />', () => {
name: 'foo',
},
];
test('initially renders without crashing', () => {
wrapper = shallowWithContexts(
<SelectRoleStep
@ -43,8 +44,8 @@ describe('<SelectRoleStep />', () => {
/>
);
expect(wrapper.length).toBe(1);
wrapper.unmount();
});
test('clicking role fires onRolesClick callback', () => {
const onRolesClick = jest.fn();
wrapper = mountWithContexts(
@ -63,6 +64,5 @@ describe('<SelectRoleStep />', () => {
name: 'Project Admin',
description: 'Can manage all projects of the organization',
});
wrapper.unmount();
});
});

View File

@ -1,5 +1,5 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import PropTypes, { oneOfType, string, arrayOf } from 'prop-types';
import { matchPath, Link, withRouter } from 'react-router-dom';
import { NavExpandable, NavItem } from '@patternfly/react-core';
@ -58,9 +58,9 @@ class NavExpandableGroup extends Component {
}
NavExpandableGroup.propTypes = {
groupId: PropTypes.string.isRequired,
groupTitle: PropTypes.element.isRequired,
routes: PropTypes.arrayOf(PropTypes.object).isRequired,
groupId: string.isRequired,
groupTitle: oneOfType([PropTypes.element, string]).isRequired,
routes: arrayOf(PropTypes.object).isRequired,
};
export default withRouter(NavExpandableGroup);

View File

@ -14,10 +14,6 @@ describe('PageHeaderToolbar', () => {
const onAboutClick = jest.fn();
const onLogoutClick = jest.fn();
afterEach(() => {
wrapper.unmount();
});
test('expected content is rendered on initialization', async () => {
await act(async () => {
wrapper = mountWithContexts(

View File

@ -6,14 +6,18 @@ import CheckboxListItem from './CheckboxListItem';
describe('CheckboxListItem', () => {
test('renders the expected content', () => {
const wrapper = mount(
<CheckboxListItem
itemId={1}
name="Buzz"
label="Buzz"
isSelected={false}
onSelect={() => {}}
onDeselect={() => {}}
/>
<table>
<tbody>
<CheckboxListItem
itemId={1}
name="Buzz"
label="Buzz"
isSelected={false}
onSelect={() => {}}
onDeselect={() => {}}
/>
</tbody>
</table>
);
expect(wrapper).toHaveLength(1);
});

View File

@ -8,7 +8,7 @@ jest.mock('../../api');
describe('<VariablesDetail>', () => {
test('should render readonly CodeEditor', () => {
const wrapper = mountWithContexts(
<VariablesDetail value="---foo: bar" label="Variables" />
<VariablesDetail value="---foo: bar" label="Variables" name="test" />
);
const input = wrapper.find('VariablesDetail___StyledCodeEditor');
expect(input).toHaveLength(1);
@ -19,7 +19,7 @@ describe('<VariablesDetail>', () => {
test('should detect JSON', () => {
const wrapper = mountWithContexts(
<VariablesDetail value='{"foo": "bar"}' label="Variables" />
<VariablesDetail value='{"foo": "bar"}' label="Variables" name="test" />
);
const input = wrapper.find('VariablesDetail___StyledCodeEditor');
expect(input).toHaveLength(1);
@ -28,7 +28,7 @@ describe('<VariablesDetail>', () => {
test('should format JSON', () => {
const wrapper = mountWithContexts(
<VariablesDetail value='{"foo": "bar"}' label="Variables" />
<VariablesDetail value='{"foo": "bar"}' label="Variables" name="test" />
);
const input = wrapper.find('VariablesDetail___StyledCodeEditor');
expect(input).toHaveLength(1);
@ -37,7 +37,7 @@ describe('<VariablesDetail>', () => {
test('should convert between modes', () => {
const wrapper = mountWithContexts(
<VariablesDetail value="---foo: bar" label="Variables" />
<VariablesDetail value="---foo: bar" label="Variables" name="test" />
);
wrapper.find('MultiButtonToggle').invoke('onChange')('javascript');
const input = wrapper.find('VariablesDetail___StyledCodeEditor');
@ -52,7 +52,7 @@ describe('<VariablesDetail>', () => {
test('should render label and value --- when there are no values', () => {
const wrapper = mountWithContexts(
<VariablesDetail value="" label="Variables" />
<VariablesDetail value="" label="Variables" name="test" />
);
expect(wrapper.find('VariablesDetail___StyledCodeEditor').length).toBe(1);
expect(wrapper.find('.pf-c-form__label').text()).toBe('Variables');
@ -60,7 +60,7 @@ describe('<VariablesDetail>', () => {
test('should update value if prop changes', () => {
const wrapper = mountWithContexts(
<VariablesDetail value="---foo: bar" label="Variables" />
<VariablesDetail value="---foo: bar" label="Variables" name="test" />
);
act(() => {
wrapper.find('MultiButtonToggle').invoke('onChange')('javascript');
@ -76,7 +76,7 @@ describe('<VariablesDetail>', () => {
test('should default yaml value to "---"', () => {
const wrapper = mountWithContexts(
<VariablesDetail value="" label="Variables" />
<VariablesDetail value="" label="Variables" name="test" />
);
const input = wrapper.find('VariablesDetail___StyledCodeEditor');
expect(input.prop('value')).toEqual('---');
@ -84,7 +84,7 @@ describe('<VariablesDetail>', () => {
test('should default empty json to "{}"', () => {
const wrapper = mountWithContexts(
<VariablesDetail value="" label="Variables" />
<VariablesDetail value="" label="Variables" name="test" />
);
act(() => {
wrapper.find('MultiButtonToggle').invoke('onChange')('javascript');

View File

@ -8,9 +8,6 @@ jest.mock('../../api');
let wrapper;
describe('<CopyButton/>', () => {
afterEach(() => {
wrapper.unmount();
});
test('should mount properly', async () => {
await act(async () => {
wrapper = mountWithContexts(
@ -24,6 +21,7 @@ describe('<CopyButton/>', () => {
});
expect(wrapper.find('CopyButton').length).toBe(1);
});
test('should call the correct function on button click', async () => {
const copyItem = jest.fn();
await act(async () => {

View File

@ -1,5 +1,6 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { shallow } from 'enzyme';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import DataListToolbar from './DataListToolbar';
import AddDropDownButton from '../AddDropDownButton/AddDropDownButton';
@ -14,13 +15,6 @@ describe('<DataListToolbar />', () => {
integerFields: ['page', 'page_size'],
};
afterEach(() => {
if (toolbar) {
toolbar.unmount();
toolbar = null;
}
});
const onSearch = jest.fn();
const onReplaceSearch = jest.fn();
const onSort = jest.fn();
@ -100,6 +94,7 @@ describe('<DataListToolbar />', () => {
searchColumns={searchColumns}
sortColumns={sortColumns}
onSort={onSort}
onSearch={() => {}}
/>
);
const sortDropdownToggle = toolbar.find(sortDropdownToggleSelector);
@ -122,6 +117,7 @@ describe('<DataListToolbar />', () => {
searchColumns={searchColumns}
sortColumns={sortColumns}
onSort={onSort}
onSearch={() => {}}
/>
);
toolbar.update();
@ -155,92 +151,28 @@ describe('<DataListToolbar />', () => {
searchDropdownItems.at(0).simulate('click', mockedSearchEvent);
});
test('it displays correct sort icon', () => {
const NUM_QS_CONFIG = {
test('should render sort icon', () => {
const qsConfig = {
namespace: 'organization',
dateFields: ['modified', 'created'],
defaultParams: { page: 1, page_size: 5, order_by: 'id' },
integerFields: ['page', 'page_size', 'id'],
};
const sortColumns = [{ name: 'Name', key: 'name' }];
const NUM_DESC_QS_CONFIG = {
namespace: 'organization',
dateFields: ['modified', 'created'],
defaultParams: { page: 1, page_size: 5, order_by: '-id' },
integerFields: ['page', 'page_size', 'id'],
};
const ALPH_QS_CONFIG = {
namespace: 'organization',
dateFields: ['modified', 'created'],
defaultParams: { page: 1, page_size: 5, order_by: 'name' },
integerFields: ['page', 'page_size', 'id'],
};
const ALPH_DESC_QS_CONFIG = {
namespace: 'organization',
dateFields: ['modified', 'created'],
defaultParams: { page: 1, page_size: 5, order_by: '-name' },
integerFields: ['page', 'page_size', 'id'],
};
const forwardNumericIconSelector = 'SortNumericDownIcon';
const reverseNumericIconSelector = 'SortNumericDownAltIcon';
const forwardAlphaIconSelector = 'SortAlphaDownIcon';
const reverseAlphaIconSelector = 'SortAlphaDownAltIcon';
const numericColumns = [{ name: 'ID', key: 'id' }];
const alphaColumns = [{ name: 'Name', key: 'name' }];
const searchColumns = [
{ name: 'Name', key: 'name', isDefault: true },
{ name: 'ID', key: 'id' },
];
toolbar = mountWithContexts(
const wrapper = shallow(
<DataListToolbar
qsConfig={NUM_DESC_QS_CONFIG}
searchColumns={searchColumns}
sortColumns={numericColumns}
qsConfig={qsConfig}
searchColumns={[{ name: 'ID', key: 'id' }]}
sortColumns={sortColumns}
onSort={onSort}
/>
);
const reverseNumericIcon = toolbar.find(reverseNumericIconSelector);
expect(reverseNumericIcon.length).toBe(1);
toolbar = mountWithContexts(
<DataListToolbar
qsConfig={NUM_QS_CONFIG}
searchColumns={searchColumns}
sortColumns={numericColumns}
/>
);
const forwardNumericIcon = toolbar.find(forwardNumericIconSelector);
expect(forwardNumericIcon.length).toBe(1);
toolbar = mountWithContexts(
<DataListToolbar
qsConfig={ALPH_DESC_QS_CONFIG}
searchColumns={searchColumns}
sortColumns={alphaColumns}
/>
);
const reverseAlphaIcon = toolbar.find(reverseAlphaIconSelector);
expect(reverseAlphaIcon.length).toBe(1);
toolbar = mountWithContexts(
<DataListToolbar
qsConfig={ALPH_QS_CONFIG}
searchColumns={searchColumns}
sortColumns={alphaColumns}
/>
);
const forwardAlphaIcon = toolbar.find(forwardAlphaIconSelector);
expect(forwardAlphaIcon.length).toBe(1);
const sort = wrapper.find('Sort');
expect(sort.prop('qsConfig')).toEqual(qsConfig);
expect(sort.prop('columns')).toEqual(sortColumns);
expect(sort.prop('onSort')).toEqual(onSort);
});
test('should render additionalControls', () => {

View File

@ -40,7 +40,6 @@ describe('<DisassociateButton />', () => {
afterAll(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should render button', () => {

View File

@ -36,6 +36,10 @@ function ErrorDetail({ error }) {
const { response } = error;
const [isExpanded, setIsExpanded] = useState(false);
if (!error) {
return null;
}
const handleToggle = () => {
setIsExpanded(!isExpanded);
};
@ -84,7 +88,10 @@ function ErrorDetail({ error }) {
}
ErrorDetail.propTypes = {
error: PropTypes.instanceOf(Error).isRequired,
error: PropTypes.instanceOf(Error),
};
ErrorDetail.defaultProps = {
error: null,
};
export default ErrorDetail;

View File

@ -15,6 +15,5 @@ describe('<ExpandCollapse />', () => {
/>
);
expect(wrapper.length).toBe(1);
wrapper.unmount();
});
});

View File

@ -6,10 +6,6 @@ import FieldWithPrompt from './FieldWithPrompt';
describe('FieldWithPrompt', () => {
let wrapper;
afterEach(() => {
wrapper.unmount();
});
test('Required asterisk and Popover hidden when not required and tooltip not provided', () => {
wrapper = mountWithContexts(
<Formik

View File

@ -5,9 +5,6 @@ import JobListCancelButton from './JobListCancelButton';
describe('<JobListCancelButton />', () => {
let wrapper;
afterEach(() => {
wrapper.unmount();
});
test('should be disabled when no rows are selected', () => {
wrapper = mountWithContexts(<JobListCancelButton jobsToCancel={[]} />);
expect(wrapper.find('JobListCancelButton button').props().disabled).toBe(

View File

@ -41,10 +41,6 @@ describe('<JobListItem />', () => {
);
});
afterEach(() => {
wrapper.unmount();
});
test('initially renders successfully', () => {
expect(wrapper.find('JobListItem').length).toBe(1);
});
@ -118,10 +114,6 @@ describe('<JobListItem with failed job />', () => {
);
});
afterEach(() => {
wrapper.unmount();
});
test('launch button shown to users with launch capabilities', () => {
expect(wrapper.find('LaunchButton').length).toBe(1);
});

View File

@ -24,7 +24,6 @@ describe('ListHeader', () => {
/>
);
expect(wrapper.length).toBe(1);
wrapper.unmount();
});
test('should navigate when DataListToolbar calls onSort prop', async () => {

View File

@ -36,7 +36,6 @@ describe('ApplicationLookup', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should render successfully', async () => {

View File

@ -38,7 +38,6 @@ describe('ExecutionEnvironmentLookup', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should render successfully', async () => {

View File

@ -26,7 +26,6 @@ describe('InventoryLookup', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should render successfully and fetch data', async () => {

View File

@ -7,6 +7,7 @@ import {
number,
oneOfType,
shape,
node,
} from 'prop-types';
import { withRouter } from 'react-router-dom';
import { useField } from 'formik';
@ -206,7 +207,7 @@ const Item = shape({
Lookup.propTypes = {
id: string,
header: string,
modalDescription: string,
modalDescription: oneOfType([string, node]),
onChange: func.isRequired,
value: oneOfType([Item, arrayOf(Item)]),
multiple: bool,

View File

@ -122,7 +122,6 @@ describe('<Formik><MultiCredentialsLookup /></Formik>', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should load credential types', async () => {

View File

@ -12,7 +12,6 @@ describe('OrganizationLookup', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should render successfully', async () => {

View File

@ -10,6 +10,7 @@ const SmallButton = styled(Button)`
font-size: var(--pf-global--FontSize--xs);
}
`;
SmallButton.displayName = 'SmallButton';
function MultiButtonToggle({ buttons, value, onChange, name }) {
const setValue = newValue => {

View File

@ -1,12 +1,13 @@
import React from 'react';
import { mount } from 'enzyme';
import { shallow } from 'enzyme';
import MultiButtonToggle from './MultiButtonToggle';
describe('<MultiButtonToggle />', () => {
let wrapper;
const onChange = jest.fn();
beforeAll(() => {
wrapper = mount(
wrapper = shallow(
<MultiButtonToggle
buttons={[
['yaml', 'YAML'],
@ -14,20 +15,20 @@ describe('<MultiButtonToggle />', () => {
]}
value="yaml"
onChange={onChange}
name="the-button"
/>
);
});
afterAll(() => {
wrapper.unmount();
});
it('should render buttons successfully', () => {
const buttons = wrapper.find('Button');
const buttons = wrapper.find('SmallButton');
expect(buttons.length).toBe(2);
expect(buttons.at(0).props().variant).toBe('primary');
expect(buttons.at(1).props().variant).toBe('secondary');
});
it('should call onChange function when button clicked', () => {
const buttons = wrapper.find('Button');
const buttons = wrapper.find('SmallButton');
buttons.at(1).simulate('click');
expect(onChange).toHaveBeenCalledWith('json');
});

View File

@ -21,10 +21,6 @@ describe('<NotificationListItem canToggleNotifications />', () => {
});
afterEach(() => {
if (wrapper) {
wrapper.unmount();
wrapper = null;
}
jest.clearAllMocks();
});

View File

@ -40,8 +40,8 @@ describe('<ToolbarDeleteButton />', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should render button', () => {
wrapper = mountWithContexts(
<ToolbarDeleteButton onDelete={() => {}} itemsToDelete={[]} />

View File

@ -25,10 +25,6 @@ describe('PromptProjectDetail', () => {
);
});
afterAll(() => {
wrapper.unmount();
});
test('should render successfully', () => {
expect(wrapper.find('PromptProjectDetail')).toHaveLength(1);
});

View File

@ -133,7 +133,6 @@ describe('<ResourceAccessList />', () => {
});
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});

View File

@ -113,12 +113,11 @@ describe('<Schedule />', () => {
});
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
});
afterAll(() => {
wrapper.unmount();
});
test('renders successfully', async () => {
expect(wrapper.length).toBe(1);
});
test('expect all tabs to exist, including Back to Schedules', async () => {
expect(
wrapper.find('button[link="/templates/job_template/1/schedules"]').length

View File

@ -73,7 +73,9 @@ describe('<ScheduleAdd />', () => {
/>
);
});
wrapper.update();
});
test('Successfully creates a schedule with repeat frequency: None (run once)', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -95,6 +97,7 @@ describe('<ScheduleAdd />', () => {
'DTSTART;TZID=America/New_York:20200325T100000 RRULE:INTERVAL=1;COUNT=1;FREQ=MINUTELY',
});
});
test('Successfully creates a schedule with 10 minute repeat frequency after 10 occurrences', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -117,6 +120,7 @@ describe('<ScheduleAdd />', () => {
'DTSTART;TZID=America/New_York:20200325T103000 RRULE:INTERVAL=10;FREQ=MINUTELY;COUNT=10',
});
});
test('Successfully creates a schedule with hourly repeat frequency ending on a specific date/time', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -140,6 +144,7 @@ describe('<ScheduleAdd />', () => {
'DTSTART;TZID=America/New_York:20200325T104500 RRULE:INTERVAL=1;FREQ=HOURLY;UNTIL=20200326T104500',
});
});
test('Successfully creates a schedule with daily repeat frequency', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -161,6 +166,7 @@ describe('<ScheduleAdd />', () => {
'DTSTART;TZID=America/New_York:20200325T104500 RRULE:INTERVAL=1;FREQ=DAILY',
});
});
test('Successfully creates a schedule with weekly repeat frequency on mon/wed/fri', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -183,6 +189,7 @@ describe('<ScheduleAdd />', () => {
rrule: `DTSTART;TZID=America/New_York:20200325T104500 RRULE:INTERVAL=1;FREQ=WEEKLY;BYDAY=${RRule.MO},${RRule.WE},${RRule.FR}`,
});
});
test('Successfully creates a schedule with monthly repeat frequency on the first day of the month', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -207,6 +214,7 @@ describe('<ScheduleAdd />', () => {
'DTSTART;TZID=America/New_York:20200401T104500 RRULE:INTERVAL=1;FREQ=MONTHLY;BYMONTHDAY=1',
});
});
test('Successfully creates a schedule with monthly repeat frequency on the last tuesday of the month', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -259,6 +267,7 @@ describe('<ScheduleAdd />', () => {
'DTSTART;TZID=America/New_York:20200301T000000 RRULE:INTERVAL=1;FREQ=YEARLY;BYMONTH=3;BYMONTHDAY=1',
});
});
test('Successfully creates a schedule with yearly repeat frequency on the second Friday in April', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -285,6 +294,7 @@ describe('<ScheduleAdd />', () => {
'DTSTART;TZID=America/New_York:20200410T111500 RRULE:INTERVAL=1;FREQ=YEARLY;BYSETPOS=2;BYDAY=FR;BYMONTH=4',
});
});
test('Successfully creates a schedule with yearly repeat frequency on the first weekday in October', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -464,6 +474,7 @@ describe('<ScheduleAdd />', () => {
/>
);
});
scheduleSurveyWrapper.update();
await act(async () => {
scheduleSurveyWrapper.find('Formik').invoke('onSubmit')({
description: 'test description',

View File

@ -1,10 +1,7 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { RRule } from 'rrule';
import {
mountWithContexts,
waitForElement,
} from '../../../../testUtils/enzymeHelpers';
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
import {
SchedulesAPI,
InventoriesAPI,
@ -191,12 +188,13 @@ describe('<ScheduleEdit />', () => {
/>
);
});
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
wrapper.update();
});
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});
test('Successfully creates a schedule with repeat frequency: None (run once)', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -210,6 +208,7 @@ describe('<ScheduleEdit />', () => {
timezone: 'America/New_York',
});
});
expect(SchedulesAPI.update).toHaveBeenCalledWith(27, {
description: 'test description',
name: 'Run once schedule',
@ -218,6 +217,7 @@ describe('<ScheduleEdit />', () => {
'DTSTART;TZID=America/New_York:20200325T100000 RRULE:INTERVAL=1;COUNT=1;FREQ=MINUTELY',
});
});
test('Successfully creates a schedule with 10 minute repeat frequency after 10 occurrences', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -241,6 +241,7 @@ describe('<ScheduleEdit />', () => {
'DTSTART;TZID=America/New_York:20200325T103000 RRULE:INTERVAL=10;FREQ=MINUTELY;COUNT=10',
});
});
test('Successfully creates a schedule with hourly repeat frequency ending on a specific date/time', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -256,6 +257,7 @@ describe('<ScheduleEdit />', () => {
timezone: 'America/New_York',
});
});
expect(SchedulesAPI.update).toHaveBeenCalledWith(27, {
description: 'test description',
name: 'Run every hour until date',
@ -264,6 +266,7 @@ describe('<ScheduleEdit />', () => {
'DTSTART;TZID=America/New_York:20200325T104500 RRULE:INTERVAL=1;FREQ=HOURLY;UNTIL=20200326T104500',
});
});
test('Successfully creates a schedule with daily repeat frequency', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -308,6 +311,7 @@ describe('<ScheduleEdit />', () => {
rrule: `DTSTART;TZID=America/New_York:20200325T104500 RRULE:INTERVAL=1;FREQ=WEEKLY;BYDAY=${RRule.MO},${RRule.WE},${RRule.FR}`,
});
});
test('Successfully creates a schedule with monthly repeat frequency on the first day of the month', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -333,6 +337,7 @@ describe('<ScheduleEdit />', () => {
'DTSTART;TZID=America/New_York:20200401T104500 RRULE:INTERVAL=1;FREQ=MONTHLY;BYMONTHDAY=1',
});
});
test('Successfully creates a schedule with monthly repeat frequency on the last tuesday of the month', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -362,6 +367,7 @@ describe('<ScheduleEdit />', () => {
'DTSTART;TZID=America/New_York:20200331T110000 RRULE:INTERVAL=1;FREQ=MONTHLY;BYSETPOS=-1;BYDAY=TU',
});
});
test('Successfully creates a schedule with yearly repeat frequency on the first day of March', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -388,6 +394,7 @@ describe('<ScheduleEdit />', () => {
'DTSTART;TZID=America/New_York:20200301T000000 RRULE:INTERVAL=1;FREQ=YEARLY;BYMONTH=3;BYMONTHDAY=1',
});
});
test('Successfully creates a schedule with yearly repeat frequency on the second Friday in April', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -416,6 +423,7 @@ describe('<ScheduleEdit />', () => {
'DTSTART;TZID=America/New_York:20200410T111500 RRULE:INTERVAL=1;FREQ=YEARLY;BYSETPOS=2;BYDAY=FR;BYMONTH=4',
});
});
test('Successfully creates a schedule with yearly repeat frequency on the first weekday in October', async () => {
await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({
@ -653,6 +661,7 @@ describe('<ScheduleEdit />', () => {
'DTSTART;TZID=America/New_York:20200402T184500 RRULE:INTERVAL=1;COUNT=1;FREQ=MINUTELY',
});
});
test('should submit survey with default values properly, without opening prompt wizard', async () => {
let scheduleSurveyWrapper;
await act(async () => {
@ -741,6 +750,8 @@ describe('<ScheduleEdit />', () => {
/>
);
});
scheduleSurveyWrapper.update();
await act(async () => {
scheduleSurveyWrapper.find('Formik').invoke('onSubmit')({
description: 'test description',
@ -753,6 +764,7 @@ describe('<ScheduleEdit />', () => {
timezone: 'America/New_York',
});
});
expect(SchedulesAPI.update).toHaveBeenCalledWith(27, {
description: 'test description',
name: 'Run once schedule',

View File

@ -52,10 +52,6 @@ describe('ScheduleList', () => {
wrapper.update();
});
afterEach(() => {
wrapper.unmount();
});
test('should fetch schedules from api and render the list', () => {
expect(loadSchedules).toHaveBeenCalled();
expect(wrapper.find('ScheduleListItem').length).toBe(5);

View File

@ -64,10 +64,6 @@ describe('ScheduleListItem', () => {
);
});
afterAll(() => {
wrapper.unmount();
});
test('Name correctly shown with correct link', () => {
expect(
wrapper
@ -149,10 +145,6 @@ describe('ScheduleListItem', () => {
);
});
afterAll(() => {
wrapper.unmount();
});
test('Name correctly shown with correct link', () => {
expect(
wrapper
@ -217,10 +209,6 @@ describe('ScheduleListItem', () => {
);
});
afterAll(() => {
wrapper.unmount();
});
test('should show missing resource icon', () => {
expect(wrapper.find('ExclamationTriangleIcon').length).toBe(1);
expect(wrapper.find('ScheduleToggle').prop('isDisabled')).toBe(true);

View File

@ -15,15 +15,15 @@ describe('<ScheduleOccurrences>', () => {
/>
);
});
afterAll(() => {
wrapper.unmount();
});
test('Local option initially set', async () => {
expect(wrapper.find('MultiButtonToggle').props().value).toBe('local');
});
test('It renders the correct number of dates', async () => {
expect(wrapper.find('dd').children().length).toBe(2);
});
test('Clicking UTC button toggles the dates to utc', async () => {
wrapper.find('button[aria-label="UTC"]').simulate('click');
expect(wrapper.find('MultiButtonToggle').props().value).toBe('utc');
@ -44,6 +44,7 @@ describe('<ScheduleOccurrences>', () => {
).toBe('3/30/2020, 4:00:00 AM');
});
});
describe('Only one date passed in', () => {
test('Component should not render chldren', async () => {
wrapper = mountWithContexts(
@ -55,7 +56,6 @@ describe('<ScheduleOccurrences>', () => {
/>
);
expect(wrapper.find('ScheduleOccurrences').children().length).toBe(0);
wrapper.unmount();
});
});
});

View File

@ -19,6 +19,7 @@ describe('<Schedules />', () => {
jobTemplate={jobTemplate}
loadSchedules={() => {}}
loadScheduleOptions={() => {}}
apiModel={{ createSchedule: () => {} }}
/>,
{

View File

@ -178,7 +178,6 @@ function ScheduleForm({
hasDaysToKeepField,
handleCancel,
handleSubmit,
schedule,
submitError,
resource,
@ -234,8 +233,14 @@ function ScheduleForm({
{
zonesOptions: [],
credentials: [],
isLoading: true,
}
);
useEffect(() => {
loadScheduleData();
}, [loadScheduleData]);
const missingRequiredInventory = useCallback(() => {
let missingInventory = false;
if (
@ -357,10 +362,6 @@ function ScheduleForm({
hasCredentialsThatPrompt,
]);
useEffect(() => {
loadScheduleData();
}, [loadScheduleData]);
let showPromptButton = false;
if (

View File

@ -168,6 +168,7 @@ describe('<ScheduleForm />', () => {
expect(wrapper.find('ContentError').length).toBe(1);
});
});
describe('Cancel', () => {
test('should make the appropriate callback', async () => {
const handleCancel = jest.fn();
@ -226,8 +227,10 @@ describe('<ScheduleForm />', () => {
expect(handleCancel).toHaveBeenCalledTimes(1);
});
});
describe('Prompted Schedule', () => {
let promptWrapper;
beforeEach(async () => {
SchedulesAPI.readZoneInfo.mockResolvedValue({
data: [
@ -284,8 +287,8 @@ describe('<ScheduleForm />', () => {
el => el.length > 0
);
});
afterEach(() => {
promptWrapper.unmount();
jest.clearAllMocks();
});
@ -375,6 +378,7 @@ describe('<ScheduleForm />', () => {
promptWrapper.update();
expect(promptWrapper.find('Wizard').length).toBe(0);
});
test('should render prompt button with disabled save button', async () => {
await act(async () => {
wrapper = mountWithContexts(
@ -423,6 +427,7 @@ describe('<ScheduleForm />', () => {
);
});
});
describe('Add', () => {
beforeAll(async () => {
SchedulesAPI.readZoneInfo.mockResolvedValue({
@ -473,9 +478,7 @@ describe('<ScheduleForm />', () => {
});
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
});
afterAll(() => {
wrapper.unmount();
});
test('initially renders expected fields and values', () => {
const now = new Date();
const closestQuarterHour = new Date(
@ -503,6 +506,7 @@ describe('<ScheduleForm />', () => {
'none'
);
});
test('correct frequency details fields and values shown when frequency changed to minute', async () => {
const runFrequencySelect = wrapper.find(
'FormGroup[label="Run frequency"] FormSelect'
@ -526,6 +530,7 @@ describe('<ScheduleForm />', () => {
expect(wrapper.find('input#end-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').prop('checked')).toBe(false);
});
test('correct frequency details fields and values shown when frequency changed to hour', async () => {
const runFrequencySelect = wrapper.find(
'FormGroup[label="Run frequency"] FormSelect'
@ -549,6 +554,7 @@ describe('<ScheduleForm />', () => {
expect(wrapper.find('input#end-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').prop('checked')).toBe(false);
});
test('correct frequency details fields and values shown when frequency changed to day', async () => {
const runFrequencySelect = wrapper.find(
'FormGroup[label="Run frequency"] FormSelect'
@ -572,6 +578,7 @@ describe('<ScheduleForm />', () => {
expect(wrapper.find('input#end-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').prop('checked')).toBe(false);
});
test('correct frequency details fields and values shown when frequency changed to week', async () => {
const runFrequencySelect = wrapper.find(
'FormGroup[label="Run frequency"] FormSelect'
@ -595,6 +602,7 @@ describe('<ScheduleForm />', () => {
expect(wrapper.find('input#end-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').prop('checked')).toBe(false);
});
test('correct frequency details fields and values shown when frequency changed to month', async () => {
const runFrequencySelect = wrapper.find(
'FormGroup[label="Run frequency"] FormSelect'
@ -629,6 +637,7 @@ describe('<ScheduleForm />', () => {
expect(wrapper.find('select#schedule-run-on-day-month').length).toBe(0);
expect(wrapper.find('select#schedule-run-on-the-month').length).toBe(0);
});
test('correct frequency details fields and values shown when frequency changed to year', async () => {
const runFrequencySelect = wrapper.find(
'FormGroup[label="Run frequency"] FormSelect'
@ -663,6 +672,7 @@ describe('<ScheduleForm />', () => {
expect(wrapper.find('select#schedule-run-on-day-month').length).toBe(1);
expect(wrapper.find('select#schedule-run-on-the-month').length).toBe(1);
});
test('occurrences field properly shown when end after selection is made', async () => {
await act(async () => {
wrapper
@ -690,6 +700,7 @@ describe('<ScheduleForm />', () => {
});
wrapper.update();
});
test('error shown when end date/time comes before start date/time', async () => {
await act(async () => {
wrapper
@ -719,15 +730,12 @@ describe('<ScheduleForm />', () => {
);
});
await act(async () => {
wrapper.find('DatePicker[aria-label="End date"]').simulate('blur');
});
wrapper.update();
expect(wrapper.find('#schedule-End-datetime-helper').text()).toBe(
'Please select an end date/time that comes after the start date/time.'
);
});
test('error shown when on day number is not between 1 and 31', async () => {
act(() => {
wrapper.find('select[id="schedule-frequency"]').invoke('onChange')(
@ -761,6 +769,7 @@ describe('<ScheduleForm />', () => {
);
});
});
describe('Edit', () => {
beforeEach(async () => {
SchedulesAPI.readZoneInfo.mockResolvedValue({
@ -773,12 +782,12 @@ describe('<ScheduleForm />', () => {
SchedulesAPI.readCredentials.mockResolvedValue(credentials);
});
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});
test('should make API calls to fetch credentials, launch configuration, and survey configuration', async () => {
test('should make API calls to fetch credentials, launch configuration, and survey configuration', async () => {
await act(async () => {
wrapper = mountWithContexts(
<ScheduleForm
@ -906,6 +915,7 @@ describe('<ScheduleForm />', () => {
/>
);
});
wrapper.update();
expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible();
expect(wrapper.find('FormGroup[label="Run every"]').length).toBe(0);
@ -920,6 +930,7 @@ describe('<ScheduleForm />', () => {
'none'
);
});
test('initially renders expected fields and values with existing schedule that runs every 10 minutes', async () => {
await act(async () => {
wrapper = mountWithContexts(
@ -941,6 +952,8 @@ describe('<ScheduleForm />', () => {
/>
);
});
wrapper.update();
expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible();
expect(wrapper.find('FormGroup[label="End"]').length).toBe(1);
@ -959,6 +972,7 @@ describe('<ScheduleForm />', () => {
expect(wrapper.find('input#end-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').prop('checked')).toBe(false);
});
test('initially renders expected fields and values with existing schedule that runs every hour 10 times', async () => {
await act(async () => {
wrapper = mountWithContexts(
@ -981,6 +995,8 @@ describe('<ScheduleForm />', () => {
/>
);
});
wrapper.update();
expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible();
expect(wrapper.find('FormGroup[label="End"]').length).toBe(1);
@ -1000,6 +1016,7 @@ describe('<ScheduleForm />', () => {
expect(wrapper.find('input#end-on-date').prop('checked')).toBe(false);
expect(wrapper.find('input#schedule-occurrences').prop('value')).toBe(10);
});
test('initially renders expected fields and values with existing schedule that runs every day', async () => {
await act(async () => {
wrapper = mountWithContexts(
@ -1021,25 +1038,28 @@ describe('<ScheduleForm />', () => {
}}
/>
);
expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible();
expect(wrapper.find('FormGroup[label="Run every"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="End"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="On days"]').length).toBe(0);
expect(wrapper.find('FormGroup[label="Run on"]').length).toBe(0);
expect(wrapper.find('FormGroup[label="Occurrences"]').length).toBe(0);
expect(wrapper.find('FormGroup[label="End date/time"]').length).toBe(0);
nonRRuleValuesMatch();
expect(wrapper.find('select#schedule-frequency').prop('value')).toBe(
'day'
);
expect(wrapper.find('input#end-never').prop('checked')).toBe(true);
expect(wrapper.find('input#end-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').prop('checked')).toBe(false);
expect(wrapper.find('input#schedule-run-every').prop('value')).toBe(1);
});
wrapper.update();
expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible();
expect(wrapper.find('FormGroup[label="Run every"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="End"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="On days"]').length).toBe(0);
expect(wrapper.find('FormGroup[label="Run on"]').length).toBe(0);
expect(wrapper.find('FormGroup[label="Occurrences"]').length).toBe(0);
expect(wrapper.find('FormGroup[label="End date/time"]').length).toBe(0);
nonRRuleValuesMatch();
expect(wrapper.find('select#schedule-frequency').prop('value')).toBe(
'day'
);
expect(wrapper.find('input#end-never').prop('checked')).toBe(true);
expect(wrapper.find('input#end-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').prop('checked')).toBe(false);
expect(wrapper.find('input#schedule-run-every').prop('value')).toBe(1);
});
test('initially renders expected fields and values with existing schedule that runs every week on m/w/f until Jan 1, 2020', async () => {
await act(async () => {
wrapper = mountWithContexts(
@ -1062,6 +1082,8 @@ describe('<ScheduleForm />', () => {
/>
);
});
wrapper.update();
expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible();
expect(wrapper.find('FormGroup[label="End"]').length).toBe(1);
@ -1107,6 +1129,7 @@ describe('<ScheduleForm />', () => {
wrapper.find('TimePicker[aria-label="End time"]').prop('value')
).toBe('1:00 AM');
});
test('initially renders expected fields and values with existing schedule that runs every month on the last weekday', async () => {
await act(async () => {
wrapper = mountWithContexts(
@ -1128,37 +1151,43 @@ describe('<ScheduleForm />', () => {
}}
/>
);
expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible();
expect(wrapper.find('FormGroup[label="End"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="Run every"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="Run on"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="End date/time"]').length).toBe(0);
expect(wrapper.find('FormGroup[label="On days"]').length).toBe(0);
expect(wrapper.find('FormGroup[label="Occurrences"]').length).toBe(0);
nonRRuleValuesMatch();
expect(wrapper.find('select#schedule-frequency').prop('value')).toBe(
'month'
);
expect(wrapper.find('input#end-never').prop('checked')).toBe(true);
expect(wrapper.find('input#end-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').prop('checked')).toBe(false);
expect(wrapper.find('input#schedule-run-every').prop('value')).toBe(1);
expect(wrapper.find('input#schedule-run-on-day').prop('checked')).toBe(
false
);
expect(wrapper.find('input#schedule-run-on-the').prop('checked')).toBe(
true
);
expect(
wrapper.find('select#schedule-run-on-the-occurrence').prop('value')
).toBe(-1);
expect(
wrapper.find('select#schedule-run-on-the-day').prop('value')
).toBe('weekday');
});
wrapper.update();
expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible();
expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible();
expect(wrapper.find('FormGroup[label="End"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="Run every"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="Run on"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="End date/time"]').length).toBe(0);
expect(wrapper.find('FormGroup[label="On days"]').length).toBe(0);
expect(wrapper.find('FormGroup[label="Occurrences"]').length).toBe(0);
nonRRuleValuesMatch();
expect(wrapper.find('select#schedule-frequency').prop('value')).toBe(
'month'
);
expect(wrapper.find('input#end-never').prop('checked')).toBe(true);
expect(wrapper.find('input#end-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').prop('checked')).toBe(false);
expect(wrapper.find('input#schedule-run-every').prop('value')).toBe(1);
expect(wrapper.find('input#schedule-run-on-day').prop('checked')).toBe(
false
);
expect(wrapper.find('input#schedule-run-on-the').prop('checked')).toBe(
true
);
expect(
wrapper.find('select#schedule-run-on-the-occurrence').prop('value')
).toBe(-1);
expect(wrapper.find('select#schedule-run-on-the-day').prop('value')).toBe(
'weekday'
);
});
test('initially renders expected fields and values with existing schedule that runs every year on the May 6', async () => {
await act(async () => {
wrapper = mountWithContexts(
@ -1180,36 +1209,38 @@ describe('<ScheduleForm />', () => {
}}
/>
);
expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible();
expect(wrapper.find('FormGroup[label="End"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="Run every"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="Run on"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="End date/time"]').length).toBe(0);
expect(wrapper.find('FormGroup[label="On days"]').length).toBe(0);
expect(wrapper.find('FormGroup[label="Occurrences"]').length).toBe(0);
nonRRuleValuesMatch();
expect(wrapper.find('select#schedule-frequency').prop('value')).toBe(
'year'
);
expect(wrapper.find('input#end-never').prop('checked')).toBe(true);
expect(wrapper.find('input#end-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').prop('checked')).toBe(false);
expect(wrapper.find('input#schedule-run-every').prop('value')).toBe(1);
expect(wrapper.find('input#schedule-run-on-day').prop('checked')).toBe(
true
);
expect(wrapper.find('input#schedule-run-on-the').prop('checked')).toBe(
false
);
expect(
wrapper.find('select#schedule-run-on-day-month').prop('value')
).toBe(5);
expect(
wrapper.find('input#schedule-run-on-day-number').prop('value')
).toBe(6);
});
wrapper.update();
expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible();
expect(wrapper.find('FormGroup[label="End"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="Run every"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="Run on"]').length).toBe(1);
expect(wrapper.find('FormGroup[label="End date/time"]').length).toBe(0);
expect(wrapper.find('FormGroup[label="On days"]').length).toBe(0);
expect(wrapper.find('FormGroup[label="Occurrences"]').length).toBe(0);
nonRRuleValuesMatch();
expect(wrapper.find('select#schedule-frequency').prop('value')).toBe(
'year'
);
expect(wrapper.find('input#end-never').prop('checked')).toBe(true);
expect(wrapper.find('input#end-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').prop('checked')).toBe(false);
expect(wrapper.find('input#schedule-run-every').prop('value')).toBe(1);
expect(wrapper.find('input#schedule-run-on-day').prop('checked')).toBe(
true
);
expect(wrapper.find('input#schedule-run-on-the').prop('checked')).toBe(
false
);
expect(
wrapper.find('select#schedule-run-on-day-month').prop('value')
).toBe(5);
expect(
wrapper.find('input#schedule-run-on-day-number').prop('value')
).toBe(6);
});
});
});

View File

@ -5,10 +5,6 @@ import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import ScreenHeader from './ScreenHeader';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
}));
describe('<ScreenHeader />', () => {
let breadcrumbWrapper;
let breadcrumb;
@ -43,7 +39,6 @@ describe('<ScreenHeader />', () => {
expect(breadcrumbItem.first().text()).toBe('Foo');
expect(breadcrumbItem.last().text()).toBe('One');
expect(breadcrumbHeading.text()).toBe('Bar');
breadcrumbWrapper.unmount();
});
test('renders breadcrumb items defined in breadcrumbConfig', () => {
@ -66,7 +61,6 @@ describe('<ScreenHeader />', () => {
expect(breadcrumbWrapper.find('BreadcrumbItem')).toHaveLength(
crumbLength
);
breadcrumbWrapper.unmount();
});
});
});

View File

@ -7,7 +7,6 @@ describe('<AdvancedSearch />', () => {
let wrapper;
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});

View File

@ -8,11 +8,10 @@ describe('<SelectableCard />', () => {
test('initially renders without crashing when not selected', () => {
wrapper = shallow(<SelectableCard onClick={onClick} />);
expect(wrapper.length).toBe(1);
wrapper.unmount();
});
test('initially renders without crashing when selected', () => {
wrapper = shallow(<SelectableCard isSelected onClick={onClick} />);
expect(wrapper.length).toBe(1);
wrapper.unmount();
});
});

View File

@ -6,8 +6,8 @@ describe('<DraggableSelectedList />', () => {
let wrapper;
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should render expected rows', () => {
const mockSelected = [
{

View File

@ -147,4 +147,7 @@ Sort.defaultProps = {
onSort: null,
};
export default withRouter(Sort);
export { Sort as _Sort };
const Wrapped = withRouter(Sort);
Wrapped.displayName = 'Sort';
export default Wrapped;

View File

@ -1,11 +1,19 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { shallow } from 'enzyme';
import {
mountWithContexts,
waitForElement,
} from '../../../testUtils/enzymeHelpers';
import Sort from './Sort';
import Sort, { _Sort as SortUnwrapped } from './Sort';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useLocation: () => ({
pathname: '/organizations',
}),
}));
describe('<Sort />', () => {
let sort;
@ -16,7 +24,7 @@ describe('<Sort />', () => {
}
});
test('it triggers the expected callbacks', () => {
test('should trigger onSort callback', () => {
const qsConfig = {
namespace: 'item',
defaultParams: { page: 1, page_size: 5, order_by: 'name' },
@ -150,71 +158,79 @@ describe('<Sort />', () => {
expect(onSort).toBeCalledWith('bar', 'ascending');
});
test('It displays correct sort icon', () => {
const forwardNumericIconSelector = 'SortNumericDownIcon';
const reverseNumericIconSelector = 'SortNumericDownAltIcon';
const forwardAlphaIconSelector = 'SortAlphaDownIcon';
const reverseAlphaIconSelector = 'SortAlphaDownAltIcon';
test('should display numeric descending icon', () => {
const qsConfigNumDown = {
namespace: 'item',
defaultParams: { page: 1, page_size: 5, order_by: '-id' },
integerFields: ['page', 'page_size', 'id'],
};
const numericColumns = [{ name: 'ID', key: 'id' }];
const wrapper = shallow(
<SortUnwrapped
qsConfig={qsConfigNumDown}
columns={numericColumns}
onSort={jest.fn()}
/>
);
expect(wrapper.find('SortNumericDownAltIcon')).toHaveLength(1);
});
test('should display numeric ascending icon', () => {
const qsConfigNumUp = {
namespace: 'item',
defaultParams: { page: 1, page_size: 5, order_by: 'id' },
integerFields: ['page', 'page_size', 'id'],
};
const numericColumns = [{ name: 'ID', key: 'id' }];
const wrapper = shallow(
<SortUnwrapped
qsConfig={qsConfigNumUp}
columns={numericColumns}
onSort={jest.fn()}
/>
);
expect(wrapper.find('SortNumericDownIcon')).toHaveLength(1);
});
test('should display alphanumeric descending icon', () => {
const qsConfigAlphaDown = {
namespace: 'item',
defaultParams: { page: 1, page_size: 5, order_by: '-name' },
integerFields: ['page', 'page_size'],
};
const qsConfigAlphaUp = {
const alphaColumns = [{ name: 'Name', key: 'name' }];
const wrapper = shallow(
<SortUnwrapped
qsConfig={qsConfigAlphaDown}
columns={alphaColumns}
onSort={jest.fn()}
/>
);
expect(wrapper.find('SortAlphaDownAltIcon')).toHaveLength(1);
});
test('should display alphanumeric ascending icon', () => {
const qsConfigAlphaDown = {
namespace: 'item',
defaultParams: { page: 1, page_size: 5, order_by: 'name' },
integerFields: ['page', 'page_size'],
};
const numericColumns = [{ name: 'ID', key: 'id' }];
const alphaColumns = [{ name: 'Name', key: 'name' }];
const onSort = jest.fn();
sort = mountWithContexts(
<Sort
qsConfig={qsConfigNumDown}
columns={numericColumns}
onSort={onSort}
/>
);
const reverseNumericIcon = sort.find(reverseNumericIconSelector);
expect(reverseNumericIcon.length).toBe(1);
sort = mountWithContexts(
<Sort qsConfig={qsConfigNumUp} columns={numericColumns} onSort={onSort} />
);
const forwardNumericIcon = sort.find(forwardNumericIconSelector);
expect(forwardNumericIcon.length).toBe(1);
sort = mountWithContexts(
<Sort
const wrapper = shallow(
<SortUnwrapped
qsConfig={qsConfigAlphaDown}
columns={alphaColumns}
onSort={onSort}
onSort={jest.fn()}
/>
);
const reverseAlphaIcon = sort.find(reverseAlphaIconSelector);
expect(reverseAlphaIcon.length).toBe(1);
sort = mountWithContexts(
<Sort qsConfig={qsConfigAlphaUp} columns={alphaColumns} onSort={onSort} />
);
const forwardAlphaIcon = sort.find(forwardAlphaIconSelector);
expect(forwardAlphaIcon.length).toBe(1);
expect(wrapper.find('SortAlphaDownIcon')).toHaveLength(1);
});
});

View File

@ -1,25 +1,17 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import ActivityStream from './ActivityStream';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
}));
jest.mock('../../api');
describe('<ActivityStream />', () => {
let pageWrapper;
beforeEach(() => {
pageWrapper = mountWithContexts(<ActivityStream />);
});
afterEach(() => {
pageWrapper.unmount();
});
test('initially renders without crashing', () => {
test('initially renders without crashing', async () => {
let pageWrapper;
await act(async () => {
pageWrapper = await mountWithContexts(<ActivityStream />);
});
expect(pageWrapper.length).toBe(1);
});
});

View File

@ -15,6 +15,7 @@ jest.mock('react-router-dom', () => ({
}),
useParams: () => ({ id: 1 }),
}));
const options = {
data: {
actions: {

View File

@ -1,21 +1,13 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { createMemoryHistory } from 'history';
import { shallow } from 'enzyme';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import Applications from './Applications';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
}));
describe('<Applications />', () => {
let wrapper;
afterEach(() => {
wrapper.unmount();
});
test('renders successfully', () => {
wrapper = mountWithContexts(<Applications />);
const pageSections = wrapper.find('PageSection');
@ -28,22 +20,20 @@ describe('<Applications />', () => {
const history = createMemoryHistory({
initialEntries: ['/applications/add'],
});
wrapper = mountWithContexts(<Applications />, {
wrapper = shallow(<Applications />, {
context: { router: { history } },
});
expect(wrapper.find('Modal[title="Application information"]').length).toBe(
0
);
await act(async () => {
wrapper
.find('ApplicationAdd')
.props()
.onSuccessfulAdd({
name: 'test',
client_id: 'foobar',
client_secret: 'aaaaaaaaaaaaaaaaaaaaaaaaaa',
});
});
wrapper
.find('ApplicationAdd')
.props()
.onSuccessfulAdd({
name: 'test',
client_id: 'foobar',
client_secret: 'aaaaaaaaaaaaaaaaaaaaaaaaaa',
});
wrapper.update();
expect(wrapper.find('Modal[title="Application information"]').length).toBe(
1

View File

@ -196,7 +196,6 @@ describe('<CredentialAdd />', () => {
});
wrapper.update();
expect(wrapper.find('ContentError').length).toBe(1);
wrapper.unmount();
});
});
});

View File

@ -350,10 +350,6 @@ describe('<CredentialEdit />', () => {
});
});
afterEach(() => {
wrapper.unmount();
});
test('initially renders successfully', async () => {
expect(wrapper.find('CredentialEdit').length).toBe(1);
});
@ -489,7 +485,6 @@ describe('<CredentialEdit />', () => {
});
wrapper.update();
expect(wrapper.find('ContentError').length).toBe(1);
wrapper.unmount();
});
});
});

View File

@ -33,7 +33,6 @@ describe('<CredentialList />', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('initially renders successfully', () => {

View File

@ -10,10 +10,6 @@ jest.mock('../../../api');
describe('<CredentialListItem />', () => {
let wrapper;
afterEach(() => {
wrapper.unmount();
});
test('edit button shown to users with edit capabilities', () => {
wrapper = mountWithContexts(
<table>

View File

@ -1,60 +1,16 @@
import React from 'react';
import { createMemoryHistory } from 'history';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import { shallow } from 'enzyme';
import Credentials from './Credentials';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
}));
describe('<Credentials />', () => {
let wrapper;
test('should set breadcrumb config', () => {
const wrapper = shallow(<Credentials />);
afterEach(() => {
wrapper.unmount();
});
test('initially renders successfully', () => {
wrapper = mountWithContexts(<Credentials />);
});
test('should display credential list breadcrumb heading', () => {
const history = createMemoryHistory({
initialEntries: ['/credentials'],
const header = wrapper.find('ScreenHeader');
expect(header.prop('streamType')).toEqual('credential');
expect(header.prop('breadcrumbConfig')).toEqual({
'/credentials': 'Credentials',
'/credentials/add': 'Create New Credential',
});
wrapper = mountWithContexts(<Credentials />, {
context: {
router: {
history,
route: {
location: history.location,
},
},
},
});
expect(wrapper.find('Crumb').length).toBe(0);
expect(wrapper.find('Title').text()).toBe('Credentials');
});
test('should display create new credential breadcrumb heading', () => {
const history = createMemoryHistory({
initialEntries: ['/credentials/add'],
});
wrapper = mountWithContexts(<Credentials />, {
context: {
router: {
history,
route: {
location: history.location,
},
},
},
});
expect(wrapper.find('Crumb').length).toBe(2);
expect(wrapper.find('Title').text()).toBe('Create New Credential');
});
});

View File

@ -95,15 +95,15 @@ describe('<CredentialForm />', () => {
);
});
});
afterAll(() => {
wrapper.unmount();
});
test('should display form fields on add properly', async () => {
addFieldExpects();
});
test('should hide Test button initially', () => {
expect(wrapper.find('Button[children="Test"]').length).toBe(0);
});
test('should update form values', async () => {
// name and description change
await act(async () => {
@ -135,6 +135,7 @@ describe('<CredentialForm />', () => {
name: 'organization',
});
});
test('should display cred type subform when scm type select has a value', async () => {
await act(async () => {
await wrapper
@ -218,6 +219,7 @@ describe('<CredentialForm />', () => {
wrapper.find('textarea#credential-ssh_key_data').prop('value')
).toBe('');
});
test('should update field when RSA Private Key file uploaded', async () => {
await act(async () => {
wrapper.find('FileUpload#credential-ssh_key_data').invoke('onChange')(
@ -232,6 +234,7 @@ describe('<CredentialForm />', () => {
'-----BEGIN PRIVATE KEY-----\\nBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\\n-----END PRIVATE KEY-----\\n'
);
});
test('should show error when error thrown parsing JSON', async () => {
await act(async () => {
await wrapper
@ -295,9 +298,6 @@ describe('<CredentialForm />', () => {
});
describe('Edit', () => {
afterEach(() => {
wrapper.unmount();
});
test('Initially renders successfully', async () => {
await act(async () => {
wrapper = mountWithContexts(

View File

@ -15,9 +15,6 @@ const fieldOptions = {
describe('<CredentialField />', () => {
let wrapper;
afterEach(() => {
wrapper.unmount();
});
test('renders correctly without initial value', () => {
wrapper = mountWithContexts(
<Formik
@ -42,6 +39,7 @@ describe('<CredentialField />', () => {
expect(wrapper.find('KeyIcon').length).toBe(1);
expect(wrapper.find('PficonHistoryIcon').length).toBe(0);
});
test('renders correctly with initial value', () => {
wrapper = mountWithContexts(
<Formik
@ -68,6 +66,7 @@ describe('<CredentialField />', () => {
expect(wrapper.find('KeyIcon').length).toBe(1);
expect(wrapper.find('PficonHistoryIcon').length).toBe(1);
});
test('replace/revert button behaves as expected', async () => {
wrapper = mountWithContexts(
<Formik

View File

@ -128,6 +128,7 @@ function CredentialPluginField(props) {
{fieldOptions.ask_at_runtime ? (
<FieldWithPrompt
isRequired={isRequired}
fieldId={`credential-${fieldOptions.id}`}
label={fieldOptions.label}
promptId={`credential-prompt-${fieldOptions.id}`}
promptName={`passwordPrompts.${fieldOptions.id}`}

View File

@ -1,6 +1,7 @@
import React from 'react';
import { Formik } from 'formik';
import { TextInput } from '@patternfly/react-core';
import { act } from 'react-dom/test-utils';
import { mountWithContexts } from '../../../../../testUtils/enzymeHelpers';
import CredentialPluginField from './CredentialPluginField';
@ -10,6 +11,8 @@ const fieldOptions = {
type: 'string',
};
jest.mock('../../../../api');
describe('<CredentialPluginField />', () => {
let wrapper;
describe('No plugin configured', () => {
@ -34,20 +37,23 @@ describe('<CredentialPluginField />', () => {
</Formik>
);
});
afterAll(() => {
wrapper.unmount();
});
test('renders the expected content', () => {
expect(wrapper.find('input').length).toBe(1);
expect(wrapper.find('KeyIcon').length).toBe(1);
expect(wrapper.find('CredentialPluginSelected').length).toBe(0);
});
test('clicking plugin button shows plugin prompt', () => {
test('clicking plugin button shows plugin prompt', async () => {
expect(wrapper.find('CredentialPluginPrompt').length).toBe(0);
wrapper.find('KeyIcon').simulate('click');
await act(async () => {
wrapper.find('KeyIcon').simulate('click');
});
wrapper.update();
expect(wrapper.find('CredentialPluginPrompt').length).toBe(1);
});
});
describe('Plugin already configured', () => {
beforeAll(() => {
wrapper = mountWithContexts(
@ -78,9 +84,7 @@ describe('<CredentialPluginField />', () => {
</Formik>
);
});
afterAll(() => {
wrapper.unmount();
});
test('renders the expected content', () => {
expect(wrapper.find('CredentialPluginPrompt').length).toBe(0);
expect(wrapper.find('input').length).toBe(0);

View File

@ -99,10 +99,6 @@ describe('<CredentialPluginPrompt />', () => {
});
});
afterAll(() => {
wrapper.unmount();
});
test('should render Wizard with all steps', async () => {
const wizard = await waitForElement(wrapper, 'Wizard');
const steps = wizard.prop('steps');
@ -119,15 +115,18 @@ describe('<CredentialPluginPrompt />', () => {
wrapper.find('Radio').filterWhere(radio => radio.isChecked).length
).toBe(0);
});
test('next button disabled until credential selected', () => {
expect(wrapper.find('Button[children="Next"]').prop('isDisabled')).toBe(
true
);
});
test('clicking cancel button calls correct function', () => {
wrapper.find('Button[children="Cancel"]').simulate('click');
expect(onClose).toHaveBeenCalledTimes(1);
});
test('clicking credential row enables next button', async () => {
await waitForElement(wrapper, 'CheckboxListItem', el => el.length > 0);
await act(async () => {
@ -207,9 +206,7 @@ describe('<CredentialPluginPrompt />', () => {
);
});
});
afterAll(() => {
wrapper.unmount();
});
test('should render Wizard with all steps', async () => {
const wizard = await waitForElement(wrapper, 'Wizard');
const steps = wizard.prop('steps');
@ -218,6 +215,7 @@ describe('<CredentialPluginPrompt />', () => {
expect(steps[0].name).toEqual('Credential');
expect(steps[1].name).toEqual('Metadata');
});
test('credentials step renders correctly', async () => {
await waitForElement(wrapper, 'CheckboxListItem', el => el.length > 0);
@ -233,6 +231,7 @@ describe('<CredentialPluginPrompt />', () => {
false
);
});
test('metadata step renders correctly', async () => {
await act(async () => {
wrapper.find('Button[children="Next"]').simulate('click');
@ -247,6 +246,7 @@ describe('<CredentialPluginPrompt />', () => {
wrapper.find('input#credential-secret_version').prop('value')
).toBe('9000');
});
test('clicking Test button makes correct call', async () => {
await act(async () => {
wrapper.find('Button[children="Test"]').simulate('click');

View File

@ -16,17 +16,17 @@ describe('<CredentialPluginSelected />', () => {
/>
);
});
afterAll(() => {
wrapper.unmount();
});
test('renders the expected content', () => {
expect(wrapper.find('CredentialChip').length).toBe(1);
expect(wrapper.find('KeyIcon').length).toBe(1);
});
test('clearing plugin calls expected function', () => {
wrapper.find('CredentialChip button').simulate('click');
expect(onClearPlugin).toBeCalledTimes(1);
});
test('editing plugin calls expected function', () => {
wrapper.find('KeyIcon').simulate('click');
expect(onEditPlugin).toBeCalledTimes(1);

View File

@ -4,9 +4,7 @@ import CredentialPluginTestAlert from './CredentialPluginTestAlert';
describe('<CredentialPluginTestAlert />', () => {
let wrapper;
afterEach(() => {
wrapper.unmount();
});
test('renders expected content when test is successful', () => {
wrapper = mountWithContexts(
<CredentialPluginTestAlert
@ -20,6 +18,7 @@ describe('<CredentialPluginTestAlert />', () => {
'Test passed'
);
});
test('renders expected content when test fails with the expected return string formatting', () => {
wrapper = mountWithContexts(
<CredentialPluginTestAlert
@ -41,6 +40,7 @@ describe('<CredentialPluginTestAlert />', () => {
'HTTP 404: not found'
);
});
test('renders expected content when test fails without the expected return string formatting', () => {
wrapper = mountWithContexts(
<CredentialPluginTestAlert

View File

@ -30,7 +30,7 @@ const credential = {
describe('<ExternalTestModal />', () => {
let wrapper;
afterEach(() => wrapper.unmount());
test('should display metadata fields correctly', async () => {
wrapper = mountWithContexts(
<ExternalTestModal
@ -46,6 +46,7 @@ describe('<ExternalTestModal />', () => {
expect(wrapper.find('input#credential-secret_key').length).toBe(1);
expect(wrapper.find('input#credential-secret_version').length).toBe(1);
});
test('should make the test request correctly when testing an existing credential', async () => {
wrapper = mountWithContexts(
<ExternalTestModal
@ -85,6 +86,7 @@ describe('<ExternalTestModal />', () => {
},
});
});
test('should make the test request correctly when testing a new credential', async () => {
wrapper = mountWithContexts(
<ExternalTestModal
@ -123,6 +125,7 @@ describe('<ExternalTestModal />', () => {
},
});
});
test('should display the alert after a successful test', async () => {
CredentialTypesAPI.test.mockResolvedValue({});
wrapper = mountWithContexts(
@ -148,6 +151,7 @@ describe('<ExternalTestModal />', () => {
expect(wrapper.find('Alert').length).toBe(1);
expect(wrapper.find('Alert').props().variant).toBe('success');
});
test('should display the alert after a failed test', async () => {
CredentialTypesAPI.test.mockRejectedValue({
inputs: `HTTP 404

View File

@ -4,10 +4,6 @@ import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import CredentialTypes from './CredentialTypes';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
}));
describe('<CredentialTypes/>', () => {
let pageWrapper;
let pageSections;
@ -17,10 +13,6 @@ describe('<CredentialTypes/>', () => {
pageSections = pageWrapper.find('PageSection');
});
afterEach(() => {
pageWrapper.unmount();
});
test('initially renders without crashing', () => {
expect(pageWrapper.length).toBe(1);
expect(pageSections.length).toBe(1);

View File

@ -7,9 +7,6 @@ import { DashboardAPI } from '../../api';
import Dashboard from './Dashboard';
jest.mock('../../api');
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
}));
describe('<Dashboard />', () => {
let pageWrapper;
@ -24,10 +21,6 @@ describe('<Dashboard />', () => {
});
});
afterEach(() => {
pageWrapper.unmount();
});
test('initially renders without crashing', () => {
expect(pageWrapper.length).toBe(1);
});

View File

@ -7,9 +7,6 @@ import { DashboardAPI } from '../../api';
import DashboardGraph from './DashboardGraph';
jest.mock('../../api');
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
}));
describe('<DashboardGraph/>', () => {
let pageWrapper;
@ -24,9 +21,6 @@ describe('<DashboardGraph/>', () => {
});
});
afterEach(() => {
pageWrapper.unmount();
});
test('renders month-based/all job type chart by default', () => {
expect(graphRequest).toHaveBeenCalledWith({
job_type: 'all',

View File

@ -7,10 +7,6 @@ import Count from './Count';
describe('<Count />', () => {
let pageWrapper;
afterEach(() => {
pageWrapper.unmount();
});
test('initially renders without crashing', () => {
pageWrapper = mountWithContexts(<Count link="foo" />);
expect(pageWrapper.length).toBe(1);

View File

@ -90,7 +90,6 @@ describe('<ExecutionEnvironmentAdd/>', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('handleSubmit should call the api and redirect to details page', async () => {

View File

@ -82,7 +82,6 @@ describe('<ExecutionEnvironmentEdit/>', () => {
afterAll(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('handleSubmit should call the api and redirect to details page', async () => {

View File

@ -13,10 +13,6 @@ describe('<ExecutionEnvironments/>', () => {
pageSections = pageWrapper.find('PageSection');
});
afterEach(() => {
pageWrapper.unmount();
});
test('initially renders without crashing', () => {
expect(pageWrapper.length).toBe(1);
expect(pageSections.length).toBe(1);

View File

@ -145,7 +145,6 @@ describe('<ExecutionEnvironmentForm/>', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('Initially renders successfully', () => {

View File

@ -37,10 +37,6 @@ describe('<Host />', () => {
});
});
afterEach(() => {
wrapper.unmount();
});
test('should render expected tabs', async () => {
const expectedTabs = ['Details', 'Facts', 'Groups', 'Completed Jobs'];
wrapper.find('RoutedTabs li').forEach((tab, index) => {

View File

@ -108,7 +108,6 @@ describe('<HostGroupsList />', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('initially renders successfully', () => {

View File

@ -38,10 +38,6 @@ describe('<HostsListItem />', () => {
);
});
afterEach(() => {
wrapper.unmount();
});
test('edit button shown to users with edit capabilities', () => {
expect(wrapper.find('PencilAltIcon').exists()).toBeTruthy();
});

View File

@ -1,41 +1,28 @@
import React from 'react';
import { createMemoryHistory } from 'history';
import { shallow } from 'enzyme';
import { act } from 'react-dom/test-utils';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import Hosts from './Hosts';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
}));
jest.mock('../../api');
describe('<Hosts />', () => {
test('initially renders successfully', () => {
mountWithContexts(<Hosts />);
});
test('should display a breadcrumb heading', () => {
const history = createMemoryHistory({
initialEntries: ['/hosts'],
});
const match = { path: '/hosts', url: '/hosts', isExact: true };
const wrapper = shallow(<Hosts />);
const wrapper = mountWithContexts(<Hosts />, {
context: {
router: {
history,
route: {
location: history.location,
match,
},
},
},
const header = wrapper.find('ScreenHeader');
expect(header.prop('streamType')).toEqual('host');
expect(header.prop('breadcrumbConfig')).toEqual({
'/hosts': 'Hosts',
'/hosts/add': 'Create New Host',
});
expect(wrapper.find('Title').length).toBe(1);
wrapper.unmount();
});
test('should render Host component', () => {
test('should render Host component', async () => {
let wrapper;
const history = createMemoryHistory({
initialEntries: ['/hosts/1'],
});
@ -46,11 +33,12 @@ describe('<Hosts />', () => {
isExact: true,
};
const wrapper = mountWithContexts(<Hosts />, {
context: { router: { history, route: { match } } },
await act(async () => {
wrapper = await mountWithContexts(<Hosts />, {
context: { router: { history, route: { match } } },
});
});
expect(wrapper.find('Host').length).toBe(1);
wrapper.unmount();
});
});

View File

@ -67,7 +67,6 @@ describe('<ContainerGroupAdd/>', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('handleSubmit should call the api and redirect to details page', async () => {

View File

@ -113,7 +113,6 @@ describe('<ContainerGroupEdit/>', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('initially renders successfully', async () => {

View File

@ -63,7 +63,6 @@ describe('<InstanceGroupAdd/>', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('handleSubmit should call the api and redirect to details page', async () => {

View File

@ -68,7 +68,6 @@ describe('<InstanceGroupEdit>', () => {
afterAll(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('controlplane instance group name can not be updated', async () => {

View File

@ -4,10 +4,6 @@ import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import InstanceGroups from './InstanceGroups';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
}));
describe('<InstanceGroups/>', () => {
let pageWrapper;
let pageSections;
@ -17,10 +13,6 @@ describe('<InstanceGroups/>', () => {
pageSections = pageWrapper.find('PageSection');
});
afterEach(() => {
pageWrapper.unmount();
});
test('initially renders without crashing', () => {
expect(pageWrapper.length).toBe(1);
expect(pageSections.length).toBe(1);

View File

@ -134,7 +134,6 @@ describe('<InstanceList/>', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should have data fetched', () => {

View File

@ -91,7 +91,6 @@ describe('<ContainerGroupForm/>', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('Initially renders successfully', () => {

View File

@ -60,7 +60,6 @@ describe('<InstanceGroupForm/>', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('Initially renders successfully', () => {

View File

@ -4,10 +4,6 @@ import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import Inventories from './Inventories';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
}));
describe('<Inventories />', () => {
let pageWrapper;
@ -15,10 +11,6 @@ describe('<Inventories />', () => {
pageWrapper = mountWithContexts(<Inventories />);
});
afterEach(() => {
pageWrapper.unmount();
});
test('initially renders without crashing', () => {
expect(pageWrapper.length).toBe(1);
});

View File

@ -43,7 +43,6 @@ describe('<InventoryGroupHostList />', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('initially renders successfully ', () => {

View File

@ -26,10 +26,6 @@ describe('<InventoryGroupHostListItem />', () => {
);
});
afterEach(() => {
wrapper.unmount();
});
test('should display expected row item content', () => {
expect(wrapper.find('b').text()).toContain(
'.host-000001.group-00000.dummy'

View File

@ -96,7 +96,6 @@ describe('<InventoryGroupsList />', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should fetch groups from api and render them in the list', async () => {
@ -201,7 +200,6 @@ describe('<InventoryGroupsList/> error handling', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should show content error when api throws error on initial render', async () => {

View File

@ -32,9 +32,7 @@ describe('<InventoryHost />', () => {
let history;
beforeEach(async () => {
InventoriesAPI.readHostDetail.mockResolvedValue({
data: { ...mockHost },
});
InventoriesAPI.readHostDetail.mockResolvedValue(mockHost);
await act(async () => {
wrapper = mountWithContexts(
@ -43,10 +41,6 @@ describe('<InventoryHost />', () => {
});
});
afterEach(() => {
wrapper.unmount();
});
test('should render expected tabs', async () => {
const expectedTabs = [
'Back to Hosts',

View File

@ -100,7 +100,6 @@ describe('<InventoryHostGroupsList />', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('initially renders successfully', () => {

View File

@ -44,10 +44,6 @@ describe('<InventoryHostItem />', () => {
);
});
afterEach(() => {
wrapper.unmount();
});
test('edit button shown to users with edit capabilities', () => {
expect(wrapper.find('PencilAltIcon').exists()).toBeTruthy();
});

View File

@ -3,6 +3,14 @@ import { createMemoryHistory } from 'history';
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
import InventoryHosts from './InventoryHosts';
jest.mock('./InventoryHostList', () => {
const InventoryHostList = () => <div />;
return {
__esModule: true,
default: InventoryHostList,
};
});
describe('<InventoryHosts />', () => {
test('should render inventory host list', () => {
const history = createMemoryHistory({
@ -20,6 +28,5 @@ describe('<InventoryHosts />', () => {
});
expect(wrapper.find('InventoryHostList').length).toBe(1);
wrapper.unmount();
});
});

View File

@ -95,7 +95,6 @@ describe('<InventoryRelatedGroupList />', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('initially renders successfully ', () => {

View File

@ -11,21 +11,21 @@ describe('<InventoryRelatedGroupListItem />', () => {
beforeEach(() => {
wrapper = mountWithContexts(
<InventoryRelatedGroupListItem
detailUrl="/group/1"
editUrl="/group/1"
group={mockGroup}
isSelected={false}
onSelect={() => {}}
rowIndex={0}
/>
<table>
<tbody>
<InventoryRelatedGroupListItem
detailUrl="/group/1"
editUrl="/group/1"
group={mockGroup}
isSelected={false}
onSelect={() => {}}
rowIndex={0}
/>
</tbody>
</table>
);
});
afterEach(() => {
wrapper.unmount();
});
test('should display expected row item content', () => {
expect(wrapper.find('b').text()).toContain('Group 2 Inventory 0');
});
@ -36,14 +36,18 @@ describe('<InventoryRelatedGroupListItem />', () => {
test('edit button hidden from users without edit capabilities', () => {
wrapper = mountWithContexts(
<InventoryRelatedGroupListItem
detailUrl="/group/1"
editUrl="/group/1"
group={mockRelatedGroups.results[2]}
isSelected={false}
onSelect={() => {}}
rowIndex={0}
/>
<table>
<tbody>
<InventoryRelatedGroupListItem
detailUrl="/group/1"
editUrl="/group/1"
group={mockRelatedGroups.results[2]}
isSelected={false}
onSelect={() => {}}
rowIndex={0}
/>
</tbody>
</table>
);
expect(wrapper.find('PencilAltIcon').exists()).toBeFalsy();
});

View File

@ -72,7 +72,6 @@ describe('<InventorySourceAdd />', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('new form displays primary form fields', async () => {

View File

@ -23,7 +23,6 @@ const source = {
describe('<InventorySourceListItem />', () => {
let wrapper;
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});

View File

@ -6,6 +6,5 @@ describe('<InventorySources />', () => {
test('initially renders without crashing', () => {
const wrapper = shallow(<InventorySources />);
expect(wrapper.length).toBe(1);
wrapper.unmount();
});
});

View File

@ -22,7 +22,6 @@ describe('<SmartInventory />', () => {
let wrapper;
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});

View File

@ -29,14 +29,11 @@ describe('<SmartInventoryHost />', () => {
let history;
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});
test('should render expected tabs', async () => {
InventoriesAPI.readHostDetail.mockResolvedValue({
data: { ...mockHost },
});
InventoriesAPI.readHostDetail.mockResolvedValue(mockHost);
await act(async () => {
wrapper = mountWithContexts(
<SmartInventoryHost
@ -73,9 +70,7 @@ describe('<SmartInventoryHost />', () => {
});
test('should show content error when user attempts to navigate to erroneous route', async () => {
InventoriesAPI.readHostDetail.mockResolvedValue({
data: { ...mockHost },
});
InventoriesAPI.readHostDetail.mockResolvedValue(mockHost);
history = createMemoryHistory({
initialEntries: ['/inventories/smart_inventory/1/hosts/1/foobar'],
});

View File

@ -37,7 +37,6 @@ describe('<SmartInventoryHostList />', () => {
afterAll(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('initially renders successfully', () => {

Some files were not shown because too many files have changed in this diff Show More