From da9aa475218fe35e22e654ede0ac5f35c5417e93 Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 30 Nov 2021 14:30:35 -0500 Subject: [PATCH] Created layout-helper --- src/helpers/layout-helper.js | 29 ++++++++++ src/helpers/unit-test-helper.js | 14 ++--- src/layouts/vehicle-year/vehicle-year.spec.js | 43 ++++++++++++--- src/layouts/vehicle-year/vehicle-year.vue | 27 +++++++--- .../year-question/year-question.spec.js | 29 +--------- .../year-question/year-question.vue | 6 +-- src/mixins/base-mixin.spec.js | 54 ------------------- 7 files changed, 89 insertions(+), 113 deletions(-) create mode 100644 src/helpers/layout-helper.js diff --git a/src/helpers/layout-helper.js b/src/helpers/layout-helper.js new file mode 100644 index 000000000..f3b4284dd --- /dev/null +++ b/src/helpers/layout-helper.js @@ -0,0 +1,29 @@ +export function settleAllPromises(layoutPromiseTable) { + + // Pull our keys out of the promise 'table' + const promiseNames = Object.entries(layoutPromiseTable); + + 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].key; + + // 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/unit-test-helper.js b/src/helpers/unit-test-helper.js index 94027cc05..9b5f2a763 100644 --- a/src/helpers/unit-test-helper.js +++ b/src/helpers/unit-test-helper.js @@ -1,6 +1,6 @@ import { storeActions } from "@/constants/store-actions"; -export function getMountOptions(mockData, cmsMockData = null) { +export function getMountOptions(mockData) { // Define our mocks to attached to the 'global' object for Vue/Jest. const mocks = {}; @@ -17,20 +17,12 @@ export function getMountOptions(mockData, cmsMockData = null) { } }); - if(cmsMockData){ - mocks.GetContentFromCms = jest.fn(); - mocks.GetContentFromCms.mockImplementation(() => - { - return cmsMockData; - }); - } - // Mock store actions from js file mocks.storeActions = storeActions; + const global = { mocks: mocks, }; return { global }; -} - +} \ No newline at end of file diff --git a/src/layouts/vehicle-year/vehicle-year.spec.js b/src/layouts/vehicle-year/vehicle-year.spec.js index fbc3afedf..1d5096e60 100644 --- a/src/layouts/vehicle-year/vehicle-year.spec.js +++ b/src/layouts/vehicle-year/vehicle-year.spec.js @@ -1,27 +1,56 @@ -import { shallowMount, flushPromises } from "@vue/test-utils"; +import { shallowMount, flushPromises } from "@vue/test-utils"; import { getMountOptions } from "@/helpers/unit-test-helper.js"; import vehicleYear from "@/layouts/vehicle-year/vehicle-year.vue"; +import { settleAllPromises } from "@/helpers/layout-helper.js"; +import { nextTick } from 'vue' + +// Mock our module for promises. +jest.mock("@/helpers/layout-helper.js", () => ({ + settleAllPromises: jest.fn() +})); describe("vehicle-year.vue", () => { test("vehicle-year.vue should render data from CMS", async () => { // Arrange - const cmsMockData = { - PageHeaderWidget: [{ HeaderText: "Select a year to get started" }], - RadioQuestionWidget: [{ QuestionText: "What year is your vehicle?" }], + + // Our mock data for our call to settleAllPromises + const mockData = { + pageContentPromise: { + PageHeaderWidget: [{ HeaderText: "Select a year to get started" }], + RadioQuestionWidget: [{ QuestionText: "What year is your vehicle?" }], + isCmsContentReady: true, + }, + vehicleYearsPromise: [2023, 2022, 2021] } - const mountOptions = getMountOptions({}, cmsMockData); + // our router information needed. + const to = { + query: { + fmgPage: 'vehicle-year' + } + }; + + const mountOptions = getMountOptions(mockData); + + // our mock implementation of settleAllPromises + settleAllPromises.mockImplementation(() => { return Promise.resolve(mockData);}); // Act const wrapper = shallowMount(vehicleYear, mountOptions); - await flushPromises(); + + // Call our beforeRouteEnter on the component. + // This passes (c) => c(wrapper.vm) so that next can be called and our + // data can be set. + vehicleYear.beforeRouteEnter.call(wrapper.vm, to, undefined, (c) => c(wrapper.vm)); + + await nextTick(); // Wait for the DOM to update. // Assert const header = await wrapper.find(".Header"); expect(header.attributes("text")).toEqual("Select a year to get started"); - const yearQuestion = await wrapper.findComponent({name: 'year-question'}); + const yearQuestion = wrapper.findComponent({ name: 'year-question' }); expect(yearQuestion.attributes("questiontext")).toEqual("What year is your vehicle?"); }); }); diff --git a/src/layouts/vehicle-year/vehicle-year.vue b/src/layouts/vehicle-year/vehicle-year.vue index 14d1e85cb..86c89c9f8 100644 --- a/src/layouts/vehicle-year/vehicle-year.vue +++ b/src/layouts/vehicle-year/vehicle-year.vue @@ -2,7 +2,7 @@
- +
@@ -11,6 +11,7 @@ import yearQuestion from "@/layouts/vehicle-year/year-question/year-question"; import pageHeader from "@/ux-components/header/header"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; +import { settleAllPromises } from "@/helpers/layout-helper"; import store from "@/store"; import { storeActions } from "@/constants/store-actions.js"; @@ -20,23 +21,33 @@ export default { return { pageHeaderWidgets: {}, radioQuestionWidgets: {}, + vehicleYears: [], }; }, computed: {}, beforeRouteEnter(to, from, next) { - Promise.allSettled([ - fetchCmsContentForPage(to.query.fmgPage), - store.dispatch(storeActions.GET_VEHICLE_YEARS, {}), - ]).then(([contentPromise, getYearsPromise]) => { - + const layoutPromiseTable = [ + { + key: "pageContentPromise", + promise: fetchCmsContentForPage(to.query.fmgPage), + }, + { + key: "vehicleYearsPromise", + promise: store.dispatch(storeActions.GET_VEHICLE_YEARS, {}), + }, + ]; + settleAllPromises(layoutPromiseTable).then((resultMap) => { // Call our next function to transition to the next page. next((vm) => { - vm.pageHeaderWidgets = contentPromise.value.PageHeaderWidget[0]; - vm.radioQuestionWidgets = contentPromise.value.RadioQuestionWidget[0]; + vm.pageHeaderWidgets = resultMap.pageContentPromise.PageHeaderWidget[0]; + vm.radioQuestionWidgets = resultMap.pageContentPromise.RadioQuestionWidget[0]; + vm.vehicleYears = resultMap.vehicleYearsPromise; + }); }); + }, components: { yearQuestion, diff --git a/src/layouts/vehicle-year/year-question/year-question.spec.js b/src/layouts/vehicle-year/year-question/year-question.spec.js index a5ab50320..3d0843e10 100644 --- a/src/layouts/vehicle-year/year-question/year-question.spec.js +++ b/src/layouts/vehicle-year/year-question/year-question.spec.js @@ -1,28 +1 @@ -import { shallowMount, flushPromises } from "@vue/test-utils"; -import { getMountOptions } from "@/helpers/unit-test-helper.js"; -import { storeActions } from "@/constants/store-actions.js"; -import yearQuestion from "@/layouts/vehicle-year/year-question/year-question"; - -describe('year-question.vue', () => { - - test('year-question should call API to get years', async () => { - // Arrange - const mockDataAndAction = { - actionList: [{ actionName: storeActions.GET_VEHICLE_YEARS, data: ["2023", "2022", "2021"], - }, - ], - }; - - const mountOptions = getMountOptions(mockDataAndAction); - - // Act - const wrapper = shallowMount(yearQuestion, mountOptions); - await wrapper.setProps({questionText: 'What year is your vehicle?'}) - await flushPromises(); - - // Assert - const radioQuestion = await wrapper.findComponent({name: 'radioQuestion'}); - expect(radioQuestion.attributes('questiontext')).toBe("What year is your vehicle?"); - expect(radioQuestion.attributes('answers')).toBe('2023,2022,2021'); - }); -}); +test.todo("some test to be written in the future"); diff --git a/src/layouts/vehicle-year/year-question/year-question.vue b/src/layouts/vehicle-year/year-question/year-question.vue index 5df3cffa8..e3b2fc4cb 100644 --- a/src/layouts/vehicle-year/year-question/year-question.vue +++ b/src/layouts/vehicle-year/year-question/year-question.vue @@ -9,11 +9,7 @@ export default { name: "year-question", props: { questionText: String, - }, - data() { - return { - years: [], - }; + years: Array }, created() { }, diff --git a/src/mixins/base-mixin.spec.js b/src/mixins/base-mixin.spec.js index a6eb8d504..628a3ef2f 100644 --- a/src/mixins/base-mixin.spec.js +++ b/src/mixins/base-mixin.spec.js @@ -23,60 +23,6 @@ describe("baseMixin.js", () => { expect(mixIn.methods.$store.dispatch).toBeCalledWith(type, payload); }); - - test('GetContentFromCms: Should return mapped data and call dispatchNonblockingStoreAction', async () => { - const mixIn = getMixInInstance({}); - - // Mock dispatch action - mixIn.methods.dispatchNonBlockingStoreAction = jest.fn(); - mixIn.methods.dispatchNonBlockingStoreAction.mockImplementation((action) => { - if (action === 'getPageData') { - return Promise.resolve({ - data: { - Result: [ - { - Type: "PageConfigWidget", - Model: { - LayoutNames: [ - "None", - "vehicle-year" - ], - LayoutStyle: "vehicle-year" - } - }, - { - Type: "RadioQuestionWidget", - Model: { - "QuestionText": "What year is your vehicle?" - } - }, - { - Type: "RadioQuestionWidget", - Model: { - "QuestionText": "This is a second radio question" - } - }, - { - Type: "PageHeaderWidget", - Model: { - "HeaderText": "Select a year to get started" - } - } - ] - }, - }); - } - }); - - const result = await mixIn.methods.GetContentFromCms(); - await flushPromises(); - - - expect(mixIn.methods.dispatchNonBlockingStoreAction).toBeCalledWith(storeActions.GET_PAGE_DATA, { pageName: 'test-page'}); - - expect(result.PageHeaderWidget[0].HeaderText).toEqual('Select a year to get started'); - - }); }) function getMixInInstance({ isDispatchSuccess = true }) {