Update to react-scripts 4

Co-authored-by: nixocio <nixocio@gmail.com>
This commit is contained in:
Jake McDermott 2021-03-22 09:14:39 -04:00
parent b862434bec
commit 562ba53833
No known key found for this signature in database
GPG Key ID: 0E56ED990CDFCB4F
195 changed files with 10926 additions and 8998 deletions

View File

@ -392,7 +392,7 @@ clean-ui:
rm -rf $(UI_BUILD_FLAG_FILE)
awx/ui_next/node_modules:
$(NPM_BIN) --prefix awx/ui_next --loglevel warn --ignore-scripts install
$(NPM_BIN) --prefix awx/ui_next --loglevel warn install
$(UI_BUILD_FLAG_FILE):
$(NPM_BIN) --prefix awx/ui_next --loglevel warn run compile-strings

File diff suppressed because it is too large Load Diff

View File

@ -43,7 +43,7 @@
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
"enzyme-to-json": "^3.3.5",
"eslint": "^6.8.0",
"eslint": "^7.11.0",
"eslint-config-airbnb": "^17.1.0",
"eslint-config-prettier": "^5.0.0",
"eslint-import-resolver-webpack": "0.11.1",
@ -56,7 +56,7 @@
"jest-websocket-mock": "^2.0.2",
"mock-socket": "^9.0.3",
"prettier": "^1.18.2",
"react-scripts": "^3.4.4"
"react-scripts": "^4.0.3"
},
"scripts": {
"prelint": "lingui compile",

View File

@ -1,34 +1,37 @@
import Base from './Base';
describe('Base', () => {
const createPromise = () => Promise.resolve();
const mockBaseURL = '/api/v2/organizations/';
const mockHttp = {
delete: jest.fn(createPromise),
get: jest.fn(createPromise),
options: jest.fn(createPromise),
patch: jest.fn(createPromise),
post: jest.fn(createPromise),
put: jest.fn(createPromise),
};
const BaseAPI = new Base(mockHttp, mockBaseURL);
let BaseAPI;
let mockHttp;
afterEach(() => {
jest.clearAllMocks();
beforeEach(() => {
const createPromise = () => Promise.resolve();
mockHttp = {
delete: jest.fn(createPromise),
get: jest.fn(createPromise),
options: jest.fn(createPromise),
patch: jest.fn(createPromise),
post: jest.fn(createPromise),
put: jest.fn(createPromise),
};
BaseAPI = new Base(mockHttp, mockBaseURL);
});
test('create calls http method with expected data', async done => {
afterEach(() => {
jest.resetAllMocks();
});
test('create calls http method with expected data', async () => {
const data = { name: 'test ' };
await BaseAPI.create(data);
expect(mockHttp.post).toHaveBeenCalledTimes(1);
expect(mockHttp.post.mock.calls[0][1]).toEqual(data);
done();
});
test('destroy calls http method with expected data', async done => {
test('destroy calls http method with expected data', async () => {
const resourceId = 1;
await BaseAPI.destroy(resourceId);
@ -36,11 +39,9 @@ describe('Base', () => {
expect(mockHttp.delete.mock.calls[0][0]).toEqual(
`${mockBaseURL}${resourceId}/`
);
done();
});
test('read calls http method with expected data', async done => {
test('read calls http method with expected data', async () => {
const testParams = { foo: 'bar' };
const testParamsDuplicates = { foo: ['bar', 'baz'] };
@ -57,10 +58,9 @@ describe('Base', () => {
expect(mockHttp.get.mock.calls[2][1]).toEqual({
params: { foo: ['bar', 'baz'] },
});
done();
});
test('readDetail calls http method with expected data', async done => {
test('readDetail calls http method with expected data', async () => {
const resourceId = 1;
await BaseAPI.readDetail(resourceId);
@ -69,18 +69,16 @@ describe('Base', () => {
expect(mockHttp.get.mock.calls[0][0]).toEqual(
`${mockBaseURL}${resourceId}/`
);
done();
});
test('readOptions calls http method with expected data', async done => {
test('readOptions calls http method with expected data', async () => {
await BaseAPI.readOptions();
expect(mockHttp.options).toHaveBeenCalledTimes(1);
expect(mockHttp.options.mock.calls[0][0]).toEqual(`${mockBaseURL}`);
done();
});
test('replace calls http method with expected data', async done => {
test('replace calls http method with expected data', async () => {
const resourceId = 1;
const data = { name: 'test ' };
@ -91,11 +89,9 @@ describe('Base', () => {
`${mockBaseURL}${resourceId}/`
);
expect(mockHttp.put.mock.calls[0][1]).toEqual(data);
done();
});
test('update calls http method with expected data', async done => {
test('update calls http method with expected data', async () => {
const resourceId = 1;
const data = { name: 'test ' };
@ -106,7 +102,5 @@ describe('Base', () => {
`${mockBaseURL}${resourceId}/`
);
expect(mockHttp.patch.mock.calls[0][1]).toEqual(data);
done();
});
});

View File

@ -3,16 +3,20 @@ import Organizations from './Organizations';
describe('OrganizationsAPI', () => {
const orgId = 1;
const createPromise = () => Promise.resolve();
const mockHttp = { get: jest.fn(createPromise) };
let mockHttp;
let OrganizationsAPI;
beforeEach(() => {
const createPromise = () => Promise.resolve();
mockHttp = { get: jest.fn(createPromise) };
const OrganizationsAPI = new Organizations(mockHttp);
afterEach(() => {
jest.clearAllMocks();
OrganizationsAPI = new Organizations(mockHttp);
});
test('read access list calls get with expected params', async done => {
afterEach(() => {
jest.resetAllMocks();
});
test('read access list calls get with expected params', async () => {
const testParams = { foo: 'bar' };
const testParamsDuplicates = { foo: ['bar', 'baz'] };
@ -31,10 +35,9 @@ describe('OrganizationsAPI', () => {
expect(mockHttp.get.mock.calls[2][1]).toEqual({
params: { foo: ['bar', 'baz'] },
});
done();
});
test('read teams calls get with expected params', async done => {
test('read teams calls get with expected params', async () => {
const testParams = { foo: 'bar' };
const testParamsDuplicates = { foo: ['bar', 'baz'] };
@ -53,7 +56,6 @@ describe('OrganizationsAPI', () => {
expect(mockHttp.get.mock.calls[2][1]).toEqual({
params: { foo: ['bar', 'baz'] },
});
done();
});
});

View File

@ -1,19 +1,23 @@
import Root from './Root';
describe('RootAPI', () => {
const createPromise = () => Promise.resolve();
const mockHttp = {
get: jest.fn(createPromise),
post: jest.fn(createPromise),
};
let mockHttp;
let RootAPI;
beforeEach(() => {
const createPromise = () => Promise.resolve();
mockHttp = {
get: jest.fn(createPromise),
post: jest.fn(createPromise),
};
const RootAPI = new Root(mockHttp);
RootAPI = new Root(mockHttp);
});
afterEach(() => {
jest.clearAllMocks();
});
test('login calls get and post with expected content headers', async done => {
test('login calls get and post with expected content headers', async () => {
const headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
await RootAPI.login('username', 'password');
@ -23,11 +27,9 @@ describe('RootAPI', () => {
expect(mockHttp.post).toHaveBeenCalledTimes(1);
expect(mockHttp.post.mock.calls[0]).toContainEqual({ headers });
done();
});
test('login sends expected data', async done => {
test('login sends expected data', async () => {
await RootAPI.login('foo', 'bar');
await RootAPI.login('foo', 'bar', 'baz');
@ -38,15 +40,11 @@ describe('RootAPI', () => {
expect(mockHttp.post.mock.calls[1]).toContainEqual(
'username=foo&password=bar&next=baz'
);
done();
});
test('logout calls expected http method', async done => {
test('logout calls expected http method', async () => {
await RootAPI.logout();
expect(mockHttp.get).toHaveBeenCalledTimes(1);
done();
});
});

View File

@ -3,27 +3,31 @@ import Teams from './Teams';
describe('TeamsAPI', () => {
const teamId = 1;
const roleId = 7;
const createPromise = () => Promise.resolve();
const mockHttp = { post: jest.fn(createPromise) };
const TeamsAPI = new Teams(mockHttp);
let TeamsAPI;
let mockHttp;
afterEach(() => {
jest.clearAllMocks();
beforeEach(() => {
const createPromise = () => Promise.resolve();
mockHttp = { post: jest.fn(createPromise) };
TeamsAPI = new Teams(mockHttp);
});
test('associate role calls post with expected params', async done => {
afterEach(() => {
jest.resetAllMocks();
});
test('associate role calls post with expected params', async () => {
await TeamsAPI.associateRole(teamId, roleId);
expect(mockHttp.post).toHaveBeenCalledTimes(1);
expect(
mockHttp.post.mock.calls[0]
).toContainEqual(`/api/v2/teams/${teamId}/roles/`, { id: roleId });
done();
});
test('read teams calls post with expected params', async done => {
test('read teams calls post with expected params', async () => {
await TeamsAPI.disassociateRole(teamId, roleId);
expect(mockHttp.post).toHaveBeenCalledTimes(1);
@ -34,7 +38,5 @@ describe('TeamsAPI', () => {
disassociate: true,
}
);
done();
});
});

View File

@ -3,27 +3,28 @@ import Users from './Users';
describe('UsersAPI', () => {
const userId = 1;
const roleId = 7;
const createPromise = () => Promise.resolve();
const mockHttp = { post: jest.fn(createPromise) };
const UsersAPI = new Users(mockHttp);
afterEach(() => {
jest.clearAllMocks();
let UsersAPI;
let mockHttp;
beforeEach(() => {
const createPromise = () => Promise.resolve();
mockHttp = { post: jest.fn(createPromise) };
UsersAPI = new Users(mockHttp);
});
test('associate role calls post with expected params', async done => {
afterEach(() => {
jest.resetAllMocks();
});
test('associate role calls post with expected params', async () => {
await UsersAPI.associateRole(userId, roleId);
expect(mockHttp.post).toHaveBeenCalledTimes(1);
expect(
mockHttp.post.mock.calls[0]
).toContainEqual(`/api/v2/users/${userId}/roles/`, { id: roleId });
done();
});
test('read users calls post with expected params', async done => {
test('read users calls post with expected params', async () => {
await UsersAPI.disassociateRole(userId, roleId);
expect(mockHttp.post).toHaveBeenCalledTimes(1);
@ -34,7 +35,5 @@ describe('UsersAPI', () => {
disassociate: true,
}
);
done();
});
});

View File

@ -32,11 +32,6 @@ const initialValues = {
describe('<AdHocDetailsStep />', () => {
let wrapper;
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should mount properly', async () => {
await act(async () => {
wrapper = mountWithContexts(

View File

@ -23,30 +23,6 @@ jest.mock('react-router-dom', () => ({
// this component write tests for it
describe('<_AddResourceRole />', () => {
UsersAPI.read.mockResolvedValue({
data: {
count: 2,
results: [
{ id: 1, username: 'foo', url: '' },
{ id: 2, username: 'bar', url: '' },
],
},
});
UsersAPI.readOptions.mockResolvedValue({
data: { related: {}, actions: { GET: {} } },
});
TeamsAPI.read.mockResolvedValue({
data: {
count: 2,
results: [
{ id: 1, name: 'Team foo', url: '' },
{ id: 2, name: 'Team bar', url: '' },
],
},
});
TeamsAPI.readOptions.mockResolvedValue({
data: { related: {}, actions: { GET: {} } },
});
const roles = {
admin_role: {
description: 'Can manage all aspects of the organization',
@ -59,6 +35,34 @@ describe('<_AddResourceRole />', () => {
name: 'Execute',
},
};
beforeEach(() => {
UsersAPI.read.mockResolvedValue({
data: {
count: 2,
results: [
{ id: 1, username: 'foo', url: '' },
{ id: 2, username: 'bar', url: '' },
],
},
});
UsersAPI.readOptions.mockResolvedValue({
data: { related: {}, actions: { GET: {} } },
});
TeamsAPI.read.mockResolvedValue({
data: {
count: 2,
results: [
{ id: 1, name: 'Team foo', url: '' },
{ id: 2, name: 'Team bar', url: '' },
],
},
});
TeamsAPI.readOptions.mockResolvedValue({
data: { related: {}, actions: { GET: {} } },
});
});
test('initially renders without crashing', () => {
shallow(
<_AddResourceRole

View File

@ -17,7 +17,7 @@ const mockData = [
describe('<AnsibleSelect />', () => {
const onChange = jest.fn();
test('initially renders succesfully', async () => {
test('initially renders successfully', async () => {
mountWithContexts(
<AnsibleSelect
id="bar"

View File

@ -4,15 +4,6 @@ import WS from 'jest-websocket-mock';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import useWsPendingApprovalCount from './useWsPendingApprovalCount';
/*
Jest mock timers dont play well with jest-websocket-mock,
so we'll stub out throttling to resolve immediately
*/
jest.mock('../../util/useThrottle', () => ({
__esModule: true,
default: jest.fn(val => val),
}));
function TestInner() {
return <div />;
}
@ -28,6 +19,14 @@ describe('useWsPendingApprovalCount hook', () => {
let debug;
let wrapper;
beforeEach(() => {
/*
Jest mock timers dont play well with jest-websocket-mock,
so we'll stub out throttling to resolve immediately
*/
jest.mock('../../util/useThrottle', () => ({
__esModule: true,
default: jest.fn(val => val),
}));
debug = global.console.debug; // eslint-disable-line prefer-destructuring
global.console.debug = () => {};
});

View File

@ -12,20 +12,24 @@ jest.mock('../../api');
describe('<AssociateModal />', () => {
let wrapper;
const onClose = jest.fn();
const onAssociate = jest.fn().mockResolvedValue();
const fetchRequest = jest.fn().mockReturnValue({ data: { ...mockHosts } });
const optionsRequest = jest.fn().mockResolvedValue({
data: {
actions: {
GET: {},
POST: {},
},
related_search_fields: [],
},
});
let onClose;
let onAssociate;
let fetchRequest;
let optionsRequest;
beforeEach(async () => {
onClose = jest.fn();
onAssociate = jest.fn().mockResolvedValue();
fetchRequest = jest.fn().mockReturnValue({ data: { ...mockHosts } });
optionsRequest = jest.fn().mockResolvedValue({
data: {
actions: {
GET: {},
POST: {},
},
related_search_fields: [],
},
});
await act(async () => {
wrapper = mountWithContexts(
<AssociateModal
@ -41,7 +45,6 @@ describe('<AssociateModal />', () => {
});
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});

View File

@ -2,11 +2,15 @@ import React from 'react';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import ClipboardCopyButton from './ClipboardCopyButton';
document.execCommand = jest.fn();
jest.useFakeTimers();
describe('ClipboardCopyButton', () => {
beforeEach(() => {
document.execCommand = jest.fn();
});
afterEach(() => {
jest.clearAllMocks();
});
test('renders the expected content', () => {
const wrapper = mountWithContexts(
<ClipboardCopyButton
@ -20,7 +24,8 @@ describe('ClipboardCopyButton', () => {
);
expect(wrapper).toHaveLength(1);
});
test('clicking button calls execCommand to copy to clipboard', () => {
test('clicking button calls execCommand to copy to clipboard', async () => {
const mockDelay = 1;
const wrapper = mountWithContexts(
<ClipboardCopyButton
clickTip="foo"
@ -29,13 +34,14 @@ describe('ClipboardCopyButton', () => {
copiedSuccessTip="qux"
stringToCopy="foobar!"
isDisabled={false}
switchDelay={mockDelay}
/>
).find('ClipboardCopyButton');
expect(wrapper.state('copied')).toBe(false);
wrapper.find('Button').simulate('click');
expect(document.execCommand).toBeCalledWith('copy');
expect(wrapper.state('copied')).toBe(true);
jest.runAllTimers();
await new Promise(resolve => setTimeout(resolve, mockDelay));
wrapper.update();
expect(wrapper.state('copied')).toBe(false);
});

View File

@ -39,7 +39,6 @@ describe('<HostForm />', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('changing inputs should update form values', async () => {

View File

@ -116,20 +116,6 @@ const mockResults = [
},
];
UnifiedJobsAPI.read.mockResolvedValue({
data: { count: 6, results: mockResults },
});
UnifiedJobsAPI.readOptions.mockResolvedValue({
data: {
actions: {
GET: {},
POST: {},
},
related_search_fields: [],
},
});
function waitForLoaded(wrapper) {
return waitForElement(
wrapper,
@ -142,7 +128,17 @@ describe('<JobList />', () => {
let debug;
beforeEach(() => {
UnifiedJobsAPI.read.mockResolvedValue({
data: { count: 6, results: mockResults },
data: { count: 3, results: mockResults },
});
UnifiedJobsAPI.readOptions.mockResolvedValue({
data: {
actions: {
GET: {},
POST: {},
},
related_search_fields: [],
},
});
debug = global.console.debug; // eslint-disable-line prefer-destructuring
global.console.debug = () => {};
@ -150,9 +146,10 @@ describe('<JobList />', () => {
afterEach(() => {
global.console.debug = debug;
jest.clearAllMocks();
});
test('initially renders succesfully', async () => {
test('initially renders successfully', async () => {
let wrapper;
await act(async () => {
wrapper = mountWithContexts(<JobList />);

View File

@ -4,15 +4,6 @@ import WS from 'jest-websocket-mock';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import useWsJobs from './useWsJobs';
/*
Jest mock timers dont play well with jest-websocket-mock,
so we'll stub out throttling to resolve immediately
*/
jest.mock('../../util/useThrottle', () => ({
__esModule: true,
default: jest.fn(val => val),
}));
function TestInner() {
return <div />;
}
@ -26,12 +17,21 @@ describe('useWsJobs hook', () => {
let debug;
let wrapper;
beforeEach(() => {
/*
Jest mock timers dont play well with jest-websocket-mock,
so we'll stub out throttling to resolve immediately
*/
jest.mock('../../util/useThrottle', () => ({
__esModule: true,
default: jest.fn(val => val),
}));
debug = global.console.debug; // eslint-disable-line prefer-destructuring
global.console.debug = () => {};
});
afterEach(() => {
global.console.debug = debug;
jest.clearAllMocks();
});
test('should return jobs list', () => {

View File

@ -17,18 +17,6 @@ import {
jest.mock('../../api');
describe('LaunchButton', () => {
JobTemplatesAPI.readLaunch.mockResolvedValue({
data: {
can_start_without_user_input: true,
ask_inventory_on_launch: false,
ask_variables_on_launch: false,
ask_limit_on_launch: false,
ask_scm_branch_on_launch: false,
survey_enabled: false,
variables_needed_to_start: [],
},
});
const launchButton = ({ handleLaunch }) => (
<button type="submit" onClick={() => handleLaunch()} />
);
@ -42,6 +30,20 @@ describe('LaunchButton', () => {
type: 'job_template',
};
beforeEach(() => {
JobTemplatesAPI.readLaunch.mockResolvedValue({
data: {
can_start_without_user_input: true,
ask_inventory_on_launch: false,
ask_variables_on_launch: false,
ask_limit_on_launch: false,
ask_scm_branch_on_launch: false,
survey_enabled: false,
variables_needed_to_start: [],
},
});
});
afterEach(() => jest.clearAllMocks());
test('renders the expected content', () => {

View File

@ -26,7 +26,6 @@ describe('CredentialLookup', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should render successfully', async () => {
@ -89,27 +88,6 @@ describe('CredentialLookup', () => {
expect(_CredentialLookup.defaultProps.onBlur).not.toThrow();
});
test('should auto-select credential when only one available and autoPopulate prop is true', async () => {
CredentialsAPI.read.mockReturnValue({
data: {
results: [{ id: 1 }],
count: 1,
},
});
const onChange = jest.fn();
await act(async () => {
wrapper = mountWithContexts(
<CredentialLookup
autoPopulate
credentialTypeId={1}
label="Foo"
onChange={onChange}
/>
);
});
expect(onChange).toHaveBeenCalledWith({ id: 1 });
});
test('should not auto-select credential when autoPopulate prop is false', async () => {
CredentialsAPI.read.mockReturnValue({
data: {
@ -151,3 +129,26 @@ describe('CredentialLookup', () => {
expect(onChange).not.toHaveBeenCalled();
});
});
describe('CredentialLookup auto select', () => {
test('should auto-select credential when only one available and autoPopulate prop is true', async () => {
CredentialsAPI.read.mockResolvedValue({
data: {
results: [{ id: 1 }],
count: 1,
},
});
const onChange = jest.fn();
await act(async () => {
mountWithContexts(
<CredentialLookup
autoPopulate
credentialTypeId={1}
label="Foo"
onChange={onChange}
/>
);
});
expect(onChange).toHaveBeenCalledWith({ id: 1 });
});
});

View File

@ -86,7 +86,7 @@ describe('<Lookup />', () => {
jest.restoreAllMocks();
});
test('should render succesfully', async () => {
test('should render successfully', async () => {
wrapper = await mountWrapper();
expect(wrapper.find('Lookup')).toHaveLength(1);
});

View File

@ -55,7 +55,12 @@ describe('<ProjectLookup />', () => {
test('project lookup should be enabled', async () => {
let wrapper;
ProjectsAPI.read.mockReturnValue({
data: {
results: [{ id: 1 }],
count: 1,
},
});
ProjectsAPI.readOptions.mockReturnValue({
data: {
actions: {

View File

@ -31,17 +31,22 @@ function TagMultiSelect({ onChange, value }) {
));
};
const onFilter = event => {
if (event) {
const str = event.target.value.toLowerCase();
const matches = options.filter(o => o.toLowerCase().includes(str));
return renderOptions(matches);
}
return null;
};
return (
<Select
variant={SelectVariant.typeaheadMulti}
onToggle={toggleExpanded}
onSelect={onSelect}
onClear={() => onChange('')}
onFilter={event => {
const str = event.target.value.toLowerCase();
const matches = options.filter(o => o.toLowerCase().includes(str));
return renderOptions(matches);
}}
onFilter={onFilter}
isCreatable
onCreateOption={name => {
name = name.trim();

View File

@ -1,7 +1,7 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import { NotificationTemplatesAPI } from '../../api';
import { NotificationTemplatesAPI, JobTemplatesAPI } from '../../api';
import NotificationList from './NotificationList';
jest.mock('../../api');
@ -32,67 +32,51 @@ describe('<NotificationList />', () => {
],
};
const MockModel = jest.fn().mockImplementation(() => {
return {
readNotificationTemplatesSuccess: jest.fn(),
readNotificationTemplatesError: jest.fn(),
readNotificationTemplatesStarted: jest.fn(),
associateNotificationTemplate: jest.fn(),
disassociateNotificationTemplate: jest.fn(),
};
});
const MockModelAPI = new MockModel();
NotificationTemplatesAPI.readOptions.mockReturnValue({
data: {
actions: {
GET: {
notification_type: {
choices: [['email', 'Email']],
beforeEach(async () => {
NotificationTemplatesAPI.readOptions.mockReturnValue({
data: {
actions: {
GET: {
notification_type: {
choices: [['email', 'Email']],
},
},
},
},
},
});
});
NotificationTemplatesAPI.read.mockReturnValue({ data });
NotificationTemplatesAPI.read.mockReturnValue({ data });
MockModelAPI.readNotificationTemplatesSuccess.mockReturnValue({
data: { results: [{ id: 1 }] },
});
JobTemplatesAPI.readNotificationTemplatesSuccess.mockReturnValue({
data: { results: [{ id: 1 }] },
});
MockModelAPI.readNotificationTemplatesError.mockReturnValue({
data: { results: [{ id: 2 }] },
});
JobTemplatesAPI.readNotificationTemplatesError.mockReturnValue({
data: { results: [{ id: 2 }] },
});
MockModelAPI.readNotificationTemplatesStarted.mockReturnValue({
data: { results: [{ id: 3 }] },
});
JobTemplatesAPI.readNotificationTemplatesStarted.mockReturnValue({
data: { results: [{ id: 3 }] },
});
beforeEach(async () => {
await act(async () => {
wrapper = mountWithContexts(
<NotificationList
id={1}
canToggleNotifications
apiModel={MockModelAPI}
apiModel={JobTemplatesAPI}
/>
);
});
wrapper.update();
});
afterEach(() => {
wrapper.unmount();
});
test('should render list fetched of items', () => {
expect(NotificationTemplatesAPI.read).toHaveBeenCalled();
expect(NotificationTemplatesAPI.readOptions).toHaveBeenCalled();
expect(MockModelAPI.readNotificationTemplatesSuccess).toHaveBeenCalled();
expect(MockModelAPI.readNotificationTemplatesError).toHaveBeenCalled();
expect(MockModelAPI.readNotificationTemplatesStarted).toHaveBeenCalled();
expect(JobTemplatesAPI.readNotificationTemplatesSuccess).toHaveBeenCalled();
expect(JobTemplatesAPI.readNotificationTemplatesError).toHaveBeenCalled();
expect(JobTemplatesAPI.readNotificationTemplatesStarted).toHaveBeenCalled();
expect(wrapper.find('NotificationListItem').length).toBe(3);
expect(
wrapper.find('input#notification-1-success-toggle').props().checked
@ -131,7 +115,7 @@ describe('<NotificationList />', () => {
wrapper.find('Switch#notification-2-success-toggle').prop('onChange')();
});
wrapper.update();
expect(MockModelAPI.associateNotificationTemplate).toHaveBeenCalledWith(
expect(JobTemplatesAPI.associateNotificationTemplate).toHaveBeenCalledWith(
1,
2,
'success'
@ -149,7 +133,7 @@ describe('<NotificationList />', () => {
wrapper.find('Switch#notification-1-error-toggle').prop('onChange')();
});
wrapper.update();
expect(MockModelAPI.associateNotificationTemplate).toHaveBeenCalledWith(
expect(JobTemplatesAPI.associateNotificationTemplate).toHaveBeenCalledWith(
1,
1,
'error'
@ -167,7 +151,7 @@ describe('<NotificationList />', () => {
wrapper.find('Switch#notification-1-started-toggle').prop('onChange')();
});
wrapper.update();
expect(MockModelAPI.associateNotificationTemplate).toHaveBeenCalledWith(
expect(JobTemplatesAPI.associateNotificationTemplate).toHaveBeenCalledWith(
1,
1,
'started'
@ -185,11 +169,9 @@ describe('<NotificationList />', () => {
wrapper.find('Switch#notification-1-success-toggle').prop('onChange')();
});
wrapper.update();
expect(MockModelAPI.disassociateNotificationTemplate).toHaveBeenCalledWith(
1,
1,
'success'
);
expect(
JobTemplatesAPI.disassociateNotificationTemplate
).toHaveBeenCalledWith(1, 1, 'success');
expect(
wrapper.find('input#notification-1-success-toggle').props().checked
).toBe(false);
@ -203,11 +185,9 @@ describe('<NotificationList />', () => {
wrapper.find('Switch#notification-2-error-toggle').prop('onChange')();
});
wrapper.update();
expect(MockModelAPI.disassociateNotificationTemplate).toHaveBeenCalledWith(
1,
2,
'error'
);
expect(
JobTemplatesAPI.disassociateNotificationTemplate
).toHaveBeenCalledWith(1, 2, 'error');
expect(
wrapper.find('input#notification-2-error-toggle').props().checked
).toBe(false);
@ -221,18 +201,16 @@ describe('<NotificationList />', () => {
wrapper.find('Switch#notification-3-started-toggle').prop('onChange')();
});
wrapper.update();
expect(MockModelAPI.disassociateNotificationTemplate).toHaveBeenCalledWith(
1,
3,
'started'
);
expect(
JobTemplatesAPI.disassociateNotificationTemplate
).toHaveBeenCalledWith(1, 3, 'started');
expect(
wrapper.find('input#notification-3-started-toggle').props().checked
).toBe(false);
});
test('should throw toggle error', async () => {
MockModelAPI.associateNotificationTemplate.mockRejectedValue(
JobTemplatesAPI.associateNotificationTemplate.mockRejectedValue(
new Error({
response: {
config: {
@ -248,7 +226,7 @@ describe('<NotificationList />', () => {
wrapper.find('Switch#notification-1-started-toggle').prop('onChange')();
});
wrapper.update();
expect(MockModelAPI.associateNotificationTemplate).toHaveBeenCalledWith(
expect(JobTemplatesAPI.associateNotificationTemplate).toHaveBeenCalledWith(
1,
1,
'started'

View File

@ -28,7 +28,7 @@ describe('<NotificationListItem canToggleNotifications />', () => {
jest.clearAllMocks();
});
test('initially renders succesfully and displays correct label', () => {
test('initially renders successfully and displays correct label', () => {
wrapper = mountWithContexts(
<table>
<tbody>

View File

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<NotificationListItem canToggleNotifications /> initially renders succesfully and displays correct label 1`] = `
exports[`<NotificationListItem canToggleNotifications /> initially renders successfully and displays correct label 1`] = `
<NotificationListItem
approvalsTurnedOn={false}
canToggleNotifications={true}

View File

@ -210,7 +210,9 @@ PaginatedDataList.defaultProps = {
toolbarSortColumns: [],
pluralizedItemName: 'Items',
showPageSizeOptions: true,
renderItem: item => <PaginatedDataListItem key={item.id} item={item} />,
renderItem: ({ id, ...rest }) => (
<PaginatedDataListItem key={id} item={{ id, ...rest }} />
),
renderToolbar: props => <DataListToolbar {...props} />,
onRowClick: () => null,
};

View File

@ -2969,9 +2969,7 @@ message. For more information, refer to the",
}
}
trigger={
<div
aria-describedby="pf-tooltip-1"
>
<div>
<Button
aria-label="Delete"
isDisabled={true}
@ -2988,9 +2986,7 @@ message. For more information, refer to the",
<FindRefWrapper
onFoundRef={[Function]}
>
<div
aria-describedby="pf-tooltip-1"
>
<div>
<Button
aria-label="Delete"
isDisabled={true}

View File

@ -53,10 +53,6 @@ describe('PromptDetail', () => {
);
});
afterAll(() => {
wrapper.unmount();
});
test('should render successfully', () => {
expect(wrapper.find('PromptDetail').length).toBe(1);
});
@ -111,10 +107,6 @@ describe('PromptDetail', () => {
wrapper = mountWithContexts(<PromptDetail resource={mockTemplate} />);
});
afterAll(() => {
wrapper.unmount();
});
test('should render basic detail values', () => {
expect(wrapper.find(`Detail[label="Name"]`).length).toBe(1);
expect(wrapper.find(`Detail[label="Description"]`).length).toBe(1);
@ -174,10 +166,6 @@ describe('PromptDetail', () => {
);
});
afterAll(() => {
wrapper.unmount();
});
test('should render overridden details', () => {
function assertDetail(label, value) {
expect(wrapper.find(`Detail[label="${label}"] dt`).text()).toBe(label);

View File

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

View File

@ -30,10 +30,6 @@ describe('PromptJobTemplateDetail', () => {
wrapper = mountWithContexts(<PromptJobTemplateDetail resource={mockJT} />);
});
afterAll(() => {
wrapper.unmount();
});
test('should render successfully', () => {
expect(wrapper.find('PromptJobTemplateDetail')).toHaveLength(1);
});

View File

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

View File

@ -92,6 +92,10 @@ describe('<ResourceAccessList />', () => {
],
};
const history = createMemoryHistory({
initialEntries: ['/organizations/1/access'],
});
beforeEach(async () => {
OrganizationsAPI.readAccessList.mockResolvedValue({ data });
OrganizationsAPI.readAccessOptions.mockResolvedValue({
@ -113,9 +117,7 @@ describe('<ResourceAccessList />', () => {
],
},
});
const history = createMemoryHistory({
initialEntries: ['/organizations/1/access'],
});
await act(async () => {
wrapper = mountWithContexts(
<ResourceAccessList
@ -125,6 +127,8 @@ describe('<ResourceAccessList />', () => {
{ context: { router: { history } } }
);
});
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
wrapper.update();
});
@ -133,18 +137,17 @@ describe('<ResourceAccessList />', () => {
jest.clearAllMocks();
});
test('initially renders succesfully', () => {
test('initially renders successfully', () => {
expect(wrapper.find('PaginatedDataList')).toHaveLength(1);
});
test('should fetch and display access records on mount', async done => {
test('should fetch and display access records on mount', async () => {
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
expect(OrganizationsAPI.readAccessList).toHaveBeenCalled();
expect(wrapper.find('ResourceAccessListItem').length).toBe(2);
done();
});
test('should open and close confirmation dialog when deleting role', async done => {
test('should open and close confirmation dialog when deleting role', async () => {
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
expect(wrapper.find('DeleteRoleConfirmationModal')).toHaveLength(0);
const button = wrapper.find('Chip Button').at(0);
@ -160,10 +163,9 @@ describe('<ResourceAccessList />', () => {
expect(wrapper.find('DeleteRoleConfirmationModal')).toHaveLength(0);
expect(TeamsAPI.disassociateRole).not.toHaveBeenCalled();
expect(UsersAPI.disassociateRole).not.toHaveBeenCalled();
done();
});
it('should delete user role', async done => {
test('should delete user role', async () => {
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
const button = wrapper.find('Chip Button').at(0);
await act(async () => {
@ -178,10 +180,9 @@ describe('<ResourceAccessList />', () => {
expect(TeamsAPI.disassociateRole).not.toHaveBeenCalled();
expect(UsersAPI.disassociateRole).toHaveBeenCalledWith(1, 1);
expect(OrganizationsAPI.readAccessList).toHaveBeenCalledTimes(2);
done();
});
it('should delete team role', async done => {
test('should delete team role', async () => {
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
const button = wrapper.find('Chip Button').at(1);
await act(async () => {
@ -196,8 +197,8 @@ describe('<ResourceAccessList />', () => {
expect(TeamsAPI.disassociateRole).toHaveBeenCalledWith(5, 3);
expect(UsersAPI.disassociateRole).not.toHaveBeenCalled();
expect(OrganizationsAPI.readAccessList).toHaveBeenCalledTimes(2);
done();
});
test('should call api to get org details', async () => {
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);

View File

@ -29,7 +29,7 @@ const accessRecord = {
};
describe('<ResourceAccessListItem />', () => {
test('initially renders succesfully', () => {
test('initially renders successfully', () => {
const wrapper = mountWithContexts(
<ResourceAccessListItem
accessRecord={accessRecord}

View File

@ -5895,8 +5895,8 @@ message. For more information, refer to the",
className=""
hasNoBodyWrapper={false}
header={
<ForwardRef(AlertModal__Header)>
<ForwardRef(AlertModal___StyledExclamationCircleIcon)
<AlertModal__Header>
<AlertModal___StyledExclamationCircleIcon
size="lg"
/>
<Title
@ -5906,7 +5906,7 @@ message. For more information, refer to the",
>
Remove Team Access
</Title>
</ForwardRef(AlertModal__Header)>
</AlertModal__Header>
}
isOpen={true}
onClose={[Function]}
@ -6057,8 +6057,8 @@ message. For more information, refer to the",
descriptorId="pf-modal-part-2"
hasNoBodyWrapper={false}
header={
<ForwardRef(AlertModal__Header)>
<ForwardRef(AlertModal___StyledExclamationCircleIcon)
<AlertModal__Header>
<AlertModal___StyledExclamationCircleIcon
size="lg"
/>
<Title
@ -6068,7 +6068,7 @@ message. For more information, refer to the",
>
Remove Team Access
</Title>
</ForwardRef(AlertModal__Header)>
</AlertModal__Header>
}
isOpen={true}
labelId="pf-modal-part-1"

View File

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
exports[`<ResourceAccessListItem /> initially renders successfully 1`] = `
<ResourceAccessListItem
accessRecord={
Object {
@ -2954,12 +2954,12 @@ message. For more information, refer to the",
<ResourceAccessListItem__DataListItemCells
dataListCells={
Array [
<ForwardRef(Styled(PFDataListCell))>
<DataListCell>
<TextContent>
<Text
component="h6"
>
<ForwardRef(ResourceAccessListItem___StyledLink)
<ResourceAccessListItem___StyledLink
to={
Object {
"pathname": "/users/2/details",
@ -2967,10 +2967,10 @@ message. For more information, refer to the",
}
>
jane
</ForwardRef(ResourceAccessListItem___StyledLink)>
</ResourceAccessListItem___StyledLink>
</Text>
</TextContent>
<ForwardRef(Styled(DetailList))
<Styled(DetailList)
stacked={true}
>
<Detail
@ -2980,10 +2980,10 @@ message. For more information, refer to the",
label="Name"
value="jane brown"
/>
</ForwardRef(Styled(DetailList))>
</ForwardRef(Styled(PFDataListCell))>,
<ForwardRef(Styled(PFDataListCell))>
<ForwardRef(Styled(DetailList))
</Styled(DetailList)>
</DataListCell>,
<DataListCell>
<Styled(DetailList)
stacked={true}
>
<Detail
@ -3011,8 +3011,8 @@ message. For more information, refer to the",
</Unknown>
}
/>
</ForwardRef(Styled(DetailList))>
</ForwardRef(Styled(PFDataListCell))>,
</Styled(DetailList)>
</DataListCell>,
]
}
key=".0"
@ -3021,12 +3021,12 @@ message. For more information, refer to the",
<StyledComponent
dataListCells={
Array [
<ForwardRef(Styled(PFDataListCell))>
<DataListCell>
<TextContent>
<Text
component="h6"
>
<ForwardRef(ResourceAccessListItem___StyledLink)
<ResourceAccessListItem___StyledLink
to={
Object {
"pathname": "/users/2/details",
@ -3034,10 +3034,10 @@ message. For more information, refer to the",
}
>
jane
</ForwardRef(ResourceAccessListItem___StyledLink)>
</ResourceAccessListItem___StyledLink>
</Text>
</TextContent>
<ForwardRef(Styled(DetailList))
<Styled(DetailList)
stacked={true}
>
<Detail
@ -3047,10 +3047,10 @@ message. For more information, refer to the",
label="Name"
value="jane brown"
/>
</ForwardRef(Styled(DetailList))>
</ForwardRef(Styled(PFDataListCell))>,
<ForwardRef(Styled(PFDataListCell))>
<ForwardRef(Styled(DetailList))
</Styled(DetailList)>
</DataListCell>,
<DataListCell>
<Styled(DetailList)
stacked={true}
>
<Detail
@ -3078,8 +3078,8 @@ message. For more information, refer to the",
</Unknown>
}
/>
</ForwardRef(Styled(DetailList))>
</ForwardRef(Styled(PFDataListCell))>,
</Styled(DetailList)>
</DataListCell>,
]
}
forwardedComponent={
@ -3111,12 +3111,12 @@ message. For more information, refer to the",
className="ResourceAccessListItem__DataListItemCells-sc-658iqk-0 jCdAGK"
dataListCells={
Array [
<ForwardRef(Styled(PFDataListCell))>
<DataListCell>
<TextContent>
<Text
component="h6"
>
<ForwardRef(ResourceAccessListItem___StyledLink)
<ResourceAccessListItem___StyledLink
to={
Object {
"pathname": "/users/2/details",
@ -3124,10 +3124,10 @@ message. For more information, refer to the",
}
>
jane
</ForwardRef(ResourceAccessListItem___StyledLink)>
</ResourceAccessListItem___StyledLink>
</Text>
</TextContent>
<ForwardRef(Styled(DetailList))
<Styled(DetailList)
stacked={true}
>
<Detail
@ -3137,10 +3137,10 @@ message. For more information, refer to the",
label="Name"
value="jane brown"
/>
</ForwardRef(Styled(DetailList))>
</ForwardRef(Styled(PFDataListCell))>,
<ForwardRef(Styled(PFDataListCell))>
<ForwardRef(Styled(DetailList))
</Styled(DetailList)>
</DataListCell>,
<DataListCell>
<Styled(DetailList)
stacked={true}
>
<Detail
@ -3168,8 +3168,8 @@ message. For more information, refer to the",
</Unknown>
}
/>
</ForwardRef(Styled(DetailList))>
</ForwardRef(Styled(PFDataListCell))>,
</Styled(DetailList)>
</DataListCell>,
]
}
rowid="access-list-item"

View File

@ -1,24 +1,11 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { RRule } from 'rrule';
import {
mountWithContexts,
waitForElement,
} from '../../../../testUtils/enzymeHelpers';
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
import { SchedulesAPI, JobTemplatesAPI, InventoriesAPI } from '../../../api';
import ScheduleAdd from './ScheduleAdd';
jest.mock('../../../api/models/Schedules');
jest.mock('../../../api/models/JobTemplates');
jest.mock('../../../api/models/Inventories');
SchedulesAPI.readZoneInfo.mockResolvedValue({
data: [
{
name: 'America/New_York',
},
],
});
jest.mock('../../../api');
const launchConfig = {
can_start_without_user_input: false,
@ -58,12 +45,18 @@ const launchConfig = {
},
};
JobTemplatesAPI.createSchedule.mockResolvedValue({ data: { id: 3 } });
let wrapper;
describe('<ScheduleAdd />', () => {
beforeAll(async () => {
beforeEach(async () => {
SchedulesAPI.readZoneInfo.mockResolvedValue({
data: [
{
name: 'America/New_York',
},
],
});
JobTemplatesAPI.createSchedule.mockResolvedValue({ data: { id: 3 } });
await act(async () => {
wrapper = mountWithContexts(
<ScheduleAdd
@ -78,10 +71,6 @@ describe('<ScheduleAdd />', () => {
/>
);
});
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
});
afterEach(() => {
jest.clearAllMocks();
});
test('Successfully creates a schedule with repeat frequency: None (run once)', async () => {
await act(async () => {

View File

@ -9,9 +9,7 @@ import {
} from '../../../../testUtils/enzymeHelpers';
import ScheduleDetail from './ScheduleDetail';
jest.mock('../../../api/models/JobTemplates');
jest.mock('../../../api/models/Schedules');
jest.mock('../../../api/models/WorkflowJobTemplates');
jest.mock('../../../api');
const allPrompts = {
data: {
@ -108,20 +106,21 @@ const scheduleWithPrompts = {
extra_data: { foo: 'fii' },
};
SchedulesAPI.createPreview.mockResolvedValue({
data: {
local: [],
utc: [],
},
});
describe('<ScheduleDetail />', () => {
let wrapper;
const history = createMemoryHistory({
initialEntries: ['/templates/job_template/1/schedules/1/details'],
});
beforeEach(() => {
SchedulesAPI.createPreview.mockResolvedValue({
data: {
local: [],
utc: [],
},
});
});
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});

View File

@ -13,66 +13,7 @@ import {
} from '../../../api';
import ScheduleEdit from './ScheduleEdit';
jest.mock('../../../api/models/Schedules');
jest.mock('../../../api/models/JobTemplates');
jest.mock('../../../api/models/Inventories');
jest.mock('../../../api/models/Credentials');
jest.mock('../../../api/models/CredentialTypes');
SchedulesAPI.readZoneInfo.mockResolvedValue({
data: [
{
name: 'America/New_York',
},
],
});
SchedulesAPI.readCredentials.mockResolvedValue({
data: {
results: [
{
name: 'schedule credential 1',
id: 1,
kind: 'vault',
credential_type: 3,
inputs: {},
},
{
name: 'schedule credential 2',
id: 2,
kind: 'aws',
credential_type: 4,
inputs: {},
},
],
count: 2,
},
});
CredentialTypesAPI.loadAllTypes.mockResolvedValue([
{ id: 1, name: 'ssh', kind: 'ssh' },
]);
CredentialsAPI.read.mockResolvedValue({
data: {
count: 3,
results: [
{ id: 1, name: 'Credential 1', kind: 'ssh', url: '', credential_type: 1 },
{ id: 2, name: 'Credential 2', kind: 'ssh', url: '', credential_type: 1 },
{ id: 3, name: 'Credential 3', kind: 'ssh', url: '', credential_type: 1 },
],
},
});
CredentialsAPI.readOptions.mockResolvedValue({
data: { related_search_fields: [], actions: { GET: { filterabled: true } } },
});
SchedulesAPI.update.mockResolvedValue({
data: {
id: 27,
},
});
jest.mock('../../../api');
let wrapper;
@ -113,6 +54,81 @@ const mockSchedule = {
describe('<ScheduleEdit />', () => {
beforeEach(async () => {
SchedulesAPI.readZoneInfo.mockResolvedValue({
data: [
{
name: 'America/New_York',
},
],
});
SchedulesAPI.readCredentials.mockResolvedValue({
data: {
results: [
{
name: 'schedule credential 1',
id: 1,
kind: 'vault',
credential_type: 3,
inputs: {},
},
{
name: 'schedule credential 2',
id: 2,
kind: 'aws',
credential_type: 4,
inputs: {},
},
],
count: 2,
},
});
CredentialTypesAPI.loadAllTypes.mockResolvedValue([
{ id: 1, name: 'ssh', kind: 'ssh' },
]);
CredentialsAPI.read.mockResolvedValue({
data: {
count: 3,
results: [
{
id: 1,
name: 'Credential 1',
kind: 'ssh',
url: '',
credential_type: 1,
},
{
id: 2,
name: 'Credential 2',
kind: 'ssh',
url: '',
credential_type: 1,
},
{
id: 3,
name: 'Credential 3',
kind: 'ssh',
url: '',
credential_type: 1,
},
],
},
});
CredentialsAPI.readOptions.mockResolvedValue({
data: {
related_search_fields: [],
actions: { GET: { filterabled: true } },
},
});
SchedulesAPI.update.mockResolvedValue({
data: {
id: 27,
},
});
await act(async () => {
wrapper = mountWithContexts(
<ScheduleEdit
@ -486,17 +502,13 @@ describe('<ScheduleEdit />', () => {
await act(async () => {
wrapper
.find('input[aria-labelledby="check-action-item-3"]')
.simulate('change', {
target: {
checked: true,
},
});
.find('input[aria-labelledby="check-action-item-2"]')
.simulate('click');
});
wrapper.update();
expect(
wrapper
.find('input[aria-labelledby="check-action-item-3"]')
.find('input[aria-labelledby="check-action-item-2"]')
.prop('checked')
).toBe(true);
await act(async () =>

View File

@ -5,34 +5,39 @@ import { SchedulesAPI } from '../../../api';
import ScheduleList from './ScheduleList';
import mockSchedules from '../data.schedules.json';
jest.mock('../../../api/models/Schedules');
SchedulesAPI.destroy = jest.fn();
SchedulesAPI.update.mockResolvedValue({
data: mockSchedules.results[0],
});
SchedulesAPI.read.mockResolvedValue({ data: mockSchedules });
SchedulesAPI.readOptions.mockResolvedValue({
data: {
actions: {
GET: {},
POST: {},
},
},
});
const loadSchedules = params => SchedulesAPI.read(params);
const loadScheduleOptions = () => SchedulesAPI.readOptions();
jest.mock('../../../api');
describe('ScheduleList', () => {
let wrapper;
afterAll(() => {
jest.clearAllMocks();
});
let loadSchedules;
let loadScheduleOptions;
describe('read call successful', () => {
beforeEach(async () => {
SchedulesAPI.destroy = jest.fn();
SchedulesAPI.update.mockResolvedValue({
data: mockSchedules.results[0],
});
SchedulesAPI.read.mockResolvedValue({ data: mockSchedules });
SchedulesAPI.readOptions.mockResolvedValue({
data: {
actions: {
GET: {},
POST: {},
},
},
});
loadSchedules = jest.fn();
loadSchedules.mockResolvedValue({ data: mockSchedules });
loadScheduleOptions = jest.fn();
loadScheduleOptions.mockResolvedValue({
data: {
actions: {
GET: {},
POST: {},
},
},
});
await act(async () => {
wrapper = mountWithContexts(
<ScheduleList
@ -52,7 +57,7 @@ describe('ScheduleList', () => {
});
test('should fetch schedules from api and render the list', () => {
expect(SchedulesAPI.read).toHaveBeenCalled();
expect(loadSchedules).toHaveBeenCalled();
expect(wrapper.find('ScheduleListItem').length).toBe(5);
});
@ -193,6 +198,44 @@ describe('ScheduleList', () => {
});
describe('hidden add button', () => {
beforeEach(async () => {
SchedulesAPI.destroy = jest.fn();
SchedulesAPI.update.mockResolvedValue({
data: mockSchedules.results[0],
});
SchedulesAPI.read.mockResolvedValue({ data: mockSchedules });
SchedulesAPI.readOptions.mockResolvedValue({
data: {
actions: {
GET: {},
POST: {},
},
},
});
loadSchedules = jest.fn();
loadSchedules.mockResolvedValue({ data: mockSchedules });
loadScheduleOptions = jest.fn();
loadScheduleOptions.mockResolvedValue({
data: {
actions: {
GET: {},
POST: {},
},
},
});
await act(async () => {
wrapper = mountWithContexts(
<ScheduleList
loadSchedules={loadSchedules}
loadScheduleOptions={loadScheduleOptions}
resource={{ type: 'job_template', inventory: 1 }}
launchConfig={{ survey_enabled: false }}
surveyConfig={{}}
/>
);
});
wrapper.update();
});
test('should hide add button when flag is passed', async () => {
await act(async () => {
wrapper = mountWithContexts(
@ -263,8 +306,47 @@ describe('ScheduleList', () => {
});
describe('read call unsuccessful', () => {
beforeEach(async () => {
SchedulesAPI.destroy = jest.fn();
SchedulesAPI.update.mockResolvedValue({
data: mockSchedules.results[0],
});
SchedulesAPI.read.mockResolvedValue({ data: mockSchedules });
SchedulesAPI.readOptions.mockResolvedValue({
data: {
actions: {
GET: {},
POST: {},
},
},
});
loadSchedules = jest.fn();
loadSchedules.mockResolvedValue({ data: mockSchedules });
loadScheduleOptions = jest.fn();
loadScheduleOptions.mockResolvedValue({
data: {
actions: {
GET: {},
POST: {},
},
},
});
await act(async () => {
wrapper = mountWithContexts(
<ScheduleList
loadSchedules={loadSchedules}
loadScheduleOptions={loadScheduleOptions}
resource={{ type: 'job_template', inventory: 1 }}
launchConfig={{ survey_enabled: false }}
surveyConfig={{}}
/>
);
});
wrapper.update();
});
test('should show content error when read call unsuccessful', async () => {
SchedulesAPI.read.mockRejectedValue(new Error());
loadSchedules.mockRejectedValue(new Error());
await act(async () => {
wrapper = mountWithContexts(
<ScheduleList

View File

@ -28,7 +28,7 @@ describe('<ScreenHeader />', () => {
breadcrumbHeading = breadcrumbWrapper.find('Title');
};
test('initially renders succesfully', () => {
test('initially renders successfully', () => {
breadcrumbWrapper = mountWithContexts(
<MemoryRouter initialEntries={['/foo/1/bar']} initialIndex={0}>
<ScreenHeader streamType="all_activity" breadcrumbConfig={config} />

View File

@ -7,9 +7,7 @@ import {
} from '../../../testUtils/enzymeHelpers';
import UserAndTeamAccessAdd from './UserAndTeamAccessAdd';
jest.mock('../../api/models/Teams');
jest.mock('../../api/models/Users');
jest.mock('../../api/models/JobTemplates');
jest.mock('../../api');
describe('<UserAndTeamAccessAdd/>', () => {
const resources = {
@ -66,8 +64,7 @@ describe('<UserAndTeamAccessAdd/>', () => {
await waitForElement(wrapper, 'Button[aria-label="Add"]');
});
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
jest.resetAllMocks();
});
test('should mount properly', async () => {
expect(wrapper.find('Button[aria-label="Add"]').length).toBe(1);

View File

@ -4,14 +4,12 @@ import App from './App';
jest.mock('react-dom', () => ({ render: jest.fn() }));
const div = document.createElement('div');
div.setAttribute('id', 'app');
document.body.appendChild(div);
require('./index.jsx');
describe('index.jsx', () => {
it('renders ok', () => {
const div = document.createElement('div');
div.setAttribute('id', 'app');
document.body.appendChild(div);
require('./index.jsx'); // eslint-disable-line global-require
expect(ReactDOM.render).toHaveBeenCalledWith(
<React.StrictMode>
<App />

View File

@ -3,7 +3,7 @@ import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import ActivityStreamDescription from './ActivityStreamDescription';
describe('ActivityStreamDescription', () => {
test('initially renders succesfully', () => {
test('initially renders successfully', () => {
const description = mountWithContexts(
<ActivityStreamDescription activity={{}} />
);

View File

@ -7,7 +7,7 @@ import ActivityStreamDetailButton from './ActivityStreamDetailButton';
jest.mock('../../api/models/ActivityStream');
describe('<ActivityStreamDetailButton />', () => {
test('initially renders succesfully', () => {
test('initially renders successfully', () => {
mountWithContexts(
<ActivityStreamDetailButton
streamItem={{

View File

@ -5,7 +5,7 @@ import ActivityStreamListItem from './ActivityStreamListItem';
jest.mock('../../api/models/ActivityStream');
describe('<ActivityStreamListItem />', () => {
test('initially renders succesfully', () => {
test('initially renders successfully', () => {
mountWithContexts(
<table>
<tbody>

View File

@ -19,14 +19,16 @@ jest.mock('react-router-dom', () => ({
}),
}));
CredentialsAPI.readDetail.mockResolvedValueOnce({
data: mockCredential,
});
describe('<Credential />', () => {
let wrapper;
test('initially renders user-based credential succesfully', async () => {
beforeEach(() => {
CredentialsAPI.readDetail.mockResolvedValueOnce({
data: mockCredential,
});
});
test('initially renders user-based credential successfully', async () => {
await act(async () => {
wrapper = mountWithContexts(<Credential setBreadcrumb={() => {}} />);
});
@ -34,7 +36,7 @@ describe('<Credential />', () => {
await waitForElement(wrapper, '.pf-c-tabs__item', el => el.length === 3);
});
test('initially renders org-based credential succesfully', async () => {
test('initially renders org-based credential successfully', async () => {
CredentialsAPI.readDetail.mockResolvedValueOnce({
data: mockOrgCredential,
});

View File

@ -15,7 +15,7 @@ import CredentialAdd from './CredentialAdd';
jest.mock('../../../api');
CredentialTypesAPI.read.mockResolvedValue({
const mockCredentialResults = {
data: {
results: [
{
@ -100,9 +100,7 @@ CredentialTypesAPI.read.mockResolvedValue({
},
],
},
});
CredentialsAPI.create.mockResolvedValue({ data: { id: 13 } });
};
describe('<CredentialAdd />', () => {
let wrapper;
@ -110,6 +108,8 @@ describe('<CredentialAdd />', () => {
describe('Initial GET request succeeds', () => {
beforeEach(async () => {
CredentialsAPI.read.mockResolvedValue(mockCredentialResults);
CredentialsAPI.create.mockResolvedValue({ data: { id: 13 } });
history = createMemoryHistory({ initialEntries: ['/credentials'] });
await act(async () => {
wrapper = mountWithContexts(<CredentialAdd />, {
@ -118,10 +118,6 @@ describe('<CredentialAdd />', () => {
});
});
afterEach(() => {
wrapper.unmount();
});
test('handleSubmit should call the api and redirect to details page', async () => {
await waitForElement(wrapper, 'isLoading', el => el.length === 0);
await act(async () => {

View File

@ -33,16 +33,6 @@ const mockInputSource = {
},
};
CredentialTypesAPI.readDetail.mockResolvedValue({
data: mockCredentialType,
});
CredentialsAPI.readInputSources.mockResolvedValue({
data: {
results: [mockInputSource],
},
});
function expectDetailToMatch(wrapper, label, value) {
const detail = wrapper.find(`Detail[label="${label}"]`);
expect(detail).toHaveLength(1);
@ -53,6 +43,15 @@ describe('<CredentialDetail />', () => {
let wrapper;
beforeEach(async () => {
CredentialTypesAPI.readDetail.mockResolvedValue({
data: mockCredentialType,
});
CredentialsAPI.readInputSources.mockResolvedValue({
data: {
results: [mockInputSource],
},
});
await act(async () => {
wrapper = mountWithContexts(
<CredentialDetail credential={mockCredential} />

View File

@ -116,7 +116,7 @@ const mockCredential = {
kubernetes: false,
};
UsersAPI.readAdminOfOrganizations.mockResolvedValue({
const mockOrgAdmins = {
data: {
count: 1,
results: [
@ -126,16 +126,16 @@ UsersAPI.readAdminOfOrganizations.mockResolvedValue({
},
],
},
});
};
OrganizationsAPI.read.mockResolvedValue({
const mockOrganizations = {
data: {
results: [{ id: 1 }],
count: 1,
},
});
};
CredentialTypesAPI.read.mockResolvedValue({
const mockCredentialResults = {
data: {
results: [
{
@ -272,10 +272,9 @@ CredentialTypesAPI.read.mockResolvedValue({
},
],
},
});
};
CredentialsAPI.update.mockResolvedValue({ data: { id: 3 } });
CredentialsAPI.readInputSources.mockResolvedValue({
const mockInputSources = {
data: {
results: [
{
@ -318,7 +317,7 @@ CredentialsAPI.readInputSources.mockResolvedValue({
},
],
},
});
};
describe('<CredentialEdit />', () => {
let wrapper;
@ -326,6 +325,15 @@ describe('<CredentialEdit />', () => {
describe('Initial GET request succeeds', () => {
beforeEach(async () => {
[
[UsersAPI.readAdminOfOrganizations, mockOrgAdmins],
[OrganizationsAPI.read, mockOrganizations],
[CredentialsAPI.read, mockCredentialResults],
[CredentialsAPI.update, { data: { id: 3 } }],
[CredentialsAPI.readInputSources, mockInputSources],
].forEach(([apiMethod, mockData]) => {
apiMethod.mockResolvedValue(mockData);
});
history = createMemoryHistory({ initialEntries: ['/credentials'] });
await act(async () => {
wrapper = mountWithContexts(

View File

@ -14,7 +14,7 @@ describe('<Credentials />', () => {
wrapper.unmount();
});
test('initially renders succesfully', () => {
test('initially renders successfully', () => {
wrapper = mountWithContexts(<Credentials />);
});

View File

@ -1,4 +1,5 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { Formik } from 'formik';
import { mountWithContexts } from '../../../../../testUtils/enzymeHelpers';
import credentialTypes from '../data.credentialTypes.json';
@ -67,7 +68,7 @@ describe('<CredentialField />', () => {
expect(wrapper.find('KeyIcon').length).toBe(1);
expect(wrapper.find('PficonHistoryIcon').length).toBe(1);
});
test('replace/revert button behaves as expected', () => {
test('replace/revert button behaves as expected', async () => {
wrapper = mountWithContexts(
<Formik
initialValues={{
@ -90,7 +91,10 @@ describe('<CredentialField />', () => {
.content
).toBe('Replace');
expect(wrapper.find('TextInput').props().isDisabled).toBe(true);
expect(wrapper.find('PficonHistoryIcon').simulate('click'));
wrapper.find('PficonHistoryIcon').simulate('click');
await act(async () => {
wrapper.update();
});
expect(
wrapper.find('Tooltip#credential-password-replace-tooltip').props()
.content
@ -98,7 +102,10 @@ describe('<CredentialField />', () => {
expect(wrapper.find('TextInput').props().isDisabled).toBe(false);
expect(wrapper.find('TextInput').props().value).toBe('');
expect(wrapper.find('TextInput').props().placeholder).toBe(undefined);
expect(wrapper.find('PficonHistoryIcon').simulate('click'));
wrapper.find('PficonHistoryIcon').simulate('click');
await act(async () => {
wrapper.update();
});
expect(
wrapper.find('Tooltip#credential-password-replace-tooltip').props()
.content

View File

@ -10,19 +10,16 @@ import azureVaultCredential from '../../data.azureVaultCredential.json';
import hashiCorpCredential from '../../data.hashiCorpCredential.json';
import CredentialPluginPrompt from './CredentialPluginPrompt';
jest.mock('../../../../../api/models/Credentials');
jest.mock('../../../../../api/models/CredentialTypes');
jest.mock('../../../../../api');
CredentialsAPI.test.mockResolvedValue({});
CredentialsAPI.read.mockResolvedValue({
const mockCredentialResults = {
data: {
count: 3,
results: [selectedCredential, azureVaultCredential, hashiCorpCredential],
},
});
};
CredentialsAPI.readOptions.mockResolvedValue({
const mockCredentialOptions = {
data: {
actions: {
GET: {},
@ -30,9 +27,9 @@ CredentialsAPI.readOptions.mockResolvedValue({
},
related_search_fields: [],
},
});
};
CredentialTypesAPI.readDetail.mockResolvedValue({
const mockCredentialTypeDetail = {
data: {
id: 20,
type: 'credential_type',
@ -83,7 +80,7 @@ CredentialTypesAPI.readDetail.mockResolvedValue({
},
injectors: {},
},
});
};
describe('<CredentialPluginPrompt />', () => {
describe('Plugin not configured', () => {
@ -91,15 +88,21 @@ describe('<CredentialPluginPrompt />', () => {
const onClose = jest.fn();
const onSubmit = jest.fn();
beforeAll(async () => {
CredentialsAPI.test.mockResolvedValue({});
CredentialsAPI.read.mockResolvedValue(mockCredentialResults);
CredentialsAPI.readOptions.mockResolvedValue(mockCredentialOptions);
CredentialTypesAPI.readDetail = async () => mockCredentialTypeDetail;
await act(async () => {
wrapper = mountWithContexts(
<CredentialPluginPrompt onClose={onClose} onSubmit={onSubmit} />
);
});
});
afterAll(() => {
wrapper.unmount();
});
test('should render Wizard with all steps', async () => {
const wizard = await waitForElement(wrapper, 'Wizard');
const steps = wizard.prop('steps');
@ -108,6 +111,7 @@ describe('<CredentialPluginPrompt />', () => {
expect(steps[0].name).toEqual('Credential');
expect(steps[1].name).toEqual('Metadata');
});
test('credentials step renders correctly', () => {
expect(wrapper.find('CredentialsStep').length).toBe(1);
expect(wrapper.find('DataListItem').length).toBe(3);
@ -182,6 +186,11 @@ describe('<CredentialPluginPrompt />', () => {
const onClose = jest.fn();
const onSubmit = jest.fn();
beforeAll(async () => {
jest.resetAllMocks();
CredentialsAPI.test.mockResolvedValue({});
CredentialsAPI.read.mockResolvedValue(mockCredentialResults);
CredentialsAPI.readOptions.mockResolvedValue(mockCredentialOptions);
CredentialTypesAPI.readDetail = async () => mockCredentialTypeDetail;
await act(async () => {
wrapper = mountWithContexts(
<CredentialPluginPrompt

View File

@ -36,12 +36,6 @@ const credentialTypeData = {
}),
};
CredentialTypesAPI.create.mockResolvedValue({
data: {
id: 42,
},
});
describe('<CredentialTypeAdd/>', () => {
let wrapper;
let history;
@ -50,6 +44,11 @@ describe('<CredentialTypeAdd/>', () => {
history = createMemoryHistory({
initialEntries: ['/credential_types'],
});
CredentialTypesAPI.create.mockResolvedValue({
data: {
id: 42,
},
});
await act(async () => {
wrapper = mountWithContexts(<CredentialTypeAdd />, {
context: { router: { history } },
@ -59,7 +58,6 @@ describe('<CredentialTypeAdd/>', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('handleSubmit should call the api and redirect to details page', async () => {

View File

@ -67,7 +67,6 @@ function expectDetailToMatch(wrapper, label, value) {
describe('<CredentialTypeDetails/>', () => {
let wrapper;
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});
test('should render details properly', async () => {

View File

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

View File

@ -43,6 +43,12 @@ const options = { data: { actions: { POST: true } } };
describe('<CredentialTypeList', () => {
let wrapper;
beforeEach(() => {
CredentialsAPI.read.mockResolvedValue({ data: { count: 0 } });
CredentialTypesAPI.read.mockResolvedValue(credentialTypes);
CredentialTypesAPI.readOptions.mockResolvedValue(options);
});
test('should mount successfully', async () => {
await act(async () => {
wrapper = mountWithContexts(<CredentialTypeList />);
@ -57,9 +63,6 @@ describe('<CredentialTypeList', () => {
});
test('should have data fetched and render 2 rows', async () => {
CredentialTypesAPI.read.mockResolvedValue(credentialTypes);
CredentialTypesAPI.readOptions.mockResolvedValue(options);
await act(async () => {
wrapper = mountWithContexts(<CredentialTypeList />);
});
@ -71,9 +74,6 @@ describe('<CredentialTypeList', () => {
test('should delete item successfully', async () => {
CredentialTypesAPI.read.mockResolvedValue(credentialTypes);
CredentialTypesAPI.readOptions.mockResolvedValue(options);
CredentialsAPI.read.mockResolvedValue({ data: { count: 0 } });
await act(async () => {
wrapper = mountWithContexts(<CredentialTypeList />);
});
@ -108,7 +108,19 @@ describe('<CredentialTypeList', () => {
);
});
test('should not render add button', async () => {
CredentialTypesAPI.readOptions.mockResolvedValue({
data: { actions: { POST: false } },
});
await act(async () => {
wrapper = mountWithContexts(<CredentialTypeList />);
});
waitForElement(wrapper, 'CredentialTypeList', el => el.length > 0);
expect(wrapper.find('ToolbarAddButton').length).toBe(0);
});
test('should thrown content error', async () => {
CredentialTypesAPI.destroy = jest.fn();
CredentialTypesAPI.read.mockRejectedValue(
new Error({
response: {
@ -120,7 +132,6 @@ describe('<CredentialTypeList', () => {
},
})
);
CredentialTypesAPI.readOptions.mockResolvedValue(options);
await act(async () => {
wrapper = mountWithContexts(<CredentialTypeList />);
});
@ -129,6 +140,7 @@ describe('<CredentialTypeList', () => {
});
test('should render deletion error modal', async () => {
CredentialTypesAPI.destroy = jest.fn();
CredentialTypesAPI.destroy.mockRejectedValue(
new Error({
response: {
@ -140,8 +152,6 @@ describe('<CredentialTypeList', () => {
},
})
);
CredentialTypesAPI.read.mockResolvedValue(credentialTypes);
CredentialTypesAPI.readOptions.mockResolvedValue(options);
await act(async () => {
wrapper = mountWithContexts(<CredentialTypeList />);
});
@ -172,16 +182,4 @@ describe('<CredentialTypeList', () => {
wrapper.update();
expect(wrapper.find('ErrorDetail').length).toBe(1);
});
test('should not render add button', async () => {
CredentialTypesAPI.read.mockResolvedValue(credentialTypes);
CredentialTypesAPI.readOptions.mockResolvedValue({
data: { actions: { POST: false } },
});
await act(async () => {
wrapper = mountWithContexts(<CredentialTypeList />);
});
waitForElement(wrapper, 'CredentialTypeList', el => el.length > 0);
expect(wrapper.find('ToolbarAddButton').length).toBe(0);
});
});

View File

@ -79,8 +79,7 @@ describe('<CredentialTypeForm/>', () => {
});
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
jest.resetAllMocks();
});
test('Initially renders successfully', () => {
@ -106,7 +105,7 @@ describe('<CredentialTypeForm/>', () => {
expect(onSubmit).toHaveBeenCalledTimes(1);
});
test('should update form values', () => {
test('should update form values', async () => {
act(() => {
wrapper.find('input#credential-type-name').simulate('change', {
target: { value: 'Foo', name: 'name' },
@ -115,7 +114,7 @@ describe('<CredentialTypeForm/>', () => {
target: { value: 'New description', name: 'description' },
});
});
wrapper.update();
await act(async () => wrapper.update());
expect(wrapper.find('input#credential-type-name').prop('value')).toEqual(
'Foo'
);

View File

@ -80,6 +80,12 @@ describe('<ExecutionEnvironmentAdd/>', () => {
history = createMemoryHistory({
initialEntries: ['/execution_environments'],
});
ExecutionEnvironmentsAPI.readOptions.mockResolvedValue(mockOptions);
ExecutionEnvironmentsAPI.create.mockResolvedValue({
data: {
id: 42,
},
});
await act(async () => {
wrapper = mountWithContexts(<ExecutionEnvironmentAdd me={mockMe} />, {
context: { router: { history } },

View File

@ -14,13 +14,6 @@ const hostData = {
variables: '---\nfoo: bar',
};
HostsAPI.create.mockResolvedValue({
data: {
...hostData,
id: 5,
},
});
describe('<HostAdd />', () => {
let wrapper;
let history;
@ -30,6 +23,12 @@ describe('<HostAdd />', () => {
initialEntries: ['/templates/job_templates/1/survey/edit/foo'],
state: { some: 'state' },
});
HostsAPI.create.mockResolvedValue({
data: {
...hostData,
id: 5,
},
});
await act(async () => {
wrapper = mountWithContexts(<HostAdd />, {
context: { router: { history } },
@ -39,7 +38,6 @@ describe('<HostAdd />', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('handleSubmit should post to api', async () => {

View File

@ -19,10 +19,6 @@ describe('<HostDetail />', () => {
wrapper = mountWithContexts(<HostDetail host={mockHost} />);
});
afterAll(() => {
wrapper.unmount();
});
test('should render Details', async () => {
function assertDetail(label, value) {
expect(wrapper.find(`Detail[label="${label}"] dt`).text()).toBe(label);
@ -81,10 +77,6 @@ describe('<HostDetail />', () => {
wrapper = mountWithContexts(<HostDetail host={mockHost} />);
});
afterAll(() => {
wrapper.unmount();
});
test('should hide activity stream when there are no recent jobs', async () => {
expect(wrapper.find(`Detail[label="Activity"] Sparkline`)).toHaveLength(
0

View File

@ -29,7 +29,6 @@ describe('<HostEdit />', () => {
afterAll(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('handleSubmit should call api update', async () => {

View File

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

View File

@ -10,7 +10,7 @@ jest.mock('react-router-dom', () => ({
}));
describe('<Hosts />', () => {
test('initially renders succesfully', () => {
test('initially renders successfully', () => {
mountWithContexts(<Hosts />);
});

View File

@ -37,18 +37,6 @@ const instanceGroupCreateData = {
'apiVersion: v1\nkind: Pod\nmetadata:\n namespace: default\nspec:\n containers:\n - image: ansible/ansible-runner\n tty: true\n stdin: true\n imagePullPolicy: Always\n args:\n - sleep\n - infinity\n - test',
};
InstanceGroupsAPI.create.mockResolvedValue({
data: {
id: 123,
},
});
InstanceGroupsAPI.readOptions.mockResolvedValue({
data: {
results: initialPodSpec,
},
});
describe('<ContainerGroupAdd/>', () => {
let wrapper;
let history;
@ -58,6 +46,18 @@ describe('<ContainerGroupAdd/>', () => {
initialEntries: ['/instance_groups'],
});
InstanceGroupsAPI.create.mockResolvedValue({
data: {
id: 123,
},
});
InstanceGroupsAPI.readOptions.mockResolvedValue({
data: {
results: initialPodSpec,
},
});
await act(async () => {
wrapper = mountWithContexts(<ContainerGroupAdd />, {
context: { router: { history } },

View File

@ -41,12 +41,6 @@ const instanceGroupData = {
},
};
InstanceGroupsAPI.create.mockResolvedValue({
data: {
id: 42,
},
});
describe('<InstanceGroupAdd/>', () => {
let wrapper;
let history;
@ -55,6 +49,11 @@ describe('<InstanceGroupAdd/>', () => {
history = createMemoryHistory({
initialEntries: ['/instance_groups'],
});
InstanceGroupsAPI.create.mockResolvedValue({
data: {
id: 42,
},
});
await act(async () => {
wrapper = mountWithContexts(<InstanceGroupAdd />, {
context: { router: { history } },

View File

@ -52,17 +52,19 @@ const instanceGroups = {
};
const options = { data: { actions: { POST: true } } };
OrganizationsAPI.read.mockResolvedValue({ data: { count: 0 } });
InventoriesAPI.read.mockResolvedValue({ data: { count: 0 } });
UnifiedJobTemplatesAPI.read.mockResolvedValue({ data: { count: 0 } });
describe('<InstanceGroupList />', () => {
let wrapper;
test('should have data fetched and render 3 rows', async () => {
beforeEach(() => {
OrganizationsAPI.read.mockResolvedValue({ data: { count: 0 } });
InventoriesAPI.read.mockResolvedValue({ data: { count: 0 } });
UnifiedJobTemplatesAPI.read.mockResolvedValue({ data: { count: 0 } });
InstanceGroupsAPI.read.mockResolvedValue(instanceGroups);
InstanceGroupsAPI.readOptions.mockResolvedValue(options);
});
test('should have data fetched and render 3 rows', async () => {
await act(async () => {
wrapper = mountWithContexts(<InstanceGroupList />);
});
@ -73,9 +75,6 @@ describe('<InstanceGroupList />', () => {
});
test('should delete item successfully', async () => {
InstanceGroupsAPI.read.mockResolvedValue(instanceGroups);
InstanceGroupsAPI.readOptions.mockResolvedValue(options);
await act(async () => {
wrapper = mountWithContexts(<InstanceGroupList />);
});
@ -111,9 +110,6 @@ describe('<InstanceGroupList />', () => {
});
test('should not be able to delete tower instance group', async () => {
InstanceGroupsAPI.read.mockResolvedValue(instanceGroups);
InstanceGroupsAPI.readOptions.mockResolvedValue(options);
await act(async () => {
wrapper = mountWithContexts(<InstanceGroupList />);
});
@ -144,6 +140,7 @@ describe('<InstanceGroupList />', () => {
});
test('should thrown content error', async () => {
InstanceGroupsAPI.read = jest.fn();
InstanceGroupsAPI.read.mockRejectedValue(
new Error({
response: {
@ -155,7 +152,6 @@ describe('<InstanceGroupList />', () => {
},
})
);
InstanceGroupsAPI.readOptions.mockResolvedValue(options);
await act(async () => {
wrapper = mountWithContexts(<InstanceGroupList />);
});
@ -165,6 +161,7 @@ describe('<InstanceGroupList />', () => {
test('should render deletion error modal', async () => {
jest.setTimeout(5000 * 4);
InstanceGroupsAPI.destroy = jest.fn();
InstanceGroupsAPI.destroy.mockRejectedValue(
new Error({
response: {
@ -176,8 +173,6 @@ describe('<InstanceGroupList />', () => {
},
})
);
InstanceGroupsAPI.read.mockResolvedValue(instanceGroups);
InstanceGroupsAPI.readOptions.mockResolvedValue(options);
await act(async () => {
wrapper = mountWithContexts(<InstanceGroupList />);
});

View File

@ -111,7 +111,7 @@ describe('<ContainerGroupForm/>', () => {
expect(wrapper.find('CredentialLookup').prop('value').name).toBe('test');
});
test('should update form values', () => {
test('should update form values', async () => {
act(() => {
wrapper.find('CredentialLookup').invoke('onBlur')();
wrapper.find('CredentialLookup').invoke('onChange')({
@ -122,7 +122,9 @@ describe('<ContainerGroupForm/>', () => {
target: { value: 'new Foo', name: 'name' },
});
});
wrapper.update();
await act(async () => {
wrapper.update();
});
expect(wrapper.find('CredentialLookup').prop('value')).toEqual({
id: 99,
name: 'credential',

View File

@ -85,7 +85,7 @@ describe('<InstanceGroupForm/>', () => {
expect(onSubmit).toHaveBeenCalledTimes(1);
});
test('should update form values', () => {
test('should update form values', async () => {
act(() => {
wrapper.find('input#instance-group-name').simulate('change', {
target: { value: 'Foo', name: 'name' },
@ -96,7 +96,9 @@ describe('<InstanceGroupForm/>', () => {
target: { value: 10, name: 'policy_instance_minimum' },
});
});
wrapper.update();
await act(async () => {
wrapper.update();
});
expect(wrapper.find('input#instance-group-name').prop('value')).toEqual(
'Foo'
);

View File

@ -18,14 +18,16 @@ jest.mock('react-router-dom', () => ({
}),
}));
InventoriesAPI.readDetail.mockResolvedValue({
data: mockInventory,
});
describe('<Inventory />', () => {
let wrapper;
test('initially renders succesfully', async () => {
beforeEach(async () => {
InventoriesAPI.readDetail.mockResolvedValue({
data: mockInventory,
});
});
test('initially renders successfully', async () => {
await act(async () => {
wrapper = mountWithContexts(<Inventory setBreadcrumb={() => {}} />);
});

View File

@ -12,24 +12,23 @@ import InventoryAdd from './InventoryAdd';
jest.mock('../../../api');
CredentialTypesAPI.read.mockResolvedValue({
data: {
results: [
{
id: 14,
name: 'insights',
},
],
},
});
InventoriesAPI.create.mockResolvedValue({ data: { id: 13 } });
describe('<InventoryAdd />', () => {
let wrapper;
let history;
beforeEach(async () => {
history = createMemoryHistory({ initialEntries: ['/inventories'] });
CredentialTypesAPI.read.mockResolvedValue({
data: {
results: [
{
id: 14,
name: 'insights',
},
],
},
});
InventoriesAPI.create.mockResolvedValue({ data: { id: 13 } });
await act(async () => {
wrapper = mountWithContexts(<InventoryAdd />, {
context: { router: { history } },
@ -37,10 +36,6 @@ describe('<InventoryAdd />', () => {
});
});
afterEach(() => {
wrapper.unmount();
});
test('Initially renders successfully', () => {
expect(wrapper.length).toBe(1);
});

View File

@ -47,16 +47,6 @@ const mockInventory = {
pending_deletion: false,
};
CredentialTypesAPI.read.mockResolvedValue({
data: {
results: [
{
id: 14,
name: 'insights',
},
],
},
});
const associatedInstanceGroups = [
{
id: 1,
@ -71,6 +61,18 @@ function expectDetailToMatch(wrapper, label, value) {
}
describe('<InventoryDetail />', () => {
beforeEach(async () => {
CredentialTypesAPI.read.mockResolvedValue({
data: {
results: [
{
id: 14,
name: 'insights',
},
],
},
});
});
test('should render details', async () => {
InventoriesAPI.readInstanceGroups.mockResolvedValue({
data: {
@ -90,11 +92,11 @@ describe('<InventoryDetail />', () => {
expectDetailToMatch(wrapper, 'Type', 'Inventory');
const org = wrapper.find('Detail[label="Organization"]');
expect(org.prop('value')).toMatchInlineSnapshot(`
<ForwardRef
<Link
to="/organizations/1/details"
>
The Organization
</ForwardRef>
</Link>
`);
const vars = wrapper.find('VariablesDetail');
expect(vars).toHaveLength(1);

View File

@ -53,33 +53,33 @@ const mockInventory = {
pending_deletion: false,
};
CredentialTypesAPI.read.mockResolvedValue({
data: {
results: [
{
id: 14,
name: 'insights',
},
],
},
});
const associatedInstanceGroups = [
{
id: 1,
name: 'Foo',
},
];
InventoriesAPI.readInstanceGroups.mockResolvedValue({
data: {
results: associatedInstanceGroups,
},
});
describe('<InventoryEdit />', () => {
let wrapper;
let history;
beforeEach(async () => {
CredentialTypesAPI.read.mockResolvedValue({
data: {
results: [
{
id: 14,
name: 'insights',
},
],
},
});
InventoriesAPI.readInstanceGroups.mockResolvedValue({
data: {
results: associatedInstanceGroups,
},
});
history = createMemoryHistory({ initialEntries: ['/inventories'] });
await act(async () => {
wrapper = mountWithContexts(<InventoryEdit inventory={mockInventory} />, {
@ -88,10 +88,6 @@ describe('<InventoryEdit />', () => {
});
});
afterEach(() => {
wrapper.unmount();
});
test('initially renders successfully', async () => {
expect(wrapper.find('InventoryEdit').length).toBe(1);
});

View File

@ -19,28 +19,27 @@ jest.mock('react-router-dom', () => ({
}),
}));
GroupsAPI.readDetail.mockResolvedValue({
data: {
id: 1,
name: 'Foo',
description: 'Bar',
variables: 'bizz: buzz',
summary_fields: {
inventory: { id: 1 },
created_by: { id: 1, username: 'Athena' },
modified_by: { id: 1, username: 'Apollo' },
},
created: '2020-04-25T01:23:45.678901Z',
modified: '2020-04-25T01:23:45.678901Z',
},
});
describe('<InventoryGroup />', () => {
let wrapper;
let history;
const inventory = { id: 1, name: 'Foo' };
beforeEach(async () => {
GroupsAPI.readDetail.mockResolvedValue({
data: {
id: 1,
name: 'Foo',
description: 'Bar',
variables: 'bizz: buzz',
summary_fields: {
inventory: { id: 1 },
created_by: { id: 1, username: 'Athena' },
modified_by: { id: 1, username: 'Apollo' },
},
created: '2020-04-25T01:23:45.678901Z',
modified: '2020-04-25T01:23:45.678901Z',
},
});
history = createMemoryHistory({
initialEntries: ['/inventories/inventory/1/groups/1/details'],
});
@ -55,10 +54,6 @@ describe('<InventoryGroup />', () => {
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
});
afterEach(() => {
wrapper.unmount();
});
test('renders successfully', async () => {
expect(wrapper.length).toBe(1);
});

View File

@ -30,9 +30,6 @@ describe('<InventoryGroupAdd />', () => {
);
});
});
afterEach(() => {
wrapper.unmount();
});
test('InventoryGroupAdd renders successfully', () => {
expect(wrapper.length).toBe(1);
});

View File

@ -64,7 +64,6 @@ describe('<InventoryGroupDetail />', () => {
});
});
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});
test('InventoryGroupDetail renders successfully', () => {
@ -150,8 +149,6 @@ describe('<InventoryGroupDetail />', () => {
expect(wrapper.find('button[aria-label="Edit"]').length).toBe(0);
expect(wrapper.find('button[aria-label="Delete"]').length).toBe(0);
wrapper.unmount();
});
});
});

View File

@ -8,17 +8,18 @@ import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
import InventoryGroupEdit from './InventoryGroupEdit';
jest.mock('../../../api');
GroupsAPI.readDetail.mockResolvedValue({
data: {
name: 'Foo',
description: 'Bar',
variables: 'bizz: buzz',
},
});
describe('<InventoryGroupEdit />', () => {
let wrapper;
let history;
beforeEach(async () => {
GroupsAPI.readDetail.mockResolvedValue({
data: {
name: 'Foo',
description: 'Bar',
variables: 'bizz: buzz',
},
});
history = createMemoryHistory({
initialEntries: ['/inventories/inventory/1/groups/2/edit'],
});
@ -37,9 +38,7 @@ describe('<InventoryGroupEdit />', () => {
);
});
});
afterEach(() => {
wrapper.unmount();
});
test('InventoryGroupEdit renders successfully', () => {
expect(wrapper.length).toBe(1);
});

View File

@ -8,18 +8,19 @@ import { GroupsAPI } from '../../../api';
jest.mock('../../../api');
GroupsAPI.createHost.mockResolvedValue({
data: {
...mockHost,
},
});
describe('<InventoryGroupHostAdd />', () => {
let wrapper;
let history;
beforeAll(async () => {
beforeEach(async () => {
history = createMemoryHistory();
GroupsAPI.createHost.mockResolvedValue({
data: {
...mockHost,
},
});
await act(async () => {
wrapper = mountWithContexts(
<InventoryGroupHostAdd inventoryGroup={{ id: 123, inventory: 3 }} />,
@ -32,7 +33,6 @@ describe('<InventoryGroupHostAdd />', () => {
afterAll(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('handleSubmit should post to api', async () => {

View File

@ -32,6 +32,10 @@ describe('<InventoryHost />', () => {
let history;
beforeEach(async () => {
InventoriesAPI.readHostDetail.mockResolvedValue({
data: { ...mockHost },
});
await act(async () => {
wrapper = mountWithContexts(
<InventoryHost inventory={mockInventory} setBreadcrumb={() => {}} />

View File

@ -8,18 +8,17 @@ import { HostsAPI } from '../../../api';
jest.mock('../../../api');
HostsAPI.create.mockResolvedValue({
data: {
...mockHost,
},
});
describe('<InventoryHostAdd />', () => {
let wrapper;
let history;
beforeAll(async () => {
beforeEach(async () => {
history = createMemoryHistory();
HostsAPI.create.mockResolvedValue({
data: {
...mockHost,
},
});
await act(async () => {
wrapper = mountWithContexts(<InventoryHostAdd inventory={{ id: 3 }} />, {
context: { router: { history } },
@ -29,7 +28,6 @@ describe('<InventoryHostAdd />', () => {
afterAll(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('handleSubmit should post to api', async () => {

View File

@ -18,10 +18,6 @@ describe('<InventoryHostDetail />', () => {
wrapper = mountWithContexts(<InventoryHostDetail host={mockHost} />);
});
afterAll(() => {
wrapper.unmount();
});
test('should render Details', async () => {
function assertDetail(label, value) {
expect(wrapper.find(`Detail[label="${label}"] dt`).text()).toBe(label);
@ -91,10 +87,6 @@ describe('<InventoryHostDetail />', () => {
wrapper = mountWithContexts(<InventoryHostDetail host={readOnlyHost} />);
});
afterAll(() => {
wrapper.unmount();
});
test('should hide activity stream when there are no recent jobs', async () => {
expect(wrapper.find(`Detail[label="Activity"] Sparkline`)).toHaveLength(
0

View File

@ -32,7 +32,6 @@ describe('<InventoryHostEdit />', () => {
afterAll(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('handleSubmit should call api update', async () => {

View File

@ -9,7 +9,7 @@ import { HostsAPI } from '../../../api';
import mockHost from '../shared/data.host.json';
import mockHostFacts from '../shared/data.hostFacts.json';
jest.mock('../../../api/models/Hosts');
jest.mock('../../../api');
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => ({
@ -31,7 +31,6 @@ describe('<InventoryHostFacts />', () => {
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('initially renders successfully ', () => {

View File

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

View File

@ -4,15 +4,6 @@ import WS from 'jest-websocket-mock';
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
import useWsInventories from './useWsInventories';
/*
Jest mock timers dont play well with jest-websocket-mock,
so we'll stub out throttling to resolve immediately
*/
jest.mock('../../../util/useThrottle', () => ({
__esModule: true,
default: jest.fn(val => val),
}));
function TestInner() {
return <div />;
}
@ -39,6 +30,14 @@ describe('useWsInventories hook', () => {
let debug;
let wrapper;
beforeEach(() => {
/*
Jest mock timers dont play well with jest-websocket-mock,
so we'll stub out throttling to resolve immediately
*/
jest.mock('../../../util/useThrottle', () => ({
__esModule: true,
default: jest.fn(val => val),
}));
debug = global.console.debug; // eslint-disable-line prefer-destructuring
global.console.debug = () => {};
});

View File

@ -25,10 +25,6 @@ describe('<InventoryRelatedGroupAdd/>', () => {
wrapper = mountWithContexts(<InventoryRelatedGroupAdd />);
});
afterEach(() => {
wrapper.unmount();
});
test('should render properly', () => {
expect(wrapper.find('InventoryRelatedGroupAdd').length).toBe(1);
});

View File

@ -41,31 +41,33 @@ describe('<InventorySourceAdd />', () => {
organization: 2,
};
InventorySourcesAPI.readOptions.mockResolvedValue({
data: {
actions: {
GET: {
source: {
choices: [
['file', 'File, Directory or Script'],
['scm', 'Sourced from a Project'],
['ec2', 'Amazon EC2'],
['gce', 'Google Compute Engine'],
['azure_rm', 'Microsoft Azure Resource Manager'],
['vmware', 'VMware vCenter'],
['satellite6', 'Red Hat Satellite 6'],
['openstack', 'OpenStack'],
['rhv', 'Red Hat Virtualization'],
['tower', 'Ansible Tower'],
],
beforeEach(async () => {
InventorySourcesAPI.readOptions.mockResolvedValue({
data: {
actions: {
GET: {
source: {
choices: [
['file', 'File, Directory or Script'],
['scm', 'Sourced from a Project'],
['ec2', 'Amazon EC2'],
['gce', 'Google Compute Engine'],
['azure_rm', 'Microsoft Azure Resource Manager'],
['vmware', 'VMware vCenter'],
['satellite6', 'Red Hat Satellite 6'],
['openstack', 'OpenStack'],
['rhv', 'Red Hat Virtualization'],
['tower', 'Ansible Tower'],
],
},
},
},
},
},
});
});
ProjectsAPI.readInventories.mockResolvedValue({
data: [],
ProjectsAPI.readInventories.mockResolvedValue({
data: [],
});
});
afterEach(() => {

View File

@ -13,36 +13,7 @@ import {
WorkflowJobTemplateNodesAPI,
} from '../../../api';
jest.mock('../../../api/models/InventorySources');
jest.mock('../../../api/models/Inventories');
jest.mock('../../../api/models/WorkflowJobTemplateNodes');
InventoriesAPI.updateSources.mockResolvedValue({
data: [{ inventory_source: 1 }],
});
WorkflowJobTemplateNodesAPI.read.mockResolvedValue({ data: { count: 0 } });
InventorySourcesAPI.readOptions.mockResolvedValue({
data: {
actions: {
GET: {
source: {
choices: [
['file', 'File, Directory or Script'],
['scm', 'Sourced from a Project'],
['ec2', 'Amazon EC2'],
['gce', 'Google Compute Engine'],
['azure_rm', 'Microsoft Azure Resource Manager'],
['vmware', 'VMware vCenter'],
['satellite6', 'Red Hat Satellite 6'],
['openstack', 'OpenStack'],
['rhv', 'Red Hat Virtualization'],
['tower', 'Ansible Tower'],
],
},
},
},
},
});
jest.mock('../../../api');
function assertDetail(wrapper, label, value) {
expect(wrapper.find(`Detail[label="${label}"] dt`).text()).toBe(label);
@ -52,8 +23,36 @@ function assertDetail(wrapper, label, value) {
describe('InventorySourceDetail', () => {
let wrapper;
beforeEach(async () => {
InventoriesAPI.updateSources.mockResolvedValue({
data: [{ inventory_source: 1 }],
});
WorkflowJobTemplateNodesAPI.read.mockResolvedValue({ data: { count: 0 } });
InventorySourcesAPI.readOptions.mockResolvedValue({
data: {
actions: {
GET: {
source: {
choices: [
['file', 'File, Directory or Script'],
['scm', 'Sourced from a Project'],
['ec2', 'Amazon EC2'],
['gce', 'Google Compute Engine'],
['azure_rm', 'Microsoft Azure Resource Manager'],
['vmware', 'VMware vCenter'],
['satellite6', 'Red Hat Satellite 6'],
['openstack', 'OpenStack'],
['rhv', 'Red Hat Virtualization'],
['tower', 'Ansible Tower'],
],
},
},
},
},
});
});
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});

View File

@ -8,9 +8,7 @@ import {
import InventorySourceEdit from './InventorySourceEdit';
import { CredentialsAPI, InventorySourcesAPI, ProjectsAPI } from '../../../api';
jest.mock('../../../api/models/Projects');
jest.mock('../../../api/models/Credentials');
jest.mock('../../../api/models/InventorySources');
jest.mock('../../../api');
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => ({
@ -20,7 +18,6 @@ jest.mock('react-router-dom', () => ({
describe('<InventorySourceEdit />', () => {
let wrapper;
let history;
const mockInvSrc = {
id: 23,
description: 'bar',
@ -42,57 +39,58 @@ describe('<InventorySourceEdit />', () => {
name: 'Foo',
organization: 1,
};
InventorySourcesAPI.readOptions.mockResolvedValue({
data: {
actions: {
GET: {
source: {
choices: [
['file', 'File, Directory or Script'],
['scm', 'Sourced from a Project'],
['ec2', 'Amazon EC2'],
['gce', 'Google Compute Engine'],
['azure_rm', 'Microsoft Azure Resource Manager'],
['vmware', 'VMware vCenter'],
['satellite6', 'Red Hat Satellite 6'],
['openstack', 'OpenStack'],
['rhv', 'Red Hat Virtualization'],
['tower', 'Ansible Tower'],
],
const history = createMemoryHistory();
beforeEach(async () => {
InventorySourcesAPI.readOptions.mockResolvedValue({
data: {
actions: {
GET: {
source: {
choices: [
['file', 'File, Directory or Script'],
['scm', 'Sourced from a Project'],
['ec2', 'Amazon EC2'],
['gce', 'Google Compute Engine'],
['azure_rm', 'Microsoft Azure Resource Manager'],
['vmware', 'VMware vCenter'],
['satellite6', 'Red Hat Satellite 6'],
['openstack', 'OpenStack'],
['rhv', 'Red Hat Virtualization'],
['tower', 'Ansible Tower'],
],
},
},
},
},
},
});
InventorySourcesAPI.replace.mockResolvedValue({
data: {
...mockInvSrc,
},
});
ProjectsAPI.readInventories.mockResolvedValue({
data: [],
});
CredentialsAPI.read.mockResolvedValue({
data: { count: 0, results: [] },
});
ProjectsAPI.read.mockResolvedValue({
data: {
count: 2,
results: [
{
id: 1,
name: 'mock proj one',
},
{
id: 2,
name: 'mock proj two',
},
],
},
});
});
InventorySourcesAPI.replace.mockResolvedValue({
data: {
...mockInvSrc,
},
});
ProjectsAPI.readInventories.mockResolvedValue({
data: [],
});
CredentialsAPI.read.mockResolvedValue({
data: { count: 0, results: [] },
});
ProjectsAPI.read.mockResolvedValue({
data: {
count: 2,
results: [
{
id: 1,
name: 'mock proj one',
},
{
id: 2,
name: 'mock proj two',
},
],
},
});
beforeAll(async () => {
history = createMemoryHistory();
await act(async () => {
wrapper = mountWithContexts(
<InventorySourceEdit inventory={mockInventory} source={mockInvSrc} />,
@ -106,7 +104,6 @@ describe('<InventorySourceEdit />', () => {
afterAll(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('handleSubmit should call api update', async () => {

View File

@ -110,7 +110,6 @@ describe('<InventorySourceList />', () => {
});
});
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
global.console.debug = debug;
});
@ -366,7 +365,6 @@ describe('<InventorySourceList /> RBAC testing', () => {
el => el.length > 0
);
expect(newWrapper.find('ToolbarAddButton').length).toBe(0);
newWrapper.unmount();
jest.clearAllMocks();
});
@ -406,7 +404,6 @@ describe('<InventorySourceList /> RBAC testing', () => {
el => el.length > 0
);
expect(newWrapper.find('Button[aria-label="Sync All"]').length).toBe(0);
newWrapper.unmount();
jest.clearAllMocks();
});
});

View File

@ -26,7 +26,7 @@ describe('<SmartInventory />', () => {
jest.clearAllMocks();
});
test('initially renders succesfully', async () => {
test('initially renders successfully', async () => {
InventoriesAPI.readDetail.mockResolvedValue({
data: mockSmartInventory,
});

View File

@ -19,11 +19,7 @@ jest.mock('react-router-dom', () => ({
}),
}));
jest.mock('../../../api/models/Inventories');
jest.mock('../../../api/models/Organizations');
jest.mock('../../../api/models/InstanceGroups');
OrganizationsAPI.read.mockResolvedValue({ data: { results: [], count: 0 } });
InstanceGroupsAPI.read.mockResolvedValue({ data: { results: [], count: 0 } });
jest.mock('../../../api');
const formData = {
name: 'Mock',
@ -36,18 +32,34 @@ const formData = {
};
describe('<SmartInventoryAdd />', () => {
describe('when initialized by users with POST capability', () => {
let history;
let wrapper;
const history = createMemoryHistory({
initialEntries: [`/inventories/smart_inventory/add`],
});
beforeAll(async () => {
describe('when initialized by users with POST capability', () => {
let wrapper;
let consoleError;
beforeAll(() => {
consoleError = global.console.error;
global.console.error = jest.fn();
});
beforeEach(async () => {
OrganizationsAPI.read.mockResolvedValue({
data: { results: [], count: 0 },
});
InstanceGroupsAPI.read.mockResolvedValue({
data: { results: [], count: 0 },
});
InventoriesAPI.create.mockResolvedValueOnce({ data: { id: 1 } });
InventoriesAPI.readOptions.mockResolvedValue({
data: { actions: { POST: true } },
});
history = createMemoryHistory({
initialEntries: [`/inventories/smart_inventory/add`],
InstanceGroupsAPI.read.mockResolvedValue({
data: { results: [], count: 0 },
});
await act(async () => {
wrapper = mountWithContexts(<SmartInventoryAdd />, {
context: { router: { history } },
@ -57,8 +69,8 @@ describe('<SmartInventoryAdd />', () => {
});
afterAll(() => {
global.console.error = consoleError;
jest.clearAllMocks();
wrapper.unmount();
});
test('should enable save button', () => {
@ -116,18 +128,31 @@ describe('<SmartInventoryAdd />', () => {
describe('when initialized by users without POST capability', () => {
let wrapper;
beforeAll(async () => {
InventoriesAPI.readOptions.mockResolvedValueOnce({
data: { actions: { POST: false } },
});
await act(async () => {
wrapper = mountWithContexts(<SmartInventoryAdd />);
});
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
});
afterAll(() => {
jest.clearAllMocks();
wrapper.unmount();
});
beforeEach(async () => {
OrganizationsAPI.read.mockResolvedValue({
data: { results: [], count: 0 },
});
InstanceGroupsAPI.read.mockResolvedValue({
data: { results: [], count: 0 },
});
InventoriesAPI.create.mockResolvedValueOnce({ data: { id: 1 } });
InventoriesAPI.readOptions.mockResolvedValue({
data: { actions: { POST: false } },
});
InstanceGroupsAPI.read.mockResolvedValue({
data: { results: [], count: 0 },
});
await act(async () => {
wrapper = mountWithContexts(<SmartInventoryAdd />, {
context: { router: { history } },
});
});
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
});
test('should disable save button', () => {

View File

@ -9,32 +9,30 @@ import { InventoriesAPI, UnifiedJobsAPI } from '../../../api';
import mockSmartInventory from '../shared/data.smart_inventory.json';
jest.mock('../../../api/models/UnifiedJobs');
jest.mock('../../../api/models/Inventories');
UnifiedJobsAPI.read.mockResolvedValue({
data: {
results: [
{
id: 1,
name: 'job 1',
type: 'job',
status: 'successful',
},
],
},
});
InventoriesAPI.readInstanceGroups.mockResolvedValue({
data: {
results: [{ id: 1, name: 'mock instance group' }],
},
});
jest.mock('../../../api');
describe('<SmartInventoryDetail />', () => {
let wrapper;
describe('User has edit permissions', () => {
beforeAll(async () => {
beforeEach(async () => {
UnifiedJobsAPI.read.mockResolvedValue({
data: {
results: [
{
id: 1,
name: 'job 1',
type: 'job',
status: 'successful',
},
],
},
});
InventoriesAPI.readInstanceGroups.mockResolvedValue({
data: {
results: [{ id: 1, name: 'mock instance group' }],
},
});
await act(async () => {
wrapper = mountWithContexts(
<SmartInventoryDetail inventory={mockSmartInventory} />
@ -44,7 +42,6 @@ describe('<SmartInventoryDetail />', () => {
});
afterAll(() => {
wrapper.unmount();
jest.clearAllMocks();
});
@ -118,7 +115,6 @@ describe('<SmartInventoryDetail />', () => {
describe('User has read-only permissions', () => {
afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});

View File

@ -19,11 +19,7 @@ jest.mock('react-router-dom', () => ({
id: 2,
}),
}));
jest.mock('../../../api/models/Inventories');
jest.mock('../../../api/models/Organizations');
jest.mock('../../../api/models/InstanceGroups');
OrganizationsAPI.read.mockResolvedValue({ data: { results: [], count: 0 } });
InstanceGroupsAPI.read.mockResolvedValue({ data: { results: [], count: 0 } });
jest.mock('../../../api');
const mockSmartInv = Object.assign(
{},
@ -36,10 +32,19 @@ const mockSmartInv = Object.assign(
);
describe('<SmartInventoryEdit />', () => {
let history;
let wrapper;
beforeAll(async () => {
const history = createMemoryHistory({
initialEntries: [`/inventories/smart_inventory/${mockSmartInv.id}/edit`],
});
beforeEach(async () => {
OrganizationsAPI.read.mockResolvedValue({
data: { results: [], count: 0 },
});
InstanceGroupsAPI.read.mockResolvedValue({
data: { results: [], count: 0 },
});
InventoriesAPI.associateInstanceGroup.mockResolvedValue();
InventoriesAPI.disassociateInstanceGroup.mockResolvedValue();
InventoriesAPI.update.mockResolvedValue({ data: mockSmartInv });
@ -55,9 +60,7 @@ describe('<SmartInventoryEdit />', () => {
],
},
});
history = createMemoryHistory({
initialEntries: [`/inventories/smart_inventory/${mockSmartInv.id}/edit`],
});
await act(async () => {
wrapper = mountWithContexts(
<SmartInventoryEdit inventory={{ ...mockSmartInv }} />,
@ -71,7 +74,6 @@ describe('<SmartInventoryEdit />', () => {
afterAll(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should render CodeEditor field', () => {

View File

@ -73,6 +73,9 @@ describe('<SmartInventoryHost />', () => {
});
test('should show content error when user attempts to navigate to erroneous route', async () => {
InventoriesAPI.readHostDetail.mockResolvedValue({
data: { ...mockHost },
});
history = createMemoryHistory({
initialEntries: ['/inventories/smart_inventory/1/hosts/1/foobar'],
});

View File

@ -12,10 +12,6 @@ describe('<SmartInventoryHostDetail />', () => {
wrapper = mountWithContexts(<SmartInventoryHostDetail host={mockHost} />);
});
afterAll(() => {
wrapper.unmount();
});
test('should render Details', () => {
function assertDetail(label, value) {
expect(wrapper.find(`Detail[label="${label}"] dt`).text()).toBe(label);

View File

@ -23,7 +23,7 @@ describe('<SmartInventoryHostList />', () => {
},
};
beforeAll(async () => {
beforeEach(async () => {
InventoriesAPI.readHosts.mockResolvedValue({
data: mockHosts,
});

View File

@ -77,7 +77,6 @@ describe('<InventoryForm />', () => {
});
afterAll(() => {
wrapper.unmount();
jest.clearAllMocks();
});

View File

@ -19,9 +19,6 @@ describe('<InventoryGroupForm />', () => {
/>
);
});
afterEach(() => {
wrapper.unmount();
});
test('initially renders successfully', () => {
expect(wrapper.length).toBe(1);
});

View File

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

View File

@ -7,45 +7,43 @@ import {
import InventorySourceForm from './InventorySourceForm';
import { InventorySourcesAPI, ProjectsAPI, CredentialsAPI } from '../../../api';
jest.mock('../../../api/models/Credentials');
jest.mock('../../../api/models/InventorySources');
jest.mock('../../../api/models/Projects');
jest.mock('../../../api');
describe('<InventorySourceForm />', () => {
let wrapper;
CredentialsAPI.read.mockResolvedValue({
data: { count: 0, results: [] },
});
ProjectsAPI.readInventories.mockResolvedValue({
data: ['foo', 'bar'],
});
InventorySourcesAPI.readOptions.mockResolvedValue({
data: {
actions: {
GET: {
source: {
choices: [
['file', 'File, Directory or Script'],
['scm', 'Sourced from a Project'],
['ec2', 'Amazon EC2'],
['gce', 'Google Compute Engine'],
['azure_rm', 'Microsoft Azure Resource Manager'],
['vmware', 'VMware vCenter'],
['satellite6', 'Red Hat Satellite 6'],
['openstack', 'OpenStack'],
['rhv', 'Red Hat Virtualization'],
['tower', 'Ansible Tower'],
],
},
},
},
},
});
describe('Successful form submission', () => {
const onSubmit = jest.fn();
beforeAll(async () => {
CredentialsAPI.read.mockResolvedValue({
data: { count: 0, results: [] },
});
ProjectsAPI.readInventories.mockResolvedValue({
data: ['foo', 'bar'],
});
InventorySourcesAPI.readOptions = async () => ({
data: {
actions: {
GET: {
source: {
choices: [
['file', 'File, Directory or Script'],
['scm', 'Sourced from a Project'],
['ec2', 'Amazon EC2'],
['gce', 'Google Compute Engine'],
['azure_rm', 'Microsoft Azure Resource Manager'],
['vmware', 'VMware vCenter'],
['satellite6', 'Red Hat Satellite 6'],
['openstack', 'OpenStack'],
['rhv', 'Red Hat Virtualization'],
['tower', 'Ansible Tower'],
],
},
},
},
},
});
await act(async () => {
wrapper = mountWithContexts(
<InventorySourceForm onCancel={() => {}} onSubmit={onSubmit} />
@ -56,7 +54,6 @@ describe('<InventorySourceForm />', () => {
afterAll(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('should initially display primary form fields', () => {
@ -113,19 +110,6 @@ describe('<InventorySourceForm />', () => {
});
});
test('should display ContentError on throw', async () => {
InventorySourcesAPI.readOptions.mockImplementationOnce(() =>
Promise.reject(new Error())
);
await act(async () => {
wrapper = mountWithContexts(
<InventorySourceForm onCancel={() => {}} onSubmit={() => {}} />
);
});
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
expect(wrapper.find('ContentError').length).toBe(1);
});
test('calls "onCancel" when Cancel button is clicked', async () => {
const onCancel = jest.fn();
await act(async () => {
@ -138,4 +122,16 @@ describe('<InventorySourceForm />', () => {
wrapper.find('button[aria-label="Cancel"]').prop('onClick')();
expect(onCancel).toBeCalled();
});
test('should display ContentError on throw', async () => {
InventorySourcesAPI.readOptions = jest.fn();
InventorySourcesAPI.readOptions.mockRejectedValueOnce(new Error());
await act(async () => {
wrapper = mountWithContexts(
<InventorySourceForm onCancel={() => {}} onSubmit={() => {}} />
);
});
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
expect(wrapper.find('ContentError').length).toBe(1);
});
});

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