Skip to content

Commit

Permalink
feat(OperatingSystem): enhance the filter to fetch custom endpoint (#…
Browse files Browse the repository at this point in the history
…2262)

* feat(OperatingSystem): enhance the filter to fetch custom endpoint

* fix: fetchOperatingSystems useCallback hook deps

* chore: make codeclimate happy

* chore: remove console log

* chore: apply pr suggestions, update README
  • Loading branch information
mkholjuraev authored Oct 14, 2024
1 parent 6d767e6 commit 8eff938
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 28 deletions.
26 changes: 26 additions & 0 deletions doc/props_table.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- [initialLoading](#initialloading)
- [ignoreRefresh](#ignorerefresh)
- [showTagModal](#showtagmodal)
- [fetchCustomOSes](#fetchCustomOSes)

# Props

Expand Down Expand Up @@ -123,3 +124,28 @@ On the initial mount and when items/sortBy are changed, the inventoryTable ignor
*boolean*

Will enable TagModal even the filter or the column is not shown.

## fetchCustomOSes

*falsy | (apFilters) => array*

Operating systems filter by default fetches the os versions from inventory API. However, there might be requirement to fetch from some other custom API endpoints. In this case, you can provide your custom operating system API fetch funtion as a prop. The returned result must be in the shape of:

```
{
"total": Number,
"count": Number,
"page": Number,
"per_page": Number,
"results": [
{
"value": {
"name": String,
"major": Number,
"minor": Number,
},
"count": Number
},
]
}
```
36 changes: 25 additions & 11 deletions src/Utilities/hooks/useFetchOperatingSystems.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,46 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { getOperatingSystems } from '../../api';

const initialState = {
operatingSystems: [],
operatingSystemsLoaded: false,
};

const useFetchOperatingSystems = ({
apiParams = [],
hasAccess,
showCentosVersions,
fetchCustomOSes,
}) => {
const mounted = useRef(true);
const initialState = {
operatingSystems: [],
operatingSystemsLoaded: false,
};

const [data, setData] = useState(initialState);

const fetchOperatingSystems = useCallback(async () => {
if (typeof hasAccess === 'undefined') {
return await getOperatingSystems(apiParams, showCentosVersions);
} else if (typeof hasAccess !== 'undefined' && hasAccess === true) {
return await getOperatingSystems(apiParams, showCentosVersions);
if (hasAccess === false) return;

const fetchFn = fetchCustomOSes || getOperatingSystems;
const fetchArgs = [apiParams, showCentosVersions];

try {
return await fetchFn(...fetchArgs);
} catch (error) {
console.error(error);
return { results: [] };
}
}, [hasAccess, apiParams, showCentosVersions]);
}, [
hasAccess,
JSON.stringify(apiParams),
showCentosVersions,
fetchCustomOSes,
]);

useEffect(() => {
(async () => {
const result = await fetchOperatingSystems();
if (mounted.current) {
setData({
operatingSystems: result.results,
operatingSystems: result?.results || [],
operatingSystemsLoaded: true,
});
}
Expand All @@ -36,7 +50,7 @@ const useFetchOperatingSystems = ({
setData(initialState);
mounted.current = false;
};
}, []);
}, [fetchOperatingSystems]);

return data;
};
Expand Down
10 changes: 9 additions & 1 deletion src/components/InventoryTable/EntityTableToolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const EntityTableToolbar = ({
showCentosVersions,
showNoGroupOption,
enableExport,
fetchCustomOSes,
...props
}) => {
const dispatch = useDispatch();
Expand Down Expand Up @@ -171,7 +172,13 @@ const EntityTableToolbar = ({
setEndDate,
] = useLastSeenFilter(reducer);
const [osFilterConfig, osFilterChips, osFilterValue, setOsFilterValue] =
useOperatingSystemFilter(reducer, [], hasAccess, showCentosVersions);
useOperatingSystemFilter(
reducer,
[],
hasAccess,
showCentosVersions,
fetchCustomOSes
);
const [
updateMethodConfig,
updateMethodChips,
Expand Down Expand Up @@ -691,6 +698,7 @@ EntityTableToolbar.propTypes = {
showSystemTypeFilter: PropTypes.bool,
enableExport: PropTypes.bool,
exportConfig: PropTypes.object,
fetchCustomOSes: PropTypes.func,
};

EntityTableToolbar.defaultProps = {
Expand Down
47 changes: 34 additions & 13 deletions src/components/InventoryTable/InventoryTable.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@ import { buildHosts, buildHostsPayload } from '../../__factories__/hosts';
import * as api from '../../api/api';
import * as groupsApi from '../InventoryGroups/utils/api';
import useFetchBatched from '../../Utilities/hooks/useFetchBatched';
import useFetchOperatingSystems from '../../Utilities/hooks/useFetchOperatingSystems';
import { buildOperatingSystems } from '../../__factories__/operatingSystems';

import InventoryTable from './InventoryTable';
import { shouldDispatch, shouldNotDispatch } from '../../Utilities/testUtils';

jest.mock('../../Utilities/hooks/useFetchOperatingSystems');
import { getOperatingSystems } from '../../api/api';

jest.mock('../../api/api', () => ({
__esModule: true,
...jest.requireActual('../../api/api'),
getOperatingSystems: jest.fn(() =>
Promise.resolve({ total: 0, results: [] })
),
}));
jest.mock('../../Utilities/hooks/useFetchBatched');

const TABLE_HEADERS = ['Name', 'Group', 'OS', 'Last seen'];
Expand Down Expand Up @@ -182,17 +188,20 @@ const errorState = {
},
};

const operatingSystems = [
...buildOperatingSystems(20, { osName: 'RHEL', major: 8 }),
...buildOperatingSystems(20, { osName: 'CentOS Linux', major: 7 }),
];
describe('InventoryTable', () => {
const operatingSystems = [
...buildOperatingSystems(20, { osName: 'RHEL', major: 8 }),
...buildOperatingSystems(20, { osName: 'CentOS Linux', major: 7 }),
];
useFeatureFlag.mockReturnValue(false);
useFetchOperatingSystems.mockReturnValue({
operatingSystems,
operatingSystemsLoaded: true,
beforeEach(() => {
getOperatingSystems.mockReturnValue(
Promise.resolve({
results: operatingSystems,
total: operatingSystems.length,
})
);
});

useFetchBatched.mockReturnValue({
fetchBatched: () =>
new Promise((resolve) => resolve([{ results: [{ name: 'group-1' }] }])),
Expand Down Expand Up @@ -227,12 +236,24 @@ describe('InventoryTable', () => {
});
});

it('fetches operating system versions', async () => {
it('fetches operating system versions using custom API', async () => {
const store = mockStore(initialState);
const fetchCustomOSes = jest.fn(() =>
Promise.resolve({ total: 0, results: [] })
);
renderTable(store, { fetchCustomOSes });

await waitFor(() => {
expect(fetchCustomOSes).toBeCalled();
});
});

it('fetches operating system versions using default API', async () => {
const store = mockStore(initialState);
renderTable(store);

await waitFor(() => {
expect(useFetchOperatingSystems).toBeCalled();
expect(getOperatingSystems).toBeCalled();
});
});

Expand Down
4 changes: 3 additions & 1 deletion src/components/filters/useOperatingSystemFilter.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export const useOperatingSystemFilter = (
// TODO Get rid of all additional (unnecessary) parameters
apiParams,
hasAccess,
showCentosVersions
showCentosVersions,
fetchCustomOSes
) => {
const [operatingSystemsStateValue, setStateValue] = useState({});
const operatingSystemsValue = dispatch
Expand All @@ -28,6 +29,7 @@ export const useOperatingSystemFilter = (
apiParams,
hasAccess,
showCentosVersions,
fetchCustomOSes,
}
);

Expand Down
24 changes: 22 additions & 2 deletions src/components/filters/useOperatingSystemFilter.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { act, renderHook } from '@testing-library/react';
import { act, renderHook, waitFor } from '@testing-library/react';
import { mockSystemProfile } from '../../__mocks__/hostApi';
import useFetchOperatingSystems from '../../Utilities/hooks/useFetchOperatingSystems';
import { buildOperatingSystems } from '../../__factories__/operatingSystems';

import { useOperatingSystemFilter } from './useOperatingSystemFilter';
jest.mock('../../Utilities/hooks/useFetchOperatingSystems');

Expand Down Expand Up @@ -72,4 +71,25 @@ describe('useOperatingSystemFilter', () => {
expect(chipsUpdated).toMatchSnapshot();
});
});

describe('with custom operating system fetch endpoint', () => {
it('Should use the provided custom fetch function', async () => {
const fetchCustomOSes = jest.fn(
Promise.resolve({
operatingSystems,
operatingSystemsLoaded: true,
})
);

renderHook(() =>
useOperatingSystemFilter(undefined, [], true, true, fetchCustomOSes)
);

await waitFor(() =>
expect(useFetchOperatingSystems).toHaveBeenCalledWith(
expect.objectContaining({ fetchCustomOSes })
)
);
});
});
});

0 comments on commit 8eff938

Please sign in to comment.