diff --git a/jest.config.js b/jest.config.js index cc95af335..e36f1a70d 100644 --- a/jest.config.js +++ b/jest.config.js @@ -11,7 +11,7 @@ module.exports = { "!src/constants/*.js", "!src/router/**/*.js", "!src/helpers/unit-test-helper.js", - "!src/layouts/component-test/component-test.vue" + "!src/layouts/component-test/component-test.vue", ], //! means exclude from coverage. testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"], coverageThreshold: { diff --git a/src/common-components/radio-question/radio-question.spec.js b/src/common-components/radio-question/radio-question.spec.js index 17b6ff311..de6458122 100644 --- a/src/common-components/radio-question/radio-question.spec.js +++ b/src/common-components/radio-question/radio-question.spec.js @@ -4,11 +4,11 @@ import radioQuestion from "@/common-components/radio-question/radio-question"; describe("radioQuestion.vue", () => { it("Should render the 'questionText' prop value as a span value for the radio question and the 'answer' values should render as text values for radio components.", async () => { // Act - const wrapper = shallowMount(radioQuestion) + const wrapper = shallowMount(radioQuestion); await wrapper.setProps({ questionText: "Question Text", answers: ["2023", "2022", "2021"], - modelValue: "2020" + modelValue: "2020", }); wrapper.vm.chooseAnswer("2021"); diff --git a/src/common-components/radio-question/radio-question.vue b/src/common-components/radio-question/radio-question.vue index 8e44d965c..2c088fcc7 100644 --- a/src/common-components/radio-question/radio-question.vue +++ b/src/common-components/radio-question/radio-question.vue @@ -6,19 +6,32 @@ }}
-
+

*

