diff --git a/src/layouts/vehicle-damage/vehicle-damage.spec.js b/src/layouts/vehicle-damage/vehicle-damage.spec.js index caf008b78..0dbcc5c69 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.spec.js +++ b/src/layouts/vehicle-damage/vehicle-damage.spec.js @@ -12,6 +12,8 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { shallowMount } from "@vue/test-utils"; import { getMountOptions } from "@/helpers/unit-test-helper.js"; import { nextTick } from "vue"; +import { storeActions } from "@/constants/store-actions"; +import store from "@/store"; // Mock our module for promises. jest.mock("@/helpers/layout-helper.js", () => ({ @@ -25,6 +27,8 @@ jest.mock("@/helpers/cms-content-helper", () => ({ // Mock Store jest.mock("@/store", () => ({ + commit: jest.fn(), + dispatch: jest.fn(), getters: { vehicle: { carId: "C00000000", @@ -137,6 +141,28 @@ describe("vehicle-damage.vue", () => { }); }); +describe("vehicle-damage.vue", () => { + test("Call invalidation, ResetPartsAndDeps should be called", async () => { + + //Arrange + const { wrapper } = setupMocks({}); + + //Act + vehicleDamage.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "vehicle-damage" } }, + undefined, + (c) => c(wrapper.vm) + ); + + wrapper.vm.resetDependentState(); + + //Assert + expect(store.dispatch).toBeCalledWith(storeActions.RESET_PARTS_AND_DEPS) + + }); +}); + function setupMocks({ pageHeaderWidgetHeaderText = {}, mountOptionsMockData = {}, diff --git a/src/layouts/vehicle-make/vehicle-make.spec.js b/src/layouts/vehicle-make/vehicle-make.spec.js index b3a006c20..b2c4dcaf7 100644 --- a/src/layouts/vehicle-make/vehicle-make.spec.js +++ b/src/layouts/vehicle-make/vehicle-make.spec.js @@ -1,15 +1,23 @@ -import { shallowMount, flushPromises } from "@vue/test-utils"; +// Supporting Files +import { shallowMount } from "@vue/test-utils"; import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import { settleAllPromises } from "@/helpers/layout-helper.js"; +import { nextTick } from "vue"; +import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; +import { storeMutations } from "@/constants/store-mutations"; +import { storeActions } from "@/constants/store-actions"; + +// Components import vehicleMake from "@/layouts/vehicle-make/vehicle-make.vue"; import makeQuestion from "@/layouts/vehicle-make/make-question/make-question"; import funnelHeader from "@/common-components/funnel-header/funnel-header"; import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header"; -import { settleAllPromises } from "@/helpers/layout-helper.js"; -import { nextTick } from "vue"; -import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; +import store from "@/store"; jest.mock("@/store", () => ({ + commit: jest.fn(), + dispatch: jest.fn(), getters: { vehicle: { year: 2019, @@ -27,9 +35,6 @@ jest.mock("@/helpers/layout-helper.js", () => ({ settleAllPromises: jest.fn(), })); -beforeEach(() => { - jest.resetModules(); -}); describe("vehicle-make.vue", () => { test("Make question component is initized with api data", async (done) => { @@ -153,7 +158,7 @@ describe("vehicle-make.vue", () => { pageHeaderWidgetHeaderText: "Select a make to get started", mountOptionsMockData: { router: { - navigateForward: jest.fn(), + navigate: jest.fn(), }, }, }); @@ -170,7 +175,7 @@ describe("vehicle-make.vue", () => { //Assert apiPromise.finally(() => { - expect(wrapper.vm.$router.navigateForward).toHaveBeenCalled(); + expect(wrapper.vm.$router.navigate).toHaveBeenCalled(); done(); }); }); @@ -190,13 +195,40 @@ describe("vehicle-make.vue", () => { ); let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); - await nextTick(); //Assert expect(arePagePrerequisitesValid).toBe(true); }); }); +describe("vehicle-make.vue", () => { + test("Year set, call invalidation, model, style, carId, category should be null", async () => { + + //Arrange + const { wrapper } = setupMocks({}); + + //Act + vehicleMake.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "vehicle-make" } }, + undefined, + (c) => c(wrapper.vm) + ); + + wrapper.vm.resetDependentState(); + + //Assert + expect(store.commit).toBeCalledWith(storeMutations.UPDATE_MODEL, null) + expect(store.commit).toBeCalledWith(storeMutations.UPDATE_STYLE, null) + expect(store.commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null) + expect(store.commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null) + + expect(store.dispatch).toBeCalledWith(storeActions.RESET_DAMAGE_AND_DEPS) + expect(store.dispatch).toBeCalledWith(storeActions.RESET_REGISTRATION_AND_DEPS) + + }); +}); + function setupMocks({ vehicleMakeQuestionCmsContent = {}, makeQuestionInitialData = {}, diff --git a/src/layouts/vehicle-make/vehicle-make.vue b/src/layouts/vehicle-make/vehicle-make.vue index f95172547..b7be8f578 100644 --- a/src/layouts/vehicle-make/vehicle-make.vue +++ b/src/layouts/vehicle-make/vehicle-make.vue @@ -78,7 +78,7 @@ export default { methods: { backButtonAction() { // route to move backwards - this.$router.navigateForward( + this.$router.navigate( this.navigationScenarios.CLICKED_BACK, this.$route ); diff --git a/src/layouts/vehicle-model/vehicle-model.spec.js b/src/layouts/vehicle-model/vehicle-model.spec.js index b1e240288..7f8f96eb6 100644 --- a/src/layouts/vehicle-model/vehicle-model.spec.js +++ b/src/layouts/vehicle-model/vehicle-model.spec.js @@ -7,10 +7,13 @@ import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-he // Supporting files import { settleAllPromises } from "@/helpers/layout-helper.js"; -import { shallowMount, flushPromises } from "@vue/test-utils"; +import { shallowMount } from "@vue/test-utils"; import { getMountOptions } from "@/helpers/unit-test-helper.js"; import { nextTick } from "vue"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; +import { storeMutations } from "@/constants/store-mutations"; +import { storeActions } from "@/constants/store-actions"; +import store from "@/store"; // Mock our module for promises. jest.mock("@/helpers/layout-helper.js", () => ({ @@ -24,6 +27,8 @@ jest.mock("@/helpers/cms-content-helper", () => ({ // Mock Store jest.mock("@/store", () => ({ + commit: jest.fn(), + dispatch: jest.fn(), getters: { vehicle: { make: "Acura", @@ -141,7 +146,7 @@ describe("vehicle-model.vue", () => { pageHeaderWidgetHeaderText: "Select a model to get started", mountOptionsMockData: { router: { - navigateForward: jest.fn(), + navigate: jest.fn(), }, }, }); @@ -156,7 +161,7 @@ describe("vehicle-model.vue", () => { await nextTick(); //Assert apiPromise.finally(() => { - expect(wrapper.vm.$router.navigateForward).toHaveBeenCalled(); + expect(wrapper.vm.$router.navigate).toHaveBeenCalled(); done(); }); }); @@ -182,6 +187,33 @@ describe("vehicle-model.vue", () => { }); }); +describe("vehicle-model.vue", () => { + test("Year set, call invalidation, style, carId, category should be null", async () => { + + //Arrange + const { wrapper } = setupMocks({}); + + //Act + vehicleModel.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "vehicle-model" } }, + undefined, + (c) => c(wrapper.vm) + ); + + wrapper.vm.resetDependentState(); + + //Assert + expect(store.commit).toBeCalledWith(storeMutations.UPDATE_STYLE, null) + expect(store.commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null) + expect(store.commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null) + + expect(store.dispatch).toBeCalledWith(storeActions.RESET_DAMAGE_AND_DEPS) + expect(store.dispatch).toBeCalledWith(storeActions.RESET_REGISTRATION_AND_DEPS) + + }); +}); + function setupMocks({ buttonQuestionContent = {}, modelQuestionInitialData = {}, diff --git a/src/layouts/vehicle-model/vehicle-model.vue b/src/layouts/vehicle-model/vehicle-model.vue index 06794e9a2..72faea5a1 100644 --- a/src/layouts/vehicle-model/vehicle-model.vue +++ b/src/layouts/vehicle-model/vehicle-model.vue @@ -79,7 +79,7 @@ export default { methods: { backButtonAction() { // route to move backwards - this.$router.navigateForward( + this.$router.navigate( this.navigationScenarios.CLICKED_BACK, this.$route ); diff --git a/src/layouts/vehicle-style/vehicle-style.spec.js b/src/layouts/vehicle-style/vehicle-style.spec.js index e52818cf6..183b22d57 100644 --- a/src/layouts/vehicle-style/vehicle-style.spec.js +++ b/src/layouts/vehicle-style/vehicle-style.spec.js @@ -154,7 +154,7 @@ describe("vehicle-style.vue", () => { pageHeaderWidgetHeaderText: "Select a style to get started", mountOptionsMockData: { router: { - navigateForward: jest.fn(), + navigate: jest.fn(), }, }, }); @@ -171,7 +171,7 @@ describe("vehicle-style.vue", () => { //Assert apiPromise.finally(() => { - expect(wrapper.vm.$router.navigateForward).toHaveBeenCalled(); + expect(wrapper.vm.$router.navigate).toHaveBeenCalled(); done(); }); }); diff --git a/src/layouts/vehicle-style/vehicle-style.vue b/src/layouts/vehicle-style/vehicle-style.vue index ec1cd4598..8cf948cdc 100644 --- a/src/layouts/vehicle-style/vehicle-style.vue +++ b/src/layouts/vehicle-style/vehicle-style.vue @@ -78,7 +78,7 @@ export default { methods: { backButtonAction() { // route to move backwards - this.$router.navigateForward( + this.$router.navigate( this.navigationScenarios.CLICKED_BACK, this.$route ); diff --git a/src/layouts/vehicle-year/vehicle-year.spec.js b/src/layouts/vehicle-year/vehicle-year.spec.js index 9b27e6555..5ef3ea404 100644 --- a/src/layouts/vehicle-year/vehicle-year.spec.js +++ b/src/layouts/vehicle-year/vehicle-year.spec.js @@ -1,18 +1,35 @@ import { shallowMount, flushPromises } from "@vue/test-utils"; import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import { settleAllPromises } from "@/helpers/layout-helper.js"; +import { nextTick } from "vue"; +import { storeMutations } from "@/constants/store-mutations"; +import { storeActions } from "@/constants/store-actions"; +import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; + import vehicleYear from "@/layouts/vehicle-year/vehicle-year.vue"; import yearQuestion from "@/layouts/vehicle-year/year-question/year-question"; import funnelHeader from "@/common-components/funnel-header/funnel-header"; import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header"; -import { settleAllPromises } from "@/helpers/layout-helper.js"; -import { nextTick } from "vue"; + +import store from "@/store"; + +jest.mock("@/store", () => ({ + commit: jest.fn(), + dispatch: jest.fn(), +})); // Mock our module for promises. jest.mock("@/helpers/layout-helper.js", () => ({ settleAllPromises: jest.fn(), })); +// Mock fetchCmsContentForPage +jest.mock("@/helpers/cms-content-helper", () => ({ + fetchCmsContentForPage: jest.fn(), +})); + + describe("vehicle-year.vue", () => { test("Year question component is initized with api data", async (done) => { //Arrange @@ -123,6 +140,34 @@ describe("vehicle-year.vue", () => { }); }); +describe("vehicle-year.vue", () => { + test("Year set, call invalidation, make, model, style, carId, category should be null", async () => { + + //Arrange + const { wrapper } = setupMocks({}); + + //Act + vehicleYear.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "vehicle-year" } }, + undefined, + (c) => c(wrapper.vm) + ); + + wrapper.vm.resetDependentState(); + + //Assert + expect(store.commit).toBeCalledWith(storeMutations.UPDATE_MAKE, null) + expect(store.commit).toBeCalledWith(storeMutations.UPDATE_MODEL, null) + expect(store.commit).toBeCalledWith(storeMutations.UPDATE_STYLE, null) + expect(store.commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null) + expect(store.commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null) + + expect(store.dispatch).toBeCalledWith(storeActions.RESET_DAMAGE_AND_DEPS) + expect(store.dispatch).toBeCalledWith(storeActions.RESET_REGISTRATION_AND_DEPS) + + }); +}); function setupMocks({ vehicleYearQuestionCmsContent = {}, yearQuestionInitialData = {}, @@ -146,7 +191,9 @@ function setupMocks({ yearQuestionInitialData: yearQuestionInitialData, }; const apiPromise = Promise.resolve(apiResponses); + settleAllPromises.mockImplementation(() => apiPromise); + fetchCmsContentForPage.mockImplementation(() => Promise.resolve()); //Mock year question methods yearQuestion.methods = { @@ -162,6 +209,7 @@ function setupMocks({ funnelSubHeader.methods = { initializeComponent: jest.fn(), }; + const mountOptions = getMountOptions(mountOptionsMockData); const wrapper = shallowMount(vehicleYear, mountOptions); const yearQuestionWrapper = wrapper.findComponent({ name: "yearQuestion" }); diff --git a/src/router/index.js b/src/router/index.js index ac31a1c6d..02859e660 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -102,7 +102,7 @@ const router = createRouter({ //---------------------------------------------------------- Router Functions ---------------------------------------------------------- -router.navigateForward = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}) => { +router.navigate = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}) => { navigate(scenario, currentRoute, false, optionalQuery, optionalParams); } diff --git a/src/store/index.js b/src/store/index.js index 22107ab76..41a78c5c8 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -35,7 +35,6 @@ export default createStore({ // See IMPORTANT note at top of "state" declaration. mutations: { - // VEHICLE MUTATIONS updateYear(state, year) { state.order.vehicle.year = year; diff --git a/src/store/store.spec.js b/src/store/store.spec.js index e71f07909..0fd96f719 100644 --- a/src/store/store.spec.js +++ b/src/store/store.spec.js @@ -1,16 +1,240 @@ -import store from "./index"; import globalMethods from "@/global-methods"; +import store from "@/store"; + +// Mock Store +jest.mock("@/store", () => ({ + commit: jest.fn(), + dispatch: jest.fn(), + // IMPORTANT: Be VERY careful when modifying these fields for at least a few reasons: + // * The CMS can reference the fields by name + // * Return users may have a previous "version" of the model, and we don't want + // them to have a breaking experience, because the model might have changed. + state: { + order: { + vehicle: { + year: null, + make: null, + model: null, + style: null, + carId: null, + category: null, + damage: { + isRepair: null, + numberOfChips: null, + glassToReplace: null, + }, + }, + }, + applicationUser: { + eventBus: [], + }, + }, + // See IMPORTANT note at top of "state" declaration. + + mutations: { + // VEHICLE MUTATIONS + updateYear: jest.fn(), + updateMake: jest.fn(), + updateModel(state, model) { + state.order.vehicle.model = model; + }, + updateStyle(state, style) { + state.order.vehicle.style = style; + }, + updateCarId(state, carId) { + state.order.vehicle.carId = carId; + }, + updateVehicleCategory(state, category) { + state.order.vehicle.category = category; + }, + updateVehicle(state, data) { + state.order.vehicle.carId = data.carId; + state.order.vehicle.category = data.category; + }, + + // EVENT BUS MUTATIONS + addEventToBus(state, event) { + state.applicationUser.eventBus.push(event); + }, + removeEventFromBus(state, eventData) { + const matchedEvent = state.applicationUser.eventBus.find( + ({ category, subCategory }) => + category === eventData.category && + subCategory === eventData.subCategory + ); + const itemIndex = state.applicationUser.eventBus.indexOf(matchedEvent); + + // If the item exists, remove it. + if (itemIndex > -1) { + state.applicationUser.eventBus.splice(itemIndex, 1); + } + }, + + // DEPENDENCY MUTATIONS + resetVehicleAndDependencies(state) { + state.order.vehicle.year = null; + state.order.vehicle.make = null; + state.order.vehicle.model = null; + state.order.vehicle.style = null; + state.order.vehicle.carId = null; + state.order.vehicle.category = null; + }, + resetDamageAndDependencies(state) { + state.order.vehicle.damage.isRepair = null; + state.order.vehicle.damage.numberOfChips = null; + state.order.vehicle.damage.windshieldGlassToReplace = null; + state.order.vehicle.damage.driverSideGlassToReplace = null; + state.order.vehicle.damage.passengerSideGlassToReplace = null; + state.order.vehicle.damage.rearGlassToReplace = null; + + }, + resetRegistrationAndDependencies(state) { + + }, + resetPartsAndDependencies(state) { + + } + }, + getters: { + vehicle: (state) => state.order.vehicle, + eventBusItem: (state) => (eventCategory, eventSubCategory) => { + const matchedEvent = state.applicationUser.eventBus.find( + ({ category, subCategory }) => + category === eventCategory && subCategory === eventSubCategory + ); + + return matchedEvent !== undefined ? matchedEvent.eventValue : undefined; + }, + eventBus: (state) => state.applicationUser.eventBus, + }, + actions: { + // Vehicle API Actions + getVehicleYears(context) { + return globalMethods.callHttpClient({ + method: endpoints.GetVehicleYears.method, + endpoint: endpoints.GetVehicleYears.url, + payload: {}, + }); + }, + lookupVehicleByYmms(context, { year, make, model, style }) { + return globalMethods.callHttpClient({ + method: endpoints.LookupVehicleByYmms.method, + endpoint: `${endpoints.LookupVehicleByYmms.url}/${year}/${make}/${model}/${style}`, + payload: {}, + }); + }, + lookupVehicleByVin(context, { vin }) { + return globalMethods.callHttpClient({ + method: endpoints.LookupVehicleByVin.method, + endpoint: endpoints.LookupVehicleByVin.url, + payload: { + vin: vin, // EX "1J4GW58S4XC541166" + }, + }); + }, + getVehicleMakes(context, { year }) { + return globalMethods.callHttpClient({ + method: endpoints.GetVehicleMakes.method, + endpoint: `${endpoints.GetVehicleMakes.url}/${year}`, + payload: {}, + }); + }, + getVehicleModels(context, { year, make }) { + return globalMethods.callHttpClient({ + method: endpoints.GetVehicleModels.method, + endpoint: `${endpoints.GetVehicleModels.url}/${year}/${make}`, + payload: {}, + }); + }, + getVehicleStyles(context, { year, make, model }) { + return globalMethods.callHttpClient({ + method: endpoints.GetVehicleStyles.method, + endpoint: `${endpoints.GetVehicleStyles.url}/${year}/${make}/${model}`, + payload: {}, + }); + }, + setVehicle(context, { year, make, model, style }) { + return globalMethods + .callHttpClient({ + methods: endpoints.GetVehicle.method, + endpoint: `${endpoints.GetVehicle.url}/${year}/${make}/${model}/${style}`, + payload: {}, + }) + .then((response) => { + context.commit(storeMutations.UPDATE_VEHICLE, response.data); + return response; + }); + }, + getDamageOptions(context, { carId }) { + return globalMethods.callHttpClient({ + methods: endpoints.GetDamageOptions.method, + endpoint: `${endpoints.GetDamageOptions.url}/${carId}`, + payload: {}, + }); + }, + + // DEPENDENCY ACTIONS + resetVehicleAndDependencies(context) { + context.commit(storeMutations.RESET_VEHICLE_AND_DEPS); + context.commit(storeMutations.RESET_DAMAGE_AND_DEPS); + context.commit(storeMutations.RESET_REGISTRATION_AND_DEPS); + }, + resetDamageAndDependencies(context) { + context.commit(storeMutations.RESET_DAMAGE_AND_DEPS); + context.commit(storeMutations.RESET_PARTS_AND_DEPS); + }, + resetRegistrationAndDependencies(context) { + context.commit(storeMutations.RESET_REGISTRATION_AND_DEPS); + context.commit(storeMutations.RESET_PARTS_AND_DEPS) + }, + resetPartsAndDependencies(context) { + context.commit(storeMutations.RESET_PARTS_AND_DEPS); + }, + + // Content API Actions + getRouteInfo(context, { pageName }) { + return globalMethods.callHttpClient({ + method: endpoints.GetRouteInfo.method, + endpoint: endpoints.GetRouteInfo.url, + payload: { + pageName: pageName, + }, + }); + }, + getHomepageName(context) { + return globalMethods.callHttpClient({ + method: endpoints.GetHomepageInfo.method, + endpoint: endpoints.GetHomepageInfo.url, + }); + }, + getPageData(context, { pageName }) { + return globalMethods.callHttpClient({ + method: endpoints.GetPageData.method, + endpoint: `${endpoints.GetPageData.url}/${pageName}`, + payload: {}, + }); + }, + getEvoxImage(context, { relativeUrl }) { + return globalMethods.callMockHttpClient({ + method: endpoints.GetPageData.method, + endpoint: relativeUrl, + payload: {}, + }); + }, + }, +})); describe("Actions", () => { it("Should return list of years retrieved", async () => { // Arrange let years = []; - + console.log(getPageData); // Act globalMethods.callHttpClient = jest.fn(); globalMethods.callHttpClient.mockImplementation(() => { return Promise.resolve({ data: [2023, 2022, 2021] }); }); + await store.dispatch("getVehicleYears").then((response) => { years = response.data; });