mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 01:57:35 -03:30
Merge pull request #9563 from AlexSCorey/8769-WizardFailure
Fixes crashing wizard, and adds error handle on adding role SUMMARY This addresses #8769. It also adds error handling if there is some sort of request error during the submit request. ISSUE TYPE Bugfix Pull Request COMPONENT NAME UI AWX VERSION ADDITIONAL INFORMATION Reviewed-by: John Mitchell <None>
This commit is contained in:
commit
597435141d
@ -1,5 +1,6 @@
|
||||
import React, { Fragment, useState } from 'react';
|
||||
import React, { Fragment, useState, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import SelectableCard from '../SelectableCard';
|
||||
@ -17,7 +18,9 @@ const readTeams = async queryParams => TeamsAPI.read(queryParams);
|
||||
|
||||
const readTeamsOptions = async () => TeamsAPI.readOptions();
|
||||
|
||||
function AddResourceRole({ onSave, onClose, roles, i18n, resource }) {
|
||||
function AddResourceRole({ onSave, onClose, roles, i18n, resource, onError }) {
|
||||
const history = useHistory();
|
||||
|
||||
const [selectedResource, setSelectedResource] = useState(null);
|
||||
const [selectedResourceRows, setSelectedResourceRows] = useState([]);
|
||||
const [selectedRoleRows, setSelectedRoleRows] = useState([]);
|
||||
@ -39,6 +42,12 @@ function AddResourceRole({ onSave, onClose, roles, i18n, resource }) {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (currentStepId === 1 && maxEnabledStep > 1) {
|
||||
history.push(history.location.pathname);
|
||||
}
|
||||
}, [currentStepId, history, maxEnabledStep]);
|
||||
|
||||
const handleRoleCheckboxClick = role => {
|
||||
const selectedIndex = selectedRoleRows.findIndex(
|
||||
selectedRow => selectedRow.id === role.id
|
||||
@ -94,7 +103,8 @@ function AddResourceRole({ onSave, onClose, roles, i18n, resource }) {
|
||||
await Promise.all(roleRequests);
|
||||
onSave();
|
||||
} catch (err) {
|
||||
// TODO: handle this error
|
||||
onError(err);
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
/* eslint-disable react/jsx-pascal-case */
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
|
||||
import {
|
||||
@ -13,6 +14,11 @@ import { TeamsAPI, UsersAPI } from '../../api';
|
||||
jest.mock('../../api/models/Teams');
|
||||
jest.mock('../../api/models/Users');
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
|
||||
useHistory: () => ({ push: jest.fn(), location: { pathname: {} } }),
|
||||
}));
|
||||
// TODO: Once error handling is functional in
|
||||
// this component write tests for it
|
||||
|
||||
@ -111,6 +117,112 @@ describe('<_AddResourceRole />', () => {
|
||||
expect(UsersAPI.associateRole).toBeCalledWith(1, 1);
|
||||
});
|
||||
|
||||
test('should call on error properly', async () => {
|
||||
let wrapper;
|
||||
const onError = jest.fn();
|
||||
UsersAPI.associateRole.mockRejectedValue(
|
||||
new Error({
|
||||
response: {
|
||||
config: {
|
||||
method: 'post',
|
||||
url: '/api/v2/users',
|
||||
},
|
||||
data: 'An error occurred',
|
||||
status: 403,
|
||||
},
|
||||
})
|
||||
);
|
||||
act(() => {
|
||||
wrapper = mountWithContexts(
|
||||
<AddResourceRole
|
||||
onClose={() => {}}
|
||||
onError={onError}
|
||||
onSave={() => {}}
|
||||
roles={roles}
|
||||
/>,
|
||||
{ context: { network: { handleHttpError: () => {} } } }
|
||||
);
|
||||
});
|
||||
wrapper.update();
|
||||
|
||||
// Step 1
|
||||
const selectableCardWrapper = wrapper.find('SelectableCard');
|
||||
expect(selectableCardWrapper.length).toBe(2);
|
||||
act(() => wrapper.find('SelectableCard[label="Users"]').prop('onClick')());
|
||||
wrapper.update();
|
||||
await act(async () =>
|
||||
wrapper.find('Button[type="submit"]').prop('onClick')()
|
||||
);
|
||||
wrapper.update();
|
||||
|
||||
// Step 2
|
||||
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
|
||||
act(() =>
|
||||
wrapper.find('DataListCheck[name="foo"]').invoke('onChange')(true)
|
||||
);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('DataListCheck[name="foo"]').prop('checked')).toBe(
|
||||
true
|
||||
);
|
||||
act(() => wrapper.find('Button[type="submit"]').prop('onClick')());
|
||||
wrapper.update();
|
||||
|
||||
// Step 3
|
||||
act(() =>
|
||||
wrapper.find('Checkbox[aria-label="Admin"]').invoke('onChange')(true)
|
||||
);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('Checkbox[aria-label="Admin"]').prop('isChecked')).toBe(
|
||||
true
|
||||
);
|
||||
|
||||
// Save
|
||||
await act(async () =>
|
||||
wrapper.find('Button[type="submit"]').prop('onClick')()
|
||||
);
|
||||
expect(UsersAPI.associateRole).toBeCalledWith(1, 1);
|
||||
expect(onError).toBeCalled();
|
||||
});
|
||||
|
||||
test('should should update history properly', async () => {
|
||||
let wrapper;
|
||||
const history = createMemoryHistory({
|
||||
initialEntries: ['organizations/2/access?resource.order_by=-username'],
|
||||
});
|
||||
act(() => {
|
||||
wrapper = mountWithContexts(
|
||||
<AddResourceRole onClose={() => {}} onSave={() => {}} roles={roles} />,
|
||||
{ context: { router: { history } } }
|
||||
);
|
||||
});
|
||||
wrapper.update();
|
||||
|
||||
// Step 1
|
||||
const selectableCardWrapper = wrapper.find('SelectableCard');
|
||||
expect(selectableCardWrapper.length).toBe(2);
|
||||
act(() => wrapper.find('SelectableCard[label="Users"]').prop('onClick')());
|
||||
wrapper.update();
|
||||
await act(async () =>
|
||||
wrapper.find('Button[type="submit"]').prop('onClick')()
|
||||
);
|
||||
wrapper.update();
|
||||
|
||||
// Step 2
|
||||
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
|
||||
act(() =>
|
||||
wrapper.find('DataListCheck[name="foo"]').invoke('onChange')(true)
|
||||
);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('DataListCheck[name="foo"]').prop('checked')).toBe(
|
||||
true
|
||||
);
|
||||
await act(async () =>
|
||||
wrapper.find('PFWizard').prop('onGoToStep')({ id: 1 })
|
||||
);
|
||||
wrapper.update();
|
||||
expect(history.location.pathname).toEqual('organizations/2/access');
|
||||
});
|
||||
|
||||
test('should successfuly click user/team cards', async () => {
|
||||
let wrapper;
|
||||
act(() => {
|
||||
|
||||
@ -11,6 +11,7 @@ import { getQSConfig, parseQueryString } from '../../util/qs';
|
||||
import useRequest, { useDeleteItems } from '../../util/useRequest';
|
||||
import DeleteRoleConfirmationModal from './DeleteRoleConfirmationModal';
|
||||
import ResourceAccessListItem from './ResourceAccessListItem';
|
||||
import ErrorDetail from '../ErrorDetail';
|
||||
|
||||
const QS_CONFIG = getQSConfig('access', {
|
||||
page: 1,
|
||||
@ -19,6 +20,7 @@ const QS_CONFIG = getQSConfig('access', {
|
||||
});
|
||||
|
||||
function ResourceAccessList({ i18n, apiModel, resource }) {
|
||||
const [submitError, setSubmitError] = useState(null);
|
||||
const [deletionRecord, setDeletionRecord] = useState(null);
|
||||
const [deletionRole, setDeletionRole] = useState(null);
|
||||
const [showAddModal, setShowAddModal] = useState(false);
|
||||
@ -206,6 +208,7 @@ function ResourceAccessList({ i18n, apiModel, resource }) {
|
||||
setShowAddModal(false);
|
||||
fetchAccessRecords();
|
||||
}}
|
||||
onError={err => setSubmitError(err)}
|
||||
roles={resource.summary_fields.object_roles}
|
||||
resource={resource}
|
||||
/>
|
||||
@ -227,6 +230,17 @@ function ResourceAccessList({ i18n, apiModel, resource }) {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{submitError && (
|
||||
<AlertModal
|
||||
variant="error"
|
||||
title={i18n._(t`Error!`)}
|
||||
isOpen={submitError}
|
||||
onClose={() => setSubmitError(null)}
|
||||
>
|
||||
{i18n._(t`Failed to assign roles properly`)}
|
||||
<ErrorDetail error={submitError} />
|
||||
</AlertModal>
|
||||
)}
|
||||
{deletionError && (
|
||||
<AlertModal
|
||||
isOpen={deletionError}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user