mirror of
https://github.com/ansible/awx.git
synced 2026-03-01 00:38:45 -03:30
Adds Alert Modal, Breadcrumb, Nested Tabs and Refactors PR.
This commit is contained in:
@@ -3,6 +3,7 @@ import { shape, string, number, arrayOf } from 'prop-types';
|
|||||||
import { Tab, Tabs as PFTabs } from '@patternfly/react-core';
|
import { Tab, Tabs as PFTabs } from '@patternfly/react-core';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||||
|
|
||||||
const Tabs = styled(PFTabs)`
|
const Tabs = styled(PFTabs)`
|
||||||
--pf-c-tabs__button--PaddingLeft: 20px;
|
--pf-c-tabs__button--PaddingLeft: 20px;
|
||||||
@@ -62,7 +63,15 @@ function RoutedTabs(props) {
|
|||||||
eventKey={tab.id}
|
eventKey={tab.id}
|
||||||
key={tab.id}
|
key={tab.id}
|
||||||
link={tab.link}
|
link={tab.link}
|
||||||
title={tab.name}
|
title={
|
||||||
|
tab.isNestedTabs ? (
|
||||||
|
<>
|
||||||
|
<CaretLeftIcon /> {tab.name}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
tab.name
|
||||||
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@@ -61,9 +61,11 @@ class Inventories extends Component {
|
|||||||
t`Create New Group`
|
t`Create New Group`
|
||||||
),
|
),
|
||||||
[`/inventories/inventory/${inventory.id}/groups/${group &&
|
[`/inventories/inventory/${inventory.id}/groups/${group &&
|
||||||
group.id}/details`]: i18n._(t`Details`),
|
group.id}`]: `${group && group.name}`,
|
||||||
[`/inventories/inventory/${inventory.id}/groups/${group &&
|
[`/inventories/inventory/${inventory.id}/groups/${group &&
|
||||||
group.id}/edit`]: `${group && group.name}`,
|
group.id}/details`]: i18n._(t`Group Details`),
|
||||||
|
[`/inventories/inventory/${inventory.id}/groups/${group &&
|
||||||
|
group.id}/edit`]: i18n._(t`Edit Details`),
|
||||||
};
|
};
|
||||||
this.setState({ breadcrumbConfig });
|
this.setState({ breadcrumbConfig });
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -57,7 +57,11 @@ function Inventory({ history, i18n, location, match, setBreadcrumb }) {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (location.pathname.endsWith('edit') || location.pathname.endsWith('add')) {
|
if (
|
||||||
|
location.pathname.endsWith('edit') ||
|
||||||
|
location.pathname.endsWith('add') ||
|
||||||
|
location.pathname.includes('groups/')
|
||||||
|
) {
|
||||||
cardHeader = null;
|
cardHeader = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,6 +131,7 @@ function Inventory({ history, i18n, location, match, setBreadcrumb }) {
|
|||||||
<InventoryGroups
|
<InventoryGroups
|
||||||
location={location}
|
location={location}
|
||||||
match={match}
|
match={match}
|
||||||
|
history={history}
|
||||||
setBreadcrumb={setBreadcrumb}
|
setBreadcrumb={setBreadcrumb}
|
||||||
inventory={inventory}
|
inventory={inventory}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
|
import { CardHeader } from '@patternfly/react-core';
|
||||||
|
|
||||||
import { Switch, Route, withRouter, Link, Redirect } from 'react-router-dom';
|
import { Switch, Route, withRouter, Link, Redirect } from 'react-router-dom';
|
||||||
import { GroupsAPI } from '@api';
|
import { GroupsAPI } from '@api';
|
||||||
|
import CardCloseButton from '@components/CardCloseButton';
|
||||||
|
import RoutedTabs from '@components/RoutedTabs';
|
||||||
import ContentError from '@components/ContentError';
|
import ContentError from '@components/ContentError';
|
||||||
import ContentLoading from '@components/ContentLoading';
|
import ContentLoading from '@components/ContentLoading';
|
||||||
|
|
||||||
import InventoryGroupEdit from '../InventoryGroupEdit/InventoryGroupEdit';
|
import InventoryGroupEdit from '../InventoryGroupEdit/InventoryGroupEdit';
|
||||||
|
|
||||||
import InventoryGroupDetail from '../InventoryGroupDetail/InventoryGroupDetail';
|
import InventoryGroupDetail from '../InventoryGroupDetail/InventoryGroupDetail';
|
||||||
|
|
||||||
function InventoryGroups({ i18n, match, setBreadcrumb, inventory }) {
|
function InventoryGroups({ i18n, match, setBreadcrumb, inventory, history }) {
|
||||||
const [inventoryGroup, setInventoryGroup] = useState(null);
|
const [inventoryGroup, setInventoryGroup] = useState(null);
|
||||||
const [hasContentLoading, setContentLoading] = useState(true);
|
const [hasContentLoading, setContentLoading] = useState(true);
|
||||||
const [hasContentError, setHasContentError] = useState(false);
|
const [hasContentError, setHasContentError] = useState(false);
|
||||||
@@ -32,64 +32,101 @@ function InventoryGroups({ i18n, match, setBreadcrumb, inventory }) {
|
|||||||
|
|
||||||
loadData();
|
loadData();
|
||||||
}, [match.params.groupId, setBreadcrumb, inventory]);
|
}, [match.params.groupId, setBreadcrumb, inventory]);
|
||||||
|
const tabsArray = [
|
||||||
|
{
|
||||||
|
name: i18n._(t`Return to Groups`),
|
||||||
|
link: `/inventories/inventory/${inventory.id}/groups`,
|
||||||
|
id: 99,
|
||||||
|
isNestedTabs: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: i18n._(t`Details`),
|
||||||
|
link: `/inventories/inventory/${inventory.id}/groups/${inventoryGroup &&
|
||||||
|
inventoryGroup.id}/details`,
|
||||||
|
id: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: i18n._(t`RelatedGroups`),
|
||||||
|
link: `/inventories/inventory/${inventory.id}/groups/${inventoryGroup &&
|
||||||
|
inventoryGroup.id}/nested_groups`,
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: i18n._(t`Hosts`),
|
||||||
|
link: `/inventories/inventory/${inventory.id}/groups/${inventoryGroup &&
|
||||||
|
inventoryGroup.id}/nested_hosts`,
|
||||||
|
id: 2,
|
||||||
|
},
|
||||||
|
];
|
||||||
if (hasContentError) {
|
if (hasContentError) {
|
||||||
return <ContentError />;
|
return <ContentError />;
|
||||||
}
|
}
|
||||||
if (hasContentLoading) {
|
if (hasContentLoading) {
|
||||||
return <ContentLoading />;
|
return <ContentLoading />;
|
||||||
}
|
}
|
||||||
return (
|
let cardHeader = hasContentLoading ? null : (
|
||||||
<Switch>
|
<CardHeader style={{ padding: 0 }}>
|
||||||
<Redirect
|
<RoutedTabs history={history} tabsArray={tabsArray} />
|
||||||
from="/inventories/inventory/:id/groups/:groupId"
|
<CardCloseButton
|
||||||
to="/inventories/inventory/:id/groups/:groupId/details"
|
linkTo={`/inventories/inventory/${inventory.id}/group`}
|
||||||
exact
|
|
||||||
/>
|
/>
|
||||||
{inventoryGroup && [
|
</CardHeader>
|
||||||
<Route
|
);
|
||||||
key="edit"
|
if (
|
||||||
path="/inventories/inventory/:id/groups/:groupId/edit"
|
!history.location.pathname.includes('groups/') ||
|
||||||
render={() => {
|
history.location.pathname.endsWith('edit')
|
||||||
return (
|
) {
|
||||||
<InventoryGroupEdit
|
cardHeader = null;
|
||||||
inventory={inventory}
|
}
|
||||||
inventoryGroup={inventoryGroup}
|
return (
|
||||||
/>
|
<>
|
||||||
);
|
{cardHeader}
|
||||||
}}
|
<Switch>
|
||||||
/>,
|
<Redirect
|
||||||
<Route
|
from="/inventories/inventory/:id/groups/:groupId"
|
||||||
key="details"
|
to="/inventories/inventory/:id/groups/:groupId/details"
|
||||||
path="/inventories/inventory/:id/groups/:groupId/details"
|
exact
|
||||||
render={() => {
|
/>
|
||||||
return (
|
{inventoryGroup && [
|
||||||
<InventoryGroupDetail
|
<Route
|
||||||
inventory={inventory}
|
key="edit"
|
||||||
inventoryGroup={inventoryGroup}
|
path="/inventories/inventory/:id/groups/:groupId/edit"
|
||||||
/>
|
render={() => {
|
||||||
);
|
return (
|
||||||
}}
|
<InventoryGroupEdit
|
||||||
/>,
|
inventory={inventory}
|
||||||
|
inventoryGroup={inventoryGroup}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
<Route
|
||||||
|
key="details"
|
||||||
|
path="/inventories/inventory/:id/groups/:groupId/details"
|
||||||
|
render={() => {
|
||||||
|
return <InventoryGroupDetail inventoryGroup={inventoryGroup} />;
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
]}
|
||||||
<Route
|
<Route
|
||||||
key="not-found"
|
key="not-found"
|
||||||
path="*"
|
path="*"
|
||||||
render={() =>
|
render={() => {
|
||||||
!hasContentLoading && (
|
return (
|
||||||
<ContentError>
|
!hasContentLoading && (
|
||||||
{match.params.id && (
|
<ContentError>
|
||||||
<Link
|
{inventory && (
|
||||||
to={`/inventories/inventory/${match.params.id}/details`}
|
<Link to={`/inventories/inventory/${inventory.id}/details`}>
|
||||||
>
|
{i18n._(t`View Inventory Details`)}
|
||||||
{i18n._(t`View Inventory Details`)}
|
</Link>
|
||||||
</Link>
|
)}
|
||||||
)}
|
</ContentError>
|
||||||
</ContentError>
|
)
|
||||||
)
|
);
|
||||||
}
|
}}
|
||||||
/>,
|
/>
|
||||||
]}
|
</Switch>
|
||||||
</Switch>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { GroupsAPI } from '@api';
|
||||||
|
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
|
import { createMemoryHistory } from 'history';
|
||||||
|
|
||||||
|
import InventoryGroup from './InventoryGroup';
|
||||||
|
|
||||||
|
jest.mock('@api');
|
||||||
|
GroupsAPI.readDetail.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
id: 1,
|
||||||
|
name: 'Foo',
|
||||||
|
description: 'Bar',
|
||||||
|
variables: 'bizz: buzz',
|
||||||
|
summary_fields: {
|
||||||
|
created_by: { id: 1, name: 'Athena' },
|
||||||
|
modified_by: { id: 1, name: 'Apollo' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
describe('<InventoryGroup />', () => {
|
||||||
|
let wrapper;
|
||||||
|
let history;
|
||||||
|
const inventory = { id: 1, name: 'Foo' };
|
||||||
|
beforeEach(async () => {
|
||||||
|
history = createMemoryHistory({
|
||||||
|
initialEntries: ['/inventories/inventory/1/groups/1/details'],
|
||||||
|
});
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<InventoryGroup inventory={inventory} setBreadcrumb={() => {}} />,
|
||||||
|
{
|
||||||
|
context: {
|
||||||
|
router: {
|
||||||
|
history,
|
||||||
|
route: {
|
||||||
|
location: history.location,
|
||||||
|
match: {
|
||||||
|
params: { id: 1 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
wrapper.unmount();
|
||||||
|
});
|
||||||
|
test('renders successfully', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||||
|
});
|
||||||
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(wrapper.find('button[aria-label="Return to Groups"]').length).toBe(
|
||||||
|
1
|
||||||
|
);
|
||||||
|
});
|
||||||
|
test('expect Return to Groups tab to exist', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||||
|
});
|
||||||
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(wrapper.find('button[aria-label="Return to Groups"]').length).toBe(
|
||||||
|
1
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -2,8 +2,8 @@ import React, { useState, useEffect } from 'react';
|
|||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { GroupsAPI } from '@api';
|
import { GroupsAPI } from '@api';
|
||||||
|
import { Card } from '@patternfly/react-core';
|
||||||
|
|
||||||
import ContentError from '@components/ContentError';
|
|
||||||
import InventoryGroupForm from '../InventoryGroupForm/InventoryGroupForm';
|
import InventoryGroupForm from '../InventoryGroupForm/InventoryGroupForm';
|
||||||
|
|
||||||
function InventoryGroupsAdd({ history, inventory, setBreadcrumb }) {
|
function InventoryGroupsAdd({ history, inventory, setBreadcrumb }) {
|
||||||
@@ -21,15 +21,14 @@ function InventoryGroupsAdd({ history, inventory, setBreadcrumb }) {
|
|||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
history.push(`/inventories/inventory/${inventory.id}/groups`);
|
history.push(`/inventories/inventory/${inventory.id}/groups`);
|
||||||
};
|
};
|
||||||
if (error) {
|
|
||||||
return <ContentError />;
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<InventoryGroupForm
|
<Card>
|
||||||
error={error}
|
<InventoryGroupForm
|
||||||
handleCancel={handleCancel}
|
error={error}
|
||||||
handleSubmit={handleSubmit}
|
handleCancel={handleCancel}
|
||||||
/>
|
handleSubmit={handleSubmit}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export default withI18n()(withRouter(InventoryGroupsAdd));
|
export default withI18n()(withRouter(InventoryGroupsAdd));
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ describe('<InventoryGroupAdd />', () => {
|
|||||||
let history;
|
let history;
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
history = createMemoryHistory({
|
history = createMemoryHistory({
|
||||||
initialEntries: ['/inventories/1/groups'],
|
initialEntries: ['/inventories/inventory/1/groups'],
|
||||||
});
|
});
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper = mountWithContexts(
|
wrapper = mountWithContexts(
|
||||||
@@ -34,14 +34,16 @@ describe('<InventoryGroupAdd />', () => {
|
|||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
wrapper.unmount();
|
wrapper.unmount();
|
||||||
});
|
});
|
||||||
test('InventoryGroupEdit renders successfully', () => {
|
test('InventoryGroupAdd renders successfully', () => {
|
||||||
expect(wrapper.length).toBe(1);
|
expect(wrapper.length).toBe(1);
|
||||||
});
|
});
|
||||||
test('cancel should navigate user to Inventory Groups List', async () => {
|
test('cancel should navigate user to Inventory Groups List', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
waitForElement(wrapper, 'isLoading', el => el.length === 0);
|
waitForElement(wrapper, 'isLoading', el => el.length === 0);
|
||||||
});
|
});
|
||||||
expect(history.location.pathname).toEqual('/inventories/1/groups');
|
expect(history.location.pathname).toEqual(
|
||||||
|
'/inventories/inventory/1/groups'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
test('handleSubmit should call api', async () => {
|
test('handleSubmit should call api', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
|
|||||||
@@ -5,14 +5,21 @@ import { CardBody, Button } from '@patternfly/react-core';
|
|||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { withRouter, Link } from 'react-router-dom';
|
import { withRouter, Link } from 'react-router-dom';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { VariablesInput } from '@components/CodeMirrorInput';
|
import { VariablesInput as CodeMirrorInput } from '@components/CodeMirrorInput';
|
||||||
import ContentError from '@components/ContentError';
|
import ErrorDetail from '@components/ErrorDetail';
|
||||||
import AlertModal from '@components/AlertModal';
|
import AlertModal from '@components/AlertModal';
|
||||||
import { formatDateString } from '@util/dates';
|
import { formatDateString } from '@util/dates';
|
||||||
|
|
||||||
import { GroupsAPI } from '@api';
|
import { GroupsAPI } from '@api';
|
||||||
import { DetailList, Detail } from '@components/DetailList';
|
import { DetailList, Detail } from '@components/DetailList';
|
||||||
|
|
||||||
|
const VariablesInput = styled(CodeMirrorInput)`
|
||||||
|
.pf-c-form__label {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
margin: 20px 0;
|
||||||
|
`;
|
||||||
const ActionButtonWrapper = styled.div`
|
const ActionButtonWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
@@ -26,6 +33,7 @@ function InventoryGroupDetail({ i18n, history, match, inventoryGroup }) {
|
|||||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||||
|
|
||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
|
setIsDeleteModalOpen(false);
|
||||||
try {
|
try {
|
||||||
await GroupsAPI.destroy(inventoryGroup.id);
|
await GroupsAPI.destroy(inventoryGroup.id);
|
||||||
history.push(`/inventories/inventory/${match.params.id}/groups`);
|
history.push(`/inventories/inventory/${match.params.id}/groups`);
|
||||||
@@ -34,7 +42,17 @@ function InventoryGroupDetail({ i18n, history, match, inventoryGroup }) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (error) {
|
if (error) {
|
||||||
return <ContentError />;
|
return (
|
||||||
|
<AlertModal
|
||||||
|
variant="danger"
|
||||||
|
title={i18n._(t`Error!`)}
|
||||||
|
isOpen={error}
|
||||||
|
onClose={() => setError(false)}
|
||||||
|
>
|
||||||
|
{i18n._(t`Failed to delete group ${inventoryGroup.name}.`)}
|
||||||
|
<ErrorDetail error={error} />
|
||||||
|
</AlertModal>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (isDeleteModalOpen) {
|
if (isDeleteModalOpen) {
|
||||||
return (
|
return (
|
||||||
@@ -77,21 +95,14 @@ function InventoryGroupDetail({ i18n, history, match, inventoryGroup }) {
|
|||||||
label={i18n._(t`Description`)}
|
label={i18n._(t`Description`)}
|
||||||
value={inventoryGroup.description}
|
value={inventoryGroup.description}
|
||||||
/>
|
/>
|
||||||
<Detail
|
|
||||||
fullWidth
|
|
||||||
label={i18n._(t`Variables`)}
|
|
||||||
value={
|
|
||||||
<VariablesInput
|
|
||||||
css="margin: 20px 0"
|
|
||||||
id="inventoryGroup-variables"
|
|
||||||
readOnly
|
|
||||||
value={inventoryGroup.variables}
|
|
||||||
rows={4}
|
|
||||||
label=""
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</DetailList>
|
</DetailList>
|
||||||
|
<VariablesInput
|
||||||
|
id="inventoryGroup-variables"
|
||||||
|
readOnly
|
||||||
|
value={inventoryGroup.variables}
|
||||||
|
rows={4}
|
||||||
|
label={i18n._(t`Variables`)}
|
||||||
|
/>
|
||||||
<DetailList>
|
<DetailList>
|
||||||
<Detail
|
<Detail
|
||||||
label={i18n._(t`Created`)}
|
label={i18n._(t`Created`)}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { GroupsAPI } from '@api';
|
import { GroupsAPI } from '@api';
|
||||||
import { MemoryRouter, Route } from 'react-router-dom';
|
import { Route } from 'react-router-dom';
|
||||||
import { act } from 'react-dom/test-utils';
|
import { createMemoryHistory } from 'history';
|
||||||
|
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
|
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
|
||||||
|
|
||||||
import InventoryGroupDetail from './InventoryGroupDetail';
|
import InventoryGroupDetail from './InventoryGroupDetail';
|
||||||
@@ -28,19 +29,24 @@ const inventoryGroup = {
|
|||||||
};
|
};
|
||||||
describe('<InventoryGroupDetail />', () => {
|
describe('<InventoryGroupDetail />', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
|
let history;
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
|
history = createMemoryHistory({
|
||||||
|
initialEntries: ['/inventories/inventory/1/groups/1/edit'],
|
||||||
|
});
|
||||||
wrapper = mountWithContexts(
|
wrapper = mountWithContexts(
|
||||||
<MemoryRouter
|
<Route
|
||||||
initialEntries={['/inventories/inventory/1/groups/1/edit']}
|
path="/inventories/inventory/:id/groups/:groupId"
|
||||||
>
|
component={() => (
|
||||||
<Route
|
<InventoryGroupDetail inventoryGroup={inventoryGroup} />
|
||||||
path="/inventories/inventory/:id/groups/:groupId"
|
)}
|
||||||
component={() => (
|
/>,
|
||||||
<InventoryGroupDetail inventoryGroup={inventoryGroup} />
|
{
|
||||||
)}
|
context: {
|
||||||
/>
|
router: { history, route: { location: history.location } },
|
||||||
</MemoryRouter>
|
},
|
||||||
|
}
|
||||||
);
|
);
|
||||||
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||||
});
|
});
|
||||||
@@ -51,20 +57,22 @@ describe('<InventoryGroupDetail />', () => {
|
|||||||
test('InventoryGroupDetail renders successfully', () => {
|
test('InventoryGroupDetail renders successfully', () => {
|
||||||
expect(wrapper.length).toBe(1);
|
expect(wrapper.length).toBe(1);
|
||||||
});
|
});
|
||||||
test('should open delete modal and then call api to delete the group', () => {
|
test('should open delete modal and then call api to delete the group', async () => {
|
||||||
wrapper.find('button[aria-label="Delete"]').simulate('click');
|
await act(async () => {
|
||||||
|
wrapper.find('button[aria-label="Delete"]').simulate('click');
|
||||||
|
});
|
||||||
|
await waitForElement(wrapper, 'Modal', el => el.length === 1);
|
||||||
expect(wrapper.find('Modal').length).toBe(1);
|
expect(wrapper.find('Modal').length).toBe(1);
|
||||||
wrapper.find('button[aria-label="confirm delete"]').simulate('click');
|
await act(async () => {
|
||||||
|
wrapper.find('button[aria-label="confirm delete"]').simulate('click');
|
||||||
|
});
|
||||||
expect(GroupsAPI.destroy).toBeCalledWith(1);
|
expect(GroupsAPI.destroy).toBeCalledWith(1);
|
||||||
});
|
});
|
||||||
test('should navigate user to edit form on edit button click', async () => {
|
test('should navigate user to edit form on edit button click', async () => {
|
||||||
wrapper.find('button[aria-label="Edit"]').prop('onClick');
|
wrapper.find('button[aria-label="Edit"]').prop('onClick');
|
||||||
expect(
|
expect(history.location.pathname).toEqual(
|
||||||
wrapper
|
'/inventories/inventory/1/groups/1/edit'
|
||||||
.find('Router')
|
);
|
||||||
.at(1)
|
|
||||||
.prop('history').location.pathname
|
|
||||||
).toEqual('/inventories/inventory/1/groups/1/edit');
|
|
||||||
});
|
});
|
||||||
test('details shoudld render with the proper values', () => {
|
test('details shoudld render with the proper values', () => {
|
||||||
expect(wrapper.find('Detail[label="Name"]').prop('value')).toBe('Foo');
|
expect(wrapper.find('Detail[label="Name"]').prop('value')).toBe('Foo');
|
||||||
|
|||||||
@@ -14,11 +14,15 @@ function InventoryGroupEdit({ history, inventoryGroup, inventory, match }) {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError(err);
|
setError(err);
|
||||||
} finally {
|
} finally {
|
||||||
history.push(`/inventories/inventory/${inventory.id}/groups`);
|
history.push(
|
||||||
|
`/inventories/inventory/${inventory.id}/groups/${inventoryGroup.id}/details`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
history.push(`/inventories/inventory/${inventory.id}/groups`);
|
history.push(
|
||||||
|
`/inventories/inventory/${inventory.id}/groups/${inventoryGroup.id}/details`
|
||||||
|
);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<InventoryGroupForm
|
<InventoryGroupForm
|
||||||
|
|||||||
Reference in New Issue
Block a user