From 5ca6887464e1c22d6ce6c8b8e8c93c6db45a904f Mon Sep 17 00:00:00 2001 From: Kulbhushan Kaushik Date: Mon, 10 Oct 2022 08:35:23 -0400 Subject: [PATCH 1/8] commit --- src/constants/application-config.js | 3 +- src/constants/endpoints.js | 28 +++---- src/helpers/cms-content-helper.js | 118 ++++++++++++++++++++++++++++ src/router/index.js | 11 +-- src/store/index.js | 37 ++++++++- 5 files changed, 168 insertions(+), 29 deletions(-) create mode 100644 src/helpers/cms-content-helper.js diff --git a/src/constants/application-config.js b/src/constants/application-config.js index ff2229e3..9c3a3d05 100644 --- a/src/constants/application-config.js +++ b/src/constants/application-config.js @@ -2,7 +2,8 @@ const applicationConfig = { CURRENT_ENVIRONMENT: process.env.VUE_APP_CURRENT_ENVIRONMENT, // "Localhost", "Dev", "QA", and "Prod" CONSUMER_CF_DISTRO: process.env.VUE_APP_CONSUMER_CF_DISTRO, APPLICATION_NAME: "SelfService", - SITE_ENTRY_TRIGGER_VALUE: "SelfService" + SITE_ENTRY_TRIGGER_VALUE: "SelfService", + APPLICATION_ABBREVIATION: "iss", }; export { applicationConfig }; \ No newline at end of file diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index 7581f022..19833112 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -1,17 +1,17 @@ const endpoints = { - GetRouteInfo: { - url: "/content/api/v1/content/RouteInfo", - method: "POST", - }, - GetHomepageInfo: { - url: "/content/api/v1/content/HomepageInfo", - method: "GET", - }, - GetPageData: { - url: "/content/api/v1/content", - method: "GET", - }, - }; + GetRouteInfo: { + url: (applicationAbbreviation) => `/content/api/v1/content/${applicationAbbreviation}/RouteInfo`, + method: "POST", + }, + GetHomepageInfo: { + url: (applicationAbbreviation) => `/content/api/v1/content/${applicationAbbreviation}/HomepageInfo`, + method: "GET", + }, + GetPageData: { + url: (applicationAbbreviation, pageName) => `/content/api/v1/content/${applicationAbbreviation}/${pageName}`, + method: "GET", + }, +}; - export { endpoints }; +export { endpoints }; \ No newline at end of file diff --git a/src/helpers/cms-content-helper.js b/src/helpers/cms-content-helper.js new file mode 100644 index 00000000..9a7c0925 --- /dev/null +++ b/src/helpers/cms-content-helper.js @@ -0,0 +1,118 @@ +export function fetchCmsContentForPage(issPage) { + return this.mainStore.getRouteInfo(issPage) + .then((response) => { + const pageDataFromCms = {}; + + response.data.Result.forEach((widget) => { + let widgetWithReplacements = findAndReplaceGlobalStateValues( + widget.Model, + widget.Name + ); + + // If we already have this widget, push it on the collection + if (widgetWithReplacements.Name in pageDataFromCms) { + pageDataFromCms[widgetWithReplacements.Name].push( + widgetWithReplacements.Model + ); + return; + } + + pageDataFromCms[widgetWithReplacements.Name] = [ + widgetWithReplacements.Model, + ]; + }); + + Object.keys(pageDataFromCms).forEach((key) => { + if (pageDataFromCms[key].length === 1) { + pageDataFromCms[key] = pageDataFromCms[key][0]; + } + }); + + return pageDataFromCms; + }); + } + + // Parent function for processWidgetItemForReplacement. This will loop through the parent +// object and pass any objects that need additional processing to the processWidgetItemForReplacement function. +function findAndReplaceGlobalStateValues(widgetModel, widgetName) { + const objWithReplacements = { + Name: widgetName, + Model: {}, + }; + + Object.keys(widgetModel).forEach((key) => { + let modelWithReplacements = processWidgetItemForReplacement( + widgetModel, + key + ); + + objWithReplacements.Model[key] = modelWithReplacements; + }); + + return objWithReplacements; + } + + // This function will process the widget item and replace any global state variables with their values. +// This is a recursive function, it will call itself until it runs out of items to iterate on given the object. +function processWidgetItemForReplacement(widgetModel, key) { + // If we have a string, and it needs to be replaced. + if (typeof widgetModel[key] === "string") { + if (widgetModel[key].includes(dynamicStrings.GLOBAL_STATE)) { + widgetModel[key] = mapStringToState(widgetModel[key]); + } + return widgetModel[key]; + } + + // If we have an object. array, etc + if ( + typeof widgetModel[key] === "object" && + Object.keys(widgetModel[key]).length + ) { + Object.keys(widgetModel[key]).forEach((item) => { + processWidgetItemForReplacement(widgetModel[key], item); + }); + + return widgetModel[key]; + } + + // If we have something else like a number, boolean, etc. just return it + return widgetModel[key]; + } + + // Function to convert a string, into a matching global state item. +function mapStringToState(str) { + // Pull all matches out of the string. + const regexExp = new RegExp("{(.*?):(.*?)}", "g"); + const regexMatches = [...str.matchAll(regexExp)]; + const globalStateMatches = regexMatches.filter(match => { + return match[1] === dynamicStrings.GLOBAL_STATE; + }) + + // Our final string value that will be built from the matches. + let stringBuilder = ""; + + for (const match of globalStateMatches) { + // Reset store state for each match. + let storeState = store.state; + + for (const s of match[2].split(".")) { + if (storeState[s] != undefined) { + storeState = storeState[s]; + } else { + return ""; // if we can't map our string to state data, return an empty string. + } + } + + const stringWithReplacement = str.replace(match[0], storeState); + + // If we still have values we need to substitute, call this function again. + if (stringWithReplacement.includes(dynamicStrings.GLOBAL_STATE)) { + return mapStringToState(stringWithReplacement); + } + + // Concatenate the string. + stringBuilder = `${stringBuilder} ${stringWithReplacement}`; + } + + return stringBuilder.trimStart(); + } \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js index ab5cae25..30e4980b 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -1,7 +1,5 @@ import { createWebHistory, createRouter } from "vue-router"; import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader"; -import { endpoints } from "@/constants/mock-endpoints"; -import globalMethods from "@/global-methods"; import {issPageValues} from '@/router/router-constants/issPage-values'; import { routingTable } from "@/router/router-constants/routing-table"; import { useMainStore } from '@/store'; @@ -56,15 +54,8 @@ const router = createRouter({ // Get route information by page name. // This will reach out to the Cms and there is a 1:1 relationship between page names and route names. async function GetRouteInfoFromPageName(pageName) { - - //move to store actions later? - /* - const response = await store.dispatch(storeActions.GET_ROUTE_INFO_ACTION, { - pageName: pageName, - }); - */ + const response = await this.mainStore.getRouteInfo(pageName); - const response = await globalMethods.mockCallHttpClient("GET", endpoints.GetRouteInfo.url + "?route=" + pageName) const jsonFromResponse = JSON.parse(response.data.Result); let routeData = []; diff --git a/src/store/index.js b/src/store/index.js index c78651c0..aa067c5c 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,4 +1,7 @@ import { defineStore } from "pinia"; +import { endpoints } from "@/constants/endpoints.js"; +import { globalMethods } from "@/global-methods"; +import { applicationConfig } from "@/constants/application-config"; const storeId = 'main'; @@ -47,13 +50,39 @@ export const useMainStore = defineStore({ getters: {}, actions: { - // Vehicle + // Content API Actions + getRouteInfo(context, { pageName }) { + return globalMethods.callHttpClient({ + method: endpoints.GetRouteInfo.method, + endpoint: endpoints.GetRouteInfo.url(applicationConfig.APPLICATION_ABBREVIATION), + payload: { + pageName: pageName, + }, + }); + }, + getHomepageName(context) { + return globalMethods.callHttpClient({ + method: endpoints.GetHomepageInfo.method, + endpoint: endpoints.GetHomepageInfo.url(applicationConfig.APPLICATION_ABBREVIATION), + }); + }, + getPageData(context, { pageName }) { + return globalMethods.callHttpClient({ + method: endpoints.GetPageData.method, + endpoint: endpoints.GetPageData.url(applicationConfig.APPLICATION_ABBREVIATION, pageName), + payload: {}, + }); + }, + + // Vehicle API Actions updateVehicleYear(year) { - if (this.order.vehicle.year !== year) { - this.order.vehicle.year = year; - } + if (this.order.vehicle.year !== year) { + this.order.vehicle.year = year; + } }, + + // populate initial state populateInitialState() { if(!localStorage.getItem(storeId)) { From db7648bac6480d1fa3d8578cef39a631c82bd320 Mon Sep 17 00:00:00 2001 From: Kulbhushan Kaushik Date: Mon, 10 Oct 2022 10:46:03 -0400 Subject: [PATCH 2/8] commit --- src/helpers/cms-content-helper.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/helpers/cms-content-helper.js b/src/helpers/cms-content-helper.js index 9a7c0925..cc9769eb 100644 --- a/src/helpers/cms-content-helper.js +++ b/src/helpers/cms-content-helper.js @@ -1,5 +1,7 @@ +import { dynamicStrings } from "../constants/dynamic-strings"; + export function fetchCmsContentForPage(issPage) { - return this.mainStore.getRouteInfo(issPage) + return this.mainStore.getPageData(issPage) .then((response) => { const pageDataFromCms = {}; @@ -93,7 +95,7 @@ function mapStringToState(str) { for (const match of globalStateMatches) { // Reset store state for each match. - let storeState = store.state; + let storeState = this.mainStore.state; for (const s of match[2].split(".")) { if (storeState[s] != undefined) { From afd9e8b91eab9859cbb5e6698d2c2dc2d19a6898 Mon Sep 17 00:00:00 2001 From: Kulbhushan Kaushik Date: Tue, 11 Oct 2022 07:56:29 -0400 Subject: [PATCH 3/8] commit --- src/store/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/store/index.js b/src/store/index.js index aa067c5c..2caca285 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,6 +1,6 @@ import { defineStore } from "pinia"; import { endpoints } from "@/constants/endpoints.js"; -import { globalMethods } from "@/global-methods"; +import globalMethods from "@/global-methods"; import { applicationConfig } from "@/constants/application-config"; const storeId = 'main'; From f22f42c260e28231c6789ec16ddafe16c170d586 Mon Sep 17 00:00:00 2001 From: Kulbhushan Kaushik Date: Tue, 11 Oct 2022 10:27:37 -0400 Subject: [PATCH 4/8] commit --- src/layouts/vehicle-year/vehicle-year.vue | 17 +++++++++++++++++ src/main.js | 6 ++---- src/mixins/base-mixin.js | 3 +-- src/router/index.js | 5 +++-- src/store/index.js | 10 +++++----- vue.config.js | 2 +- 6 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/layouts/vehicle-year/vehicle-year.vue b/src/layouts/vehicle-year/vehicle-year.vue index 29d5a40b..e5d0c243 100644 --- a/src/layouts/vehicle-year/vehicle-year.vue +++ b/src/layouts/vehicle-year/vehicle-year.vue @@ -3,6 +3,9 @@

Vehicle Year Placeholder

+ + {{returnVehicleYear}} +
@@ -13,5 +16,19 @@ export default { name: 'vehicle-year', components: { navButton }, + methods: + { + updateVehicleYear(item) + { + this.mainStore.updateVehicleYear(item); + } + }, + computed: + { + returnVehicleYear() + { + return this.mainStore.order.vehicle.year; + } + } } \ No newline at end of file diff --git a/src/main.js b/src/main.js index 2039c59a..4e8c1b3c 100644 --- a/src/main.js +++ b/src/main.js @@ -1,18 +1,16 @@ import { createApp } from 'vue'; -import { createPinia } from "pinia"; import App from './App.vue'; import router from './router'; import "../node_modules/bootstrap/dist/js/bootstrap.js"; import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'; -import { useMainStore } from './store'; +import { useMainStore, pinia } from '@/store'; import baseMixin from "@/mixins/base-mixin.js"; const vueApp = createApp(App); // Pinia -const pinia = createPinia(); -pinia.use(piniaPluginPersistedstate); vueApp.use(pinia); +pinia.use(piniaPluginPersistedstate); useMainStore().populateInitialState(); // Additional Vue items to setup diff --git a/src/mixins/base-mixin.js b/src/mixins/base-mixin.js index b8f6115f..83fd9097 100644 --- a/src/mixins/base-mixin.js +++ b/src/mixins/base-mixin.js @@ -3,10 +3,9 @@ import { navigationScenarios } from "@/router/router-constants/navigation-scenar import { vehicleCategories } from "@/constants/vehicle-categories.js"; import { queryStrings } from "@/constants/query-strings"; import { dynamicStrings } from "@/constants/dynamic-strings"; -import { useMainStore } from "../store"; +import { useMainStore } from "@/store"; import { mapStores } from "pinia"; - export default { data() { return { diff --git a/src/router/index.js b/src/router/index.js index 30e4980b..cfacbfb1 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -3,6 +3,7 @@ import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader"; import {issPageValues} from '@/router/router-constants/issPage-values'; import { routingTable } from "@/router/router-constants/routing-table"; import { useMainStore } from '@/store'; +import { pinia } from "../store"; const routes = [ { @@ -54,7 +55,7 @@ const router = createRouter({ // Get route information by page name. // This will reach out to the Cms and there is a 1:1 relationship between page names and route names. async function GetRouteInfoFromPageName(pageName) { - const response = await this.mainStore.getRouteInfo(pageName); + const response = await useMainStore(pinia).getRouteInfo(pageName); const jsonFromResponse = JSON.parse(response.data.Result); let routeData = []; @@ -122,7 +123,7 @@ function navigateToUrl(url, optionalQuery = {}) { function getNavigationMap (scenario, currentRoute) { const issPageValue = currentRoute.query.issPage; try { - const matchedQueryValue = routingTable(useMainStore()) + const matchedQueryValue = routingTable(useMainStore(pinia)) .filter( (item) => item.issPageValue === issPageValue && diff --git a/src/store/index.js b/src/store/index.js index 2caca285..4aa75a25 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,4 +1,4 @@ -import { defineStore } from "pinia"; +import { defineStore, createPinia } from "pinia"; import { endpoints } from "@/constants/endpoints.js"; import globalMethods from "@/global-methods"; import { applicationConfig } from "@/constants/application-config"; @@ -51,7 +51,7 @@ export const useMainStore = defineStore({ actions: { // Content API Actions - getRouteInfo(context, { pageName }) { + getRouteInfo(pageName) { return globalMethods.callHttpClient({ method: endpoints.GetRouteInfo.method, endpoint: endpoints.GetRouteInfo.url(applicationConfig.APPLICATION_ABBREVIATION), @@ -60,13 +60,13 @@ export const useMainStore = defineStore({ }, }); }, - getHomepageName(context) { + getHomepageName() { return globalMethods.callHttpClient({ method: endpoints.GetHomepageInfo.method, endpoint: endpoints.GetHomepageInfo.url(applicationConfig.APPLICATION_ABBREVIATION), }); }, - getPageData(context, { pageName }) { + getPageData(pageName) { return globalMethods.callHttpClient({ method: endpoints.GetPageData.method, endpoint: endpoints.GetPageData.url(applicationConfig.APPLICATION_ABBREVIATION, pageName), @@ -93,4 +93,4 @@ export const useMainStore = defineStore({ persist: true }); - \ No newline at end of file +export const pinia = createPinia(); \ No newline at end of file diff --git a/vue.config.js b/vue.config.js index 9734caad..ccad75f0 100644 --- a/vue.config.js +++ b/vue.config.js @@ -1,4 +1,4 @@ -process.env.VUE_APP_CONSUMER_CF_DISTRO ="https://digitalapi.dev.sagaws.net"; +process.env.VUE_APP_CONSUMER_CF_DISTRO ="https://digitalapi.dev.safelite.io"; process.env.VUE_APP_CURRENT_ENVIRONMENT = "Localhost"; module.exports = { From 4cd3f62421774aeb468dc64d30d9914ff723bff2 Mon Sep 17 00:00:00 2001 From: Kulbhushan Kaushik Date: Tue, 11 Oct 2022 12:03:03 -0400 Subject: [PATCH 5/8] commit --- src/main.js | 4 +++- src/router/index.js | 5 ++--- src/store/index.js | 2 -- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main.js b/src/main.js index 4e8c1b3c..91c236c0 100644 --- a/src/main.js +++ b/src/main.js @@ -3,12 +3,14 @@ import App from './App.vue'; import router from './router'; import "../node_modules/bootstrap/dist/js/bootstrap.js"; import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'; -import { useMainStore, pinia } from '@/store'; +import { useMainStore, } from '@/store'; import baseMixin from "@/mixins/base-mixin.js"; +import { createPinia } from 'pinia'; const vueApp = createApp(App); // Pinia +const pinia = createPinia(); vueApp.use(pinia); pinia.use(piniaPluginPersistedstate); useMainStore().populateInitialState(); diff --git a/src/router/index.js b/src/router/index.js index cfacbfb1..ff0f0e2f 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -3,7 +3,6 @@ import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader"; import {issPageValues} from '@/router/router-constants/issPage-values'; import { routingTable } from "@/router/router-constants/routing-table"; import { useMainStore } from '@/store'; -import { pinia } from "../store"; const routes = [ { @@ -55,7 +54,7 @@ const router = createRouter({ // Get route information by page name. // This will reach out to the Cms and there is a 1:1 relationship between page names and route names. async function GetRouteInfoFromPageName(pageName) { - const response = await useMainStore(pinia).getRouteInfo(pageName); + const response = await useMainStore().getRouteInfo(pageName); const jsonFromResponse = JSON.parse(response.data.Result); let routeData = []; @@ -123,7 +122,7 @@ function navigateToUrl(url, optionalQuery = {}) { function getNavigationMap (scenario, currentRoute) { const issPageValue = currentRoute.query.issPage; try { - const matchedQueryValue = routingTable(useMainStore(pinia)) + const matchedQueryValue = routingTable(useMainStore()) .filter( (item) => item.issPageValue === issPageValue && diff --git a/src/store/index.js b/src/store/index.js index 4aa75a25..56668172 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -92,5 +92,3 @@ export const useMainStore = defineStore({ }, persist: true }); - -export const pinia = createPinia(); \ No newline at end of file From 867fa49568f8e799647e08c0664e852c4a04373c Mon Sep 17 00:00:00 2001 From: Kulbhushan Kaushik Date: Tue, 11 Oct 2022 12:19:03 -0400 Subject: [PATCH 6/8] global-methods unit tests --- src/global-methods.spec.js | 77 +++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/src/global-methods.spec.js b/src/global-methods.spec.js index a4c46989..286fe976 100644 --- a/src/global-methods.spec.js +++ b/src/global-methods.spec.js @@ -1,4 +1,77 @@ import axios from 'axios'; -import '@/global-methods.js'; +import globalMethods from "@/global-methods"; -test.todo("Need to add some tests here"); \ No newline at end of file +//Mock external dependencies +jest.mock("axios"); + +it("Global Methods - Call Http Client - Should Resolve Promise", () => { + //Arrange + const endpoint = "https://mock.safelite.com"; + const httpArgs = setupMocksForHttpClient({ endpoint: endpoint }); + + //Act + globalMethods.callHttpClient(httpArgs).then((response) => { + //Assert + expect(axios.mock.calls[0][0].url).toContain(endpoint); + expect(response.data.message).toContain("Success"); + expect(response.status).toEqual(200); + }); + }); + + it("Global Methods - Call Http Client - Should Reject Promise", () => { + //Arrange + const endpoint = "https://mock.safelite.com"; + const httpArgs = setupMocksForHttpClient({ + endpoint: endpoint, + isError: true, + }); + + //Act + globalMethods.callHttpClient(httpArgs).catch((err) => { + //Assert + expect(axios.mock.calls[0][0].url).toContain(endpoint); + expect(err.data.message).toContain("Error"); + expect(err.status).toEqual(500); + }); + }); + + function setupMocksForHttpClient({ + endpoint = null, + isError = false, + additionalData = null, + }) { + //Clear node module + axios.mockClear(); + + // Success Response + const response = { + status: 200, + data: { + message: "Success", + additionalData: additionalData, + }, + }; + + // Error Response + const error = { + response: { + status: 500, + data: { + message: "Error", + additionalData: additionalData, + }, + }, + }; + + // Error interceptor on Axios returns a different object, so we need to mimic that. + if (isError) { + axios.mockRejectedValue(error); + } else { + axios.mockResolvedValue(response); + } + + return { + endpoint: endpoint, + logApiCall: true + }; + } \ No newline at end of file From 64a23683c7208ae9409bbf0d0463cb8f6f82f344 Mon Sep 17 00:00:00 2001 From: Kulbhushan Kaushik Date: Wed, 12 Oct 2022 09:38:08 -0400 Subject: [PATCH 7/8] commit --- azure-pipelines.yml | 6 ++++- src/helpers/cms-content-helper.js | 7 +++--- src/helpers/layout-helper.js | 28 +++++++++++++++++++++++ src/helpers/layout-helper.spec.js | 25 ++++++++++++++++++++ src/layouts/vehicle-year/vehicle-year.vue | 20 ++++++++++++++++ src/main.js | 2 +- 6 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 src/helpers/layout-helper.js create mode 100644 src/helpers/layout-helper.spec.js diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 2db5a1ef..caca6e33 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -75,4 +75,8 @@ stages: clearFolder: true deployFolder: '' region: us-east-2 - cfDistributionId: $(cfDistributionId) \ No newline at end of file + appDeployVariables: + __VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__) + __VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__) + cfDistributionId: $(cfDistributionId) + \ No newline at end of file diff --git a/src/helpers/cms-content-helper.js b/src/helpers/cms-content-helper.js index cc9769eb..5dd0c87f 100644 --- a/src/helpers/cms-content-helper.js +++ b/src/helpers/cms-content-helper.js @@ -1,7 +1,8 @@ -import { dynamicStrings } from "../constants/dynamic-strings"; +import { dynamicStrings } from "@/constants/dynamic-strings"; +import { useMainStore } from '@/store'; export function fetchCmsContentForPage(issPage) { - return this.mainStore.getPageData(issPage) + return useMainStore().getPageData(issPage) .then((response) => { const pageDataFromCms = {}; @@ -95,7 +96,7 @@ function mapStringToState(str) { for (const match of globalStateMatches) { // Reset store state for each match. - let storeState = this.mainStore.state; + let storeState = useMainStore().state; for (const s of match[2].split(".")) { if (storeState[s] != undefined) { diff --git a/src/helpers/layout-helper.js b/src/helpers/layout-helper.js new file mode 100644 index 00000000..a7a31119 --- /dev/null +++ b/src/helpers/layout-helper.js @@ -0,0 +1,28 @@ +export function settleAllPromises(promiseResultMap) { + // Pull our keys out of the promise 'table' + const promiseNames = Object.entries(promiseResultMap); + + return Promise.allSettled( + promiseNames.map((e) => e[1]).map((n) => n.promise) + ).then((results) => { + const resultMap = {}; + + // Build a map of the results + for (let i = 0; i < results.length; ++i) { + const promiseName = promiseNames[i][1].resultKey; + + // Some Promises like the cms content call don't have a 'data' field + // when returned, so other promises do. Map the results to the object + // so that the object is the return data. + + if (results[i]?.value?.data === undefined) { + resultMap[promiseName] = results[i]?.value; + } else { + resultMap[promiseName] = results[i]?.value?.data; + } + } + + return resultMap; + }); + } + \ No newline at end of file diff --git a/src/helpers/layout-helper.spec.js b/src/helpers/layout-helper.spec.js new file mode 100644 index 00000000..d7181075 --- /dev/null +++ b/src/helpers/layout-helper.spec.js @@ -0,0 +1,25 @@ +import { settleAllPromises } from "@/helpers/layout-helper"; + +it("layout-helper: Should settle all promises and return mapped promise results", () => { + // Arrange + const mockPromiseOne = Promise.resolve({ data: "test-data" }); + const mockPromiseTwo = Promise.resolve({ data: "test-data-two" }); + + const promiseResultMap = [ + { + resultKey: "MockResultOne", + promise: mockPromiseOne, + }, + { + resultKey: "MockResultTwo", + promise: mockPromiseTwo, + }, + ]; + + // Act + settleAllPromises(promiseResultMap).then((results) => { + // Assert + expect(results.MockResultOne).toEqual("test-data"); + expect(results.MockResultTwo).toEqual("test-data-two"); + }); +}); diff --git a/src/layouts/vehicle-year/vehicle-year.vue b/src/layouts/vehicle-year/vehicle-year.vue index e5d0c243..e8fcbdfb 100644 --- a/src/layouts/vehicle-year/vehicle-year.vue +++ b/src/layouts/vehicle-year/vehicle-year.vue @@ -12,10 +12,30 @@