clean up 'act()' warnings in tests

This commit is contained in:
Keith Grant
2019-10-09 14:51:38 -07:00
parent 9e44fea7b5
commit 7ad2c03480
7 changed files with 153 additions and 5401 deletions

View File

@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { act } from 'react-dom/test-utils';
import { createMemoryHistory } from 'history'; import { createMemoryHistory } from 'history';
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers'; import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
import { sleep } from '@testUtils/testUtils'; import { sleep } from '@testUtils/testUtils';
@@ -28,8 +29,6 @@ const jobTemplateData = {
host_config_key: '', host_config_key: '',
}; };
// TODO: Needs React/React-router upgrade to remove `act()` warnings
// See https://github.com/ansible/awx/issues/4817
describe('<JobTemplateAdd />', () => { describe('<JobTemplateAdd />', () => {
const defaultProps = { const defaultProps = {
description: '', description: '',
@@ -53,13 +52,19 @@ describe('<JobTemplateAdd />', () => {
jest.clearAllMocks(); jest.clearAllMocks();
}); });
test('should render Job Template Form', () => { test('should render Job Template Form', async () => {
const wrapper = mountWithContexts(<JobTemplateAdd />); let wrapper;
await act(async () => {
wrapper = mountWithContexts(<JobTemplateAdd />);
});
expect(wrapper.find('JobTemplateForm').length).toBe(1); expect(wrapper.find('JobTemplateForm').length).toBe(1);
}); });
test('should render Job Template Form with default values', async () => { test('should render Job Template Form with default values', async () => {
const wrapper = mountWithContexts(<JobTemplateAdd />); let wrapper;
await act(async () => {
wrapper = mountWithContexts(<JobTemplateAdd />);
});
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
expect(wrapper.find('input#template-description').text()).toBe( expect(wrapper.find('input#template-description').text()).toBe(
defaultProps.description defaultProps.description
@@ -90,7 +95,10 @@ describe('<JobTemplateAdd />', () => {
...jobTemplateData, ...jobTemplateData,
}, },
}); });
const wrapper = mountWithContexts(<JobTemplateAdd />); let wrapper;
await act(async () => {
wrapper = mountWithContexts(<JobTemplateAdd />);
});
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
const formik = wrapper.find('Formik').instance(); const formik = wrapper.find('Formik').instance();
const changeState = new Promise(resolve => { const changeState = new Promise(resolve => {
@@ -99,6 +107,7 @@ describe('<JobTemplateAdd />', () => {
values: { values: {
...jobTemplateData, ...jobTemplateData,
labels: [], labels: [],
instanceGroups: [],
}, },
}, },
() => resolve() () => resolve()
@@ -119,10 +128,38 @@ describe('<JobTemplateAdd />', () => {
...jobTemplateData, ...jobTemplateData,
}, },
}); });
const wrapper = mountWithContexts(<JobTemplateAdd />, { let wrapper;
context: { router: { history } }, await act(async () => {
wrapper = mountWithContexts(<JobTemplateAdd />, {
context: { router: { history } },
});
}); });
const updatedTemplateData = {
name: 'new name',
description: 'new description',
job_type: 'check',
};
const labels = [
{ id: 3, name: 'Foo', isNew: true },
{ id: 4, name: 'Bar', isNew: true },
{ id: 5, name: 'Maple' },
{ id: 6, name: 'Tree' },
];
JobTemplatesAPI.update.mockResolvedValue({
data: { ...updatedTemplateData },
});
const formik = wrapper.find('Formik').instance();
const changeState = new Promise(resolve => {
const values = {
...jobTemplateData,
...updatedTemplateData,
labels,
instanceGroups: [],
};
formik.setState({ values }, () => resolve());
});
await changeState;
await wrapper.find('JobTemplateForm').invoke('handleSubmit')( await wrapper.find('JobTemplateForm').invoke('handleSubmit')(
jobTemplateData jobTemplateData
); );
@@ -134,8 +171,11 @@ describe('<JobTemplateAdd />', () => {
test('should navigate to templates list when cancel is clicked', async () => { test('should navigate to templates list when cancel is clicked', async () => {
const history = createMemoryHistory({}); const history = createMemoryHistory({});
const wrapper = mountWithContexts(<JobTemplateAdd />, { let wrapper;
context: { router: { history } }, await act(async () => {
wrapper = mountWithContexts(<JobTemplateAdd />, {
context: { router: { history } },
});
}); });
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
wrapper.find('button[aria-label="Cancel"]').invoke('onClick')(); wrapper.find('button[aria-label="Cancel"]').invoke('onClick')();

View File

@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { act } from 'react-dom/test-utils';
import { createMemoryHistory } from 'history'; import { createMemoryHistory } from 'history';
import { sleep } from '@testUtils/testUtils'; import { sleep } from '@testUtils/testUtils';
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers'; import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
@@ -36,6 +37,7 @@ const mockJobTemplate = {
results: [{ name: 'Sushi', id: 1 }, { name: 'Major', id: 2 }], results: [{ name: 'Sushi', id: 1 }, { name: 'Major', id: 2 }],
}, },
inventory: { inventory: {
id: 2,
organization_id: 1, organization_id: 1,
}, },
}, },
@@ -158,16 +160,22 @@ describe('<JobTemplateEdit />', () => {
}); });
test('initially renders successfully', async () => { test('initially renders successfully', async () => {
const wrapper = mountWithContexts( let wrapper;
<JobTemplateEdit template={mockJobTemplate} /> await act(async () => {
); wrapper = mountWithContexts(
<JobTemplateEdit template={mockJobTemplate} />
);
});
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
}); });
test('handleSubmit should call api update', async () => { test('handleSubmit should call api update', async () => {
const wrapper = mountWithContexts( let wrapper;
<JobTemplateEdit template={mockJobTemplate} /> await act(async () => {
); wrapper = mountWithContexts(
<JobTemplateEdit template={mockJobTemplate} />
);
});
await waitForElement(wrapper, 'JobTemplateForm', e => e.length === 1); await waitForElement(wrapper, 'JobTemplateForm', e => e.length === 1);
const updatedTemplateData = { const updatedTemplateData = {
name: 'new name', name: 'new name',
@@ -185,16 +193,13 @@ describe('<JobTemplateEdit />', () => {
}); });
const formik = wrapper.find('Formik').instance(); const formik = wrapper.find('Formik').instance();
const changeState = new Promise(resolve => { const changeState = new Promise(resolve => {
formik.setState( const values = {
{ ...mockJobTemplate,
values: { ...updatedTemplateData,
...mockJobTemplate, labels,
...updatedTemplateData, instanceGroups: [],
labels, };
}, formik.setState({ values }, () => resolve());
},
() => resolve()
);
}); });
await changeState; await changeState;
wrapper.find('button[aria-label="Save"]').simulate('click'); wrapper.find('button[aria-label="Save"]').simulate('click');
@@ -211,10 +216,13 @@ describe('<JobTemplateEdit />', () => {
test('should navigate to job template detail when cancel is clicked', async () => { test('should navigate to job template detail when cancel is clicked', async () => {
const history = createMemoryHistory({}); const history = createMemoryHistory({});
const wrapper = mountWithContexts( let wrapper;
<JobTemplateEdit template={mockJobTemplate} />, await act(async () => {
{ context: { router: { history } } } wrapper = mountWithContexts(
); <JobTemplateEdit template={mockJobTemplate} />,
{ context: { router: { history } } }
);
});
const cancelButton = await waitForElement( const cancelButton = await waitForElement(
wrapper, wrapper,
'button[aria-label="Cancel"]', 'button[aria-label="Cancel"]',

View File

@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { act } from 'react-dom/test-utils';
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers'; import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
import { sleep } from '@testUtils/testUtils'; import { sleep } from '@testUtils/testUtils';
import JobTemplateForm from './JobTemplateForm'; import JobTemplateForm from './JobTemplateForm';
@@ -71,14 +72,17 @@ describe('<JobTemplateForm />', () => {
}); });
test('should render LabelsSelect', async () => { test('should render LabelsSelect', async () => {
const wrapper = mountWithContexts( let wrapper;
<JobTemplateForm await act(async () => {
template={mockData} wrapper = mountWithContexts(
handleSubmit={jest.fn()} <JobTemplateForm
handleCancel={jest.fn()} template={mockData}
/> handleSubmit={jest.fn()}
); handleCancel={jest.fn()}
await waitForElement(wrapper, 'Form', el => el.length === 0); />
);
});
// await waitForElement(wrapper, 'Form', el => el.length === 0);
expect(LabelsAPI.read).toHaveBeenCalled(); expect(LabelsAPI.read).toHaveBeenCalled();
expect(JobTemplatesAPI.readInstanceGroups).toHaveBeenCalled(); expect(JobTemplatesAPI.readInstanceGroups).toHaveBeenCalled();
wrapper.update(); wrapper.update();
@@ -90,13 +94,16 @@ describe('<JobTemplateForm />', () => {
}); });
test('should update form values on input changes', async () => { test('should update form values on input changes', async () => {
const wrapper = mountWithContexts( let wrapper;
<JobTemplateForm await act(async () => {
template={mockData} wrapper = mountWithContexts(
handleSubmit={jest.fn()} <JobTemplateForm
handleCancel={jest.fn()} template={mockData}
/> handleSubmit={jest.fn()}
); handleCancel={jest.fn()}
/>
);
});
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
const form = wrapper.find('Formik'); const form = wrapper.find('Formik');
@@ -112,14 +119,16 @@ describe('<JobTemplateForm />', () => {
target: { value: 'new job type', name: 'job_type' }, target: { value: 'new job type', name: 'job_type' },
}); });
expect(form.state('values').job_type).toEqual('new job type'); expect(form.state('values').job_type).toEqual('new job type');
wrapper.find('InventoryLookup').prop('onChange')({ wrapper.find('InventoryLookup').invoke('onChange')({
id: 3, id: 3,
name: 'inventory', name: 'inventory',
}); });
expect(form.state('values').inventory).toEqual(3); expect(form.state('values').inventory).toEqual(3);
wrapper.find('ProjectLookup').prop('onChange')({ await act(async () => {
id: 4, wrapper.find('ProjectLookup').invoke('onChange')({
name: 'project', id: 4,
name: 'project',
});
}); });
expect(form.state('values').project).toEqual(4); expect(form.state('values').project).toEqual(4);
wrapper.find('AnsibleSelect[name="playbook"]').simulate('change', { wrapper.find('AnsibleSelect[name="playbook"]').simulate('change', {
@@ -130,13 +139,16 @@ describe('<JobTemplateForm />', () => {
test('should call handleSubmit when Submit button is clicked', async () => { test('should call handleSubmit when Submit button is clicked', async () => {
const handleSubmit = jest.fn(); const handleSubmit = jest.fn();
const wrapper = mountWithContexts( let wrapper;
<JobTemplateForm await act(async () => {
template={mockData} wrapper = mountWithContexts(
handleSubmit={handleSubmit} <JobTemplateForm
handleCancel={jest.fn()} template={mockData}
/> handleSubmit={handleSubmit}
); handleCancel={jest.fn()}
/>
);
});
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
expect(handleSubmit).not.toHaveBeenCalled(); expect(handleSubmit).not.toHaveBeenCalled();
wrapper.find('button[aria-label="Save"]').simulate('click'); wrapper.find('button[aria-label="Save"]').simulate('click');
@@ -146,16 +158,19 @@ describe('<JobTemplateForm />', () => {
test('should call handleCancel when Cancel button is clicked', async () => { test('should call handleCancel when Cancel button is clicked', async () => {
const handleCancel = jest.fn(); const handleCancel = jest.fn();
const wrapper = mountWithContexts( let wrapper;
<JobTemplateForm await act(async () => {
template={mockData} wrapper = mountWithContexts(
handleSubmit={jest.fn()} <JobTemplateForm
handleCancel={handleCancel} template={mockData}
/> handleSubmit={jest.fn()}
); handleCancel={handleCancel}
/>
);
});
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
expect(handleCancel).not.toHaveBeenCalled(); expect(handleCancel).not.toHaveBeenCalled();
wrapper.find('button[aria-label="Cancel"]').prop('onClick')(); wrapper.find('button[aria-label="Cancel"]').invoke('onClick')();
expect(handleCancel).toBeCalled(); expect(handleCancel).toBeCalled();
}); });
}); });

View File

@@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { act } from 'react-dom/test-utils';
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import { LabelsAPI } from '@api'; import { LabelsAPI } from '@api';
import { sleep } from '@testUtils/testUtils';
import LabelSelect from './LabelSelect'; import LabelSelect from './LabelSelect';
jest.mock('@api'); jest.mock('@api');
@@ -17,8 +17,10 @@ describe('<LabelSelect />', () => {
LabelsAPI.read.mockReturnValue({ LabelsAPI.read.mockReturnValue({
data: { results: options }, data: { results: options },
}); });
const wrapper = mount(<LabelSelect value={[]} />); let wrapper;
await sleep(1); await act(async () => {
wrapper = mount(<LabelSelect value={[]} onError={() => {}} />);
});
wrapper.update(); wrapper.update();
expect(LabelsAPI.read).toHaveBeenCalledTimes(1); expect(LabelsAPI.read).toHaveBeenCalledTimes(1);
@@ -37,8 +39,10 @@ describe('<LabelSelect />', () => {
results: options, results: options,
}, },
}); });
const wrapper = mount(<LabelSelect value={[]} />); let wrapper;
await sleep(1); await act(async () => {
wrapper = mount(<LabelSelect value={[]} onError={() => {}}/>);
});
wrapper.update(); wrapper.update();
expect(LabelsAPI.read).toHaveBeenCalledTimes(2); expect(LabelsAPI.read).toHaveBeenCalledTimes(2);

View File

@@ -1,4 +1,5 @@
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 PlaybookSelect from './PlaybookSelect'; import PlaybookSelect from './PlaybookSelect';
import { ProjectsAPI } from '@api'; import { ProjectsAPI } from '@api';
@@ -16,19 +17,24 @@ describe('<PlaybookSelect />', () => {
jest.resetAllMocks(); jest.resetAllMocks();
}); });
test('should reload playbooks when project value changes', () => { test('should reload playbooks when project value changes', async () => {
const wrapper = mountWithContexts( let wrapper;
<PlaybookSelect await act(async () => {
projectId={1} wrapper = mountWithContexts(
isValid <PlaybookSelect
form={{}} projectId={1}
field={{}} isValid
onError={() => {}} form={{}}
/> field={{onChange: () => {}, value: ''}}
); onError={() => {}}
/>
);
});
expect(ProjectsAPI.readPlaybooks).toHaveBeenCalledWith(1); expect(ProjectsAPI.readPlaybooks).toHaveBeenCalledWith(1);
wrapper.setProps({ projectId: 15 }); await act(async () => {
wrapper.setProps({ projectId: 15 });
});
expect(ProjectsAPI.readPlaybooks).toHaveBeenCalledTimes(2); expect(ProjectsAPI.readPlaybooks).toHaveBeenCalledTimes(2);
expect(ProjectsAPI.readPlaybooks).toHaveBeenCalledWith(15); expect(ProjectsAPI.readPlaybooks).toHaveBeenCalledWith(15);