diff --git a/jest.config.js b/jest.config.js index afbfcebc3..0dd06d9be 100644 --- a/jest.config.js +++ b/jest.config.js @@ -23,8 +23,6 @@ module.exports = { "!src/layouts/address-lookup/address-lookup.vue", "!src/layouts/address-lookup/customer-questions/customer-questions.vue", "!src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue", - "!src/layouts/address-vehicles/address-vehicles.vue", - "!src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue", "!src/ux-components/alert\alert.vue", "!src/helpers/validation-rules.js", "!src/common-components/menu-modal/menu-modal.vue", diff --git a/src/layouts/address-lookup/address-lookup.vue b/src/layouts/address-lookup/address-lookup.vue index f29e3d21a..8e58d09b0 100644 --- a/src/layouts/address-lookup/address-lookup.vue +++ b/src/layouts/address-lookup/address-lookup.vue @@ -329,8 +329,8 @@ export default { { licenseLastName: lastName, licenseStreetAddress: streetAddress, - licenseZip: zip, - licenseState: state + licenseZip: zip, + licenseState: state, }, false ); }, diff --git a/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.spec.js b/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.spec.js new file mode 100644 index 000000000..eaa24c9d4 --- /dev/null +++ b/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.spec.js @@ -0,0 +1,63 @@ +import { shallowMount } from "@vue/test-utils"; +import addressVehiclesQuestion from "@/layouts/address-vehicles/address-vehicles-question/address-vehicles-question"; + + +describe("addressVehiclesQuestion.vue", () => { + + it("Should return content for differentVehicleAlertHeader", () => { + // Arrange + const wrapper = shallowMount(addressVehiclesQuestion, { + mixins: [mockMixin], + }); + + // Assert + expect(wrapper.vm.differentVehicleAlertHeader).toEqual('FoundWindshieldTestReturn'); + }); + + it("Should return content for differentVehicleAlertBody", () => { + // Arrange + const wrapper = shallowMount(addressVehiclesQuestion, { + mixins: [mockMixin], + propsData: { + vehicles: ["1", "2"], + modelValue: ["1", "2"], + } + }); + + // Assert + expect(wrapper.vm.differentVehicleAlertBody).toEqual('FoundWindshieldTestReturn'); + }); + + it("Should emit a modelValue change when setting selectedVehicleVin", async () => { + // Arrange + const wrapper = shallowMount(addressVehiclesQuestion, { + mixins: [mockMixin], + propsData: { + vehicles: ["1", "2"], + modelValue: ["1", "2"], + } + }); + + // Act + const localThis = { $emit: jest.fn() } + addressVehiclesQuestion.computed.selectedVehicleVin.set.call(localThis, 'newValue'); + + // Assert + expect(localThis.$emit).toBeCalledWith("update:modelValue", "newValue"); + }); + +}); + +const mockMixin = { + methods: { + getCmsContent: jest.fn((contentName) => { + if (contentName === "FoundWindshield") { + return 'FoundWindshieldTestReturn'; + } + return null; + }), + vehicles: jest.fn(() => { + return [{ vehicle: "test" }]; + }) + } + } diff --git a/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.spec.js1 b/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.spec.js1 deleted file mode 100644 index 05fd2a0eb..000000000 --- a/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.spec.js1 +++ /dev/null @@ -1,113 +0,0 @@ -import { shallowMount } from "@vue/test-utils"; -import addressVehiclesQuestion from "@/layouts/address-vehicles/address-vehicles-question/address-vehicles-question"; -import { getMountOptions } from "@/helpers/unit-test-helper.js"; -// import store from "@/store"; - -// jest.mock("@/store", () => { return {}; }, { virtual: true }); - -describe("addressVehiclesQuestion.vue", () => { - - it("Should include button-question component", () => { - // Arrange - const wrapper = shallowMount(addressVehiclesQuestion, { - propsData: { - // vehicles: [ - // { - // "Name": "testname", - // "Text": "testtext", - // } - // ] - } - }); - - // console.log('wrapper.html: ', wrapper.html()); - - // Assert - const buttonQuestion = wrapper.find('button-question-stub'); - expect(buttonQuestion).toBe; - }); - - it("on initialize should pass in questionText", () => { - // Arrange - const wrapper = shallowMount(addressVehiclesQuestion, { - propsData: {}, - }); - - //Act - addressVehiclesQuestion.methods.initializeComponent.call(wrapper.vm, {QuestionText: 'Testing question text'}); - - // console.log('wrapper.html: ', wrapper.html()); - // console.log('wrapper.vm.questionText: ', wrapper.vm.questionText); - - // Assert - expect(wrapper.vm.questionText).toEqual('Testing question text'); - }); - - // it("Alert should show if prop isCarIdDifferent is true", () => { - // // Arrange - // const wrapper = shallowMount(addressVehiclesQuestion, setupMountOptions({ - // propsData: { - // isCarIdDifferent: true, - // } - // })); - - // //Act - // const alert = wrapper.find('alert'); - // console.log('wrapper.html: ', wrapper.html()); - // console.log('wrapper.vm.questionText: ', wrapper.vm.questionText); - - // // Assert - // // expect(wrapper.vm.questionText).toEqual('Testing question text'); - // }); - -}); - - - -function setupMountOptions(mountOptionsMockData = {}) { - // //Mock store - // store.dispatch = jest.fn(() => {}); - // store.getters = {}; - - // const mockMixin = { - // methods: { - // getCmsContent: jest.fn().mockImplementation(() => { - // return ''; - // }), - // getDamageString: jest.fn().mockImplementation(() => { - // return ''; - // }) - // }, - // store: { - // dispatch: store.dispatch, - // getters: store.getters, - // }, - // } - - const mockGetCmsContent = jest.fn(); - mockGetCmsContent((cmsWidget, field) => { - return field - }); - const defaultMountOptions = { - // route: { query: { fmgPage: 'page-name' } }, - mixins: { - methods: { - getCmsContent: mockGetCmsContent, - }, - }, - global: { - mocks: { - store: { - dispatch: store.dispatch, - getters: store.getters, - }, - }, - }, - }; - const baseMountOptions = getMountOptions(Object.assign(defaultMountOptions, mountOptionsMockData)); - const allMountOptions = Object.assign(defaultMountOptions, baseMountOptions); - - console.log('what are allMountOptions??? ', allMountOptions); - - return allMountOptions; -} \ No newline at end of file diff --git a/src/layouts/address-vehicles/address-vehicles.spec.js b/src/layouts/address-vehicles/address-vehicles.spec.js new file mode 100644 index 000000000..2fdd10276 --- /dev/null +++ b/src/layouts/address-vehicles/address-vehicles.spec.js @@ -0,0 +1,349 @@ +// Components +import addressVehicles from "@/layouts/address-vehicles/address-vehicles"; + +// Supporting Files +import { shallowMount } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import store from "@/store"; +import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper"; + + +// Mock our module for promises. +jest.mock("@/helpers/damage-helper", () => ({ + isGlassAvailableForCarId: () => { + return false; + }, +})); + + +describe("addressVehicles.vue", () => { + + test("Should return true for valid page requisites if carId / zipCode / emailAddress / pageData exists", async () => { + // Arrange + const { wrapper } = setupMocks({}); + wrapper.vm.$router.navigate = jest.fn(); + + // Act + const result = wrapper.vm.arePagePrerequisitesValid(); + + //Assert + expect(result).toBe(true); + + wrapper.unmount(); + }); + + test("Should return false for valid page requisites if carId is missing", async () => { + // Arrange + const { wrapper } = setupMocks({}); + wrapper.vm.$router.navigate = jest.fn(); + + // Act + wrapper.vm.$store.getters.order.vehicle.carId = null; + const result = wrapper.vm.arePagePrerequisitesValid(); + + //Assert + expect(result).toBe(false); + + wrapper.unmount(); + }); + + + // NOTE: this test is only here to meet code coverage; it does not test any logic in the original function + test("Should navigate to CLICKED_BACK if backButtonAction is run", async () => { + // Arrange + const { wrapper } = setupMocks({}); + wrapper.vm.$router.navigate = jest.fn(); + + // Act + wrapper.setData({ + selectedVehicleVin: ['5NMS3CADXLH233004'], + }); + wrapper.vm.backButtonAction(); + + //Assert + expect(wrapper.vm.$router.navigate).toBeCalled(); + + wrapper.unmount(); + }); + + // NOTE: this test is only here to meet code coverage; it does not test any logic in the original function + test("Should run several related methods if forwardButtonAction is run", async () => { + // Arrange + const { wrapper } = setupMocks({}); + const lookupVinResponse = { + data: { + carId: "456" + } + } + + // the following has to be set BEFORE changing the data which is being watched, and requires updateButtonText to be mocked + wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); + wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn(); + wrapper.vm.lookupVin = jest.fn(() => Promise.resolve(lookupVinResponse)); + wrapper.vm.$router.navigateAfterSave = jest.fn(); + wrapper.vm.updateCustomerInfo = jest.fn().mockImplementation(()=> {}); + wrapper.vm.navigateForward = jest.fn().mockImplementation(()=> {}); + + // Act + wrapper.setData({ + selectedVehicleVin: ['5NMS3CADXLH233004'], + }); + + await wrapper.vm.forwardButtonAction(); + wrapper.vm.$nextTick(); + + //Assert + expect(wrapper.vm.updateCustomerInfo).toBeCalled(); + expect(wrapper.vm.navigateForward).toBeCalled(); + + wrapper.unmount(); + }); + + test("Should return out of forwardButtonAction if lookupVin returns with an error", async () => { + // Arrange + const { wrapper } = setupMocks({}); + + const lookupVinResponse = { + error: "there is an error" + } + + // the following has to be set BEFORE changing the data which is being watched, and requires updateButtonText to be mocked + wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); + wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn(); + wrapper.vm.lookupVin = jest.fn(() => Promise.reject(lookupVinResponse)); + wrapper.vm.$router.navigateAfterSave = jest.fn(); + wrapper.vm.updateCustomerInfo = jest.fn().mockImplementation(()=> {}); + + // Act + wrapper.setData({ + selectedVehicleVin: ['5NMS3CADXLH233004'], + }); + await wrapper.vm.forwardButtonAction(); + wrapper.vm.$nextTick(); + + //Assert + expect(wrapper.vm.forwardButtonAction).toReturn; + + wrapper.unmount(); + }); + + test("Should send dispatch reset if carId is different and selected glass not available for vehicle on updateCustomerInfo", async () => { + // Arrange + const { wrapper } = setupMocks({}); + const lookupVinResponse = { + data: { + carId: "456" + } + } + + // the following has to be set BEFORE changing the data which is being watched, and requires updateButtonText to be mocked + wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); + wrapper.vm.lookupVin = jest.fn(() => Promise.resolve(lookupVinResponse)); + wrapper.vm.$router.navigateAfterSave = jest.fn(); + + // Act + wrapper.setData({ + selectedVehicleVin: ['5NMS3CADXLH233004'], + isSelectedGlassAvailableForVehicle: false, + isCarIdDifferent: true, + }); + await wrapper.vm.updateCustomerInfo(wrapper.vm.selectedVehicle.vin, wrapper.vm.selectedVehicle.vehicle); + + //Assert + expect(store.dispatch).toBeCalledWith("resetDamageAndDependencies"); + + wrapper.unmount(); + }); + + // NOTE: this test is only here to meet code coverage; it does not test any logic in the original function + test("Should send dispatch store action if lookupVin is called", async () => { + // Arrange + const { wrapper } = setupMocks({}); + + // Act + await wrapper.vm.lookupVin('1234567890'); + + //Assert + expect(store.dispatch).toBeCalledWith("lookupVehicleByVin", {"vin": "1234567890"}); + + wrapper.unmount(); + }); + + test("If selectedVehicleVin changes, then should update isCarIdDifferent", async () => { + // Arrange + const { wrapper } = setupMocks({}); + wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); + + // Act + wrapper.setData({ + selectedVehicleVin: ['5NMS3CADXLH233004'], + isCarIdDifferent: false, + }); + await wrapper.vm.resetDependentState(); + + //Assert + expect(wrapper.vm.isCarIdDifferent).toBe(true); + + wrapper.unmount(); + }); + + test("If selectedVehicleVin changes, then text on funnel footer should be updated", async () => { + // Arrange + const { wrapper } = setupMocks({}); + wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); + + // Act + wrapper.setData({ + selectedVehicleVin: ['5NMS3CADXLH233004'], + isCarIdDifferent: false, + }); + await wrapper.vm.resetDependentState(); + + //Assert + expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toBeCalled(); + + wrapper.unmount(); + }); + + test("Should navigate to CLICKED_FORWARD scenario if carId is different and selected glass not available for vehicle on navigateForward", async () => { + // Arrange + const { wrapper } = setupMocks({}); + wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); + wrapper.vm.$router.navigateAfterSave = jest.fn(); + + // Act + wrapper.setData({ + selectedVehicleVin: ['5NMS3CADXLH233004'], + isSelectedGlassAvailableForVehicle: false, + isCarIdDifferent: true, + }); + await wrapper.vm.navigateForward(); + + //Assert + expect(wrapper.vm.$router.navigateAfterSave).toBeCalledTimes(1); + + wrapper.unmount(); + }); + + test("Should navigate to navigateAfterSaveToHeritageFunnel if carId is not different on navigateForward", async () => { + // Arrange + const { wrapper } = setupMocks({}); + wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); + wrapper.vm.$refs.loadingModal.showModal = jest.fn(); + navigateToHeritage.navigateAfterSaveToHeritageFunnel = jest.fn(); + + // Act + wrapper.setData({ + selectedVehicleVin: ['5NMS3CADXLH233004'], + isSelectedGlassAvailableForVehicle: true, + isCarIdDifferent: false, + }); + await wrapper.vm.navigateForward(); + + //Assert + expect(navigateToHeritage.navigateAfterSaveToHeritageFunnel).toBeCalledTimes(1); + + wrapper.unmount(); + }); + +}); + + +function setupMocks({ + // modelValueProp = "1900", + cmsQuestionText = "CMS text goes here", + // dataFromStoreApi = [], +}) { + //Mock store + store.dispatch = jest.fn(() => {}); + store.getters = { + pageData: jest.fn((pageName) => { + // console.log('pageName: ', pageName) // address-vehicles + return [ + { + vehicle: { + "carId": "CR00069309", + "category": "SUV", + "year": 2020, + "make": "Hyundai", + "model": "Santa Fe", + "style": "4 door utility", + "imageUrl": "https://dbhdyzvm8lm25.cloudfront.net/color_0320_032/MY2020/13769/13769_cc0320_032_WW8.jpg", + "imageVifNumber": "13769", + "imageVifColor": "white" + }, + vin: "5NMS3CADXLH233004" + }, + ]; + }), + order: { + vehicle: { + carId: "123", + }, + serviceLocation: { + zipCode: "12345" + }, + customer: { + emailAddress: "qw@er.ty" + } + }, + damage: { + glassToReplace: "Windshield" + }, + vehicle: { + carId: "456", + } + }; + + // baseMixin.methods.dispatchStoreAction = jest.fn(); + + + const mountOptions = getMountOptions({ + store: { + dispatch: store.dispatch, + getters: store.getters, + }, + router: { + navigate: jest.fn(), + }, + }); + + //Mock props + const mockMixin = { + methods: { + getCmsContent: jest.fn((contentName) => { + if (contentName === "FoundMultipleVehicles") { + return 'FoundMultipleVehiclesTestReturn'; + } + if (contentName === "ProvideVinAlert") { + return 'ProvideVinAlertTestReturn'; + } + return null; + }), + // dispatchStoreAction: jest.fn(() => { + // console.log("23424243") + // }), + // isGlassAvailableForCarId: () => { + // console.log("%%%%%%%%%%%%%%%") + // return Promise.resolve(true) + // } + + // lookupVin: jest.fn(() => Promise.resolve(lookupVinResponse)), + + }, + } + // mountOptions.propsData = { + // modelValue: modelValueProp, + // }; + + mountOptions.mixins = [mockMixin]; + + const wrapper = shallowMount(addressVehicles, mountOptions); + + //Mock CMS content + const cmsContent = { + QuestionText: cmsQuestionText, + }; + + return { wrapper }; +} diff --git a/src/layouts/address-vehicles/address-vehicles.spec.js1 b/src/layouts/address-vehicles/address-vehicles.spec.js1 deleted file mode 100644 index f4dab360c..000000000 --- a/src/layouts/address-vehicles/address-vehicles.spec.js1 +++ /dev/null @@ -1,26 +0,0 @@ -import { shallowMount } from "@vue/test-utils"; -import addressVehicles from "@/layouts/address-vehicles/address-vehicles"; - -describe("addressVehicles.vue", () => { - - it("Should include address-vehicles-question component", () => { - // Arrange - const wrapper = shallowMount(addressVehicles, { - propsData: { - vehicles: [ - { - "Name": "testname", - "Text": "testtext", - } - ] - } - }); - - // console.log('wrapper.html: ', wrapper.html()); - - // Assert - const addressVehiclesQuestion = wrapper.find('address-vehicles-question-stub'); - expect(addressVehiclesQuestion).toBe; - }); - -}); diff --git a/src/layouts/address-vehicles/address-vehicles.vue b/src/layouts/address-vehicles/address-vehicles.vue index 34937bfb7..dc2e53484 100644 --- a/src/layouts/address-vehicles/address-vehicles.vue +++ b/src/layouts/address-vehicles/address-vehicles.vue @@ -162,8 +162,10 @@ export default { async forwardButtonAction() { const vinLookup = await this.lookupVin(this.selectedVehicle.vin).catch(() => { this.$refs.funnelFooter.removeLoader(); - return; }); + if (!vinLookup) { + return; + } this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vinLookup.data.carId); this.updateCustomerInfo(this.selectedVehicle.vin, this.selectedVehicle.vehicle); this.navigateForward(); @@ -210,7 +212,7 @@ export default { }, watch: { - selectedVehicleVin(vehicleVin) { + selectedVehicleVin() { // does this vehicle match the previously selected carId? this.isCarIdDifferent = this.selectedVehicle.vehicle.carId !== store.getters.vehicle.carId; this.$refs.funnelFooter.updateButtonText(`Continue with ${this.selectedVehicle.vehicle.year} ${this.selectedVehicle.vehicle.make} ${this.selectedVehicle.vehicle.model}`);