Skip to content

Commit

Permalink
fix(inventoryListSelectors): issues/10 itemCount, deep equals (#372)
Browse files Browse the repository at this point in the history
* inventoryListSelectors, itemCount, deep equals adjustment
* rhsmApiTypes, added inventory_id
* reduxHelpers add setNormalizedResponse
* rhsmServices mock update
  • Loading branch information
cdcabrera committed Sep 29, 2020
1 parent 88e1140 commit bfed7e8
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 43 deletions.
52 changes: 52 additions & 0 deletions src/redux/common/__tests__/__snapshots__/reduxHelpers.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,57 @@ Object {
}
`;

exports[`ReduxHelpers should generate a normalized API response using a schema: array response 1`] = `
Array [
Array [
Object {
"ipsum": 1,
"sit": undefined,
},
Object {
"ipsum": undefined,
"sit": "hello world",
},
],
]
`;

exports[`ReduxHelpers should generate a normalized API response using a schema: object response 1`] = `
Array [
Array [
Object {
"ipsum": 1,
"sit": undefined,
},
],
]
`;

exports[`ReduxHelpers should generate a normalized API response using a schema: parameters 1`] = `
Array [
Array [
Object {
"ipsum": 1,
"sit": undefined,
},
Object {
"ipsum": undefined,
"sit": "hello world",
},
],
Array [
Object {
"ipsum": "custom value = 1",
"sit": "custom value = undefined",
},
Object {
"ipsum": "custom value = undefined",
"sit": "custom value = hello world",
},
],
]
`;

exports[`ReduxHelpers should generate an expected API response with an existing schema: array 1`] = `
Array [
Object {
Expand Down Expand Up @@ -210,6 +261,7 @@ Object {
"getMessageFromResults": [Function],
"getSingleResponseFromResultArray": [Function],
"getStatusFromResults": [Function],
"setNormalizedResponse": [Function],
"setResponseSchemas": [Function],
"setStateProp": [Function],
"singlePromiseDataResponseFromArray": [Function],
Expand Down
33 changes: 33 additions & 0 deletions src/redux/common/__tests__/reduxHelpers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,39 @@ describe('ReduxHelpers', () => {
).toMatchSnapshot('array');
});

it('should generate a normalized API response using a schema', () => {
const setNormalizedResponseParams = {
schema: {
LOREM: 'ipsum',
DOLOR: 'sit'
},
data: [
{
ipsum: 1
},
{ sit: 'hello world' }
]
};

expect(
reduxHelpers.setNormalizedResponse(setNormalizedResponseParams, {
...setNormalizedResponseParams,
customResponseValue: ({ value }) => `custom value = ${value}`
})
).toMatchSnapshot('parameters');

expect(reduxHelpers.setNormalizedResponse(setNormalizedResponseParams)).toMatchSnapshot('array response');

expect(
reduxHelpers.setNormalizedResponse({
...setNormalizedResponseParams,
data: {
ipsum: 1
}
})
).toMatchSnapshot('object response');
});

it('should get a message from a service call response', () => {
expect(
reduxHelpers.getMessageFromResults({
Expand Down
63 changes: 61 additions & 2 deletions src/redux/common/reduxHelpers.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import _get from 'lodash/get';
import _isPlainObject from 'lodash/isPlainObject';
import _camelCase from 'lodash/camelCase';
import { helpers } from '../../common';

/**
Expand Down Expand Up @@ -34,6 +35,7 @@ const REJECTED_ACTION = (base = '') => `${base}_REJECTED`;
*/
const HTTP_STATUS_RANGE = status => `${status}_STATUS_RANGE`;

// ToDo: research applying a maintained schema map/normalizer such as, normalizr
/**
* Apply a set of schemas using either an array of objects in the
* form of [{ madeUpKey: 'some_api_key' }], or an array of arrays
Expand All @@ -55,6 +57,62 @@ const setResponseSchemas = (schemas = [], initialValue) =>
return generated;
});

/**
* Normalize an API response.
*
* @param {*} responses
* @param {object} responses.response
* @param {object} responses.response.schema
* @param {Array|object} responses.response.data
* @param {Function} responses.response.customResponseValue
* @param {string} responses.response.keyPrefix
* @returns {Array}
*/
const setNormalizedResponse = (...responses) => {
const parsedResponses = [];

responses.forEach(({ schema = {}, data, customResponseValue, keyPrefix: prefix }) => {
const isArray = Array.isArray(data);
const updatedData = (isArray && data) || (data && [data]) || [];
const [generatedSchema = {}] = setResponseSchemas([schema]);
const parsedResponse = [];

updatedData.forEach((value, index) => {
const generateReflectedData = ({ dataObj, keyPrefix = '', customValue = null, update = helpers.noop }) => {
const updatedDataObj = {};

Object.entries(dataObj).forEach(([dataObjKey, dataObjValue]) => {
const casedDataObjKey = _camelCase(`${keyPrefix} ${dataObjKey}`).trim();
let val = dataObjValue;

if (typeof val === 'number') {
val = (Number.isInteger(val) && Number.parseInt(val, 10)) || Number.parseFloat(val) || val;
}

if (typeof customValue === 'function') {
updatedDataObj[casedDataObjKey] = customValue({ data: dataObj, key: dataObjKey, value: val, index });
} else {
updatedDataObj[casedDataObjKey] = val;
}
});

update(updatedDataObj);
};

generateReflectedData({
keyPrefix: prefix,
dataObj: { ...generatedSchema, ...value },
customValue: customResponseValue,
update: generatedData => parsedResponse.push(generatedData)
});
});

parsedResponses.push(parsedResponse);
});

return parsedResponses;
};

/**
* Create a single response from an array of service call responses.
* Aids in handling a Promise.all response.
Expand Down Expand Up @@ -163,11 +221,11 @@ const setStateProp = (prop, data, options) => {
const { state = {}, initialState = {}, reset = true } = options;
let obj = { ...state };

if (process.env.REACT_APP_ENV === 'development' && prop && !state[prop]) {
if (helpers.DEV_MODE && prop && !state[prop]) {
console.error(`Error: Property ${prop} does not exist within the passed state.`, state);
}

if (process.env.REACT_APP_ENV === 'development' && reset && prop && !initialState[prop]) {
if (helpers.DEV_MODE && reset && prop && !initialState[prop]) {
console.warn(`Warning: Property ${prop} does not exist within the passed initialState.`, initialState);
}

Expand Down Expand Up @@ -335,6 +393,7 @@ const reduxHelpers = {
REJECTED_ACTION,
HTTP_STATUS_RANGE,
setResponseSchemas,
setNormalizedResponse,
generatedPromiseActionReducer,
getDataFromResults,
getDateFromResults,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ exports[`InventoryListSelectors should handle pending state on a product ID: pen
Object {
"error": false,
"fulfilled": false,
"itemCount": 0,
"listData": Array [],
"pending": true,
"status": undefined,
Expand All @@ -14,12 +15,14 @@ exports[`InventoryListSelectors should map a fulfilled product ID response to an
Object {
"error": false,
"fulfilled": true,
"itemCount": 0,
"listData": Array [
Object {
"cores": 2,
"displayName": "db.lorem.com",
"hardwareType": "physical",
"insightsId": "d6214a0b-b344-4778-831c-d53dcacb2da3",
"inventoryId": null,
"lastSeen": "17 days ago",
"numberOfGuests": null,
"sockets": 1,
Expand All @@ -30,6 +33,7 @@ Object {
"displayName": "db.ipsum.com",
"hardwareType": "physical",
"insightsId": "9358e312-1c9f-42f4-8910-dcef6e970852",
"inventoryId": null,
"lastSeen": "in a month",
"numberOfGuests": null,
"sockets": 1,
Expand All @@ -45,6 +49,7 @@ exports[`InventoryListSelectors should pass minimal data on a product ID without
Object {
"error": false,
"fulfilled": false,
"itemCount": 0,
"listData": Array [],
"pending": false,
"status": undefined,
Expand All @@ -55,6 +60,7 @@ exports[`InventoryListSelectors should pass minimal data on missing a reducer re
Object {
"error": false,
"fulfilled": false,
"itemCount": 0,
"listData": Array [],
"pending": false,
"status": undefined,
Expand All @@ -65,12 +71,14 @@ exports[`InventoryListSelectors should populate data from the in memory cache: c
Object {
"error": false,
"fulfilled": true,
"itemCount": 0,
"listData": Array [
Object {
"cores": 2,
"displayName": "db.ipsum.com",
"hardwareType": "physical",
"insightsId": "9358e312-1c9f-42f4-8910-dcef6e970852",
"inventoryId": null,
"lastSeen": "in a month",
"numberOfGuests": null,
"sockets": 1,
Expand All @@ -86,12 +94,14 @@ exports[`InventoryListSelectors should populate data from the in memory cache: c
Object {
"error": false,
"fulfilled": true,
"itemCount": 0,
"listData": Array [
Object {
"cores": 2,
"displayName": "db.lorem.com",
"hardwareType": "physical",
"insightsId": "d6214a0b-b344-4778-831c-d53dcacb2da3",
"inventoryId": null,
"lastSeen": "17 days ago",
"numberOfGuests": null,
"sockets": 1,
Expand All @@ -107,12 +117,14 @@ exports[`InventoryListSelectors should populate data from the in memory cache: c
Object {
"error": false,
"fulfilled": true,
"itemCount": 0,
"listData": Array [
Object {
"cores": 2,
"displayName": "db.lorem.com",
"hardwareType": "physical",
"insightsId": "d6214a0b-b344-4778-831c-d53dcacb2da3",
"inventoryId": null,
"lastSeen": "17 days ago",
"numberOfGuests": null,
"sockets": 1,
Expand All @@ -128,12 +140,14 @@ exports[`InventoryListSelectors should populate data from the in memory cache: c
Object {
"error": false,
"fulfilled": true,
"itemCount": 0,
"listData": Array [
Object {
"cores": 2,
"displayName": "db.ipsum.com",
"hardwareType": "physical",
"insightsId": "9358e312-1c9f-42f4-8910-dcef6e970852",
"inventoryId": null,
"lastSeen": "in a month",
"numberOfGuests": null,
"sockets": 1,
Expand All @@ -149,12 +163,14 @@ exports[`InventoryListSelectors should populate data on a product ID when the ap
Object {
"error": false,
"fulfilled": true,
"itemCount": 0,
"listData": Array [
Object {
"cores": 2,
"displayName": null,
"hardwareType": null,
"insightsId": "d6214a0b-b344-4778-831c-d53dcacb2da3",
"inventoryId": null,
"lastSeen": "in a year",
"numberOfGuests": null,
"sockets": 1,
Expand All @@ -165,6 +181,7 @@ Object {
"displayName": "db.example.com",
"hardwareType": "physical",
"insightsId": "9358e312-1c9f-42f4-8910-dcef6e970852",
"inventoryId": null,
"lastSeen": "in a month",
"numberOfGuests": null,
"sockets": null,
Expand Down
8 changes: 4 additions & 4 deletions src/redux/selectors/__tests__/inventoryListSelectors.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('InventoryListSelectors', () => {
const props = {
viewId: 'test',
productId: undefined,
listQuery: {}
query: {}
};
const state = {
inventory: {
Expand Down Expand Up @@ -56,7 +56,7 @@ describe('InventoryListSelectors', () => {
const props = {
viewId: 'test',
productId: 'Lorem Ipsum missing expected properties',
listQuery: {
query: {
[rhsmApiTypes.RHSM_API_QUERY_SLA_TYPES]: rhsmApiTypes.RHSM_API_QUERY_SLA_TYPES.PREMIUM
}
};
Expand Down Expand Up @@ -96,7 +96,7 @@ describe('InventoryListSelectors', () => {
const props = {
viewId: 'test',
productId: 'Lorem Ipsum fulfilled aggregated output',
listQuery: {
query: {
[rhsmApiTypes.RHSM_API_QUERY_SLA_TYPES]: rhsmApiTypes.RHSM_API_QUERY_SLA_TYPES.PREMIUM
}
};
Expand Down Expand Up @@ -141,7 +141,7 @@ describe('InventoryListSelectors', () => {
const props = {
viewId: 'cache-test',
productId: 'Lorem Ipsum ID cached',
listQuery: {
query: {
[rhsmApiTypes.RHSM_API_QUERY_SLA_TYPES]: rhsmApiTypes.RHSM_API_QUERY_SLA_TYPES.PREMIUM
}
};
Expand Down
Loading

0 comments on commit bfed7e8

Please sign in to comment.