diff --git a/src/helpers/unit-test-helper.js b/src/helpers/unit-test-helper.js index e9ffeceb..4cee713a 100644 --- a/src/helpers/unit-test-helper.js +++ b/src/helpers/unit-test-helper.js @@ -1,4 +1,5 @@ import { navigationScenarios } from "@/router/router-constants/navigation-scenarios.js"; +import { RouterLinkStub } from "@vue/test-utils"; import { vehicleCategories } from "@/constants/vehicle-categories.js"; import { issPageValues } from "@/router/router-constants/issPage-values"; import { cookieNames } from "@/constants/cookie-names"; @@ -52,7 +53,10 @@ export function getMountOptions(mockData) { mocks: mocks, mixins: [mockMixin], plugins: [pinia], - stubs: { Form } + stubs: { + Form, + RouterLink: RouterLinkStub, + } }; return { global }; diff --git a/src/layouts/vehicle-style/vehicle-style.spec.js b/src/layouts/vehicle-style/vehicle-style.spec.js index 41cf7b06..6a383572 100644 --- a/src/layouts/vehicle-style/vehicle-style.spec.js +++ b/src/layouts/vehicle-style/vehicle-style.spec.js @@ -6,11 +6,15 @@ import baseMixin from "@/mixins/base-mixin.js"; import { getMountOptions } from "@/helpers/unit-test-helper.js"; import { nextTick } from "vue"; import { useMainStore } from "@/store"; +import router from "@/router"; // Components import vehicleStyle from "@/layouts/vehicle-style/vehicle-style.vue"; import styleQuestion from "@/layouts/vehicle-style/style-question/style-question"; +jest.mock("@/router", () => ({ + overrideNavigation: jest.fn(), +})); // Mock our module for promises. jest.mock("@/helpers/layout-helper.js", () => ({ @@ -86,7 +90,8 @@ describe("vehicle-style.vue", () => { test("Model set, arePagePrerequisitesValid should be true ", () => { //Arrange - const { wrapper } = setupMocks({}); + const { wrapper } = setupMocks({ }); + useMainStore().order.vehicle = { year: 2011, make: "ford", model: "mustang", style: null } //Act @@ -96,6 +101,65 @@ describe("vehicle-style.vue", () => { expect(arePagePrerequisitesValid).toBe(true); }); + test("there is only one vehicle style => autoselect and move to vehicle damage", async () => { + //Arrange + const { wrapper } = setupMocks({ + styleQuestionInitialData: ["2 door sedan"], + }); + + useMainStore().applicationUser.pageData = { + "part-questions": null, + "vehicle-make": {}, + "vehicle-model": {}, + "vehicle-style": {}, + } + + useMainStore().updateVehicleStyle = jest.fn(); + useMainStore().setVehicle = jest.fn().mockReturnValue(Promise.resolve()) + + // Act + await vehicleStyle.beforeRouteEnter.call( + wrapper.vm, + { query: { issPage: "vehicle-style" } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(useMainStore().updateVehicleStyle).toHaveBeenCalledWith("2 door sedan"); + expect(router.overrideNavigation).toHaveBeenCalled(); + }); + + + test("there is only one vehicle style and vehicle-damage was visited => don't autoselect or move to vehicle damage", async () => { + //Arrange + const { wrapper } = setupMocks({ + styleQuestionInitialData: ["2 door sedan"], + }); + + useMainStore().updateVehicleStyle = jest.fn(); + useMainStore().setVehicle = jest.fn().mockReturnValue(Promise.resolve()) + + useMainStore().applicationUser.pageData = { + "part-questions": null, + "vehicle-make": {}, + "vehicle-model": {}, + "vehicle-style": {}, + "vehicle-damage": {}, + } + + // Act + await vehicleStyle.beforeRouteEnter.call( + wrapper.vm, + { query: { issPage: "vehicle-style" } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(useMainStore().updateVehicleStyle).not.toHaveBeenCalledWith("2 door sedan"); + expect(router.overrideNavigation).toHaveBeenCalled(); + }); }); function setupMocks({ @@ -132,6 +196,7 @@ function setupMocks({ initializeComponent: jest.fn(), }; + const mountOptions = getMountOptions(mountOptionsMockData); const wrapper = shallowMount(vehicleStyle, mountOptions); diff --git a/src/layouts/vehicle-style/vehicle-style.vue b/src/layouts/vehicle-style/vehicle-style.vue index 4c48f960..fe56d2a5 100644 --- a/src/layouts/vehicle-style/vehicle-style.vue +++ b/src/layouts/vehicle-style/vehicle-style.vue @@ -30,6 +30,10 @@ import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; // Supporting files import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; +import { issPageValues } from "@/router/router-constants/issPage-values" +import { useMainStore } from "@/store"; +import router from "@/router"; +import { navigationScenarios } from "@/router/router-constants/navigation-scenarios"; export default { name: "vehicle-style", @@ -57,10 +61,23 @@ export default { ]; const resultMap = await settleAllPromises(promiseResultMap); - next((vm) => { - vm.setCmsContent(resultMap.cmsContent); - vm.$refs.styleQuestion.initializeComponent(resultMap.styleQuestionInitialData); - }); + + const visitedVehicleDamage = useMainStore().pageData(issPageValues.VEHICLE_DAMAGE) ? true : false; + + // If we have exactly one style then navigate directly to vehicle-damage + if (resultMap.styleQuestionInitialData.length === 1 && !visitedVehicleDamage) { + useMainStore().updateVehicleStyle(resultMap.styleQuestionInitialData[0]); + + useMainStore().setVehicle().then(() => { + router.overrideNavigation(navigationScenarios.SELECTED_STYLE, to, next, true); + }); + + } else { + next((vm) => { + vm.setCmsContent(resultMap.cmsContent); + vm.$refs.styleQuestion.initializeComponent(resultMap.styleQuestionInitialData); + }); + } }, methods: { diff --git a/src/router/index.js b/src/router/index.js index 92cc932a..e5947696 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -106,6 +106,27 @@ async function GetRouteInfoFromPageName(pageName) { return routeData; }; +//Use this navigation when you need to call next() explicitly. beforeRouteEnter is a good example. +router.overrideNavigation = ( + scenario, + currentRoute, + next, + isSavingNavigation, + optionalQuery = {}, + optionalParams = {}, + optionalPageData +) => { + navigate( + scenario, + currentRoute, + isSavingNavigation, + optionalQuery, + optionalParams, + optionalPageData + ); + next(); +}; + router.navigate = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {}) => { navigate(scenario, currentRoute, false, optionalQuery, optionalParams, optionalPageData); diff --git a/src/ux-components/alert/alert.spec.js b/src/ux-components/alert/alert.spec.js index fcccbf4f..a4596d19 100644 --- a/src/ux-components/alert/alert.spec.js +++ b/src/ux-components/alert/alert.spec.js @@ -1,5 +1,6 @@ -import { shallowMount } from "@vue/test-utils"; +import { shallowMount, RouterLinkStub } from "@vue/test-utils";RouterLinkStub import { getMountOptions } from "@/helpers/unit-test-helper.js"; + import alert from "./alert"; describe("alert.vue", () => { @@ -60,12 +61,11 @@ describe("alert.vue", () => { manualHeadline: "testHeader", manualCopy: "testCopy with a {routerLink: testName, testLink} inside of it", cmsWidgetName: "alert", - }, - stubs: ["router-link"], + } }) ); // Assert - expect(wrapper.find("router-link").exists()).toBe(true); + expect(wrapper.findComponent(RouterLinkStub).exists()).toBe(true); }); it("Should contain 'n+1'
tags if the body copy has 'n'
tags", () => { @@ -79,7 +79,6 @@ describe("alert.vue", () => { "
testCopy with a {routerLink: testName, testLink} inside of it
and two paragraphs
", cmsWidgetName: "alert", }, - stubs: ["router-link"], }) ); // Assert @@ -150,6 +149,7 @@ describe("alert.vue", () => { shouldScrollToOnMount: false, manualHeadline: "testHeader", manualCopy: "testCopy", + cmsWidgetName: "alert", }, }) ); @@ -193,6 +193,9 @@ const mockMixin = { dynamicStrings: jest.fn(() => { return { ROUTER_LINK: "routerLink:" }; }), + cssClassNameForCmsWidget(){ + return "widget-name-"; + }, }, }; @@ -215,6 +218,7 @@ function setupMocks(mountOptionsMockData = {}) { propsData: { manualHeadline: "testHeader", manualCopy: "testCopy", + cmsWidgetName: "alert", }, mixins: [mockMixin], };