fix tests with errors

This commit is contained in:
Keith J. Grant
2021-07-02 13:25:05 -07:00
parent 4b41bbbf34
commit ad2f042f97
11 changed files with 121 additions and 97 deletions

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

@@ -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,8 +15,8 @@ describe('<JobDetail />', () => {
expect(wrapper.find(`Detail[label="${label}"] dt`).text()).toBe(label); expect(wrapper.find(`Detail[label="${label}"] dt`).text()).toBe(label);
expect(wrapper.find(`Detail[label="${label}"] dd`).text()).toBe(value); expect(wrapper.find(`Detail[label="${label}"] dd`).text()).toBe(value);
} }
afterEach(() => { afterEach(() => {
wrapper.unmount();
jest.clearAllMocks(); jest.clearAllMocks();
}); });

View File

@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { shallow } from 'enzyme';
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
import HostEventModal from './HostEventModal'; import HostEventModal from './HostEventModal';
@@ -62,53 +63,53 @@ const jsonValue = `{
] ]
}`; }`;
let detailsSection; // let detailsSection;
let jsonSection; // let jsonSection;
let standardOutSection; // let standardOutSection;
let standardErrorSection; // let standardErrorSection;
//
const findSections = wrapper => { // const findSections = wrapper => {
detailsSection = wrapper.find('section').at(0); // detailsSection = wrapper.find('section').at(0);
jsonSection = wrapper.find('section').at(1); // jsonSection = wrapper.find('section').at(1);
standardOutSection = wrapper.find('section').at(2); // standardOutSection = wrapper.find('section').at(2);
standardErrorSection = wrapper.find('section').at(3); // standardErrorSection = wrapper.find('section').at(3);
}; // };
describe('HostEventModal', () => { describe('HostEventModal', () => {
test('initially renders successfully', () => { test('initially renders successfully', () => {
const wrapper = mountWithContexts( const wrapper = shallow(
<HostEventModal hostEvent={hostEvent} onClose={() => {}} /> <HostEventModal hostEvent={hostEvent} onClose={() => {}} />
); );
expect(wrapper).toHaveLength(1); expect(wrapper).toHaveLength(1);
}); });
test('should render all tabs', () => { test('should render all tabs', () => {
const wrapper = mountWithContexts( const wrapper = shallow(
<HostEventModal hostEvent={hostEvent} onClose={() => {}} isOpen /> <HostEventModal hostEvent={hostEvent} onClose={() => {}} isOpen />
); );
/* eslint-disable react/button-has-type */ expect(wrapper.find('Tabs Tab').length).toEqual(4);
expect(wrapper.find('Tabs TabButton').length).toEqual(4);
}); });
test('should show details tab content on mount', () => { test('should initially show details tab', () => {
const wrapper = mountWithContexts( const wrapper = shallow(
<HostEventModal hostEvent={hostEvent} onClose={() => {}} isOpen /> <HostEventModal hostEvent={hostEvent} onClose={() => {}} isOpen />
); );
findSections(wrapper); expect(wrapper.find('Tabs').prop('activeKey')).toEqual(0);
expect(detailsSection.find('TextList').length).toBe(1); expect(wrapper.find('Detail')).toHaveLength(5);
function assertDetail(label, value) { function assertDetail(index, label, value) {
expect(wrapper.find(`Detail[label="${label}"] dt`).text()).toBe(label); const detail = wrapper.find('Detail').at(index);
expect(wrapper.find(`Detail[label="${label}"] dd`).text()).toBe(value); expect(detail.prop('label')).toEqual(label);
expect(detail.prop('value')).toEqual(value);
} }
// StatusIcon adds visibly hidden accessibility text " changed " const detail = wrapper.find('Detail').first();
assertDetail('Host Name', ' changed foo'); expect(detail.prop('value').props.children).toEqual([null, 'foo']);
assertDetail('Play', 'all'); assertDetail(1, 'Play', 'all');
assertDetail('Task', 'command'); assertDetail(2, 'Task', 'command');
assertDetail('Module', 'command'); assertDetail(3, 'Module', 'command');
assertDetail('Command', 'free-m'); assertDetail(4, 'Command', hostEvent.event_data.res.cmd);
}); });
test('should display successful host status icon', () => { test('should display successful host status icon', () => {
@@ -180,34 +181,30 @@ describe('HostEventModal', () => {
}); });
test('should display JSON tab content on tab click', () => { test('should display JSON tab content on tab click', () => {
const wrapper = mountWithContexts( const wrapper = shallow(
<HostEventModal hostEvent={hostEvent} onClose={() => {}} isOpen /> <HostEventModal hostEvent={hostEvent} onClose={() => {}} isOpen />
); );
findSections(wrapper); const handleTabClick = wrapper.find('Tabs').prop('onSelect');
expect(jsonSection.find('EmptyState').length).toBe(1); handleTabClick(null, 1);
wrapper.find('button[aria-label="JSON tab"]').simulate('click'); wrapper.update();
findSections(wrapper);
expect(jsonSection.find('CodeEditor').length).toBe(1);
const codeEditor = jsonSection.find('CodeEditor'); const codeEditor = wrapper.find('CodeEditor');
expect(codeEditor.prop('mode')).toBe('javascript'); expect(codeEditor.prop('mode')).toBe('javascript');
expect(codeEditor.prop('readOnly')).toBe(true); expect(codeEditor.prop('readOnly')).toBe(true);
expect(codeEditor.prop('value')).toEqual(jsonValue); expect(codeEditor.prop('value')).toEqual(jsonValue);
}); });
test('should display Standard Out tab content on tab click', () => { test('should display Standard Out tab content on tab click', () => {
const wrapper = mountWithContexts( const wrapper = shallow(
<HostEventModal hostEvent={hostEvent} onClose={() => {}} isOpen /> <HostEventModal hostEvent={hostEvent} onClose={() => {}} isOpen />
); );
findSections(wrapper); const handleTabClick = wrapper.find('Tabs').prop('onSelect');
expect(standardOutSection.find('EmptyState').length).toBe(1); handleTabClick(null, 2);
wrapper.find('button[aria-label="Standard out tab"]').simulate('click'); wrapper.update();
findSections(wrapper);
expect(standardOutSection.find('CodeEditor').length).toBe(1);
const codeEditor = standardOutSection.find('CodeEditor'); const codeEditor = wrapper.find('CodeEditor');
expect(codeEditor.prop('mode')).toBe('javascript'); expect(codeEditor.prop('mode')).toBe('javascript');
expect(codeEditor.prop('readOnly')).toBe(true); expect(codeEditor.prop('readOnly')).toBe(true);
expect(codeEditor.prop('value')).toEqual(hostEvent.event_data.res.stdout); expect(codeEditor.prop('value')).toEqual(hostEvent.event_data.res.stdout);
@@ -222,28 +219,27 @@ describe('HostEventModal', () => {
}, },
}, },
}; };
const wrapper = mountWithContexts( const wrapper = shallow(
<HostEventModal hostEvent={hostEventError} onClose={() => {}} isOpen /> <HostEventModal hostEvent={hostEventError} onClose={() => {}} isOpen />
); );
findSections(wrapper);
expect(standardErrorSection.find('EmptyState').length).toBe(1);
wrapper.find('button[aria-label="Standard error tab"]').simulate('click');
findSections(wrapper);
expect(standardErrorSection.find('CodeEditor').length).toBe(1);
const codeEditor = standardErrorSection.find('CodeEditor'); const handleTabClick = wrapper.find('Tabs').prop('onSelect');
handleTabClick(null, 3);
wrapper.update();
const codeEditor = wrapper.find('CodeEditor');
expect(codeEditor.prop('mode')).toBe('javascript'); expect(codeEditor.prop('mode')).toBe('javascript');
expect(codeEditor.prop('readOnly')).toBe(true); expect(codeEditor.prop('readOnly')).toBe(true);
expect(codeEditor.prop('value')).toEqual(' '); expect(codeEditor.prop('value')).toEqual(' ');
}); });
test('should call onClose when close button is clicked', () => { test('should pass onClose to Modal', () => {
const onClose = jest.fn(); const onClose = jest.fn();
const wrapper = mountWithContexts( const wrapper = shallow(
<HostEventModal hostEvent={hostEvent} onClose={onClose} isOpen /> <HostEventModal hostEvent={hostEvent} onClose={onClose} isOpen />
); );
wrapper.find('button[aria-label="Close"]').simulate('click');
expect(onClose).toBeCalled(); expect(wrapper.find('Modal').prop('onClose')).toEqual(onClose);
}); });
test('should render standard out of debug task', () => { test('should render standard out of debug task', () => {
@@ -258,12 +254,17 @@ describe('HostEventModal', () => {
}, },
}, },
}; };
const wrapper = mountWithContexts( const wrapper = shallow(
<HostEventModal hostEvent={debugTaskAction} onClose={() => {}} isOpen /> <HostEventModal hostEvent={debugTaskAction} onClose={() => {}} isOpen />
); );
wrapper.find('button[aria-label="Standard out tab"]').simulate('click');
findSections(wrapper); const handleTabClick = wrapper.find('Tabs').prop('onSelect');
const codeEditor = standardOutSection.find('CodeEditor'); handleTabClick(null, 2);
wrapper.update();
const codeEditor = wrapper.find('CodeEditor');
expect(codeEditor.prop('mode')).toBe('javascript');
expect(codeEditor.prop('readOnly')).toBe(true);
expect(codeEditor.prop('value')).toEqual('foo bar'); expect(codeEditor.prop('value')).toEqual('foo bar');
}); });
@@ -277,12 +278,17 @@ describe('HostEventModal', () => {
}, },
}, },
}; };
const wrapper = mountWithContexts( const wrapper = shallow(
<HostEventModal hostEvent={yumTaskAction} onClose={() => {}} isOpen /> <HostEventModal hostEvent={yumTaskAction} onClose={() => {}} isOpen />
); );
wrapper.find('button[aria-label="Standard out tab"]').simulate('click');
findSections(wrapper); const handleTabClick = wrapper.find('Tabs').prop('onSelect');
const codeEditor = standardOutSection.find('CodeEditor'); handleTabClick(null, 2);
wrapper.update();
const codeEditor = wrapper.find('CodeEditor');
expect(codeEditor.prop('mode')).toBe('javascript');
expect(codeEditor.prop('readOnly')).toBe(true);
expect(codeEditor.prop('value')).toEqual('baz'); expect(codeEditor.prop('value')).toEqual('baz');
}); });
}); });

View File

@@ -1,37 +1,26 @@
import React from 'react'; import React from 'react';
import { createMemoryHistory } from 'history'; import { shallow } from 'enzyme';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import Jobs from './Jobs'; import Jobs from './Jobs';
jest.mock('react-router-dom', () => ({ jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'), ...jest.requireActual('react-router-dom'),
useRouteMatch: () => ({
path: '/',
}),
})); }));
describe('<Jobs />', () => { describe('<Jobs />', () => {
test('initially renders successfully', () => { test('initially renders successfully', async () => {
mountWithContexts(<Jobs />); const wrapper = shallow(<Jobs />);
expect(wrapper.find('JobList')).toHaveLength(1);
}); });
test('should display a breadcrumb heading', () => { test('should display a breadcrumb heading', () => {
const history = createMemoryHistory({ const wrapper = shallow(<Jobs />);
initialEntries: ['/jobs'], const screenHeader = wrapper.find('ScreenHeader');
expect(screenHeader).toHaveLength(1);
expect(screenHeader.prop('breadcrumbConfig')).toEqual({
'/jobs': 'Jobs',
}); });
const match = { path: '/jobs', url: '/jobs', isExact: true };
const wrapper = mountWithContexts(<Jobs />, {
context: {
router: {
history,
route: {
location: history.location,
match,
},
},
},
});
expect(wrapper.find('Title').length).toBe(1);
wrapper.unmount();
}); });
}); });

View File

@@ -41,6 +41,8 @@ describe('<Subscription />', () => {
config: { config: {
license_info: { license_info: {
license_type: 'enterprise', license_type: 'enterprise',
automated_instances: '1',
automated_since: '1614714228',
}, },
}, },
}, },

View File

@@ -76,7 +76,12 @@ describe('<SubscriptionDetail />', () => {
test('should render edit button for system admin', () => { test('should render edit button for system admin', () => {
wrapper = mountWithContexts(<SubscriptionDetail />, { wrapper = mountWithContexts(<SubscriptionDetail />, {
context: { ...config, me: { is_superuser: true } }, context: {
config: {
...config,
me: { is_superuser: true },
},
},
}); });
expect(wrapper.find('Button[aria-label="edit"]').length).toBe(1); expect(wrapper.find('Button[aria-label="edit"]').length).toBe(1);

View File

@@ -222,7 +222,7 @@ function JobTemplateDetail({ template }) {
virtualEnvironment={custom_virtualenv} virtualEnvironment={custom_virtualenv}
executionEnvironment={summary_fields?.resolved_environment} executionEnvironment={summary_fields?.resolved_environment}
helpText={t`The execution environment that will be used when launching helpText={t`The execution environment that will be used when launching
this job template. The resolved execution environment can be overridden by this job template. The resolved execution environment can be overridden by
explicitly assigning a different one to this job template.`} explicitly assigning a different one to this job template.`}
/> />
<Detail label={t`Source Control Branch`} value={template.scm_branch} /> <Detail label={t`Source Control Branch`} value={template.scm_branch} />
@@ -290,7 +290,7 @@ function JobTemplateDetail({ template }) {
totalChips={summary_fields.credentials.length} totalChips={summary_fields.credentials.length}
> >
{summary_fields.credentials.map(c => ( {summary_fields.credentials.map(c => (
<Link to={`/credentials/${c.id}/details`}> <Link to={`/credentials/${c.id}/details`} key={c.id}>
<CredentialChip key={c.id} credential={c} isReadOnly /> <CredentialChip key={c.id} credential={c} isReadOnly />
</Link> </Link>
))} ))}

View File

@@ -37,6 +37,7 @@ describe('<JobTemplateDetail />', () => {
afterEach(() => { afterEach(() => {
jest.clearAllMocks(); jest.clearAllMocks();
}); });
test('should render successfully with missing summary fields', async () => { test('should render successfully with missing summary fields', async () => {
await act(async () => { await act(async () => {
wrapper = mountWithContexts( wrapper = mountWithContexts(

View File

@@ -16,6 +16,7 @@ export function required(message) {
return undefined; return undefined;
}; };
} }
export function validateTime() { export function validateTime() {
return value => { return value => {
const timeRegex = new RegExp( const timeRegex = new RegExp(

View File

@@ -1,3 +1,5 @@
import { i18n } from '@lingui/core';
import en from '../locales/en/messages';
import { import {
required, required,
minLength, minLength,
@@ -13,6 +15,12 @@ import {
} from './validators'; } from './validators';
describe('validators', () => { describe('validators', () => {
beforeAll(() => {
i18n.loadLocaleData({ en: { plurals: en } });
i18n.load({ en });
i18n.activate('en');
});
test('required returns undefined if value given', () => { test('required returns undefined if value given', () => {
expect(required(null)('some value')).toBeUndefined(); expect(required(null)('some value')).toBeUndefined();
expect(required('oops')('some value')).toBeUndefined(); expect(required('oops')('some value')).toBeUndefined();
@@ -169,6 +177,7 @@ describe('validators', () => {
test('bob has email', () => { test('bob has email', () => {
expect(requiredEmail()('bob@localhost')).toBeUndefined(); expect(requiredEmail()('bob@localhost')).toBeUndefined();
}); });
test('validate time validates properly', () => { test('validate time validates properly', () => {
expect(validateTime()('12:15 PM')).toBeUndefined(); expect(validateTime()('12:15 PM')).toBeUndefined();
expect(validateTime()('1:15 PM')).toBeUndefined(); expect(validateTime()('1:15 PM')).toBeUndefined();