mirror of
https://github.com/ansible/awx.git
synced 2026-03-22 03:17:39 -02:30
Merge pull request #5491 from marshmalien/inv-host-add
Add Inventory Host Add form Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
@@ -19,6 +19,10 @@ class Inventories extends InstanceGroupsMixin(Base) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createHost(id, data) {
|
||||||
|
return this.http.post(`${this.baseUrl}${id}/hosts/`, data);
|
||||||
|
}
|
||||||
|
|
||||||
readHosts(id, params) {
|
readHosts(id, params) {
|
||||||
return this.http.get(`${this.baseUrl}${id}/hosts/`, { params });
|
return this.http.get(`${this.baseUrl}${id}/hosts/`, { params });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { PageSection, Card, CardBody } from '@patternfly/react-core';
|
||||||
import {
|
|
||||||
PageSection,
|
|
||||||
Card,
|
|
||||||
CardHeader,
|
|
||||||
CardBody,
|
|
||||||
Tooltip,
|
|
||||||
} from '@patternfly/react-core';
|
|
||||||
|
|
||||||
import { HostsAPI } from '@api';
|
import { HostsAPI } from '@api';
|
||||||
import { Config } from '@contexts/Config';
|
import { Config } from '@contexts/Config';
|
||||||
import CardCloseButton from '@components/CardCloseButton';
|
import HostForm from '../shared';
|
||||||
|
|
||||||
import HostForm from '../shared/HostForm';
|
|
||||||
|
|
||||||
class HostAdd extends React.Component {
|
class HostAdd extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -41,16 +31,10 @@ class HostAdd extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { error } = this.state;
|
const { error } = this.state;
|
||||||
const { i18n } = this.props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageSection>
|
<PageSection>
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="at-u-textRight">
|
|
||||||
<Tooltip content={i18n._(t`Close`)} position="top">
|
|
||||||
<CardCloseButton onClick={this.handleCancel} />
|
|
||||||
</Tooltip>
|
|
||||||
</CardHeader>
|
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<Config>
|
<Config>
|
||||||
{({ me }) => (
|
{({ me }) => (
|
||||||
|
|||||||
@@ -35,18 +35,6 @@ describe('<HostAdd />', () => {
|
|||||||
expect(history.location.pathname).toEqual('/hosts');
|
expect(history.location.pathname).toEqual('/hosts');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should navigate to hosts list when close (x) is clicked', async () => {
|
|
||||||
const history = createMemoryHistory({});
|
|
||||||
let wrapper;
|
|
||||||
await act(async () => {
|
|
||||||
wrapper = mountWithContexts(<HostAdd />, {
|
|
||||||
context: { router: { history } },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
wrapper.find('button[aria-label="Close"]').invoke('onClick')();
|
|
||||||
expect(history.location.pathname).toEqual('/hosts');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('successful form submission should trigger redirect', async () => {
|
test('successful form submission should trigger redirect', async () => {
|
||||||
const history = createMemoryHistory({});
|
const history = createMemoryHistory({});
|
||||||
const hostData = {
|
const hostData = {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { CardBody } from '@patternfly/react-core';
|
|||||||
import { HostsAPI } from '@api';
|
import { HostsAPI } from '@api';
|
||||||
import { Config } from '@contexts/Config';
|
import { Config } from '@contexts/Config';
|
||||||
|
|
||||||
import HostForm from '../shared/HostForm';
|
import HostForm from '../shared';
|
||||||
|
|
||||||
class HostEdit extends Component {
|
class HostEdit extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import { func, shape } from 'prop-types';
|
||||||
|
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { Formik, Field } from 'formik';
|
import { Formik, Field } from 'formik';
|
||||||
@@ -15,120 +15,86 @@ import { VariablesField } from '@components/CodeMirrorInput';
|
|||||||
import { required } from '@util/validators';
|
import { required } from '@util/validators';
|
||||||
import { InventoryLookup } from '@components/Lookup';
|
import { InventoryLookup } from '@components/Lookup';
|
||||||
|
|
||||||
class HostForm extends Component {
|
function HostForm({ handleSubmit, handleCancel, host, i18n }) {
|
||||||
constructor(props) {
|
const [inventory, setInventory] = useState(
|
||||||
super(props);
|
host ? host.summary_fields.inventory : ''
|
||||||
|
);
|
||||||
|
|
||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
return (
|
||||||
|
<Formik
|
||||||
this.state = {
|
initialValues={{
|
||||||
formIsValid: true,
|
name: host.name,
|
||||||
inventory: props.host.summary_fields.inventory,
|
description: host.description,
|
||||||
};
|
inventory: host.inventory || '',
|
||||||
}
|
variables: host.variables,
|
||||||
|
}}
|
||||||
handleSubmit(values) {
|
onSubmit={handleSubmit}
|
||||||
const { handleSubmit } = this.props;
|
render={formik => (
|
||||||
|
<Form autoComplete="off" onSubmit={formik.handleSubmit}>
|
||||||
handleSubmit(values);
|
<FormRow>
|
||||||
}
|
<FormField
|
||||||
|
id="host-name"
|
||||||
render() {
|
name="name"
|
||||||
const { host, handleCancel, i18n } = this.props;
|
type="text"
|
||||||
const { formIsValid, inventory, error } = this.state;
|
label={i18n._(t`Name`)}
|
||||||
|
validate={required(null, i18n)}
|
||||||
const initialValues = !host.id
|
isRequired
|
||||||
? {
|
|
||||||
name: host.name,
|
|
||||||
description: host.description,
|
|
||||||
inventory: host.inventory || '',
|
|
||||||
variables: host.variables,
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
name: host.name,
|
|
||||||
description: host.description,
|
|
||||||
variables: host.variables,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Formik
|
|
||||||
initialValues={initialValues}
|
|
||||||
onSubmit={this.handleSubmit}
|
|
||||||
render={formik => (
|
|
||||||
<Form autoComplete="off" onSubmit={formik.handleSubmit}>
|
|
||||||
<FormRow>
|
|
||||||
<FormField
|
|
||||||
id="host-name"
|
|
||||||
name="name"
|
|
||||||
type="text"
|
|
||||||
label={i18n._(t`Name`)}
|
|
||||||
validate={required(null, i18n)}
|
|
||||||
isRequired
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
id="host-description"
|
|
||||||
name="description"
|
|
||||||
type="text"
|
|
||||||
label={i18n._(t`Description`)}
|
|
||||||
/>
|
|
||||||
{!host.id && (
|
|
||||||
<Field
|
|
||||||
name="inventory"
|
|
||||||
validate={required(
|
|
||||||
i18n._(t`Select a value for this field`),
|
|
||||||
i18n
|
|
||||||
)}
|
|
||||||
render={({ form }) => (
|
|
||||||
<InventoryLookup
|
|
||||||
value={inventory}
|
|
||||||
onBlur={() => form.setFieldTouched('inventory')}
|
|
||||||
tooltip={i18n._(
|
|
||||||
t`Select the inventory that this host will belong to.`
|
|
||||||
)}
|
|
||||||
isValid={
|
|
||||||
!form.touched.inventory || !form.errors.inventory
|
|
||||||
}
|
|
||||||
helperTextInvalid={form.errors.inventory}
|
|
||||||
onChange={value => {
|
|
||||||
form.setFieldValue('inventory', value.id);
|
|
||||||
this.setState({ inventory: value });
|
|
||||||
}}
|
|
||||||
required
|
|
||||||
touched={form.touched.inventory}
|
|
||||||
error={form.errors.inventory}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</FormRow>
|
|
||||||
<FormRow>
|
|
||||||
<VariablesField
|
|
||||||
id="host-variables"
|
|
||||||
name="variables"
|
|
||||||
label={i18n._(t`Variables`)}
|
|
||||||
/>
|
|
||||||
</FormRow>
|
|
||||||
<FormActionGroup
|
|
||||||
onCancel={handleCancel}
|
|
||||||
onSubmit={formik.handleSubmit}
|
|
||||||
submitDisabled={!formIsValid}
|
|
||||||
/>
|
/>
|
||||||
{error ? <div>error</div> : null}
|
<FormField
|
||||||
</Form>
|
id="host-description"
|
||||||
)}
|
name="description"
|
||||||
/>
|
type="text"
|
||||||
);
|
label={i18n._(t`Description`)}
|
||||||
}
|
/>
|
||||||
|
{!host.id && (
|
||||||
|
<Field
|
||||||
|
name="inventory"
|
||||||
|
validate={required(
|
||||||
|
i18n._(t`Select a value for this field`),
|
||||||
|
i18n
|
||||||
|
)}
|
||||||
|
render={({ form }) => (
|
||||||
|
<InventoryLookup
|
||||||
|
value={inventory}
|
||||||
|
onBlur={() => form.setFieldTouched('inventory')}
|
||||||
|
tooltip={i18n._(
|
||||||
|
t`Select the inventory that this host will belong to.`
|
||||||
|
)}
|
||||||
|
isValid={!form.touched.inventory || !form.errors.inventory}
|
||||||
|
helperTextInvalid={form.errors.inventory}
|
||||||
|
onChange={value => {
|
||||||
|
form.setFieldValue('inventory', value.id);
|
||||||
|
setInventory(value);
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
touched={form.touched.inventory}
|
||||||
|
error={form.errors.inventory}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</FormRow>
|
||||||
|
<FormRow>
|
||||||
|
<VariablesField
|
||||||
|
id="host-variables"
|
||||||
|
name="variables"
|
||||||
|
label={i18n._(t`Variables`)}
|
||||||
|
/>
|
||||||
|
</FormRow>
|
||||||
|
<FormActionGroup
|
||||||
|
onCancel={handleCancel}
|
||||||
|
onSubmit={formik.handleSubmit}
|
||||||
|
/>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
FormField.propTypes = {
|
|
||||||
label: PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
HostForm.propTypes = {
|
HostForm.propTypes = {
|
||||||
host: PropTypes.shape(),
|
handleSubmit: func.isRequired,
|
||||||
handleSubmit: PropTypes.func.isRequired,
|
handleCancel: func.isRequired,
|
||||||
handleCancel: PropTypes.func.isRequired,
|
host: shape({}),
|
||||||
};
|
};
|
||||||
|
|
||||||
HostForm.defaultProps = {
|
HostForm.defaultProps = {
|
||||||
|
|||||||
@@ -65,11 +65,7 @@ describe('<HostForm />', () => {
|
|||||||
expect(handleSubmit).not.toHaveBeenCalled();
|
expect(handleSubmit).not.toHaveBeenCalled();
|
||||||
wrapper.find('button[aria-label="Save"]').simulate('click');
|
wrapper.find('button[aria-label="Save"]').simulate('click');
|
||||||
await sleep(1);
|
await sleep(1);
|
||||||
expect(handleSubmit).toHaveBeenCalledWith({
|
expect(handleSubmit).toHaveBeenCalled();
|
||||||
name: 'Foo',
|
|
||||||
description: 'Bar',
|
|
||||||
variables: '---',
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('calls "handleCancel" when Cancel button is clicked', () => {
|
test('calls "handleCancel" when Cancel button is clicked', () => {
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from './HostForm';
|
||||||
|
|||||||
@@ -1,8 +1,36 @@
|
|||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import { useHistory, useParams } from 'react-router-dom';
|
||||||
import { CardBody } from '@patternfly/react-core';
|
import { CardBody } from '@patternfly/react-core';
|
||||||
|
import InventoryHostForm from '../shared/InventoryHostForm';
|
||||||
|
import { InventoriesAPI } from '@api';
|
||||||
|
|
||||||
function InventoryHostAdd() {
|
function InventoryHostAdd() {
|
||||||
return <CardBody>Coming soon :)</CardBody>;
|
const [formError, setFormError] = useState(null);
|
||||||
|
const history = useHistory();
|
||||||
|
const { id } = useParams();
|
||||||
|
|
||||||
|
const handleSubmit = async values => {
|
||||||
|
try {
|
||||||
|
const { data: response } = await InventoriesAPI.createHost(id, values);
|
||||||
|
history.push(`/inventories/inventory/${id}/hosts/${response.id}/details`);
|
||||||
|
} catch (error) {
|
||||||
|
setFormError(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
history.push(`/inventories/inventory/${id}/hosts`);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CardBody>
|
||||||
|
<InventoryHostForm
|
||||||
|
handleSubmit={handleSubmit}
|
||||||
|
handleCancel={handleCancel}
|
||||||
|
/>
|
||||||
|
{formError ? <div className="formSubmitError">error</div> : ''}
|
||||||
|
</CardBody>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default InventoryHostAdd;
|
export default InventoryHostAdd;
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Route } from 'react-router-dom';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
|
import { createMemoryHistory } from 'history';
|
||||||
|
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
|
||||||
|
import InventoryHostAdd from './InventoryHostAdd';
|
||||||
|
import { InventoriesAPI } from '@api';
|
||||||
|
|
||||||
|
jest.mock('@api');
|
||||||
|
|
||||||
|
describe('<InventoryHostAdd />', () => {
|
||||||
|
let wrapper;
|
||||||
|
let history;
|
||||||
|
|
||||||
|
const mockHostData = {
|
||||||
|
name: 'new name',
|
||||||
|
description: 'new description',
|
||||||
|
inventory: 1,
|
||||||
|
variables: '---\nfoo: bar',
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
history = createMemoryHistory({
|
||||||
|
initialEntries: ['/inventories/inventory/1/hosts/add'],
|
||||||
|
});
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<Route
|
||||||
|
path="/inventories/inventory/:id/hosts/add"
|
||||||
|
component={() => <InventoryHostAdd />}
|
||||||
|
/>,
|
||||||
|
{
|
||||||
|
context: {
|
||||||
|
router: { history, route: { location: history.location } },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
wrapper.unmount();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('handleSubmit should post to api', async () => {
|
||||||
|
InventoriesAPI.createHost.mockResolvedValue({
|
||||||
|
data: { ...mockHostData },
|
||||||
|
});
|
||||||
|
|
||||||
|
const formik = wrapper.find('Formik').instance();
|
||||||
|
await act(async () => {
|
||||||
|
const changeState = new Promise(resolve => {
|
||||||
|
formik.setState(
|
||||||
|
{
|
||||||
|
values: {
|
||||||
|
...mockHostData,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
() => resolve()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await changeState;
|
||||||
|
});
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('form').simulate('submit');
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(InventoriesAPI.createHost).toHaveBeenCalledWith('1', mockHostData);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('handleSubmit should throw an error', async () => {
|
||||||
|
InventoriesAPI.createHost.mockImplementationOnce(() =>
|
||||||
|
Promise.reject(new Error())
|
||||||
|
);
|
||||||
|
const formik = wrapper.find('Formik').instance();
|
||||||
|
await act(async () => {
|
||||||
|
const changeState = new Promise(resolve => {
|
||||||
|
formik.setState(
|
||||||
|
{
|
||||||
|
values: {
|
||||||
|
...mockHostData,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
() => resolve()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await changeState;
|
||||||
|
});
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('form').simulate('submit');
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(wrapper.find('InventoryHostAdd .formSubmitError').length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should navigate to inventory hosts list when cancel is clicked', async () => {
|
||||||
|
wrapper.find('button[aria-label="Cancel"]').simulate('click');
|
||||||
|
expect(history.location.pathname).toEqual('/inventories/inventory/1/hosts');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -23,6 +23,7 @@ import { Host } from '@types';
|
|||||||
function InventoryHostItem(props) {
|
function InventoryHostItem(props) {
|
||||||
const {
|
const {
|
||||||
detailUrl,
|
detailUrl,
|
||||||
|
editUrl,
|
||||||
host,
|
host,
|
||||||
i18n,
|
i18n,
|
||||||
isSelected,
|
isSelected,
|
||||||
@@ -79,7 +80,7 @@ function InventoryHostItem(props) {
|
|||||||
<ListActionButton
|
<ListActionButton
|
||||||
variant="plain"
|
variant="plain"
|
||||||
component={Link}
|
component={Link}
|
||||||
to={`/hosts/${host.id}/edit`}
|
to={`${editUrl}`}
|
||||||
>
|
>
|
||||||
<PencilAltIcon />
|
<PencilAltIcon />
|
||||||
</ListActionButton>
|
</ListActionButton>
|
||||||
|
|||||||
@@ -178,7 +178,8 @@ function InventoryHosts({ i18n, location, match }) {
|
|||||||
<InventoryHostItem
|
<InventoryHostItem
|
||||||
key={o.id}
|
key={o.id}
|
||||||
host={o}
|
host={o}
|
||||||
detailUrl={`/hosts/${o.id}/details`}
|
detailUrl={`/inventories/inventory/${match.params.id}/hosts/${o.id}/details`}
|
||||||
|
editUrl={`/inventories/inventory/${match.params.id}/hosts/${o.id}/edit`}
|
||||||
isSelected={selected.some(row => row.id === o.id)}
|
isSelected={selected.some(row => row.id === o.id)}
|
||||||
onSelect={() => handleSelect(o)}
|
onSelect={() => handleSelect(o)}
|
||||||
toggleHost={handleToggle}
|
toggleHost={handleToggle}
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { func, shape } from 'prop-types';
|
||||||
|
import { Formik } from 'formik';
|
||||||
|
import { withI18n } from '@lingui/react';
|
||||||
|
import { t } from '@lingui/macro';
|
||||||
|
import { Form } from '@patternfly/react-core';
|
||||||
|
import FormRow from '@components/FormRow';
|
||||||
|
import FormField from '@components/FormField';
|
||||||
|
import FormActionGroup from '@components/FormActionGroup/FormActionGroup';
|
||||||
|
import { VariablesField } from '@components/CodeMirrorInput';
|
||||||
|
import { required } from '@util/validators';
|
||||||
|
|
||||||
|
function InventoryHostForm({ handleSubmit, handleCancel, host, i18n }) {
|
||||||
|
return (
|
||||||
|
<Formik
|
||||||
|
initialValues={{
|
||||||
|
name: host.name,
|
||||||
|
description: host.description,
|
||||||
|
variables: host.variables,
|
||||||
|
}}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
render={formik => (
|
||||||
|
<Form autoComplete="off" onSubmit={formik.handleSubmit}>
|
||||||
|
<FormRow>
|
||||||
|
<FormField
|
||||||
|
id="host-name"
|
||||||
|
name="name"
|
||||||
|
type="text"
|
||||||
|
label={i18n._(t`Name`)}
|
||||||
|
validate={required(null, i18n)}
|
||||||
|
isRequired
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
id="host-description"
|
||||||
|
name="description"
|
||||||
|
type="text"
|
||||||
|
label={i18n._(t`Description`)}
|
||||||
|
/>
|
||||||
|
</FormRow>
|
||||||
|
<FormRow>
|
||||||
|
<VariablesField
|
||||||
|
id="host-variables"
|
||||||
|
name="variables"
|
||||||
|
label={i18n._(t`Variables`)}
|
||||||
|
/>
|
||||||
|
</FormRow>
|
||||||
|
<FormActionGroup
|
||||||
|
onCancel={handleCancel}
|
||||||
|
onSubmit={formik.handleSubmit}
|
||||||
|
/>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryHostForm.propTypes = {
|
||||||
|
handleSubmit: func.isRequired,
|
||||||
|
handleCancel: func.isRequired,
|
||||||
|
host: shape({}),
|
||||||
|
};
|
||||||
|
|
||||||
|
InventoryHostForm.defaultProps = {
|
||||||
|
host: {
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
variables: '---\n',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withI18n()(InventoryHostForm);
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
|
import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
||||||
|
import { sleep } from '@testUtils/testUtils';
|
||||||
|
import InventoryHostForm from './InventoryHostForm';
|
||||||
|
|
||||||
|
jest.mock('@api');
|
||||||
|
|
||||||
|
describe('<InventoryHostform />', () => {
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
const handleSubmit = jest.fn();
|
||||||
|
const handleCancel = jest.fn();
|
||||||
|
|
||||||
|
const mockHostData = {
|
||||||
|
name: 'foo',
|
||||||
|
description: 'bar',
|
||||||
|
inventory: 1,
|
||||||
|
variables: '---\nfoo: bar',
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<InventoryHostForm
|
||||||
|
handleCancel={handleCancel}
|
||||||
|
handleSubmit={handleSubmit}
|
||||||
|
host={mockHostData}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
wrapper.unmount();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should display form fields', () => {
|
||||||
|
expect(wrapper.find('FormGroup[label="Name"]').length).toBe(1);
|
||||||
|
expect(wrapper.find('FormGroup[label="Description"]').length).toBe(1);
|
||||||
|
expect(wrapper.find('VariablesField').length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should call handleSubmit when Submit button is clicked', async () => {
|
||||||
|
expect(handleSubmit).not.toHaveBeenCalled();
|
||||||
|
wrapper.find('button[aria-label="Save"]').simulate('click');
|
||||||
|
await sleep(1);
|
||||||
|
expect(handleSubmit).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should call handleCancel when Cancel button is clicked', async () => {
|
||||||
|
expect(handleCancel).not.toHaveBeenCalled();
|
||||||
|
wrapper.find('button[aria-label="Cancel"]').simulate('click');
|
||||||
|
await sleep(1);
|
||||||
|
expect(handleCancel).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user