`;
-
-exports[`BannerMessages Component should render specific messages when the appMessages prop is used: specific messages, OFF, ON 1`] = `
-
-
-
- }
- key="dolorSit"
- title="Dolor sit title"
- variant="info"
- >
-
-
-
-
-
-
- Info alert:
-
- Dolor sit title
-
-
-
-
-
-
-
- Dolor sit message
-
-
-
-
-
-`;
diff --git a/src/components/bannerMessages/__tests__/__snapshots__/bannerMessagesContext.test.js.snap b/src/components/bannerMessages/__tests__/__snapshots__/bannerMessagesContext.test.js.snap
new file mode 100644
index 000000000..0a12654f4
--- /dev/null
+++ b/src/components/bannerMessages/__tests__/__snapshots__/bannerMessagesContext.test.js.snap
@@ -0,0 +1,51 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`BannerMessagesContext should apply a hook for retrieving messages data from a selectors: error response 1`] = `
+Object {
+ "data": Object {
+ "cloudigradeMismatch": false,
+ },
+ "error": true,
+ "fulfilled": undefined,
+ "pending": undefined,
+}
+`;
+
+exports[`BannerMessagesContext should apply a hook for retrieving messages data from a selectors: mock store error response 1`] = `
+Object {
+ "data": Object {
+ "cloudigradeMismatch": false,
+ },
+ "error": true,
+ "fulfilled": false,
+ "pending": false,
+}
+`;
+
+exports[`BannerMessagesContext should apply a hook for retrieving messages data from a selectors: mock store success response 1`] = `
+Object {
+ "data": Object {
+ "cloudigradeMismatch": true,
+ },
+ "error": false,
+ "fulfilled": true,
+ "pending": false,
+}
+`;
+
+exports[`BannerMessagesContext should apply a hook for retrieving messages data from a selectors: success response 1`] = `
+Object {
+ "data": Object {
+ "cloudigradeMismatch": false,
+ },
+ "error": undefined,
+ "fulfilled": true,
+ "pending": undefined,
+}
+`;
+
+exports[`BannerMessagesContext should return specific properties: specific properties 1`] = `
+Object {
+ "useGetAppMessages": [Function],
+}
+`;
diff --git a/src/components/bannerMessages/__tests__/bannerMessages.test.js b/src/components/bannerMessages/__tests__/bannerMessages.test.js
index 8bd2bc442..844f2ac5e 100644
--- a/src/components/bannerMessages/__tests__/bannerMessages.test.js
+++ b/src/components/bannerMessages/__tests__/bannerMessages.test.js
@@ -3,7 +3,7 @@ import { AlertActionCloseButton } from '@patternfly/react-core';
import { BannerMessages } from '../bannerMessages';
describe('BannerMessages Component', () => {
- it('should render a non-connected component', async () => {
+ it('should render a basic component', async () => {
const props = {
messages: [
{
@@ -12,52 +12,15 @@ describe('BannerMessages Component', () => {
message: 'Lorem ipsum message'
}
],
- useAppMessages: () => ({ appMessages: { loremIpsum: true } }),
- useRouteDetail: () => ({})
- };
-
- const component = await mountHookComponent(
);
- expect(component).toMatchSnapshot('non-connected');
- });
-
- it('should attempt to check reports on product update', async () => {
- const props = {
- messages: [
- {
- id: 'loremIpsum',
- title: 'Lorem ipsum title',
- message: 'Lorem ipsum message'
- }
- ],
- useAppMessages: jest.fn(() => ({})),
- useRouteDetail: () => ({ productConfig: [{ productId: 'lorem' }] })
- };
-
- const component = await shallowHookComponent(
);
- component.setProps({ useRouteDetail: () => ({ productConfig: [{ productId: 'dolor' }] }) });
- expect(props.useAppMessages).toHaveBeenCalledTimes(2);
- });
-
- it('should render specific messages when the appMessages prop is used', async () => {
- const props = {
- messages: [
- {
- id: 'loremIpsum',
- title: 'Lorem ipsum title',
- message: 'Lorem ipsum message'
- },
- {
- id: 'dolorSit',
- title: 'Dolor sit title',
- message: 'Dolor sit message'
+ useGetAppMessages: () => ({
+ data: {
+ loremIpsum: true
}
- ],
- useAppMessages: () => ({ appMessages: { loremIpsum: false, dolorSit: true } }),
- useRouteDetail: () => ({})
+ })
};
-
const component = await mountHookComponent(
);
- expect(component).toMatchSnapshot('specific messages, OFF, ON');
+
+ expect(component).toMatchSnapshot('basic');
});
it('should handle closing messages from state', async () => {
@@ -69,8 +32,7 @@ describe('BannerMessages Component', () => {
message: 'Dolor sit message'
}
],
- useAppMessages: () => ({ appMessages: { dolorSit: true } }),
- useRouteDetail: () => ({})
+ useGetAppMessages: () => ({ data: { dolorSit: true } })
};
const component = await mountHookComponent(
);
diff --git a/src/components/bannerMessages/__tests__/bannerMessagesContext.test.js b/src/components/bannerMessages/__tests__/bannerMessagesContext.test.js
new file mode 100644
index 000000000..563ccb19b
--- /dev/null
+++ b/src/components/bannerMessages/__tests__/bannerMessagesContext.test.js
@@ -0,0 +1,86 @@
+import { context, useGetAppMessages } from '../bannerMessagesContext';
+import { rhsmConstants } from '../../../services/rhsm/rhsmConstants';
+
+describe('BannerMessagesContext', () => {
+ it('should return specific properties', () => {
+ expect(context).toMatchSnapshot('specific properties');
+ });
+
+ it('should apply a hook for retrieving messages data from a selectors', () => {
+ const { result: errorResponse } = shallowHook(() =>
+ useGetAppMessages({
+ useSelectorsResponse: () => ({
+ error: true,
+ data: {
+ messages: {}
+ }
+ })
+ })
+ );
+
+ expect(errorResponse).toMatchSnapshot('error response');
+
+ const { result: successResponse } = shallowHook(() =>
+ useGetAppMessages({
+ useSelectorsResponse: () => ({
+ fulfilled: true,
+ data: {
+ messages: {}
+ }
+ })
+ })
+ );
+
+ expect(successResponse).toMatchSnapshot('success response');
+
+ const { result: mockStoreSuccessResponse } = shallowHook(
+ () =>
+ useGetAppMessages({
+ useProduct: () => ({ productId: 'loremIpsum' })
+ }),
+ {
+ state: {
+ messages: {
+ report: {
+ loremIpsum: {
+ fulfilled: true,
+ data: {
+ data: [
+ {
+ [rhsmConstants.RHSM_API_RESPONSE_TALLY_META_TYPES.HAS_CLOUDIGRADE_MISMATCH]: true
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ );
+
+ expect(mockStoreSuccessResponse).toMatchSnapshot('mock store success response');
+
+ const { result: mockStoreErrorResponse } = shallowHook(
+ () =>
+ useGetAppMessages({
+ useProduct: () => ({ productId: 'loremIpsum' })
+ }),
+ {
+ state: {
+ messages: {
+ report: {
+ loremIpsum: {
+ error: true,
+ data: {
+ data: []
+ }
+ }
+ }
+ }
+ }
+ }
+ );
+
+ expect(mockStoreErrorResponse).toMatchSnapshot('mock store error response');
+ });
+});
diff --git a/src/components/bannerMessages/bannerMessages.js b/src/components/bannerMessages/bannerMessages.js
index fa28b59d7..59fa9045e 100644
--- a/src/components/bannerMessages/bannerMessages.js
+++ b/src/components/bannerMessages/bannerMessages.js
@@ -3,42 +3,22 @@ import PropTypes from 'prop-types';
import { Alert, AlertActionCloseButton, AlertVariant, Button } from '@patternfly/react-core';
import { ExternalLinkAltIcon } from '@patternfly/react-icons';
import { useShallowCompareEffect } from 'react-use';
-import { apiQueries, storeHooks } from '../../redux';
+import { useGetAppMessages } from './bannerMessagesContext';
+import { helpers } from '../../common';
import { translate } from '../i18n/i18n';
-import { dateHelpers, helpers } from '../../common';
-import { RHSM_API_QUERY_GRANULARITY_TYPES as GRANULARITY_TYPES, RHSM_API_QUERY_TYPES } from '../../types/rhsmApiTypes';
-import { useRouteDetail } from '../../hooks/useRouter';
/**
* Render banner messages.
*
* @param {object} props
* @param {Array} props.messages
- * @param {Function} props.useRouteDetail
- * @param {Function} props.useAppMessages
- * @returns {Node}
+ * @param {Function} props.useGetAppMessages
+ * @returns {React.ReactNode}
*/
-const BannerMessages = ({ messages, useRouteDetail: useAliasRouteDetail, useAppMessages: useAliasAppMessages }) => {
+const BannerMessages = ({ messages, useGetAppMessages: useAliasGetAppMessages }) => {
const [hideAlerts, setHideAlerts] = useState({});
const [alerts, setAlerts] = useState([]);
- const { pathParameter: productId, productConfig } = useAliasRouteDetail() || {};
- const isProductConfig = productConfig?.length === 1 && productConfig?.[0];
- const { query } = apiQueries.parseRhsmQuery(productConfig?.[0]?.query || {});
- const { appMessages } = useAliasAppMessages();
-
- useShallowCompareEffect(() => {
- if (productId && isProductConfig) {
- const { startDate, endDate } = dateHelpers.getRangedDateTime('CURRENT');
- const updatedGraphQuery = {
- ...query,
- [RHSM_API_QUERY_TYPES.GRANULARITY]: GRANULARITY_TYPES.DAILY,
- [RHSM_API_QUERY_TYPES.START_DATE]: startDate.toISOString(),
- [RHSM_API_QUERY_TYPES.END_DATE]: endDate.toISOString()
- };
-
- storeHooks.rhsmActions.useGetMessageReports(productId, updatedGraphQuery);
- }
- }, [productId, isProductConfig, query]);
+ const { data: appMessages } = useAliasGetAppMessages();
useShallowCompareEffect(() => {
const updatedMessages = [];
@@ -81,7 +61,7 @@ const BannerMessages = ({ messages, useRouteDetail: useAliasRouteDetail, useAppM
/**
* Prop types.
*
- * @type {{useAppMessages: Function, messages: Array, useRouteDetail: Function}}
+ * @type {{useGetAppMessages: Function, messages: Array}}
*/
BannerMessages.propTypes = {
messages: PropTypes.arrayOf(
@@ -92,14 +72,13 @@ BannerMessages.propTypes = {
variant: PropTypes.oneOf([...Object.values(AlertVariant)])
})
),
- useAppMessages: PropTypes.func,
- useRouteDetail: PropTypes.func
+ useGetAppMessages: PropTypes.func
};
/**
* Default props.
*
- * @type {{useAppMessages: Function, messages: Array, useRouteDetail: Function}}
+ * @type {{useGetAppMessages: Function, messages: Array}}
*/
BannerMessages.defaultProps = {
messages: [
@@ -126,8 +105,7 @@ BannerMessages.defaultProps = {
)
}
],
- useAppMessages: storeHooks.rhsmSelectors.useAppMessages,
- useRouteDetail
+ useGetAppMessages
};
export { BannerMessages as default, BannerMessages };
diff --git a/src/components/bannerMessages/bannerMessagesContext.js b/src/components/bannerMessages/bannerMessagesContext.js
new file mode 100644
index 000000000..15b709860
--- /dev/null
+++ b/src/components/bannerMessages/bannerMessagesContext.js
@@ -0,0 +1,86 @@
+import { useShallowCompareEffect } from 'react-use';
+import { reduxActions, storeHooks } from '../../redux';
+import { useProduct, useProductQuery } from '../productView/productViewContext';
+import { dateHelpers } from '../../common';
+import {
+ rhsmConstants,
+ RHSM_API_QUERY_GRANULARITY_TYPES as GRANULARITY_TYPES,
+ RHSM_API_QUERY_SET_TYPES
+} from '../../services/rhsm/rhsmConstants';
+
+/**
+ * ToDo: useGetAppMessages is setup to work with existing Tally response, pre-metrics
+ * Banner messages scans the returned Tally listing for the HAS_CLOUDIGRADE_MISMATCH. In the future
+ * this may need to be updated to pull from the "meta" object part of the Tally response.
+ */
+/**
+ * Get app messages.
+ *
+ * @param {object} options
+ * @param {Function} options.getMessageReports
+ * @param {Function} options.useDispatch
+ * @param {Function} options.useProduct
+ * @param {Function} options.useProductQuery
+ * @param {Function} options.useSelectorsResponse
+ * @returns {object}
+ */
+const useGetAppMessages = ({
+ getMessageReports = reduxActions.rhsm.getMessageReports,
+ useDispatch: useAliasDispatch = storeHooks.reactRedux.useDispatch,
+ useProduct: useAliasProduct = useProduct,
+ useProductQuery: useAliasProductQuery = useProductQuery,
+ useSelectorsResponse: useAliasSelectorsResponse = storeHooks.reactRedux.useSelectorsResponse
+} = {}) => {
+ const { productId } = useAliasProduct();
+ const query = useAliasProductQuery();
+ const dispatch = useAliasDispatch();
+ const { error, fulfilled, pending, data } = useAliasSelectorsResponse({
+ id: 'messages',
+ selector: ({ messages }) => messages?.report?.[productId]
+ });
+
+ useShallowCompareEffect(() => {
+ if (productId) {
+ const { startDate, endDate } = dateHelpers.getRangedDateTime('CURRENT');
+ const updatedQuery = {
+ ...query,
+ [RHSM_API_QUERY_SET_TYPES.GRANULARITY]: GRANULARITY_TYPES.DAILY,
+ [RHSM_API_QUERY_SET_TYPES.START_DATE]: startDate.toISOString(),
+ [RHSM_API_QUERY_SET_TYPES.END_DATE]: endDate.toISOString()
+ };
+
+ getMessageReports(productId, updatedQuery)(dispatch);
+ }
+ }, [productId, query]);
+
+ const updatedData = {
+ cloudigradeMismatch: false
+ };
+
+ if (fulfilled) {
+ const { messages = {} } = data || {};
+
+ updatedData.cloudigradeMismatch =
+ messages?.data
+ ?.reverse()
+ ?.find(
+ ({ [rhsmConstants.RHSM_API_RESPONSE_TALLY_META_TYPES.HAS_CLOUDIGRADE_MISMATCH]: mismatch }) =>
+ mismatch === true
+ ) !== undefined;
+ }
+
+ return {
+ error,
+ fulfilled,
+ pending,
+ data: {
+ ...updatedData
+ }
+ };
+};
+
+const context = {
+ useGetAppMessages
+};
+
+export { context as default, context, useGetAppMessages };
diff --git a/src/components/productView/__tests__/__snapshots__/productView.test.js.snap b/src/components/productView/__tests__/__snapshots__/productView.test.js.snap
index 9af6a6229..1d5104859 100644
--- a/src/components/productView/__tests__/__snapshots__/productView.test.js.snap
+++ b/src/components/productView/__tests__/__snapshots__/productView.test.js.snap
@@ -10,23 +10,6 @@ exports[`ProductView Component should allow custom inventory displays via config
>
t(curiosity-view.title, {"appName":"Subscriptions","context":"lorem ipsum product label"})
-
-
-
@@ -41,6 +24,22 @@ exports[`ProductView Component should allow custom inventory displays via config
}
}
>
+
+
+
@@ -162,23 +161,6 @@ exports[`ProductView Component should allow custom product views via props: cust
>
t(curiosity-view.title, {"appName":"Subscriptions","context":"lorem ipsum product label"})
-
-
-
@@ -192,6 +174,22 @@ exports[`ProductView Component should allow custom product views via props: cust
}
}
>
+
+
+
@@ -298,23 +296,6 @@ exports[`ProductView Component should allow custom product views via props: cust
>
t(curiosity-view.title, {"appName":"Subscriptions","context":"lorem ipsum product label"})
-
-
-
@@ -328,6 +309,22 @@ exports[`ProductView Component should allow custom product views via props: cust
}
}
>
+
+
+
@@ -382,23 +379,6 @@ exports[`ProductView Component should render a basic component: basic 1`] = `
>
t(curiosity-view.title, {"appName":"Subscriptions","context":"lorem ipsum product label"})
-
-
-
@@ -412,6 +392,22 @@ exports[`ProductView Component should render a basic component: basic 1`] = `
}
}
>
+
+
+
@@ -496,23 +492,6 @@ exports[`ProductView Component should render nothing if path and product paramet
>
t(curiosity-view.title, {"appName":"Subscriptions"})
-
-
-
diff --git a/src/components/productView/productView.js b/src/components/productView/productView.js
index 04d796022..2cdf7b956 100644
--- a/src/components/productView/productView.js
+++ b/src/components/productView/productView.js
@@ -42,7 +42,7 @@ import { translate } from '../i18n/i18n';
* @returns {Node}
*/
const ProductView = ({ t, toolbarGraph, toolbarGraphDescription, useRouteDetail: useAliasRouteDetail }) => {
- const { pathParameter: routeProductId, productParameter: routeProductLabel, productConfig } = useAliasRouteDetail();
+ const { productParameter: routeProductLabel, productConfig } = useAliasRouteDetail();
const renderProduct = config => {
const {
@@ -93,6 +93,7 @@ const ProductView = ({ t, toolbarGraph, toolbarGraphDescription, useRouteDetail:
return (
+ {productId !== RHSM_API_PATH_PRODUCT_TYPES.RHOSAK && }
@@ -168,7 +169,6 @@ const ProductView = ({ t, toolbarGraph, toolbarGraphDescription, useRouteDetail:
{t(`curiosity-view.title`, { appName: helpers.UI_DISPLAY_NAME, context: routeProductLabel })}
- {routeProductId !== RHSM_API_PATH_PRODUCT_TYPES.RHOSAK && }
{productConfig.map(config => renderProduct(config))}
);
diff --git a/src/redux/hooks/__tests__/__snapshots__/useRhsmActions.test.js.snap b/src/redux/hooks/__tests__/__snapshots__/useRhsmActions.test.js.snap
deleted file mode 100644
index 9196fe10f..000000000
--- a/src/redux/hooks/__tests__/__snapshots__/useRhsmActions.test.js.snap
+++ /dev/null
@@ -1,7 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`useRhsmActions should return specific properties: specific properties 1`] = `
-Object {
- "useGetMessageReports": [Function],
-}
-`;
diff --git a/src/redux/hooks/__tests__/__snapshots__/useRhsmSelectors.test.js.snap b/src/redux/hooks/__tests__/__snapshots__/useRhsmSelectors.test.js.snap
deleted file mode 100644
index 8cc152148..000000000
--- a/src/redux/hooks/__tests__/__snapshots__/useRhsmSelectors.test.js.snap
+++ /dev/null
@@ -1,16 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`useRhsmSelectors should apply a hook around a selector for useAppMessages: selector 1`] = `
-Object {
- "appMessages": Object {
- "cloudigradeMismatch": true,
- },
- "query": Object {},
-}
-`;
-
-exports[`useRhsmSelectors should return specific properties: specific properties 1`] = `
-Object {
- "useAppMessages": [Function],
-}
-`;
diff --git a/src/redux/hooks/__tests__/useRhsmActions.test.js b/src/redux/hooks/__tests__/useRhsmActions.test.js
deleted file mode 100644
index 95534787d..000000000
--- a/src/redux/hooks/__tests__/useRhsmActions.test.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import moxios from 'moxios';
-import { rhsmActionsHooks, useGetMessageReports } from '../useRhsmActions';
-import { store } from '../../store';
-import { rhsmApiTypes } from '../../../types/rhsmApiTypes';
-
-describe('useRhsmActions', () => {
- beforeEach(() => {
- moxios.install();
-
- moxios.stubRequest(/\/(tally|capacity|hosts|subscriptions|version).*?/, {
- status: 200,
- responseText: 'success',
- timeout: 1,
- response: {
- test: 'success',
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA]: ['success']
- }
- });
- });
-
- afterEach(() => {
- moxios.uninstall();
- });
-
- it('should return specific properties', () => {
- expect(rhsmActionsHooks).toMatchSnapshot('specific properties');
- });
-
- it('should apply a hook and receive a response for useGetMessageReports', async () => {
- await mountHook(() => useGetMessageReports());
- const { report: nullIdReport } = store.getState().messages;
- expect(nullIdReport.fulfilled).toBe(true);
- expect(nullIdReport.metaId).toBe(null);
- expect(nullIdReport.metaQuery).toMatchObject({});
-
- const mockId = 'lorem';
- const mockQuery = { dolor: 'sit' };
- await mountHook(() => useGetMessageReports(mockId, mockQuery));
- const { report: mockIdReport } = store.getState().messages;
- expect(mockIdReport[mockId].fulfilled).toBe(true);
- expect(mockIdReport[mockId].metaId).toBe(mockId);
- expect(mockIdReport[mockId].metaQuery).toMatchObject(mockQuery);
- });
-});
diff --git a/src/redux/hooks/__tests__/useRhsmSelectors.test.js b/src/redux/hooks/__tests__/useRhsmSelectors.test.js
deleted file mode 100644
index cc35cee8b..000000000
--- a/src/redux/hooks/__tests__/useRhsmSelectors.test.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import { rhsmSelectorsHooks, useAppMessages } from '../useRhsmSelectors';
-import { rhsmApiTypes } from '../../../types/rhsmApiTypes';
-
-describe('useRhsmSelectors', () => {
- it('should return specific properties', () => {
- expect(rhsmSelectorsHooks).toMatchSnapshot('specific properties');
- });
-
- it('should apply a hook around a selector for useAppMessages', () => {
- const mockProductId = 'lorem';
- const mockState = {
- messages: {
- report: {
- [mockProductId]: {
- fulfilled: true,
- data: {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA]: [
- {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.DATE]: '2019-09-04T00:00:00.000Z',
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.CORES]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.SOCKETS]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_CORES]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_SOCKETS]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_CORES]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_SOCKETS]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_MISMATCH]: true
- },
- {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.DATE]: '2019-09-05T00:00:00.000Z',
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.CORES]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.SOCKETS]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_CORES]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_SOCKETS]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_CORES]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_SOCKETS]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_MISMATCH]: true
- },
- {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.DATE]: '2019-09-06T00:00:00.000Z',
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.CORES]: 4,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.SOCKETS]: 4,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_CORES]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_SOCKETS]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_CORES]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_SOCKETS]: null,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_MISMATCH]: true
- }
- ]
- }
- }
- }
- }
- };
-
- const { result } = shallowHook(() =>
- useAppMessages({
- useRouteDetail: () => ({ pathParameter: mockProductId, productParameter: 'viewIpsum' }),
- useSelector: value => value(mockState)
- })
- );
-
- expect(result).toMatchSnapshot('selector');
- });
-});
diff --git a/src/redux/hooks/index.js b/src/redux/hooks/index.js
index a2a18a462..9e44f055d 100644
--- a/src/redux/hooks/index.js
+++ b/src/redux/hooks/index.js
@@ -1,11 +1,7 @@
import { reactReduxHooks } from './useReactRedux';
-import { rhsmActionsHooks } from './useRhsmActions';
-import { rhsmSelectorsHooks } from './useRhsmSelectors';
const storeHooks = {
- reactRedux: reactReduxHooks,
- rhsmActions: rhsmActionsHooks,
- rhsmSelectors: rhsmSelectorsHooks
+ reactRedux: reactReduxHooks
};
-export { storeHooks as default, storeHooks, reactReduxHooks, rhsmActionsHooks, rhsmSelectorsHooks };
+export { storeHooks as default, storeHooks, reactReduxHooks };
diff --git a/src/redux/hooks/useRhsmActions.js b/src/redux/hooks/useRhsmActions.js
deleted file mode 100644
index 6ad3cce17..000000000
--- a/src/redux/hooks/useRhsmActions.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import { reactReduxHooks } from './useReactRedux';
-import { rhsmTypes } from '../types/rhsmTypes';
-import { rhsmServices } from '../../services/rhsm/rhsmServices';
-
-/**
- * Get an updated store RHSM response from message reporting.
- *
- * @param {string} id
- * @param {object} query
- * @returns {Function}
- */
-const useGetMessageReports = (id = null, query = {}) =>
- reactReduxHooks.useDispatch()({
- type: rhsmTypes.GET_MESSAGE_REPORTS_RHSM,
- payload: rhsmServices.getGraphReports(id, query, { cancelId: 'messageReport' }),
- meta: {
- id,
- query,
- notifications: {}
- }
- });
-
-const rhsmActionsHooks = {
- useGetMessageReports
-};
-
-export { rhsmActionsHooks as default, rhsmActionsHooks, useGetMessageReports };
diff --git a/src/redux/hooks/useRhsmSelectors.js b/src/redux/hooks/useRhsmSelectors.js
deleted file mode 100644
index 52c9a6d04..000000000
--- a/src/redux/hooks/useRhsmSelectors.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import { useSelector } from 'react-redux';
-import { useRouteDetail } from '../../components/router/routerContext';
-import { reduxSelectors } from '../selectors';
-
-/**
- * Get app messages selector results.
- *
- * @param {object} options
- * @param {Function} options.useRouteDetail
- * @param {Function} options.useSelector
- * @returns {object}
- */
-const useAppMessages = ({
- useRouteDetail: useAliasRouteDetail = useRouteDetail,
- useSelector: useAliasSelector = useSelector
-} = {}) => {
- const { pathParameter: productId, productParameter: viewId } = useAliasRouteDetail() || {};
- const result = useAliasSelector(state => reduxSelectors.appMessages.appMessages(state, { productId, viewId }));
- return {
- ...result
- };
-};
-
-const rhsmSelectorsHooks = {
- useAppMessages
-};
-
-export { rhsmSelectorsHooks as default, rhsmSelectorsHooks, useAppMessages };
diff --git a/src/redux/selectors/__tests__/__snapshots__/appMessagesSelectors.test.js.snap b/src/redux/selectors/__tests__/__snapshots__/appMessagesSelectors.test.js.snap
deleted file mode 100644
index 61481ee1c..000000000
--- a/src/redux/selectors/__tests__/__snapshots__/appMessagesSelectors.test.js.snap
+++ /dev/null
@@ -1,71 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`AppMessagesSelectors should map a fulfilled product ID response to an aggregated output: fulfilled 1`] = `
-Object {
- "appMessages": Object {
- "cloudigradeMismatch": true,
- },
- "query": Object {},
-}
-`;
-
-exports[`AppMessagesSelectors should pass minimal data on a product ID without a product ID provided: no product id error 1`] = `
-Object {
- "appMessages": Object {
- "cloudigradeMismatch": false,
- },
- "query": Object {},
-}
-`;
-
-exports[`AppMessagesSelectors should pass minimal data on missing a reducer response: missing reducer error 1`] = `
-Object {
- "appMessages": Object {
- "cloudigradeMismatch": false,
- },
- "query": Object {},
-}
-`;
-
-exports[`AppMessagesSelectors should populate data from the in memory cache: cached data: cache used and pending 1`] = `
-Object {
- "appMessages": Object {
- "cloudigradeMismatch": true,
- },
- "query": Object {},
-}
-`;
-
-exports[`AppMessagesSelectors should populate data from the in memory cache: cached data: initial fulfilled 1`] = `
-Object {
- "appMessages": Object {
- "cloudigradeMismatch": true,
- },
- "query": Object {},
-}
-`;
-
-exports[`AppMessagesSelectors should populate data from the in memory cache: cached data: update and fulfilled 1`] = `
-Object {
- "appMessages": Object {
- "cloudigradeMismatch": true,
- },
- "query": Object {},
-}
-`;
-
-exports[`AppMessagesSelectors should populate data on a product ID when the api response is missing expected properties: data populated, missing properties 1`] = `
-Object {
- "appMessages": Object {
- "cloudigradeMismatch": false,
- },
- "query": Object {},
-}
-`;
-
-exports[`AppMessagesSelectors should return specific selectors: selectors 1`] = `
-Object {
- "appMessages": [Function],
- "makeAppMessages": [Function],
-}
-`;
diff --git a/src/redux/selectors/__tests__/appMessagesSelectors.test.js b/src/redux/selectors/__tests__/appMessagesSelectors.test.js
deleted file mode 100644
index 43987259c..000000000
--- a/src/redux/selectors/__tests__/appMessagesSelectors.test.js
+++ /dev/null
@@ -1,207 +0,0 @@
-import appMessagesSelectors from '../appMessagesSelectors';
-import { rhsmApiTypes } from '../../../types/rhsmApiTypes';
-
-describe('AppMessagesSelectors', () => {
- it('should return specific selectors', () => {
- expect(appMessagesSelectors).toMatchSnapshot('selectors');
- });
-
- it('should pass minimal data on missing a reducer response', () => {
- const state = {};
- expect(appMessagesSelectors.appMessages(state)).toMatchSnapshot('missing reducer error');
- });
-
- it('should pass minimal data on a product ID without a product ID provided', () => {
- const props = {
- viewId: 'test',
- productId: undefined
- };
- const state = {
- messages: {
- report: {
- fulfilled: true,
- data: { [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA]: [] }
- }
- }
- };
-
- expect(appMessagesSelectors.appMessages(state, props)).toMatchSnapshot('no product id error');
- });
-
- it('should populate data on a product ID when the api response is missing expected properties', () => {
- const props = {
- viewId: 'test',
- productId: 'Lorem Ipsum missing expected properties'
- };
- const state = {
- messages: {
- report: {
- 'Lorem Ipsum missing expected properties': {
- fulfilled: true,
- data: {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA]: [
- {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.DATE]: '2019-09-04T00:00:00.000Z',
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.SOCKETS]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_SOCKETS]: 1
- },
- {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.DATE]: '2019-09-05T00:00:00.000Z',
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.SOCKETS]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_SOCKETS]: 1
- },
- {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.DATE]: '2019-09-06T00:00:00.000Z',
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.SOCKETS]: 4,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_SOCKETS]: 2
- }
- ]
- }
- }
- }
- }
- };
-
- expect(appMessagesSelectors.appMessages(state, props)).toMatchSnapshot('data populated, missing properties');
- });
-
- it('should map a fulfilled product ID response to an aggregated output', () => {
- const props = {
- viewId: 'test',
- productId: 'Lorem Ipsum fulfilled aggregated output'
- };
- const state = {
- messages: {
- report: {
- 'Lorem Ipsum fulfilled aggregated output': {
- fulfilled: true,
- data: {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA]: [
- {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.DATE]: '2019-09-04T00:00:00.000Z',
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.CORES]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.SOCKETS]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_CORES]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_SOCKETS]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_CORES]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_SOCKETS]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_MISMATCH]: true
- },
- {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.DATE]: '2019-09-05T00:00:00.000Z',
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.CORES]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.SOCKETS]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_CORES]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_SOCKETS]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_CORES]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_SOCKETS]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_MISMATCH]: true
- },
- {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.DATE]: '2019-09-06T00:00:00.000Z',
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.CORES]: 4,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.SOCKETS]: 4,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_CORES]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_SOCKETS]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_CORES]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_SOCKETS]: null,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_MISMATCH]: true
- }
- ]
- }
- }
- }
- }
- };
-
- expect(appMessagesSelectors.appMessages(state, props)).toMatchSnapshot('fulfilled');
- });
-
- it('should populate data from the in memory cache', () => {
- const props = {
- viewId: 'cache-test',
- productId: 'Lorem Ipsum ID cached'
- };
- const stateInitialFulfilled = {
- messages: {
- report: {
- 'Lorem Ipsum ID cached': {
- fulfilled: true,
- data: {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA]: [
- {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.DATE]: '2019-09-04T00:00:00.000Z',
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.CORES]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.SOCKETS]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_CORES]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_SOCKETS]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_CORES]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_SOCKETS]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_MISMATCH]: true
- }
- ]
- }
- }
- }
- }
- };
-
- expect(appMessagesSelectors.appMessages(stateInitialFulfilled, props)).toMatchSnapshot(
- 'cached data: initial fulfilled'
- );
-
- const statePending = {
- messages: {
- report: {
- 'Lorem Ipsum ID cached': {
- ...stateInitialFulfilled.messages.report['Lorem Ipsum ID cached'],
- pending: true
- }
- }
- }
- };
-
- expect(appMessagesSelectors.appMessages(statePending, props)).toMatchSnapshot(
- 'cached data: cache used and pending'
- );
-
- const stateFulfilled = {
- messages: {
- report: {
- 'Lorem Ipsum ID cached': {
- ...stateInitialFulfilled.messages.report['Lorem Ipsum ID cached'],
- fulfilled: true,
- data: {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA]: [
- {
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.DATE]: '2018-07-04T00:00:00.000Z',
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.CORES]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.SOCKETS]: 2,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_CORES]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HYPERVISOR_SOCKETS]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_CORES]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.PHYSICAL_SOCKETS]: 1,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_DATA]: true,
- [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_MISMATCH]: false
- }
- ]
- }
- }
- }
- }
- };
-
- expect(appMessagesSelectors.appMessages(stateFulfilled, props)).toMatchSnapshot(
- 'cached data: update and fulfilled'
- );
- });
-});
diff --git a/src/redux/selectors/appMessagesSelectors.js b/src/redux/selectors/appMessagesSelectors.js
deleted file mode 100644
index c556976c3..000000000
--- a/src/redux/selectors/appMessagesSelectors.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import { createSelector } from 'reselect';
-import { rhsmApiTypes } from '../../types';
-
-/**
- * Selector cache.
- *
- * @private
- * @type {{data: {object}}}
- */
-const selectorCache = { data: {} };
-
-/**
- * Return a combined state, props object.
- *
- * @private
- * @param {object} state
- * @param {object} props
- * @returns {object}
- */
-const statePropsFilter = (state, props = {}) => ({
- report: state.messages?.report?.[props.productId],
- viewId: props.viewId,
- productId: props.productId
-});
-
-/**
- * Return a combined query object.
- *
- * @param {object} state
- * @param {object} props
- * @returns {object}
- */
-const queryFilter = (state, props = {}) => ({
- ...props.query,
- ...state.view?.query?.[props.productId],
- ...state.view?.query?.[props.viewId]
-});
-
-/**
- * Create selector, transform combined state, props into a consumable object.
- *
- * @type {{appMessages: {cloudigradeMismatch: boolean}}}
- */
-const selector = createSelector([statePropsFilter, queryFilter], (data, query = {}) => {
- const { viewId = null, productId = null, report = {} } = data || {};
- const appMessages = {
- cloudigradeMismatch: false
- };
-
- const cache = (viewId && productId && selectorCache.data[`${viewId}_${productId}`]) || undefined;
-
- Object.assign(appMessages, { ...cache });
-
- // Scan Tally response for Cloud Meter flags
- if (report.fulfilled && appMessages.cloudigradeMismatch !== true) {
- const { [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA]: reportData = [] } = report.data || {};
-
- const cloudigradeMismatch = reportData
- .reverse()
- .find(
- ({ [rhsmApiTypes.RHSM_API_RESPONSE_PRODUCTS_DATA_TYPES.HAS_CLOUDIGRADE_MISMATCH]: mismatch }) =>
- mismatch === true
- );
-
- appMessages.cloudigradeMismatch = cloudigradeMismatch !== undefined;
-
- selectorCache.data[`${viewId}_${productId}`] = {
- ...appMessages
- };
- }
-
- return { appMessages, query };
-});
-
-/**
- * Expose selector instance. For scenarios where a selector is reused across component instances.
- *
- * @param {object} defaultProps
- * @returns {{appMessages: {cloudigradeMismatch: boolean}}}
- */
-const makeSelector = defaultProps => (state, props) => ({
- ...selector(state, props, defaultProps)
-});
-
-const appMessagesSelectors = {
- appMessages: selector,
- makeAppMessages: makeSelector
-};
-
-export { appMessagesSelectors as default, appMessagesSelectors, selector, makeSelector };
diff --git a/src/redux/selectors/index.js b/src/redux/selectors/index.js
index 53a620d95..debc19620 100644
--- a/src/redux/selectors/index.js
+++ b/src/redux/selectors/index.js
@@ -1,11 +1,9 @@
-import appMessagesSelectors from './appMessagesSelectors';
import guestsListSelectors from './guestsListSelectors';
import graphCardSelectors from './graphCardSelectors';
import inventoryListSelectors from './inventoryListSelectors';
import userSelectors from './userSelectors';
const reduxSelectors = {
- appMessages: appMessagesSelectors,
guestsList: guestsListSelectors,
graphCard: graphCardSelectors,
inventoryList: inventoryListSelectors,
diff --git a/src/services/rhsm/__tests__/__snapshots__/rhsmTransformers.test.js.snap b/src/services/rhsm/__tests__/__snapshots__/rhsmTransformers.test.js.snap
index 2be437bc2..520055d4c 100644
--- a/src/services/rhsm/__tests__/__snapshots__/rhsmTransformers.test.js.snap
+++ b/src/services/rhsm/__tests__/__snapshots__/rhsmTransformers.test.js.snap
@@ -4,6 +4,7 @@ exports[`RHSM Transformers should attempt to parse a tally response: tally 1`] =
Object {
"data": Array [],
"meta": Object {
+ "cloudigradeHasMismatch": undefined,
"count": undefined,
"metricId": undefined,
"productId": undefined,
diff --git a/src/services/rhsm/rhsmTransformers.js b/src/services/rhsm/rhsmTransformers.js
index d703c41c7..a4658a177 100644
--- a/src/services/rhsm/rhsmTransformers.js
+++ b/src/services/rhsm/rhsmTransformers.js
@@ -79,6 +79,7 @@ const rhsmTally = response => {
updatedResponse.meta = {
count: meta[TALLY_META_TYPES.COUNT],
+ cloudigradeHasMismatch: meta[TALLY_META_TYPES.HAS_CLOUDIGRADE_MISMATCH],
metricId: meta[TALLY_META_TYPES.METRIC_ID],
productId: meta[TALLY_META_TYPES.PRODUCT],
totalMonthlyDate: meta[TALLY_META_TYPES.TOTAL_MONTHLY]?.[TALLY_META_TYPES.DATE],
diff --git a/tests/__snapshots__/dist.test.js.snap b/tests/__snapshots__/dist.test.js.snap
index 0c4673cfc..21c216b4e 100644
--- a/tests/__snapshots__/dist.test.js.snap
+++ b/tests/__snapshots__/dist.test.js.snap
@@ -25,6 +25,7 @@ Array [
"./dist/js/1355*js",
"./dist/js/136*js",
"./dist/js/1799*js",
+ "./dist/js/1824*js",
"./dist/js/1858*js",
"./dist/js/190*js",
"./dist/js/2130*js",
@@ -110,6 +111,7 @@ Array [
"./dist/sourcemaps/1355*map",
"./dist/sourcemaps/136*map",
"./dist/sourcemaps/1799*map",
+ "./dist/sourcemaps/1824*map",
"./dist/sourcemaps/1858*map",
"./dist/sourcemaps/190*map",
"./dist/sourcemaps/2130*map",