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
194 changed files with 688 additions and 1032 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -113,12 +113,11 @@ describe('<Schedule />', () => {
}); });
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0); await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
}); });
afterAll(() => {
wrapper.unmount();
});
test('renders successfully', async () => { test('renders successfully', async () => {
expect(wrapper.length).toBe(1); expect(wrapper.length).toBe(1);
}); });
test('expect all tabs to exist, including Back to Schedules', async () => { test('expect all tabs to exist, including Back to Schedules', async () => {
expect( expect(
wrapper.find('button[link="/templates/job_template/1/schedules"]').length 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 () => { test('Successfully creates a schedule with repeat frequency: None (run once)', async () => {
await act(async () => { await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({ wrapper.find('Formik').invoke('onSubmit')({
@@ -95,6 +97,7 @@ describe('<ScheduleAdd />', () => {
'DTSTART;TZID=America/New_York:20200325T100000 RRULE:INTERVAL=1;COUNT=1;FREQ=MINUTELY', '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 () => { test('Successfully creates a schedule with 10 minute repeat frequency after 10 occurrences', async () => {
await act(async () => { await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({ wrapper.find('Formik').invoke('onSubmit')({
@@ -117,6 +120,7 @@ describe('<ScheduleAdd />', () => {
'DTSTART;TZID=America/New_York:20200325T103000 RRULE:INTERVAL=10;FREQ=MINUTELY;COUNT=10', '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 () => { test('Successfully creates a schedule with hourly repeat frequency ending on a specific date/time', async () => {
await act(async () => { await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({ wrapper.find('Formik').invoke('onSubmit')({
@@ -140,6 +144,7 @@ describe('<ScheduleAdd />', () => {
'DTSTART;TZID=America/New_York:20200325T104500 RRULE:INTERVAL=1;FREQ=HOURLY;UNTIL=20200326T104500', 'DTSTART;TZID=America/New_York:20200325T104500 RRULE:INTERVAL=1;FREQ=HOURLY;UNTIL=20200326T104500',
}); });
}); });
test('Successfully creates a schedule with daily repeat frequency', async () => { test('Successfully creates a schedule with daily repeat frequency', async () => {
await act(async () => { await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({ wrapper.find('Formik').invoke('onSubmit')({
@@ -161,6 +166,7 @@ describe('<ScheduleAdd />', () => {
'DTSTART;TZID=America/New_York:20200325T104500 RRULE:INTERVAL=1;FREQ=DAILY', '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 () => { test('Successfully creates a schedule with weekly repeat frequency on mon/wed/fri', async () => {
await act(async () => { await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({ 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}`, 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 () => { test('Successfully creates a schedule with monthly repeat frequency on the first day of the month', async () => {
await act(async () => { await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({ wrapper.find('Formik').invoke('onSubmit')({
@@ -207,6 +214,7 @@ describe('<ScheduleAdd />', () => {
'DTSTART;TZID=America/New_York:20200401T104500 RRULE:INTERVAL=1;FREQ=MONTHLY;BYMONTHDAY=1', '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 () => { test('Successfully creates a schedule with monthly repeat frequency on the last tuesday of the month', async () => {
await act(async () => { await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({ 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', '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 () => { test('Successfully creates a schedule with yearly repeat frequency on the second Friday in April', async () => {
await act(async () => { await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({ 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', '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 () => { test('Successfully creates a schedule with yearly repeat frequency on the first weekday in October', async () => {
await act(async () => { await act(async () => {
wrapper.find('Formik').invoke('onSubmit')({ wrapper.find('Formik').invoke('onSubmit')({
@@ -464,6 +474,7 @@ describe('<ScheduleAdd />', () => {
/> />
); );
}); });
scheduleSurveyWrapper.update();
await act(async () => { await act(async () => {
scheduleSurveyWrapper.find('Formik').invoke('onSubmit')({ scheduleSurveyWrapper.find('Formik').invoke('onSubmit')({
description: 'test description', description: 'test description',

View File

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

View File

@@ -52,10 +52,6 @@ describe('ScheduleList', () => {
wrapper.update(); wrapper.update();
}); });
afterEach(() => {
wrapper.unmount();
});
test('should fetch schedules from api and render the list', () => { test('should fetch schedules from api and render the list', () => {
expect(loadSchedules).toHaveBeenCalled(); expect(loadSchedules).toHaveBeenCalled();
expect(wrapper.find('ScheduleListItem').length).toBe(5); 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', () => { test('Name correctly shown with correct link', () => {
expect( expect(
wrapper wrapper
@@ -149,10 +145,6 @@ describe('ScheduleListItem', () => {
); );
}); });
afterAll(() => {
wrapper.unmount();
});
test('Name correctly shown with correct link', () => { test('Name correctly shown with correct link', () => {
expect( expect(
wrapper wrapper
@@ -217,10 +209,6 @@ describe('ScheduleListItem', () => {
); );
}); });
afterAll(() => {
wrapper.unmount();
});
test('should show missing resource icon', () => { test('should show missing resource icon', () => {
expect(wrapper.find('ExclamationTriangleIcon').length).toBe(1); expect(wrapper.find('ExclamationTriangleIcon').length).toBe(1);
expect(wrapper.find('ScheduleToggle').prop('isDisabled')).toBe(true); 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 () => { test('Local option initially set', async () => {
expect(wrapper.find('MultiButtonToggle').props().value).toBe('local'); expect(wrapper.find('MultiButtonToggle').props().value).toBe('local');
}); });
test('It renders the correct number of dates', async () => { test('It renders the correct number of dates', async () => {
expect(wrapper.find('dd').children().length).toBe(2); expect(wrapper.find('dd').children().length).toBe(2);
}); });
test('Clicking UTC button toggles the dates to utc', async () => { test('Clicking UTC button toggles the dates to utc', async () => {
wrapper.find('button[aria-label="UTC"]').simulate('click'); wrapper.find('button[aria-label="UTC"]').simulate('click');
expect(wrapper.find('MultiButtonToggle').props().value).toBe('utc'); expect(wrapper.find('MultiButtonToggle').props().value).toBe('utc');
@@ -44,6 +44,7 @@ describe('<ScheduleOccurrences>', () => {
).toBe('3/30/2020, 4:00:00 AM'); ).toBe('3/30/2020, 4:00:00 AM');
}); });
}); });
describe('Only one date passed in', () => { describe('Only one date passed in', () => {
test('Component should not render chldren', async () => { test('Component should not render chldren', async () => {
wrapper = mountWithContexts( wrapper = mountWithContexts(
@@ -55,7 +56,6 @@ describe('<ScheduleOccurrences>', () => {
/> />
); );
expect(wrapper.find('ScheduleOccurrences').children().length).toBe(0); expect(wrapper.find('ScheduleOccurrences').children().length).toBe(0);
wrapper.unmount();
}); });
}); });
}); });

View File

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

View File

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

View File

@@ -168,6 +168,7 @@ describe('<ScheduleForm />', () => {
expect(wrapper.find('ContentError').length).toBe(1); expect(wrapper.find('ContentError').length).toBe(1);
}); });
}); });
describe('Cancel', () => { describe('Cancel', () => {
test('should make the appropriate callback', async () => { test('should make the appropriate callback', async () => {
const handleCancel = jest.fn(); const handleCancel = jest.fn();
@@ -226,8 +227,10 @@ describe('<ScheduleForm />', () => {
expect(handleCancel).toHaveBeenCalledTimes(1); expect(handleCancel).toHaveBeenCalledTimes(1);
}); });
}); });
describe('Prompted Schedule', () => { describe('Prompted Schedule', () => {
let promptWrapper; let promptWrapper;
beforeEach(async () => { beforeEach(async () => {
SchedulesAPI.readZoneInfo.mockResolvedValue({ SchedulesAPI.readZoneInfo.mockResolvedValue({
data: [ data: [
@@ -284,8 +287,8 @@ describe('<ScheduleForm />', () => {
el => el.length > 0 el => el.length > 0
); );
}); });
afterEach(() => { afterEach(() => {
promptWrapper.unmount();
jest.clearAllMocks(); jest.clearAllMocks();
}); });
@@ -375,6 +378,7 @@ describe('<ScheduleForm />', () => {
promptWrapper.update(); promptWrapper.update();
expect(promptWrapper.find('Wizard').length).toBe(0); expect(promptWrapper.find('Wizard').length).toBe(0);
}); });
test('should render prompt button with disabled save button', async () => { test('should render prompt button with disabled save button', async () => {
await act(async () => { await act(async () => {
wrapper = mountWithContexts( wrapper = mountWithContexts(
@@ -423,6 +427,7 @@ describe('<ScheduleForm />', () => {
); );
}); });
}); });
describe('Add', () => { describe('Add', () => {
beforeAll(async () => { beforeAll(async () => {
SchedulesAPI.readZoneInfo.mockResolvedValue({ SchedulesAPI.readZoneInfo.mockResolvedValue({
@@ -473,9 +478,7 @@ describe('<ScheduleForm />', () => {
}); });
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0); await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
}); });
afterAll(() => {
wrapper.unmount();
});
test('initially renders expected fields and values', () => { test('initially renders expected fields and values', () => {
const now = new Date(); const now = new Date();
const closestQuarterHour = new Date( const closestQuarterHour = new Date(
@@ -503,6 +506,7 @@ describe('<ScheduleForm />', () => {
'none' 'none'
); );
}); });
test('correct frequency details fields and values shown when frequency changed to minute', async () => { test('correct frequency details fields and values shown when frequency changed to minute', async () => {
const runFrequencySelect = wrapper.find( const runFrequencySelect = wrapper.find(
'FormGroup[label="Run frequency"] FormSelect' '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-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').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 () => { test('correct frequency details fields and values shown when frequency changed to hour', async () => {
const runFrequencySelect = wrapper.find( const runFrequencySelect = wrapper.find(
'FormGroup[label="Run frequency"] FormSelect' '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-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').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 () => { test('correct frequency details fields and values shown when frequency changed to day', async () => {
const runFrequencySelect = wrapper.find( const runFrequencySelect = wrapper.find(
'FormGroup[label="Run frequency"] FormSelect' '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-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').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 () => { test('correct frequency details fields and values shown when frequency changed to week', async () => {
const runFrequencySelect = wrapper.find( const runFrequencySelect = wrapper.find(
'FormGroup[label="Run frequency"] FormSelect' '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-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').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 () => { test('correct frequency details fields and values shown when frequency changed to month', async () => {
const runFrequencySelect = wrapper.find( const runFrequencySelect = wrapper.find(
'FormGroup[label="Run frequency"] FormSelect' '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-day-month').length).toBe(0);
expect(wrapper.find('select#schedule-run-on-the-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 () => { test('correct frequency details fields and values shown when frequency changed to year', async () => {
const runFrequencySelect = wrapper.find( const runFrequencySelect = wrapper.find(
'FormGroup[label="Run frequency"] FormSelect' '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-day-month').length).toBe(1);
expect(wrapper.find('select#schedule-run-on-the-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 () => { test('occurrences field properly shown when end after selection is made', async () => {
await act(async () => { await act(async () => {
wrapper wrapper
@@ -690,6 +700,7 @@ describe('<ScheduleForm />', () => {
}); });
wrapper.update(); wrapper.update();
}); });
test('error shown when end date/time comes before start date/time', async () => { test('error shown when end date/time comes before start date/time', async () => {
await act(async () => { await act(async () => {
wrapper wrapper
@@ -719,15 +730,12 @@ describe('<ScheduleForm />', () => {
); );
}); });
await act(async () => {
wrapper.find('DatePicker[aria-label="End date"]').simulate('blur');
});
wrapper.update(); wrapper.update();
expect(wrapper.find('#schedule-End-datetime-helper').text()).toBe( expect(wrapper.find('#schedule-End-datetime-helper').text()).toBe(
'Please select an end date/time that comes after the start date/time.' '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 () => { test('error shown when on day number is not between 1 and 31', async () => {
act(() => { act(() => {
wrapper.find('select[id="schedule-frequency"]').invoke('onChange')( wrapper.find('select[id="schedule-frequency"]').invoke('onChange')(
@@ -761,6 +769,7 @@ describe('<ScheduleForm />', () => {
); );
}); });
}); });
describe('Edit', () => { describe('Edit', () => {
beforeEach(async () => { beforeEach(async () => {
SchedulesAPI.readZoneInfo.mockResolvedValue({ SchedulesAPI.readZoneInfo.mockResolvedValue({
@@ -773,12 +782,12 @@ describe('<ScheduleForm />', () => {
SchedulesAPI.readCredentials.mockResolvedValue(credentials); SchedulesAPI.readCredentials.mockResolvedValue(credentials);
}); });
afterEach(() => { afterEach(() => {
wrapper.unmount();
jest.clearAllMocks(); 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 () => { await act(async () => {
wrapper = mountWithContexts( wrapper = mountWithContexts(
<ScheduleForm <ScheduleForm
@@ -906,6 +915,7 @@ describe('<ScheduleForm />', () => {
/> />
); );
}); });
wrapper.update();
expect(wrapper.find('ScheduleForm').length).toBe(1); expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible(); defaultFieldsVisible();
expect(wrapper.find('FormGroup[label="Run every"]').length).toBe(0); expect(wrapper.find('FormGroup[label="Run every"]').length).toBe(0);
@@ -920,6 +930,7 @@ describe('<ScheduleForm />', () => {
'none' 'none'
); );
}); });
test('initially renders expected fields and values with existing schedule that runs every 10 minutes', async () => { test('initially renders expected fields and values with existing schedule that runs every 10 minutes', async () => {
await act(async () => { await act(async () => {
wrapper = mountWithContexts( wrapper = mountWithContexts(
@@ -941,6 +952,8 @@ describe('<ScheduleForm />', () => {
/> />
); );
}); });
wrapper.update();
expect(wrapper.find('ScheduleForm').length).toBe(1); expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible(); defaultFieldsVisible();
expect(wrapper.find('FormGroup[label="End"]').length).toBe(1); 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-after').prop('checked')).toBe(false);
expect(wrapper.find('input#end-on-date').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 () => { test('initially renders expected fields and values with existing schedule that runs every hour 10 times', async () => {
await act(async () => { await act(async () => {
wrapper = mountWithContexts( wrapper = mountWithContexts(
@@ -981,6 +995,8 @@ describe('<ScheduleForm />', () => {
/> />
); );
}); });
wrapper.update();
expect(wrapper.find('ScheduleForm').length).toBe(1); expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible(); defaultFieldsVisible();
expect(wrapper.find('FormGroup[label="End"]').length).toBe(1); 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#end-on-date').prop('checked')).toBe(false);
expect(wrapper.find('input#schedule-occurrences').prop('value')).toBe(10); 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 () => { test('initially renders expected fields and values with existing schedule that runs every day', async () => {
await act(async () => { await act(async () => {
wrapper = mountWithContexts( 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 () => { 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 () => { await act(async () => {
wrapper = mountWithContexts( wrapper = mountWithContexts(
@@ -1062,6 +1082,8 @@ describe('<ScheduleForm />', () => {
/> />
); );
}); });
wrapper.update();
expect(wrapper.find('ScheduleForm').length).toBe(1); expect(wrapper.find('ScheduleForm').length).toBe(1);
defaultFieldsVisible(); defaultFieldsVisible();
expect(wrapper.find('FormGroup[label="End"]').length).toBe(1); expect(wrapper.find('FormGroup[label="End"]').length).toBe(1);
@@ -1107,6 +1129,7 @@ describe('<ScheduleForm />', () => {
wrapper.find('TimePicker[aria-label="End time"]').prop('value') wrapper.find('TimePicker[aria-label="End time"]').prop('value')
).toBe('1:00 AM'); ).toBe('1:00 AM');
}); });
test('initially renders expected fields and values with existing schedule that runs every month on the last weekday', async () => { test('initially renders expected fields and values with existing schedule that runs every month on the last weekday', async () => {
await act(async () => { await act(async () => {
wrapper = mountWithContexts( 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 () => { test('initially renders expected fields and values with existing schedule that runs every year on the May 6', async () => {
await act(async () => { await act(async () => {
wrapper = mountWithContexts( 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'; import ScreenHeader from './ScreenHeader';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
}));
describe('<ScreenHeader />', () => { describe('<ScreenHeader />', () => {
let breadcrumbWrapper; let breadcrumbWrapper;
let breadcrumb; let breadcrumb;
@@ -43,7 +39,6 @@ describe('<ScreenHeader />', () => {
expect(breadcrumbItem.first().text()).toBe('Foo'); expect(breadcrumbItem.first().text()).toBe('Foo');
expect(breadcrumbItem.last().text()).toBe('One'); expect(breadcrumbItem.last().text()).toBe('One');
expect(breadcrumbHeading.text()).toBe('Bar'); expect(breadcrumbHeading.text()).toBe('Bar');
breadcrumbWrapper.unmount();
}); });
test('renders breadcrumb items defined in breadcrumbConfig', () => { test('renders breadcrumb items defined in breadcrumbConfig', () => {
@@ -66,7 +61,6 @@ describe('<ScreenHeader />', () => {
expect(breadcrumbWrapper.find('BreadcrumbItem')).toHaveLength( expect(breadcrumbWrapper.find('BreadcrumbItem')).toHaveLength(
crumbLength crumbLength
); );
breadcrumbWrapper.unmount();
}); });
}); });
}); });

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -196,7 +196,6 @@ describe('<CredentialAdd />', () => {
}); });
wrapper.update(); wrapper.update();
expect(wrapper.find('ContentError').length).toBe(1); 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 () => { test('initially renders successfully', async () => {
expect(wrapper.find('CredentialEdit').length).toBe(1); expect(wrapper.find('CredentialEdit').length).toBe(1);
}); });
@@ -489,7 +485,6 @@ describe('<CredentialEdit />', () => {
}); });
wrapper.update(); wrapper.update();
expect(wrapper.find('ContentError').length).toBe(1); expect(wrapper.find('ContentError').length).toBe(1);
wrapper.unmount();
}); });
}); });
}); });

View File

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

View File

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

View File

@@ -1,60 +1,16 @@
import React from 'react'; import React from 'react';
import { createMemoryHistory } from 'history'; import { shallow } from 'enzyme';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import Credentials from './Credentials'; import Credentials from './Credentials';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
}));
describe('<Credentials />', () => { describe('<Credentials />', () => {
let wrapper; test('should set breadcrumb config', () => {
const wrapper = shallow(<Credentials />);
afterEach(() => { const header = wrapper.find('ScreenHeader');
wrapper.unmount(); expect(header.prop('streamType')).toEqual('credential');
}); expect(header.prop('breadcrumbConfig')).toEqual({
'/credentials': 'Credentials',
test('initially renders successfully', () => { '/credentials/add': 'Create New Credential',
wrapper = mountWithContexts(<Credentials />);
});
test('should display credential list breadcrumb heading', () => {
const history = createMemoryHistory({
initialEntries: ['/credentials'],
}); });
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 () => { test('should display form fields on add properly', async () => {
addFieldExpects(); addFieldExpects();
}); });
test('should hide Test button initially', () => { test('should hide Test button initially', () => {
expect(wrapper.find('Button[children="Test"]').length).toBe(0); expect(wrapper.find('Button[children="Test"]').length).toBe(0);
}); });
test('should update form values', async () => { test('should update form values', async () => {
// name and description change // name and description change
await act(async () => { await act(async () => {
@@ -135,6 +135,7 @@ describe('<CredentialForm />', () => {
name: 'organization', name: 'organization',
}); });
}); });
test('should display cred type subform when scm type select has a value', async () => { test('should display cred type subform when scm type select has a value', async () => {
await act(async () => { await act(async () => {
await wrapper await wrapper
@@ -218,6 +219,7 @@ describe('<CredentialForm />', () => {
wrapper.find('textarea#credential-ssh_key_data').prop('value') wrapper.find('textarea#credential-ssh_key_data').prop('value')
).toBe(''); ).toBe('');
}); });
test('should update field when RSA Private Key file uploaded', async () => { test('should update field when RSA Private Key file uploaded', async () => {
await act(async () => { await act(async () => {
wrapper.find('FileUpload#credential-ssh_key_data').invoke('onChange')( wrapper.find('FileUpload#credential-ssh_key_data').invoke('onChange')(
@@ -232,6 +234,7 @@ describe('<CredentialForm />', () => {
'-----BEGIN PRIVATE KEY-----\\nBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\\n-----END PRIVATE KEY-----\\n' '-----BEGIN PRIVATE KEY-----\\nBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\\n-----END PRIVATE KEY-----\\n'
); );
}); });
test('should show error when error thrown parsing JSON', async () => { test('should show error when error thrown parsing JSON', async () => {
await act(async () => { await act(async () => {
await wrapper await wrapper
@@ -295,9 +298,6 @@ describe('<CredentialForm />', () => {
}); });
describe('Edit', () => { describe('Edit', () => {
afterEach(() => {
wrapper.unmount();
});
test('Initially renders successfully', async () => { test('Initially renders successfully', async () => {
await act(async () => { await act(async () => {
wrapper = mountWithContexts( wrapper = mountWithContexts(

View File

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

View File

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

View File

@@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { Formik } from 'formik'; import { Formik } from 'formik';
import { TextInput } from '@patternfly/react-core'; import { TextInput } from '@patternfly/react-core';
import { act } from 'react-dom/test-utils';
import { mountWithContexts } from '../../../../../testUtils/enzymeHelpers'; import { mountWithContexts } from '../../../../../testUtils/enzymeHelpers';
import CredentialPluginField from './CredentialPluginField'; import CredentialPluginField from './CredentialPluginField';
@@ -10,6 +11,8 @@ const fieldOptions = {
type: 'string', type: 'string',
}; };
jest.mock('../../../../api');
describe('<CredentialPluginField />', () => { describe('<CredentialPluginField />', () => {
let wrapper; let wrapper;
describe('No plugin configured', () => { describe('No plugin configured', () => {
@@ -34,20 +37,23 @@ describe('<CredentialPluginField />', () => {
</Formik> </Formik>
); );
}); });
afterAll(() => {
wrapper.unmount();
});
test('renders the expected content', () => { test('renders the expected content', () => {
expect(wrapper.find('input').length).toBe(1); expect(wrapper.find('input').length).toBe(1);
expect(wrapper.find('KeyIcon').length).toBe(1); expect(wrapper.find('KeyIcon').length).toBe(1);
expect(wrapper.find('CredentialPluginSelected').length).toBe(0); 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); 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); expect(wrapper.find('CredentialPluginPrompt').length).toBe(1);
}); });
}); });
describe('Plugin already configured', () => { describe('Plugin already configured', () => {
beforeAll(() => { beforeAll(() => {
wrapper = mountWithContexts( wrapper = mountWithContexts(
@@ -78,9 +84,7 @@ describe('<CredentialPluginField />', () => {
</Formik> </Formik>
); );
}); });
afterAll(() => {
wrapper.unmount();
});
test('renders the expected content', () => { test('renders the expected content', () => {
expect(wrapper.find('CredentialPluginPrompt').length).toBe(0); expect(wrapper.find('CredentialPluginPrompt').length).toBe(0);
expect(wrapper.find('input').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 () => { test('should render Wizard with all steps', async () => {
const wizard = await waitForElement(wrapper, 'Wizard'); const wizard = await waitForElement(wrapper, 'Wizard');
const steps = wizard.prop('steps'); const steps = wizard.prop('steps');
@@ -119,15 +115,18 @@ describe('<CredentialPluginPrompt />', () => {
wrapper.find('Radio').filterWhere(radio => radio.isChecked).length wrapper.find('Radio').filterWhere(radio => radio.isChecked).length
).toBe(0); ).toBe(0);
}); });
test('next button disabled until credential selected', () => { test('next button disabled until credential selected', () => {
expect(wrapper.find('Button[children="Next"]').prop('isDisabled')).toBe( expect(wrapper.find('Button[children="Next"]').prop('isDisabled')).toBe(
true true
); );
}); });
test('clicking cancel button calls correct function', () => { test('clicking cancel button calls correct function', () => {
wrapper.find('Button[children="Cancel"]').simulate('click'); wrapper.find('Button[children="Cancel"]').simulate('click');
expect(onClose).toHaveBeenCalledTimes(1); expect(onClose).toHaveBeenCalledTimes(1);
}); });
test('clicking credential row enables next button', async () => { test('clicking credential row enables next button', async () => {
await waitForElement(wrapper, 'CheckboxListItem', el => el.length > 0); await waitForElement(wrapper, 'CheckboxListItem', el => el.length > 0);
await act(async () => { await act(async () => {
@@ -207,9 +206,7 @@ describe('<CredentialPluginPrompt />', () => {
); );
}); });
}); });
afterAll(() => {
wrapper.unmount();
});
test('should render Wizard with all steps', async () => { test('should render Wizard with all steps', async () => {
const wizard = await waitForElement(wrapper, 'Wizard'); const wizard = await waitForElement(wrapper, 'Wizard');
const steps = wizard.prop('steps'); const steps = wizard.prop('steps');
@@ -218,6 +215,7 @@ describe('<CredentialPluginPrompt />', () => {
expect(steps[0].name).toEqual('Credential'); expect(steps[0].name).toEqual('Credential');
expect(steps[1].name).toEqual('Metadata'); expect(steps[1].name).toEqual('Metadata');
}); });
test('credentials step renders correctly', async () => { test('credentials step renders correctly', async () => {
await waitForElement(wrapper, 'CheckboxListItem', el => el.length > 0); await waitForElement(wrapper, 'CheckboxListItem', el => el.length > 0);
@@ -233,6 +231,7 @@ describe('<CredentialPluginPrompt />', () => {
false false
); );
}); });
test('metadata step renders correctly', async () => { test('metadata step renders correctly', async () => {
await act(async () => { await act(async () => {
wrapper.find('Button[children="Next"]').simulate('click'); wrapper.find('Button[children="Next"]').simulate('click');
@@ -247,6 +246,7 @@ describe('<CredentialPluginPrompt />', () => {
wrapper.find('input#credential-secret_version').prop('value') wrapper.find('input#credential-secret_version').prop('value')
).toBe('9000'); ).toBe('9000');
}); });
test('clicking Test button makes correct call', async () => { test('clicking Test button makes correct call', async () => {
await act(async () => { await act(async () => {
wrapper.find('Button[children="Test"]').simulate('click'); wrapper.find('Button[children="Test"]').simulate('click');

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -68,7 +68,6 @@ describe('<InstanceGroupEdit>', () => {
afterAll(() => { afterAll(() => {
jest.clearAllMocks(); jest.clearAllMocks();
wrapper.unmount();
}); });
test('controlplane instance group name can not be updated', async () => { 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'; import InstanceGroups from './InstanceGroups';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
}));
describe('<InstanceGroups/>', () => { describe('<InstanceGroups/>', () => {
let pageWrapper; let pageWrapper;
let pageSections; let pageSections;
@@ -17,10 +13,6 @@ describe('<InstanceGroups/>', () => {
pageSections = pageWrapper.find('PageSection'); pageSections = pageWrapper.find('PageSection');
}); });
afterEach(() => {
pageWrapper.unmount();
});
test('initially renders without crashing', () => { test('initially renders without crashing', () => {
expect(pageWrapper.length).toBe(1); expect(pageWrapper.length).toBe(1);
expect(pageSections.length).toBe(1); expect(pageSections.length).toBe(1);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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