- +
@@ -31,12 +44,12 @@ export default { props: { questionText: String, answers: Array, - modelValue: String + modelValue: String, }, methods: { chooseAnswer(answer) { - this.$emit('update:modelValue', answer); - } + this.$emit("update:modelValue", answer); + }, }, components: { radio, diff --git a/src/common-components/site-header/site-header.spec.js b/src/common-components/site-header/site-header.spec.js index f6d442931..2a471fe26 100644 --- a/src/common-components/site-header/site-header.spec.js +++ b/src/common-components/site-header/site-header.spec.js @@ -1,21 +1,19 @@ -import { shallowMount } from '@vue/test-utils'; -import siteHeader from './site-header'; +import { shallowMount } from "@vue/test-utils"; +import siteHeader from "./site-header"; -describe('siteHeader', () => { +describe("siteHeader", () => { + test("renders the logo image", () => { + // Arrange - test('renders the logo image', () => { - // Arrange - - // Act - const wrapper = shallowMount(siteHeader, { - propsData: { - imageSrc: "image_url", - }, - }); - - // Assert - expect(wrapper.find('img')).toBeTruthy(); - wrapper.unmount(); + // Act + const wrapper = shallowMount(siteHeader, { + propsData: { + imageSrc: "image_url", + }, }); + // Assert + expect(wrapper.find("img")).toBeTruthy(); + wrapper.unmount(); + }); }); diff --git a/src/common-components/site-header/site-header.vue b/src/common-components/site-header/site-header.vue index 1d09726e9..441b188c4 100644 --- a/src/common-components/site-header/site-header.vue +++ b/src/common-components/site-header/site-header.vue @@ -1,10 +1,9 @@ @@ -14,17 +13,17 @@ export default { props: { imageSrc: { type: String, - required: true - } + required: true, + }, }, -} +}; \ No newline at end of file +.funnel-header { + height: 56px; +} +.logo-image { + max-width: 78px; +} + diff --git a/src/common-components/vehicle-banner/vehicle-banner.spec.js b/src/common-components/vehicle-banner/vehicle-banner.spec.js index aab2aa3e0..98bf90a5a 100644 --- a/src/common-components/vehicle-banner/vehicle-banner.spec.js +++ b/src/common-components/vehicle-banner/vehicle-banner.spec.js @@ -1,21 +1,19 @@ -import { shallowMount } from '@vue/test-utils'; -import vehicleBanner from './vehicle-banner'; +import { shallowMount } from "@vue/test-utils"; +import vehicleBanner from "./vehicle-banner"; -describe('vehicleBanner', () => { +describe("vehicleBanner", () => { + test("renders the blurrycar image", () => { + // Arrange - test('renders the blurrycar image', () => { - // Arrange - - // Act - const wrapper = shallowMount(vehicleBanner, { - propsData: { - vehicleImageSrc: "image_url", - }, - }); - - // Assert - expect(wrapper.find('img').attributes('class')).toContain('blurrycar'); - wrapper.unmount(); + // Act + const wrapper = shallowMount(vehicleBanner, { + propsData: { + vehicleImageSrc: "image_url", + }, }); + // Assert + expect(wrapper.find("img").attributes("class")).toContain("blurrycar"); + wrapper.unmount(); + }); }); diff --git a/src/common-components/vehicle-banner/vehicle-banner.vue b/src/common-components/vehicle-banner/vehicle-banner.vue index f259390ee..32caa82f8 100644 --- a/src/common-components/vehicle-banner/vehicle-banner.vue +++ b/src/common-components/vehicle-banner/vehicle-banner.vue @@ -14,14 +14,14 @@ export default { props: { vehicleImageSrc: { type: String, - required: true - } + required: true, + }, }, -} +}; \ No newline at end of file +.vehicle-image { + max-width: 290px; +} + diff --git a/src/constants/store-mutations.js b/src/constants/store-mutations.js index 6ade6cd1d..d9292b5f8 100644 --- a/src/constants/store-mutations.js +++ b/src/constants/store-mutations.js @@ -1,5 +1,5 @@ const storeMutations = { - UPDATE_YEAR: "updateYear", -} + UPDATE_YEAR: "updateYear", +}; -export { storeMutations }; \ No newline at end of file +export { storeMutations }; diff --git a/src/helpers/cms-content-helper.js b/src/helpers/cms-content-helper.js index d6f4547c5..e0a12d8fe 100644 --- a/src/helpers/cms-content-helper.js +++ b/src/helpers/cms-content-helper.js @@ -3,22 +3,23 @@ import { widgetNames } from "@/constants/widget-names.js"; import store from "@/store"; export function fetchCmsContentForPage(fmgPage) { - return store.dispatch(storeActions.GET_PAGE_DATA, { pageName: fmgPage }).then((response) => { - const pageDataFromCms = {}; + return store + .dispatch(storeActions.GET_PAGE_DATA, { pageName: fmgPage }) + .then((response) => { + const pageDataFromCms = {}; - response.data.Result.forEach((widget) => { - if (Object.values(widgetNames).includes(widget.Type)) { - // If we already have this widget, push it on the collection - if (widget.Type in pageDataFromCms) { - pageDataFromCms[widget.Type].push(widget.Model); - return; - } + response.data.Result.forEach((widget) => { + if (Object.values(widgetNames).includes(widget.Type)) { + // If we already have this widget, push it on the collection + if (widget.Type in pageDataFromCms) { + pageDataFromCms[widget.Type].push(widget.Model); + return; + } - pageDataFromCms[widget.Type] = [widget.Model]; - } - }); + pageDataFromCms[widget.Type] = [widget.Model]; + } + }); - return pageDataFromCms; + return pageDataFromCms; }); } - diff --git a/src/helpers/cms-helper.spec.js b/src/helpers/cms-helper.spec.js index bb0edafcb..f019aa658 100644 --- a/src/helpers/cms-helper.spec.js +++ b/src/helpers/cms-helper.spec.js @@ -2,52 +2,52 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { dispatch } from "@/store"; jest.mock("@/store", () => ({ - dispatch: jest.fn() + dispatch: jest.fn(), })); it("cms-content-helper: Should return data from CMS", () => { + // Arrange + const cmsMockData = { + Result: [ + { + Type: "VehicleBannerWidget", + Model: { + ImageId: "28452dcb-7762-4cc9-ab09-7643d0b89203", + GenericVehicleImage: + "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", + GenericVehicleImageFilePath: + "images/default-source/default-album/blurred-image.jpg", + }, + }, + { + Type: "PageHeaderWidget", + Model: { + HeaderText: "Select a year to get started", + }, + }, + { + Type: "PageHeaderWidget", + Model: { + HeaderText: "Select a model", + }, + }, + { + Type: "RadioQuestionWidget", + Model: { + QuestionText: "What year is your vehicle?", + }, + }, + ], + }; - // Arrange - const cmsMockData = { - Result: [ - { - Type: "VehicleBannerWidget", - Model: { - ImageId: "28452dcb-7762-4cc9-ab09-7643d0b89203", - GenericVehicleImage: "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", - GenericVehicleImageFilePath: "images/default-source/default-album/blurred-image.jpg" - } - }, - { - Type: "PageHeaderWidget", - Model: { - "HeaderText": "Select a year to get started" - } - }, - { - Type: "PageHeaderWidget", - Model: { - "HeaderText": "Select a model" - } - }, - { - Type: "RadioQuestionWidget", - Model: { - "QuestionText": "What year is your vehicle?" - } - } - ] - } - - dispatch.mockImplementation(() => Promise.resolve({ data: cmsMockData })); - - // Act - fetchCmsContentForPage('testPage').then((response) => { - - // Assert - expect(response.isCmsContentReady).toBe(true); - expect(response.PageHeaderWidget[0].HeaderText).toEqual('Select a year to get started'); - }); + dispatch.mockImplementation(() => Promise.resolve({ data: cmsMockData })); + // Act + fetchCmsContentForPage("testPage").then((response) => { + // Assert + expect(response.isCmsContentReady).toBe(true); + expect(response.PageHeaderWidget[0].HeaderText).toEqual( + "Select a year to get started" + ); + }); }); - diff --git a/src/helpers/layout-helper.js b/src/helpers/layout-helper.js index d62d4d59f..10f331faf 100644 --- a/src/helpers/layout-helper.js +++ b/src/helpers/layout-helper.js @@ -1,29 +1,27 @@ export function settleAllPromises(promiseResultMap) { + // Pull our keys out of the promise 'table' + const promiseNames = Object.entries(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 = {}; - return Promise.allSettled(promiseNames.map(e => e[1]).map(n => n.promise)) - .then(results => { + // Build a map of the results + for (let i = 0; i < results.length; ++i) { + const promiseName = promiseNames[i][1].resultKey; - const resultMap = {}; + // 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. - // 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; + } + } - 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 + return resultMap; + }); +} diff --git a/src/helpers/layout-helper.spec.js b/src/helpers/layout-helper.spec.js index f85667f64..d71810756 100644 --- a/src/helpers/layout-helper.spec.js +++ b/src/helpers/layout-helper.spec.js @@ -1,28 +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" }); - // 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, + }, + ]; - 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'); - }); - -}) \ No newline at end of file + // Act + settleAllPromises(promiseResultMap).then((results) => { + // Assert + expect(results.MockResultOne).toEqual("test-data"); + expect(results.MockResultTwo).toEqual("test-data-two"); + }); +}); diff --git a/src/layouts/component-test/component-test.vue b/src/layouts/component-test/component-test.vue index 61614606a..f00d29231 100644 --- a/src/layouts/component-test/component-test.vue +++ b/src/layouts/component-test/component-test.vue @@ -2,245 +2,275 @@
-

Radio Card

+

Radio Card

-

Buttons

+

Buttons

+
+
+
+
+
-

List Button

+

List Button

-

Radio - Single-Line

+

Radio - Single-Line

-
+
-

Select Vehicle Year

+

+ Select Vehicle Year +

-

Radio - Multi-Line

+

Radio - Multi-Line

-
+
-

Select Vehicle Year

+

+ Select Vehicle Year +

-

Radio - Multi-Line Centered

+

Radio - Multi-Line Centered

-
+
-

Multi-Line Centered

+

+ Multi-Line Centered +

-

Radio Horizontal

+

Radio Horizontal

-
+
-

Select Vehicle Year

+

+ Select Vehicle Year +

-

Text Link

+

Text Link

@@ -250,19 +280,23 @@
-

Typogrophy

+

Typogrophy

This is default body copy font size/weight

-

This is small body copy using .small class

-

This is also small using <small> tag

+

+ This is small body copy using .small class +

+

+ This is also small using <small> tag +

-

Headings

+

Headings

@@ -297,119 +331,128 @@
-

Alerts

+

Alerts

-
-
-
-
-
+
+
+
+
+
-

Site Header

+

Site Header

- +
-

Vehicle Banner

+

Vehicle Banner

- +
diff --git a/src/layouts/loader-demo/loader-demo.vue b/src/layouts/loader-demo/loader-demo.vue index 4c19c4d21..0407f4fd4 100644 --- a/src/layouts/loader-demo/loader-demo.vue +++ b/src/layouts/loader-demo/loader-demo.vue @@ -7,11 +7,7 @@
- +
@@ -22,7 +18,7 @@ import loader from "@/ux-components/loader/loader"; export default { name: "App", components: { - loader - } + loader, + }, }; diff --git a/src/layouts/vehicle-year/vehicle-year.spec.js b/src/layouts/vehicle-year/vehicle-year.spec.js index 8190957e7..06cc0339b 100644 --- a/src/layouts/vehicle-year/vehicle-year.spec.js +++ b/src/layouts/vehicle-year/vehicle-year.spec.js @@ -2,16 +2,15 @@ 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' +import { nextTick } from "vue"; // Mock our module for promises. -jest.mock("@/helpers/layout-helper.js", () => ({ - settleAllPromises: jest.fn() +jest.mock("@/helpers/layout-helper.js", () => ({ + settleAllPromises: jest.fn(), })); describe("vehicle-year.vue", () => { test("vehicle-year.vue should render data from CMS", async () => { - // Arrange // Our mock data for our call to settleAllPromises @@ -19,31 +18,43 @@ describe("vehicle-year.vue", () => { getPageContent: { PageHeaderWidget: [{ HeaderText: "Select a year to get started" }], RadioQuestionWidget: [{ QuestionText: "What year is your vehicle?" }], - VehicleBannerWidget: [{ GenericVehicleImage: "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3" }], - SiteHeaderWidget: [{ "LogoImage": "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3" }], + VehicleBannerWidget: [ + { + GenericVehicleImage: + "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", + }, + ], + SiteHeaderWidget: [ + { + LogoImage: + "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3", + }, + ], isCmsContentReady: true, }, getVehicleYear: [2023, 2022, 2021], store: { commit: jest.fn(), - year: null + year: null, }, router: { - push: jest.fn() - } - } + push: jest.fn(), + }, + }; // our router information needed. const to = { query: { - fmgPage: 'vehicle-year' - } + fmgPage: "vehicle-year", + }, }; const mountOptions = getMountOptions(mockData); // our mock implementation of settleAllPromises - settleAllPromises.mockImplementation(() => { return Promise.resolve(mockData);}); + settleAllPromises.mockImplementation(() => { + return Promise.resolve(mockData); + }); // Act const wrapper = shallowMount(vehicleYear, mountOptions); @@ -52,7 +63,9 @@ describe("vehicle-year.vue", () => { // 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)); + vehicleYear.beforeRouteEnter.call(wrapper.vm, to, undefined, (c) => + c(wrapper.vm) + ); await nextTick(); // Wait for the DOM to update. @@ -60,7 +73,9 @@ describe("vehicle-year.vue", () => { const header = await wrapper.find(".Header"); expect(header.attributes("text")).toEqual("Select a year to get started"); - const yearQuestion = wrapper.findComponent({ name: 'year-question' }); - expect(yearQuestion.attributes("questiontext")).toEqual("What year is your vehicle?"); + 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 6681ea3d6..6a4c6c169 100644 --- a/src/layouts/vehicle-year/vehicle-year.vue +++ b/src/layouts/vehicle-year/vehicle-year.vue @@ -2,9 +2,15 @@
- + - +
@@ -29,16 +35,18 @@ export default { vehicleYears: [], siteHeaderWidget: {}, vehicleBannerWidget: {}, - selectedYear: null + selectedYear: null, }; }, computed: {}, beforeRouteEnter(to, from, next) { - // Call APIs const contentPromise = fetchCmsContentForPage(to.query.fmgPage); - const getVehicleYearPromise = store.dispatch(storeActions.GET_VEHICLE_YEARS, {}); + const getVehicleYearPromise = store.dispatch( + storeActions.GET_VEHICLE_YEARS, + {} + ); // Settle promises and get results const promiseResultMap = [ @@ -52,13 +60,14 @@ export default { }, ]; settleAllPromises(promiseResultMap).then((resultMap) => { - // Call the "next" function to complete the transition to this page. next((vm) => { vm.pageHeaderWidgets = resultMap.getPageContent.PageHeaderWidget[0]; vm.siteHeaderWidget = resultMap.getPageContent.SiteHeaderWidget[0]; - vm.radioQuestionWidgets = resultMap.getPageContent.RadioQuestionWidget[0]; - vm.vehicleBannerWidget = resultMap.getPageContent.VehicleBannerWidget[0]; + vm.radioQuestionWidgets = + resultMap.getPageContent.RadioQuestionWidget[0]; + vm.vehicleBannerWidget = + resultMap.getPageContent.VehicleBannerWidget[0]; vm.vehicleYears = resultMap.getVehicleYear; }); }); @@ -66,9 +75,9 @@ export default { watch: { selectedYear(year) { - this.$store.commit(this.storeMutations.UPDATE_YEAR, year); - this.$router.push('?fmgPage=vehicle-make'); - } + this.$store.commit(this.storeMutations.UPDATE_YEAR, year); + this.$router.push("?fmgPage=vehicle-make"); + }, }, components: { @@ -81,15 +90,15 @@ export default { 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 5e2ffeca7..a51d25810 100644 --- a/src/layouts/vehicle-year/year-question/year-question.spec.js +++ b/src/layouts/vehicle-year/year-question/year-question.spec.js @@ -1,21 +1,25 @@ import yearQuestion from "@/layouts/vehicle-year/year-question/year-question"; import { shallowMount } from "@vue/test-utils"; -describe('year-question.vue', () => { - test('year-question should take a prop for years and questionText, and trigger a selectYear function when an option is clicked.', async () => { - // Act - const wrapper = shallowMount(yearQuestion); - await wrapper.setProps({ - questionText: 'What year is your vehicle?', - years: ['2023', '2022', '2021'], - modelValue: '2020' - }); - wrapper.vm.$options.watch.selectedYear.call(wrapper.vm); - - // 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"); - expect(wrapper.componentVM.modelValue).toBe("2020"); +describe("year-question.vue", () => { + test("year-question should take a prop for years and questionText, and trigger a selectYear function when an option is clicked.", async () => { + // Act + const wrapper = shallowMount(yearQuestion); + await wrapper.setProps({ + questionText: "What year is your vehicle?", + years: ["2023", "2022", "2021"], + modelValue: "2020", }); -}); \ No newline at end of file + wrapper.vm.$options.watch.selectedYear.call(wrapper.vm); + + // 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"); + expect(wrapper.componentVM.modelValue).toBe("2020"); + }); +}); diff --git a/src/layouts/vehicle-year/year-question/year-question.vue b/src/layouts/vehicle-year/year-question/year-question.vue index 4c5bb8d30..b3d2f8279 100644 --- a/src/layouts/vehicle-year/year-question/year-question.vue +++ b/src/layouts/vehicle-year/year-question/year-question.vue @@ -1,33 +1,34 @@ diff --git a/src/mixins/base-mixin.js b/src/mixins/base-mixin.js index eb6142910..afe618125 100644 --- a/src/mixins/base-mixin.js +++ b/src/mixins/base-mixin.js @@ -3,10 +3,9 @@ import { storeMutations } from "@/constants/store-mutations.js"; import { widgetNames } from "@/constants/widget-names.js"; export default { - data(){ + data() { return { - isCmsContentReady: false - } + }; }, methods: { // dispatchBlockingStoreAction(type, payload) { diff --git a/src/mixins/base-mixin.spec.js b/src/mixins/base-mixin.spec.js index e3acbcbb7..b10a9bbb3 100644 --- a/src/mixins/base-mixin.spec.js +++ b/src/mixins/base-mixin.spec.js @@ -1,54 +1,53 @@ -import baseMixin from "@/mixins/base-mixin" +import baseMixin from "@/mixins/base-mixin"; import { storeActions } from "@/constants/store-actions.js"; import { widgetNames } from "@/constants/widget-names.js"; describe("baseMixin.js", () => { - test('dispatchNonblockingStoreAction: calls dispatch with type and payload', () => { - const mixIn = getMixInInstance({}); - const type = {}; - const payload = {}; + test("dispatchNonblockingStoreAction: calls dispatch with type and payload", () => { + const mixIn = getMixInInstance({}); + const type = {}; + const payload = {}; - mixIn.methods.dispatchNonBlockingStoreAction(type, payload); + mixIn.methods.dispatchNonBlockingStoreAction(type, payload); - expect(mixIn.methods.$store.dispatch).toBeCalledWith(type, payload); - }); + expect(mixIn.methods.$store.dispatch).toBeCalledWith(type, payload); + }); - test('dispatchNonblockingStoreAction: calls dispatch with type and payload, handles Uri encode', () => { - const mixIn = getMixInInstance({}); - const type = {}; - const payload = { make: 'Alfa Romeo/Chrysler' }; + test("dispatchNonblockingStoreAction: calls dispatch with type and payload, handles Uri encode", () => { + const mixIn = getMixInInstance({}); + const type = {}; + const payload = { make: "Alfa Romeo/Chrysler" }; - mixIn.methods.dispatchNonBlockingStoreAction(type, payload, true); + mixIn.methods.dispatchNonBlockingStoreAction(type, payload, true); - expect(mixIn.methods.$store.dispatch).toBeCalledWith(type, payload); - }); -}) + expect(mixIn.methods.$store.dispatch).toBeCalledWith(type, payload); + }); +}); function getMixInInstance({ isDispatchSuccess = true }) { + // Mock Store + const store = { + dispatch: jest.fn(), + }; - // Mock Store - const store = { - dispatch: jest.fn() - } + if (isDispatchSuccess) { + store.dispatch.mockReturnValue(Promise.resolve()); + } else { + store.dispatch.mockReturnValue(Promise.reject()); + } - if (isDispatchSuccess) { - store.dispatch.mockReturnValue(Promise.resolve()) - } else { - store.dispatch.mockReturnValue(Promise.reject()) - } + // Mock Route + const route = { + query: { + fmgPage: "test-page", + }, + }; - // Mock Route - const route = { - query: { - fmgPage: 'test-page' - } - }; + // Attach mocks to mixin + const baseMixIn = baseMixin; + baseMixIn.methods.$route = route; + baseMixIn.methods.$store = store; + baseMixIn.methods.storeActions = storeActions; + baseMixIn.methods.widgetNames = widgetNames; - // Attach mocks to mixin - const baseMixIn = baseMixin; - baseMixIn.methods.$route = route; - baseMixIn.methods.$store = store; - baseMixIn.methods.storeActions = storeActions; - baseMixIn.methods.widgetNames = widgetNames; - - return baseMixIn; -} \ No newline at end of file + return baseMixIn; +} diff --git a/src/router/index.js b/src/router/index.js index 24854555b..a93fe6e54 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -66,18 +66,20 @@ const routes = [ }, ]; - const router = createRouter({ history: createWebHistory("/fmg/"), routes, }); - //---------------------------------------------------------- Router Functions ---------------------------------------------------------- // Navigate to the next route, depending on the scenario. -router.navigate = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}) => { - +router.navigate = ( + scenario, + currentRoute, + optionalQuery = {}, + optionalParams = {} +) => { if (!scenario) { console.error("No scenario provided. Please review the routing table."); return; @@ -88,21 +90,31 @@ router.navigate = (scenario, currentRoute, optionalQuery = {}, optionalParams = if (matchingScenarioMap.destinationFmgPageValue !== undefined) { // We're always pushing the same path, just changing query strings. Make sure our optional query strings get combined with our fmgPage one. - router.push({ path: '/', query: Object.assign(optionalQuery, { fmgPage: matchingScenarioMap.destinationFmgPageValue }), params: optionalParams }); + router.push({ + path: "/", + query: Object.assign(optionalQuery, { + fmgPage: matchingScenarioMap.destinationFmgPageValue, + }), + params: optionalParams, + }); } else if (matchingScenarioMap.destinationUrl !== undefined) { navigateToUrl(matchingScenarioMap.destinationUrl); } - -} +}; // Get navigation map depeding on the scenario and the current 'page' you're on. router.getNavigationMap = (scenario, currentRoute) => { - const fmgPageValue = currentRoute.query.fmgPage; - const matchedQueryValue = routingTable.filter(item => (item.fmgPageValue === fmgPageValue) && item.maps.filter(map => map.scenario === scenario).length > 0).map(m => m.maps.filter(map => map.scenario === scenario)); + const matchedQueryValue = routingTable + .filter( + (item) => + item.fmgPageValue === fmgPageValue && + item.maps.filter((map) => map.scenario === scenario).length > 0 + ) + .map((m) => m.maps.filter((map) => map.scenario === scenario)); return matchedQueryValue[0][0]; -} +}; //---------------------------------------------------------- Private Functions ---------------------------------------------------------- diff --git a/src/router/router-constants/fmgPage-values.js b/src/router/router-constants/fmgPage-values.js index ee3031bff..e84d9e9ea 100644 --- a/src/router/router-constants/fmgPage-values.js +++ b/src/router/router-constants/fmgPage-values.js @@ -1,6 +1,6 @@ const fmgPageValues = { - VEHICLE_YEAR: 'vehicle-year', - VEHICLE_MAKE: 'vehicle-make', + VEHICLE_YEAR: "vehicle-year", + VEHICLE_MAKE: "vehicle-make", }; -export { fmgPageValues }; \ No newline at end of file +export { fmgPageValues }; diff --git a/src/router/router-constants/navigation-scenarios.js b/src/router/router-constants/navigation-scenarios.js index 5db881eef..3fc642d65 100644 --- a/src/router/router-constants/navigation-scenarios.js +++ b/src/router/router-constants/navigation-scenarios.js @@ -1,5 +1,5 @@ -const navigationScenarios = { - SELECTED_YEAR: 'SELECTED_YEAR', +const navigationScenarios = { + SELECTED_YEAR: "SELECTED_YEAR", }; -export { navigationScenarios } ; \ No newline at end of file +export { navigationScenarios }; diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js index 584161f43..7f3f3d0d1 100644 --- a/src/router/router-constants/routing-table.js +++ b/src/router/router-constants/routing-table.js @@ -1,14 +1,16 @@ -import { fmgPageValues } from '@/router/router-constants/fmgPage-values'; -import { navigationScenarios } from '@/router/router-constants/navigation-scenarios'; +import { fmgPageValues } from "@/router/router-constants/fmgPage-values"; +import { navigationScenarios } from "@/router/router-constants/navigation-scenarios"; const routingTable = [ - { - fmgPageValue: fmgPageValues.VEHICLE_YEAR, - maps: [ - { scenario: navigationScenarios.SELECTED_YEAR, destinationFmgPageValue: fmgPageValues.VEHICLE_MAKE } - ] - }, - -] + { + fmgPageValue: fmgPageValues.VEHICLE_YEAR, + maps: [ + { + scenario: navigationScenarios.SELECTED_YEAR, + destinationFmgPageValue: fmgPageValues.VEHICLE_MAKE, + }, + ], + }, +]; -export { routingTable }; \ No newline at end of file +export { routingTable }; diff --git a/src/store/index.js b/src/store/index.js index ec8dfa4e3..036694868 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -32,7 +32,7 @@ export default createStore({ zipCode: null, firstName: null, lastName: null, - licensePlate: null + licensePlate: null, }, damage: { isRepair: null, @@ -52,16 +52,16 @@ export default createStore({ isCash: null, }, referralSeqNum: null, - } + }, }, applicationUser: { experiments: null, - } + }, }, // See IMPORTANT note at top of "state" declaration. mutations: { - updateYear(state, year){ + updateYear(state, year) { state.order.vehicle.year = year; }, }, @@ -86,7 +86,7 @@ export default createStore({ method: endpoints.LookupVehicleByVin.method, endpoint: endpoints.LookupVehicleByVin.url, payload: { - "vin": vin // EX "1J4GW58S4XC541166" + vin: vin, // EX "1J4GW58S4XC541166" }, }); }, @@ -135,6 +135,6 @@ export default createStore({ endpoint: relativeUrl, payload: {}, }); - } + }, }, }); diff --git a/src/store/store.spec.js b/src/store/store.spec.js index 6f69b1a92..76acc0dbf 100644 --- a/src/store/store.spec.js +++ b/src/store/store.spec.js @@ -1,121 +1,131 @@ -import store from './index' -import globalMethods from '@/global-methods' +import store from "./index"; +import globalMethods from "@/global-methods"; describe("Actions", () => { - it("Should return list of years retrieved", async () => { - // Arrange - let years = []; + it("Should return list of years retrieved", async () => { + // Arrange + let years = []; - // Act - globalMethods.callHttpClient = jest.fn(); - globalMethods.callHttpClient.mockImplementation(() => { - return Promise.resolve({ data: [2023,2022,2021]}); - }); - await store.dispatch('getVehicleYears') - .then( (response) => { - years = response.data; - }); - - // Assert - expect(years[0]).toBe(2023); + // Act + globalMethods.callHttpClient = jest.fn(); + globalMethods.callHttpClient.mockImplementation(() => { + return Promise.resolve({ data: [2023, 2022, 2021] }); + }); + await store.dispatch("getVehicleYears").then((response) => { + years = response.data; }); - it("Should return list of makes retrieved", async () => { - // Arrange - let makes = []; + // Assert + expect(years[0]).toBe(2023); + }); - // Act - globalMethods.callHttpClient.mockImplementation(() => { - return Promise.resolve({ data: ['Baic','Honda','Ford']}); - }); - await store.dispatch('getVehicleMakes', {year: 2023}) - .then( (response) => { - makes = response.data; - }); + it("Should return list of makes retrieved", async () => { + // Arrange + let makes = []; - // Assert - expect(makes[0]).toBe('Baic'); + // Act + globalMethods.callHttpClient.mockImplementation(() => { + return Promise.resolve({ data: ["Baic", "Honda", "Ford"] }); + }); + await store.dispatch("getVehicleMakes", { year: 2023 }).then((response) => { + makes = response.data; }); - it("Should return list of models retrieved", async () => { - // Arrange - let models = []; + // Assert + expect(makes[0]).toBe("Baic"); + }); - // Act - globalMethods.callHttpClient.mockImplementation(() => { - return Promise.resolve({ data: ['BJ40 (MEX)','Civic','Accord']}); - }); - await store.dispatch('getVehicleModels', {year: 2023, make: 'Baic'}) - .then( (response) => { - models = response.data; - }); + it("Should return list of models retrieved", async () => { + // Arrange + let models = []; - // Assert - expect(models[0]).toBe('BJ40 (MEX)'); + // Act + globalMethods.callHttpClient.mockImplementation(() => { + return Promise.resolve({ data: ["BJ40 (MEX)", "Civic", "Accord"] }); }); + await store + .dispatch("getVehicleModels", { year: 2023, make: "Baic" }) + .then((response) => { + models = response.data; + }); - it("Should return list of styles retrieved", async () => { - // Arrange - let styles = []; + // Assert + expect(models[0]).toBe("BJ40 (MEX)"); + }); - // Act - globalMethods.callHttpClient.mockImplementation(() => { - return Promise.resolve({ data: ['4 DOOR UTILITY','2 DOOR']}); - }); - await store.dispatch('getVehicleStyles', {year: 2023, make: 'Baic', model: 'BJ40 (MEX)'}) - .then( (response) => { - styles = response.data; - }); + it("Should return list of styles retrieved", async () => { + // Arrange + let styles = []; - // Assert - expect(styles[0]).toBe('4 DOOR UTILITY'); + // Act + globalMethods.callHttpClient.mockImplementation(() => { + return Promise.resolve({ data: ["4 DOOR UTILITY", "2 DOOR"] }); }); + await store + .dispatch("getVehicleStyles", { + year: 2023, + make: "Baic", + model: "BJ40 (MEX)", + }) + .then((response) => { + styles = response.data; + }); - it("Should return data from url retrieved", async () => { - // Arrange - let routeInfo = []; + // Assert + expect(styles[0]).toBe("4 DOOR UTILITY"); + }); - // Act - globalMethods.callHttpClient.mockImplementation(() => { - return Promise.resolve({ data: { - Result: 'Route Info Data' - }}); - }); - await store.dispatch('getRouteInfo', { pageName: 'vehicle-year' }) - .then( (response) => { - routeInfo = response.data.Result; - }); + it("Should return data from url retrieved", async () => { + // Arrange + let routeInfo = []; - // Assert - expect(routeInfo).toBe('Route Info Data'); + // Act + globalMethods.callHttpClient.mockImplementation(() => { + return Promise.resolve({ + data: { + Result: "Route Info Data", + }, + }); }); + await store + .dispatch("getRouteInfo", { pageName: "vehicle-year" }) + .then((response) => { + routeInfo = response.data.Result; + }); - it("Should return page data from url retrieved", async () => { - // Arrange - let pageData = []; + // Assert + expect(routeInfo).toBe("Route Info Data"); + }); - // Act - globalMethods.callHttpClient.mockImplementation(() => { - return Promise.resolve({ data: { - Result: 'Page Info Data' - }}); - }); - await store.dispatch('getPageData', { pageName: 'vehicle-year' }) - .then( (response) => { - pageData = response.data.Result; - }); + it("Should return page data from url retrieved", async () => { + // Arrange + let pageData = []; - // Assert - expect(pageData).toBe('Page Info Data'); + // Act + globalMethods.callHttpClient.mockImplementation(() => { + return Promise.resolve({ + data: { + Result: "Page Info Data", + }, + }); }); -}) + await store + .dispatch("getPageData", { pageName: "vehicle-year" }) + .then((response) => { + pageData = response.data.Result; + }); + + // Assert + expect(pageData).toBe("Page Info Data"); + }); +}); describe("Mutations", () => { - it("Should update the year property in the store", () => { - // Act - store.commit('updateYear', 2020); + it("Should update the year property in the store", () => { + // Act + store.commit("updateYear", 2020); - // Assert - expect(store.state.order.vehicle.year).toBe(2020); - }); -}); \ No newline at end of file + // Assert + expect(store.state.order.vehicle.year).toBe(2020); + }); +}); diff --git a/src/ux-components/alert/alert.spec.js b/src/ux-components/alert/alert.spec.js index 882a68129..3d0843e10 100644 --- a/src/ux-components/alert/alert.spec.js +++ b/src/ux-components/alert/alert.spec.js @@ -1 +1 @@ -test.todo('some test to be written in the future'); \ No newline at end of file +test.todo("some test to be written in the future"); diff --git a/src/ux-components/alert/alert.vue b/src/ux-components/alert/alert.vue index 7358073df..89bd366a3 100644 --- a/src/ux-components/alert/alert.vue +++ b/src/ux-components/alert/alert.vue @@ -1,12 +1,25 @@ @@ -24,7 +24,7 @@ export default { isDisabled: Boolean, loaderColor: String, loaderPosition: String, - sizeInRem: [Number,String] + sizeInRem: [Number, String], }, data() { return { diff --git a/src/ux-components/button-secondary/button-secondary.vue b/src/ux-components/button-secondary/button-secondary.vue index f6dd62631..ec4d7ec0c 100644 --- a/src/ux-components/button-secondary/button-secondary.vue +++ b/src/ux-components/button-secondary/button-secondary.vue @@ -3,14 +3,14 @@ :disabled="isDisabled" :aria-disabled="isDisabled" class="btn btn-secondary d-flex align-items-center py-3 px-4" - @click='displayComponent' - > + @click="displayComponent" + > {{ this.buttonText }} @@ -24,7 +24,7 @@ export default { isDisabled: Boolean, loaderColor: String, loaderPosition: String, - sizeInRem: [Number,String] + sizeInRem: [Number, String], }, data() { return { diff --git a/src/ux-components/header/header.vue b/src/ux-components/header/header.vue index 0749c0462..95e1e89a6 100644 --- a/src/ux-components/header/header.vue +++ b/src/ux-components/header/header.vue @@ -1,7 +1,9 @@ diff --git a/src/ux-components/list-button/list-button.vue b/src/ux-components/list-button/list-button.vue index 303ccdf2a..52997d5d6 100644 --- a/src/ux-components/list-button/list-button.vue +++ b/src/ux-components/list-button/list-button.vue @@ -1,21 +1,27 @@