Merge pull request #479 from Safelite/defect/digital/ssr-763
Fixed test, added documentation to store...
This commit is contained in:
commit
549f92af09
10 changed files with 1842 additions and 1160 deletions
|
|
@ -12,7 +12,8 @@
|
|||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"test:unit": "vue-cli-service test:unit --coverage --ci",
|
||||
"test:unit:lite": "vue-cli-service test:unit --ci"
|
||||
"test:unit:lite": "vue-cli-service test:unit --ci",
|
||||
"test:pc": "vue-cli-service test:unit site-footer.spec.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.4.0",
|
||||
|
|
|
|||
|
|
@ -7,6 +7,15 @@
|
|||
</router-view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// eslint-disable-next-line no-extend-native
|
||||
Array.prototype.safeFilter = (propertyName) => {
|
||||
if (!propertyName) return this;
|
||||
if (!this?.length) return [];
|
||||
return this.map((x) => x[propertyName])
|
||||
.filter((x) => x);
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "./node_modules/bootstrap/scss/bootstrap";
|
||||
@import "@/styles/common-styles.scss";
|
||||
|
|
|
|||
|
|
@ -462,13 +462,16 @@ export default {
|
|||
if (direction === 'future') {
|
||||
// first 0, then 1
|
||||
for (let i = 0; i <= monthsAfterToLoadOffset; i++) {
|
||||
months.push(await this.getMonthData(i, options));
|
||||
months.push(this.getMonthData(i, options));
|
||||
}
|
||||
// See https://eslint.org/docs/latest/rules/no-await-in-loop
|
||||
Promise.all(months);
|
||||
} else if (direction === 'past') {
|
||||
// first 0, then -1
|
||||
for (let i = 0; i >= 0 - monthsBeforeToLoadOffset; i--) {
|
||||
months.unshift(await this.getMonthData(i, options));
|
||||
months.unshift(this.getMonthData(i, options));
|
||||
}
|
||||
Promise.all(months);
|
||||
} else {
|
||||
// TODO - IF A CALENDAR WITH BOTH PAST AND FUTURE WAS EVER NEEDED
|
||||
// for (let i = monthsAfterToLoadOffset; i >= monthsBeforeToLoadOffset; i--) {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
:text="getRouterLinkDisplayTextFromCopy(copy)"
|
||||
href="javascript:void(0)"
|
||||
useLoadingModal
|
||||
@click-event="navigateWithScenario(getRouterLinkRouteFromCopy(copy))" />
|
||||
@clickEvent="navigateWithScenario(getRouterLinkRouteFromCopy(copy))" />
|
||||
</span>
|
||||
<span v-else-if="doesCopyContainTextLink(copy)">
|
||||
<textLink
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
:text="getRouterLinkDisplayTextFromCopy(copy)"
|
||||
:href="getExternalLink(copy)"
|
||||
:data-bs-target="'#' + getRouterLinkRouteFromCopy(copy)"
|
||||
@click-event="$emit('textLinkClicked', getRouterLinkRouteFromCopy(copy))" />
|
||||
@clickEvent="$emit('textLinkClicked', getRouterLinkRouteFromCopy(copy))" />
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
|
|
@ -57,6 +57,7 @@ export default {
|
|||
cmsWidgetName: String,
|
||||
marginTopSizeOverride: Number // override mt-2 with a bootstrap size from 0-5 or auto
|
||||
},
|
||||
emits: ['textLinkClicked'],
|
||||
computed: {
|
||||
pageQueryString() {
|
||||
return applicationConfig.PAGE_QUERYSTRING;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export function getDamageString() {
|
|||
const { isRepair } = mainStore.damage;
|
||||
const damageLocations = mainStore.damage.glassToReplace;
|
||||
|
||||
if (isRepair || !damageLocations || !Array.isArray(damageLocations)) {
|
||||
if (isRepair || !damageLocations?.length) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
import { useMainStore } from '@/store';
|
||||
import { updateOrCreateISSCookie } from '@/helpers/cookie-helper';
|
||||
|
||||
/*
|
||||
Encapsulates asynchronous Save Session logic inside a promise to allow for Save Session queuing
|
||||
*/
|
||||
async function saveSessionHelper(store) {
|
||||
const savedSessionInfo = await store.saveSession();
|
||||
store.setSaveSessionInfo(savedSessionInfo.data);
|
||||
updateOrCreateISSCookie();
|
||||
}
|
||||
|
||||
/*
|
||||
Will call API to save existing order, or create new one depending where it's called from.
|
||||
This will also set Referral information in the store after saving, and then
|
||||
|
|
@ -8,8 +17,8 @@ import { updateOrCreateISSCookie } from '@/helpers/cookie-helper';
|
|||
*/
|
||||
export async function saveSession({ shouldAwaitSaveSessionQueue = false }) {
|
||||
const store = useMainStore();
|
||||
var saveSessionPromise = store.applicationUser.saveSessionPromise
|
||||
? store.applicationUser.saveSessionPromise.then(() => { return saveSessionHelper(store); })
|
||||
const saveSessionPromise = store.applicationUser.saveSessionPromise
|
||||
? store.applicationUser.saveSessionPromise.then(() => saveSessionHelper(store))
|
||||
: saveSessionHelper(store);
|
||||
|
||||
store.setSaveSessionPromise(saveSessionPromise);
|
||||
|
|
@ -18,12 +27,3 @@ export async function saveSession({ shouldAwaitSaveSessionQueue = false }) {
|
|||
await saveSessionPromise;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Encapsulates asynchronous Save Session logic inside a promise to allow for Save Session queuing
|
||||
*/
|
||||
async function saveSessionHelper(store) {
|
||||
const savedSessionInfo = await store.saveSession();
|
||||
store.setSaveSessionInfo(savedSessionInfo.data);
|
||||
updateOrCreateISSCookie();
|
||||
}
|
||||
|
|
@ -10,26 +10,24 @@ const mockMixin = {
|
|||
};
|
||||
|
||||
describe('site-footer.vue', () => {
|
||||
// TODO: fix this so that it works correctly (toHaveBeenCalled() <-- )
|
||||
it.skip('Should emit ForwardClicked on button click', async () => {
|
||||
it('Should emit ForwardClicked on button click', async () => {
|
||||
// Act
|
||||
const wrapper = mount(siteFooter, {
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
wrapper.vm.buttonClick();
|
||||
// Assert
|
||||
expect(wrapper.emitted().forwardClicked[0]).toHaveBeenCalled;
|
||||
expect(wrapper.emitted().forwardClicked).toBeTruthy(); // This is how to verify emitted custom events.
|
||||
});
|
||||
|
||||
// TODO: fix this so that it works correctly (toHaveBeenCalled() <--
|
||||
it.skip('Should emit BackClicked on link click', async () => {
|
||||
it('Should emit BackClicked on link click', async () => {
|
||||
// Act
|
||||
const wrapper = mount(siteFooter, {
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
wrapper.vm.linkClick();
|
||||
// Assert
|
||||
expect(wrapper.emitted().backClicked[0]).toHaveBeenCalled;
|
||||
expect(wrapper.emitted().backClicked).toBeTruthy(); // This is how to verify emitted custom events.
|
||||
});
|
||||
|
||||
it('Should change button text when update button text is called', async () => {
|
||||
|
|
|
|||
385
src/store/data-processors.js
Normal file
385
src/store/data-processors.js
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
/* eslint-disable no-plusplus */
|
||||
/* eslint-disable no-param-reassign */
|
||||
import getDateDifferenceInDays from '@/helpers/date-helper';
|
||||
|
||||
if (!Array.prototype.safeFilter) {
|
||||
// eslint-disable-next-line no-extend-native
|
||||
Array.prototype.safeFilter = (propertyName) => {
|
||||
if (!propertyName) return this;
|
||||
if (!this?.length) return [];
|
||||
return this.map((x) => x[propertyName])
|
||||
.filter((x) => x);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @function addPricesToLineItems
|
||||
* @memberof StoreProcessors
|
||||
* @author T-Wrecks Team
|
||||
* @copyright Safelite
|
||||
* @summary
|
||||
* Accepts an array of items and an array of corresponding prices, then
|
||||
* adds the price data to the line items by collating on partNumber.
|
||||
* The added properties are "**laborAmount**", "**sellingPrice**" and "**kitPrice**".
|
||||
* @remarks
|
||||
* This will almost certainly change when Insurance Pricing is live.
|
||||
* @param {Array} lineItems
|
||||
* An array filled with order items (windshield, wipers, raindefense, etc.)
|
||||
* @param {Array} pricingLineItems
|
||||
* An array filled with prices for repair items.
|
||||
* @returns {Array}
|
||||
* The line items array with price data added.
|
||||
* @static
|
||||
*/
|
||||
const addPricesToLineItems = (lineItems, pricingLineItems) => {
|
||||
if (!lineItems) throw new Error('Invalid line items specified.');
|
||||
if (!pricingLineItems) throw new Error('Invalid pricing line items specified.');
|
||||
lineItems.forEach((lineItem) => {
|
||||
const lineItemIndex = pricingLineItems
|
||||
.findIndex((pricingLineItem) => pricingLineItem.partNumber === lineItem.partNumber);
|
||||
|
||||
if (lineItem.childParts) {
|
||||
addPricesToLineItems(lineItem.childParts, pricingLineItems);
|
||||
}
|
||||
|
||||
if (lineItemIndex > -1) {
|
||||
const pricedLineItem = pricingLineItems[lineItemIndex];
|
||||
lineItem.laborAmount = pricedLineItem.laborAmount;
|
||||
lineItem.sellingPrice = pricedLineItem.sellingPrice;
|
||||
lineItem.kitPrice = pricedLineItem.kitPrice;
|
||||
}
|
||||
});
|
||||
return lineItems;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function buildQueryStringParameterFromArrayOfComplexObjects
|
||||
* @memberof StoreProcessors
|
||||
* @author T-Wrecks Team
|
||||
* @copyright Safelite
|
||||
* @summary
|
||||
* Accepts an array of objects and the name of a parameter present on these objects.
|
||||
* Extracts the value of these properties so as to create a query string snippet containing
|
||||
* this data in the format "propertyName[index].[key]=[value]&..."
|
||||
* @param {Array} arrayOfObjects
|
||||
* Array of items containing data to transform into a query string snippet.
|
||||
* @param {string} parameterName
|
||||
* The name of the parameter used to extract data from the "arrayOfObjects".
|
||||
* @returns {string}
|
||||
* A string containing the query string snippet.
|
||||
* @static
|
||||
*/
|
||||
const buildQueryStringParameterFromArrayOfComplexObjects = (arrayOfObjects, parameterName) => {
|
||||
if (!arrayOfObjects) throw new Error('Invalid array of objects specified.');
|
||||
if (!parameterName) throw new Error('Invalid parameter name specified.');
|
||||
let queryStringParameter = '';
|
||||
for (let i = 0; i < arrayOfObjects.length; i++) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const [key, value] of Object.entries(arrayOfObjects[i])) {
|
||||
queryStringParameter += `${parameterName}[${i}].${key}=${value}&`;
|
||||
}
|
||||
}
|
||||
// Remove trailing &
|
||||
return queryStringParameter.slice(0, -1);
|
||||
};
|
||||
|
||||
/**
|
||||
* @function convertGlassPieceNamingFromApi
|
||||
* @memberof StoreProcessors
|
||||
* @author T-Wrecks Team
|
||||
* @copyright Safelite
|
||||
* @summary
|
||||
* Accepts an array with glass data properties.
|
||||
* Array is modified such that "glassPiece", "location" and "name" properties are removed (if present) and
|
||||
* location/name data is moved to properties "**glassLocation**" and "**glassName**".
|
||||
* @remarks
|
||||
* This is one of a few functions that deal with glassLocation data.
|
||||
* Modified to be a bit more fault tolerant/flexible.
|
||||
* Essentially the reverse of convertGlassPieceToBackEndCompatibleFormat.
|
||||
* Could potentially refactor all such to be more DRY.
|
||||
* @param {Array} glassArray
|
||||
* An array of glass parts with location and name defined.
|
||||
* @returns {Array}
|
||||
* A modified glass array with data defined on **glassLocation** and **glassName** properties.
|
||||
* @static
|
||||
*/
|
||||
const convertGlassPieceNamingFromApi = (glassArray) => {
|
||||
if (!glassArray) return [];
|
||||
return glassArray.map((glass) => {
|
||||
glass.glassLocation = glass.glassPiece?.location ?? glass.location ?? glass.glassLocation;
|
||||
glass.glassName = glass.glassPiece?.name ?? glass.name ?? glass.glassName;
|
||||
delete glass.glassPiece;
|
||||
delete glass.location;
|
||||
delete glass.name;
|
||||
return glass;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @function convertGlassPieceToBackEndCompatibleFormat
|
||||
* @memberof StoreProcessors
|
||||
* @author T-Wrecks Team
|
||||
* @copyright Safelite
|
||||
* @summary
|
||||
* Accepts an array with glass data properties.
|
||||
* Array is modified such that glassLocation/glassName data is moved to properties "**location**" and "**name**".
|
||||
* @remarks
|
||||
* This is one of a few functions that deal with glassLocation data.
|
||||
* Could potentially be combined with very similar convertResultsForApi
|
||||
* @param {Array} glassPieces
|
||||
* An array of glass parts with glassLocation and glassName defined.
|
||||
* @returns {Array}
|
||||
* A modified glass array with data defined on **location** and **name** properties.
|
||||
* @static
|
||||
*/
|
||||
// There was no meaningful difference between the below and convertGlassPieceNamingForApi
|
||||
const convertGlassPieceToBackEndCompatibleFormat = (glassPieces) => {
|
||||
if (!glassPieces?.length) return [];
|
||||
|
||||
// check if array already converted. (likely when a session has been saved previously and then reloaded)
|
||||
if (glassPieces[0].location !== undefined) {
|
||||
return glassPieces;
|
||||
}
|
||||
|
||||
return glassPieces.map((glassPiece) => ({
|
||||
location: glassPiece.glassLocation,
|
||||
name: glassPiece.glassName
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
* @function convertResultsForApi
|
||||
* @memberof StoreProcessors
|
||||
* @author T-Wrecks Team
|
||||
* @copyright Safelite
|
||||
* @summary
|
||||
* Accepts a source array and maps to an API friendly format.
|
||||
* Array with "**glassLocation**" is mapped to "**location**", "**glassName**" is mapped to
|
||||
* "**name**", and property "result" is simply copied if present.
|
||||
* @remarks
|
||||
* This is one of a few functions that deal with glassLocation data.
|
||||
* This one also copies result data if present.
|
||||
* Could potentially be refactored with others to be more DRY
|
||||
* @param {Array} resultsArray
|
||||
* Array with glassLocation and glassName properties (often result as well).
|
||||
* @returns {Array}
|
||||
* Array that only has **location**, **name** and **result** properties
|
||||
* @static
|
||||
*/
|
||||
const convertResultsForApi = (resultsArray) => {
|
||||
if (!resultsArray) return [];
|
||||
// check if array already converted.
|
||||
// (likely when a session has been saved previously and then reloaded)
|
||||
if (resultsArray[0].location !== undefined) {
|
||||
return resultsArray;
|
||||
}
|
||||
|
||||
return resultsArray.map((answer) => ({
|
||||
location: answer.glassLocation,
|
||||
name: answer.glassName,
|
||||
result: answer.result
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
* @function getFlattenedArrayOfLineItemsWithChildParts
|
||||
* @memberof StoreProcessors
|
||||
* @author T-Wrecks Team
|
||||
* @copyright Safelite
|
||||
* @summary
|
||||
* Accepts a source array of line item data.
|
||||
* Flattens array in regard to childPart line items.
|
||||
* @param {Array} lineItems
|
||||
* Array with line items and potentially childParts to be flattened.
|
||||
* @returns {Array}
|
||||
* Flattened line item array.
|
||||
* @static
|
||||
*/
|
||||
const getFlattenedArrayOfLineItemsWithChildParts = (lineItems) => {
|
||||
let flattenedArray = [];
|
||||
lineItems?.forEach((lineItem) => {
|
||||
flattenedArray.push(lineItem);
|
||||
if (lineItem.childParts) {
|
||||
flattenedArray = [
|
||||
...flattenedArray,
|
||||
...getFlattenedArrayOfLineItemsWithChildParts(lineItem.childParts)
|
||||
];
|
||||
}
|
||||
});
|
||||
return flattenedArray;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function getHasRecalibrationPart
|
||||
* @memberof StoreProcessors
|
||||
* @author T-Wrecks Team
|
||||
* @copyright Safelite
|
||||
* @summary
|
||||
* Examines the store.order.lineItems state for a requiresRecalibration portion.
|
||||
* If present, examines the state -> order -> lineItems -> glassParts state for a
|
||||
* **recalibrationType** section.
|
||||
* If present, checks that the first element is defined.
|
||||
* @param {object} state
|
||||
* The store state having a valid store -> order -> lineItems section.
|
||||
* @returns {boolean}
|
||||
* True if recalibration part is present in state, false otherwise.
|
||||
* @static
|
||||
*/
|
||||
const getHasRecalibrationPart = (state) => {
|
||||
// eslint-disable-next-line max-len
|
||||
const hasRequiresRecalibration = state.order.lineItems.glassParts.safeFilter('requiresRecalibration')?.length > 0;
|
||||
// eslint-disable-next-line max-len
|
||||
const hasRecalibrationType = state.order.lineItems.glassParts.safeFilter('recalibrationType')?.length > 0;
|
||||
|
||||
if (hasRequiresRecalibration) {
|
||||
if (hasRecalibrationType) {
|
||||
// Has both 'requiresRecalibration' and 'recalibrationType' and 'recalibrationType'
|
||||
return (
|
||||
state.order.lineItems.glassParts.safeFilter('recalibrationType')[0].toLowerCase() !== 'unknown'
|
||||
);
|
||||
}
|
||||
// Has 'requiresRecalibration' but no 'recalibrationType' at all
|
||||
return true;
|
||||
}
|
||||
// Does not have 'requiresRecalibration'
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function getLineItemQueryStringForPricing
|
||||
* @memberof StoreProcessors
|
||||
* @summary
|
||||
* Accepts an array of line items with "partNumber" properties and converts this
|
||||
* information to a query string snippet acceptable to the pricing endpoint.
|
||||
* Currently the endpoint requires the inclusion of an index.
|
||||
* However it appears that the actual index number is irrelevant.
|
||||
* @remarks
|
||||
* Please note that if the index number became relevant this method
|
||||
* would have a BUG in that it potentially calls itself recursively without
|
||||
* passing the current index. Thus child parts restart the index.
|
||||
* However, this isn't a huge concern as Insurance Pricing won't be using this
|
||||
* and it will go away completely.
|
||||
* @param {Array} lineItems
|
||||
* An array of line items to be priced.
|
||||
* @returns {string}
|
||||
* A query string text snippet containing part number data to be priced.
|
||||
* @static
|
||||
*/
|
||||
const getLineItemQueryStringForPricing = (lineItems) => lineItems
|
||||
.map((lineItem, index) => {
|
||||
let queryStringSnippet = `&LineItems[${index}].partNumber=${lineItem.partNumber}`;
|
||||
if (lineItem.childParts) {
|
||||
queryStringSnippet += getLineItemQueryStringForPricing(lineItem.childParts);
|
||||
}
|
||||
return queryStringSnippet;
|
||||
})
|
||||
.join('');
|
||||
|
||||
/**
|
||||
* @function getTimeSlotsAdditionalEventData
|
||||
* @memberof StoreProcessors
|
||||
* @summary
|
||||
* Converts provided parameters into comma delimited key/value pairs specifying data with state magic number keys.
|
||||
* @param {Array} provisionalTriggers
|
||||
* Array that is converted to comma delimited data point.
|
||||
* @param {string} zipCode
|
||||
* Service location zip code
|
||||
* @param {string} firstAvailableAppointmentDateString
|
||||
* The first available appointment date, used to determine
|
||||
* the number of days until that date.
|
||||
* @param {string} shopAppointmentType
|
||||
* Value included in return data points if present.
|
||||
* @returns {string}
|
||||
* A string containing comma delimited data points.
|
||||
* @static
|
||||
*/
|
||||
const getTimeSlotsAdditionalEventData = (
|
||||
provisionalTriggers,
|
||||
zipCode,
|
||||
firstAvailableAppointmentDateString,
|
||||
shopAppointmentType
|
||||
) => {
|
||||
let numberOfDays = null;
|
||||
if (firstAvailableAppointmentDateString) numberOfDays = getDateDifferenceInDays(new Date(), firstAvailableAppointmentDateString);
|
||||
|
||||
return (shopAppointmentType)
|
||||
// eslint-disable-next-line max-len
|
||||
? `FirstAvailableAppointment:${numberOfDays},Zip:${zipCode},ShopAppointmentType:${shopAppointmentType},ProvisionalTriggers:${provisionalTriggers.join(',')}`
|
||||
: `FirstAvailableAppointment:${numberOfDays},Zip:${zipCode},ProvisionalTriggers:${provisionalTriggers.join(',')}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function providersEqual
|
||||
* @memberof StoreProcessors
|
||||
* @summary
|
||||
* Tests equality of addy/number properties on two provider objects.
|
||||
* @remarks
|
||||
* TODO: Change back to deepEqual once zipCodeCtu is added to saveSession.
|
||||
* @param {Array} providerA
|
||||
* First Provider object to compare for equality
|
||||
* @param {string} providerB
|
||||
* Second Provider object to compare for equality
|
||||
* @returns {boolean}
|
||||
* True if provider objects have equal addy/number properties, false otherwise.
|
||||
* @static
|
||||
*/
|
||||
const providersEqual = (providerA, providerB) =>
|
||||
(
|
||||
providerA.providerNumber === providerB.providerNumber
|
||||
&& providerA.address?.city === providerB.address?.city
|
||||
&& providerA.address?.state === providerB.address?.state
|
||||
&& providerA.address?.streetAddress === providerB.address?.streetAddress
|
||||
&& providerA.address?.zipCode === providerB.address?.zipCode
|
||||
);
|
||||
|
||||
/**
|
||||
* @function provisionalTriggersToString
|
||||
* @memberof StoreProcessors
|
||||
* @summary
|
||||
* Converts provided array to comma delimited string with key prepended.
|
||||
* @remarks
|
||||
* @param {Array} provisionalTriggers
|
||||
* Array of items to include in result.
|
||||
* @returns {string}
|
||||
* Returns string with key name and parameter array converted to comma delimited string.
|
||||
* @static
|
||||
*/
|
||||
const provisionalTriggersToString = (provisionalTriggers) => `ProvisionalTriggers:${provisionalTriggers.join(',')}`;
|
||||
|
||||
/**
|
||||
* @module StoreProcessors
|
||||
* @endpoint
|
||||
* @property {StoreProcessors.addPricesToLineItems} addPricesToLineItems
|
||||
* See method for details.
|
||||
* @property {StoreProcessors.buildQueryStringParameterFromArrayOfComplexObjects} buildQueryStringParameterFromArrayOfComplexObjects
|
||||
* See method for details.
|
||||
* @property {StoreProcessors.convertGlassPieceNamingFromApi} convertGlassPieceNamingFromApi
|
||||
* See method for details.
|
||||
* @property {StoreProcessors.convertResultsForApi} convertResultsForApi
|
||||
* See method for details.
|
||||
* @property {StoreProcessors.getAllPartNumbers} getAllPartNumbers
|
||||
* See method for details.
|
||||
* @property {StoreProcessors.getHasRecalibrationPart} getHasRecalibrationPart
|
||||
* See method for details.
|
||||
* @property {StoreProcessors.getLineItemQueryStringForPricing} getLineItemQueryStringForPricing
|
||||
* See method for details.
|
||||
* @property {StoreProcessors.getTimeSlotsAdditionalEventData} getTimeSlotsAdditionalEventData
|
||||
* See method for details.
|
||||
* @static
|
||||
* @default
|
||||
*/
|
||||
const StoreProcessors = {
|
||||
addPricesToLineItems,
|
||||
buildQueryStringParameterFromArrayOfComplexObjects,
|
||||
convertGlassPieceNamingFromApi,
|
||||
convertGlassPieceToBackEndCompatibleFormat,
|
||||
convertResultsForApi,
|
||||
getFlattenedArrayOfLineItemsWithChildParts,
|
||||
getHasRecalibrationPart,
|
||||
getLineItemQueryStringForPricing,
|
||||
getTimeSlotsAdditionalEventData,
|
||||
providersEqual,
|
||||
provisionalTriggersToString
|
||||
};
|
||||
|
||||
export default StoreProcessors;
|
||||
2557
src/store/index.js
2557
src/store/index.js
File diff suppressed because it is too large
Load diff
|
|
@ -898,7 +898,7 @@ describe('Store', () => {
|
|||
store.damage.glassToReplace = [
|
||||
{ glassLocation: location1, glassName: name1 },
|
||||
{ glassLocation: location2, glassName: name2 }
|
||||
],
|
||||
];
|
||||
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
|
||||
|
||||
// Act
|
||||
|
|
|
|||
Loading…
Reference in a new issue