diff --git a/awx/ui_next/src/screens/Inventory/Inventory.jsx b/awx/ui_next/src/screens/Inventory/Inventory.jsx
index 54b5ac2298..5352b949a4 100644
--- a/awx/ui_next/src/screens/Inventory/Inventory.jsx
+++ b/awx/ui_next/src/screens/Inventory/Inventory.jsx
@@ -1,4 +1,4 @@
-import React, { Component } from 'react';
+import React, { useEffect, useState } from 'react';
import { t } from '@lingui/macro';
import { withI18n } from '@lingui/react';
import { Card, CardHeader, PageSection } from '@patternfly/react-core';
@@ -16,186 +16,152 @@ import InventorySources from './InventorySources';
import { InventoriesAPI } from '@api';
import InventoryEdit from './InventoryEdit';
-class Inventory extends Component {
- constructor(props) {
- super(props);
+function Inventory({ history, i18n, location, match, setBreadcrumb }) {
+ const [contentError, setContentError] = useState(null);
+ const [hasContentLoading, setHasContentLoading] = useState(true);
+ const [inventory, setInventory] = useState(null);
- this.state = {
- contentError: null,
- hasContentLoading: true,
- inventory: null,
- };
- this.loadInventory = this.loadInventory.bind(this);
- }
-
- async componentDidMount() {
- await this.loadInventory();
- }
-
- async componentDidUpdate(prevProps) {
- const { location, match } = this.props;
- const url = `/inventories/inventory/${match.params.id}/`;
-
- if (
- prevProps.location.pathname.startsWith(url) &&
- prevProps.location !== location &&
- location.pathname === `${url}details`
- ) {
- await this.loadInventory();
- }
- }
-
- async loadInventory() {
- const { setBreadcrumb, match } = this.props;
- const { id } = match.params;
-
- this.setState({ contentError: null, hasContentLoading: true });
- try {
- const { data } = await InventoriesAPI.readDetail(id);
- setBreadcrumb(data);
- this.setState({ inventory: data });
- } catch (err) {
- this.setState({ contentError: err });
- } finally {
- this.setState({ hasContentLoading: false });
- }
- }
-
- render() {
- const { history, i18n, location, match } = this.props;
- const { contentError, hasContentLoading, inventory } = this.state;
-
- const tabsArray = [
- { name: i18n._(t`Details`), link: `${match.url}/details`, id: 0 },
- { name: i18n._(t`Access`), link: `${match.url}/access`, id: 1 },
- { name: i18n._(t`Groups`), link: `${match.url}/groups`, id: 2 },
- { name: i18n._(t`Hosts`), link: `${match.url}/hosts`, id: 3 },
- { name: i18n._(t`Sources`), link: `${match.url}/sources`, id: 4 },
- {
- name: i18n._(t`Completed Jobs`),
- link: `${match.url}/completed_jobs`,
- id: 5,
- },
- ];
-
- let cardHeader = hasContentLoading ? null : (
-
-
-
-
- );
-
- if (
- location.pathname.endsWith('edit') ||
- location.pathname.endsWith('add')
- ) {
- cardHeader = null;
+ useEffect(() => {
+ async function fetchData() {
+ try {
+ const { data } = await InventoriesAPI.readDetail(match.params.id);
+ setBreadcrumb(data);
+ setInventory(data);
+ } catch (error) {
+ setContentError(error);
+ } finally {
+ setHasContentLoading(false);
+ }
}
- if (!hasContentLoading && contentError) {
- return (
-
-
-
- {contentError.response.status === 404 && (
-
- {i18n._(`Inventory not found.`)}{' '}
-
- {i18n._(`View all Inventories.`)}
-
-
- )}
-
-
-
- );
- }
+ fetchData();
+ }, [match.params.id, setBreadcrumb]);
+ const tabsArray = [
+ { name: i18n._(t`Details`), link: `${match.url}/details`, id: 0 },
+ { name: i18n._(t`Access`), link: `${match.url}/access`, id: 1 },
+ { name: i18n._(t`Groups`), link: `${match.url}/groups`, id: 2 },
+ { name: i18n._(t`Hosts`), link: `${match.url}/hosts`, id: 3 },
+ { name: i18n._(t`Sources`), link: `${match.url}/sources`, id: 4 },
+ {
+ name: i18n._(t`Completed Jobs`),
+ link: `${match.url}/completed_jobs`,
+ id: 5,
+ },
+ ];
+
+ let cardHeader = hasContentLoading ? null : (
+
+
+
+
+ );
+
+ if (location.pathname.endsWith('edit') || location.pathname.endsWith('add')) {
+ cardHeader = null;
+ }
+
+ if (!hasContentLoading && contentError) {
return (
- {cardHeader}
-
-
- {inventory && [
- (
-
- )}
- />,
- }
- />,
- }
- />,
- (
-
- )}
- />,
- }
- />,
- }
- />,
- }
- />,
- }
- />,
-
- !hasContentLoading && (
-
- {match.params.id && (
-
- {i18n._(`View Inventory Details`)}
-
- )}
-
- )
- }
- />,
- ]}
-
+
+ {contentError.response.status === 404 && (
+
+ {i18n._(`Inventory not found.`)}{' '}
+ {i18n._(`View all Inventories.`)}
+
+ )}
+
);
}
+
+ return (
+
+
+ {cardHeader}
+
+
+ {inventory && [
+ (
+
+ )}
+ />,
+ }
+ />,
+ }
+ />,
+ (
+
+ )}
+ />,
+ }
+ />,
+ }
+ />,
+ }
+ />,
+ }
+ />,
+
+ !hasContentLoading && (
+
+ {match.params.id && (
+
+ {i18n._(`View Inventory Details`)}
+
+ )}
+
+ )
+ }
+ />,
+ ]}
+
+
+
+ );
}
export { Inventory as _Inventory };
diff --git a/awx/ui_next/src/screens/Inventory/Inventory.test.jsx b/awx/ui_next/src/screens/Inventory/Inventory.test.jsx
index cff57dfc11..f242b01a7d 100644
--- a/awx/ui_next/src/screens/Inventory/Inventory.test.jsx
+++ b/awx/ui_next/src/screens/Inventory/Inventory.test.jsx
@@ -1,4 +1,5 @@
import React from 'react';
+import { act } from 'react-dom/test-utils';
import { createMemoryHistory } from 'history';
import { InventoriesAPI } from '@api';
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
@@ -12,41 +13,38 @@ InventoriesAPI.readDetail.mockResolvedValue({
});
describe('', () => {
- test('initially renders succesfully', async done => {
- const wrapper = mountWithContexts(
- {}} match={{ params: { id: 1 } }} />
- );
- await waitForElement(
- wrapper,
- 'Inventory',
- el => el.state('hasContentLoading') === true
- );
- await waitForElement(
- wrapper,
- 'Inventory',
- el => el.state('hasContentLoading') === false
- );
+ let wrapper;
+
+ test('initially renders succesfully', async () => {
+ await act(async () => {
+ wrapper = mountWithContexts(
+ {}} match={{ params: { id: 1 } }} />
+ );
+ });
+ await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
await waitForElement(wrapper, '.pf-c-tabs__item', el => el.length === 6);
- done();
});
+
test('should show content error when user attempts to navigate to erroneous route', async () => {
const history = createMemoryHistory({
initialEntries: ['/inventories/inventory/1/foobar'],
});
- const wrapper = mountWithContexts( {}} />, {
- context: {
- router: {
- history,
- route: {
- location: history.location,
- match: {
- params: { id: 1 },
- url: '/inventories/inventory/1/foobar',
- path: '/inventories/inventory/1/foobar',
+ await act(async () => {
+ wrapper = mountWithContexts( {}} />, {
+ context: {
+ router: {
+ history,
+ route: {
+ location: history.location,
+ match: {
+ params: { id: 1 },
+ url: '/inventories/inventory/1/foobar',
+ path: '/inventories/inventory/1/foobar',
+ },
},
},
},
- },
+ });
});
await waitForElement(wrapper, 'ContentError', el => el.length === 1);
});
diff --git a/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHosts.jsx b/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHosts.jsx
index f35d87ae1c..921b78a7a5 100644
--- a/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHosts.jsx
+++ b/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHosts.jsx
@@ -20,7 +20,7 @@ const QS_CONFIG = getQSConfig('host', {
order_by: 'name',
});
-function InventoryHosts({ i18n, location, match, inventory }) {
+function InventoryHosts({ i18n, location, match }) {
const [actions, setActions] = useState(null);
const [contentError, setContentError] = useState(null);
const [deletionError, setDeletionError] = useState(null);
@@ -47,7 +47,7 @@ function InventoryHosts({ i18n, location, match, inventory }) {
data: { actions: optionActions },
},
] = await Promise.all([
- fetchHosts(inventory.id, location.search),
+ fetchHosts(match.params.id, location.search),
InventoriesAPI.readOptions(),
]);
@@ -62,7 +62,7 @@ function InventoryHosts({ i18n, location, match, inventory }) {
}
fetchData();
- }, [inventory, location]);
+ }, [match.params.id, location]);
const handleSelectAll = isSelected => {
setSelected(isSelected ? [...hosts] : []);
@@ -88,7 +88,7 @@ function InventoryHosts({ i18n, location, match, inventory }) {
try {
const {
data: { count, results },
- } = await fetchHosts(inventory.id, location.search);
+ } = await fetchHosts(match.params.id, location.search);
setHosts(results);
setHostCount(count);
diff --git a/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHosts.test.jsx b/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHosts.test.jsx
index 59e339722d..715413c81b 100644
--- a/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHosts.test.jsx
+++ b/awx/ui_next/src/screens/Inventory/InventoryHosts/InventoryHosts.test.jsx
@@ -81,7 +81,7 @@ describe('', () => {
},
});
await act(async () => {
- wrapper = mountWithContexts();
+ wrapper = mountWithContexts();
});
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
});