diff --git a/src/layouts/license-plate-lookup/license-plate-lookup.spec.js b/src/layouts/license-plate-lookup/license-plate-lookup.spec.js index 99f1f86c8..a6c919713 100644 --- a/src/layouts/license-plate-lookup/license-plate-lookup.spec.js +++ b/src/layouts/license-plate-lookup/license-plate-lookup.spec.js @@ -6,10 +6,13 @@ import { settleAllPromises } from "@/helpers/layout-helper.js"; import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper"; import baseMixin from "@/mixins/base-mixin"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; -import { shallowMount, flushPromises } from "@vue/test-utils"; +import { shallowMount, flushPromises, mount } from "@vue/test-utils"; import { getMountOptions } from "@/helpers/unit-test-helper.js"; import { nextTick } from "vue"; +import { storeMutations } from "@/constants/store-mutations"; +import errorMessages from "@/constants/error-messages"; import store from "@/store"; +import router from "../../router"; jest.mock('@/assets/img/loader.gif', () => 'loader.gif') jest.mock('@/assets/img/windshield.png', () => 'windshield.png') @@ -24,73 +27,58 @@ jest.mock("@/helpers/cms-content-helper", () => ({ fetchCmsContentForPage: jest.fn(), })); -// Mock Store -jest.mock("@/store", () => ({ - commit: jest.fn(), - dispatch: jest.fn(), - getters: { - order: { - customer: { emailAddress: "test@test.com" }, - serviceLocation: { zip: "11111" }, - }, - vehicle: { - carId: "TESTID", - registration: { - licensePlate: "TESTPLATE", - zipCode: "12345", - }, - }, - eventBusItem: jest.fn(), - damage: { - glassToReplace: [] - }, - }, -})); - describe("license-plate-lookup.vue", () => { describe("get values from store", () => { test("getLicensePlateFromStore returns store license plate", async () => { // Arrange const { wrapper } = setupMocks({}); + const mockLicensePlate = "TESTPLATE"; + store.commit(storeMutations.UPDATE_REGISTRATION_LICENSE_PLATE, mockLicensePlate); - // ACT + // Act const licensePlate = wrapper.vm.getLicensePlateFromStore(); // Assert - expect(licensePlate).toEqual("TESTPLATE"); + expect(licensePlate).toEqual(mockLicensePlate); }); test("getRegistrationZipFromStore returns store registration zip", async () => { // Arrange const { wrapper } = setupMocks({}); + const mockRegistrationZip = "12345"; + store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, mockRegistrationZip); // ACT const registrationZip = wrapper.vm.getRegistrationZipFromStore(); // Assert - expect(registrationZip).toEqual("12345"); + expect(registrationZip).toEqual(mockRegistrationZip); }); test("getEmailFromStore returns store customer email", async () => { // Arrange const { wrapper } = setupMocks({}); + const mockEmail = "test@test.com"; + store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, mockEmail); // ACT const customerEmail = wrapper.vm.getEmailFromStore(); // Assert - expect(customerEmail).toEqual("test@test.com"); + expect(customerEmail).toEqual(mockEmail); }); test("getServiceZipFromStore returns store service zip", async () => { // Arrange const { wrapper } = setupMocks({}); + const mockServiceZip = "11111"; + store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, mockServiceZip); // ACT const serviceZip = wrapper.vm.getServiceZipFromStore(); // Assert - expect(serviceZip).toEqual("11111"); + expect(serviceZip).toEqual(mockServiceZip); }); }); @@ -99,7 +87,7 @@ describe("license-plate-lookup.vue", () => { //Arrange const { wrapper } = setupMocks({}); - + //Act licensePlateLookup.beforeRouteEnter.call( wrapper.vm, @@ -107,31 +95,31 @@ describe("license-plate-lookup.vue", () => { undefined, (c) => c(wrapper.vm) ); - + wrapper.vm.backButtonAction(); - + //Assert expect(wrapper.vm.$router.navigate).toHaveBeenCalled(); }); describe("on forwardButtonAction click", () => { - test("Navigate forward should be called and isCarId should be set to false when data entered matches store data on forwardButtonAction click", async () => { - + test("Navigate forward should be called and isCarIdDifferent should be set to false when data entered matches store data on forwardButtonAction click", async () => { // Arrange const { wrapper } = setupMocks({}); - + const mockCarId = "TESTID"; + store.commit(storeMutations.UPDATE_GLASS_TO_REPLACE, []); + store.commit(storeMutations.UPDATE_CAR_ID, mockCarId); + wrapper.vm.validateZip = jest.fn().mockImplementation(() => { return { data: { isServiceable: true } }; }); - wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => { - return ''; - }); - const vinLookup = { data: { vehicle: { carId: "TESTID" } } } + wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => ""); + const vinLookup = { data: { vehicle: { carId: mockCarId } } } wrapper.vm.lookupVin = jest.fn().mockImplementation(() => { - return { catch: () => vinLookup }; + return new Promise(resolve => resolve(vinLookup)); }); wrapper.vm.navigateForward = jest.fn(); - + //Act licensePlateLookup.beforeRouteEnter.call( wrapper.vm, @@ -139,25 +127,24 @@ describe("license-plate-lookup.vue", () => { undefined, (c) => c(wrapper.vm) ); - + await wrapper.vm.forwardButtonAction(); - + //Assert - expect(wrapper.vm.navigateForward).toHaveBeenCalled(); expect(wrapper.vm.isCarIdDifferent).toEqual(false); + expect(wrapper.vm.navigateForward).toHaveBeenCalled(); }); test("Function should stop and datam isRegistrationZipServicable should be set to false when service zip entered returns false on forwardButtonAction click", async () => { // Arrange const { wrapper } = setupMocks({}); - + wrapper.vm.validateZip = jest.fn().mockImplementation(() => { return { data: { isServiceable: false } }; }); wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => { return ''; }); - wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn(); //Act licensePlateLookup.beforeRouteEnter.call( @@ -166,9 +153,9 @@ describe("license-plate-lookup.vue", () => { undefined, (c) => c(wrapper.vm) ); - + await wrapper.vm.forwardButtonAction(); - + //Assert expect(wrapper.vm.isRegistrationZipServicable).toEqual(false); }); @@ -176,7 +163,8 @@ describe("license-plate-lookup.vue", () => { test("Function should stop and datam isCarIdDifferent should be set to true when carId entered doesn't match store carId or previously entered carId on forwardButtonAction click", async () => { // Arrange const { wrapper } = setupMocks({}); - + store.commit(storeMutations.UPDATE_GLASS_TO_REPLACE, []); + wrapper.vm.validateZip = jest.fn().mockImplementation(() => { return { data: { isServiceable: true } }; }); @@ -185,11 +173,9 @@ describe("license-plate-lookup.vue", () => { }); const vinLookup = { data: { vehicle: { carId: "TESTID1" } } } wrapper.vm.lookupVin = jest.fn().mockImplementation(() => { - return { catch: () => vinLookup }; + return new Promise(resolve => resolve(vinLookup)); }); - wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn(); - wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); - + //Act licensePlateLookup.beforeRouteEnter.call( wrapper.vm, @@ -197,9 +183,9 @@ describe("license-plate-lookup.vue", () => { undefined, (c) => c(wrapper.vm) ); - + await wrapper.vm.forwardButtonAction(); - + //Assert expect(wrapper.vm.isCarIdDifferent).toEqual(true); }); @@ -208,7 +194,7 @@ describe("license-plate-lookup.vue", () => { // Arrange const { wrapper } = setupMocks({}); - + wrapper.vm.validateZip = jest.fn().mockImplementation(() => { return { data: { isServiceable: true } }; }); @@ -217,11 +203,11 @@ describe("license-plate-lookup.vue", () => { }); const vinLookup = { data: { vehicle: { carId: "TESTID1" } } } wrapper.vm.lookupVin = jest.fn().mockImplementation(() => { - return { catch: () => vinLookup }; + return new Promise(resolve => resolve(vinLookup)); }); wrapper.vm.previouslyEnteredCarId = "TESTID1"; wrapper.vm.navigateForward = jest.fn(); - + //Act licensePlateLookup.beforeRouteEnter.call( wrapper.vm, @@ -229,9 +215,9 @@ describe("license-plate-lookup.vue", () => { undefined, (c) => c(wrapper.vm) ); - + await wrapper.vm.forwardButtonAction(); - + //Assert expect(wrapper.vm.navigateForward).toHaveBeenCalled(); expect(wrapper.vm.isCarIdDifferent).toEqual(true); @@ -243,7 +229,7 @@ describe("license-plate-lookup.vue", () => { // Arrange const { wrapper } = setupMocks({}); - + //Act wrapper.vm.isCarIdDifferent = true; wrapper.vm.isSelectedGlassAvailableForVehicle = false; @@ -252,9 +238,9 @@ describe("license-plate-lookup.vue", () => { return ''; }); store.dispatch = jest.fn(); - + await wrapper.vm.navigateForward(); - + //Assert expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalled(); }); @@ -263,16 +249,15 @@ describe("license-plate-lookup.vue", () => { // Arrange const { wrapper } = setupMocks({}); - + //Act wrapper.vm.isCarIdDifferent = false; - wrapper.vm.$refs.loadingModal.showModal = jest.fn(); wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => { return ''; }); navigateToHeritage.navigateAfterSaveToHeritageFunnel = jest.fn(); await wrapper.vm.navigateForward(); - + //Assert expect(navigateToHeritage.navigateAfterSaveToHeritageFunnel).toHaveBeenCalled(); }); @@ -284,13 +269,12 @@ describe("license-plate-lookup.vue", () => { // Arrange const { wrapper } = setupMocks({}); - + //Act wrapper.vm.licensePlate = "NEWPLATE"; wrapper.vm.getCmsContent = jest.fn(); - wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); await wrapper.vm.$nextTick(); - + //Assert expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toHaveBeenCalled(); }); @@ -299,13 +283,12 @@ describe("license-plate-lookup.vue", () => { // Arrange const { wrapper } = setupMocks({}); - + //Act wrapper.vm.registrationZip = "55555"; wrapper.vm.getCmsContent = jest.fn(); - wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); await wrapper.vm.$nextTick(); - + //Assert expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toHaveBeenCalled(); }); @@ -314,23 +297,159 @@ describe("license-plate-lookup.vue", () => { // Arrange const { wrapper } = setupMocks({}); - + //Act wrapper.vm.serviceZip = "55555"; wrapper.vm.getCmsContent = jest.fn(); - wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); await wrapper.vm.$nextTick(); - + //Assert expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toHaveBeenCalled(); }); }) + describe("saving registrationZip and serviceZip on continue", () => { + test("registrationZip is serviceable and vehicle match is found => sets service zip/state to registration zip/state", async () => { + // Arrange + const { wrapper } = setupMocks({}); + const mockCarId = "TESTID"; + store.commit(storeMutations.UPDATE_GLASS_TO_REPLACE, []); + store.commit(storeMutations.UPDATE_CAR_ID, mockCarId) + wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => ""); + wrapper.vm.validateZip = jest.fn().mockImplementation((zip) => { + if (zip) + return { data: { isServiceable: true, state: "OH" } }; + return + }); + const vinLookup = { data: { vehicle: { carId: mockCarId } } } + wrapper.vm.lookupVin = jest.fn().mockImplementation(() => new Promise(resolve => resolve(vinLookup))); + + await wrapper.setData({ registrationZip: "00000" }); + navigateToHeritage.navigateAfterSaveToHeritageFunnel = jest.fn(); + + // Act + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(store.getters.order.serviceLocation.zipCode).toEqual(store.getters.vehicle.registration.zipCode); + expect(store.getters.vehicle.registration.zipCode).toEqual("00000"); + expect(store.getters.order.serviceLocation.zipCode).toEqual("00000"); + }) + + test("vehicle match is found but registrationZip is not serviceable => shows service zip/state field", async () => { + // Arrange + const { wrapper } = setupMocks({}); + wrapper.vm.validateZip = jest.fn().mockImplementation(() => { + return { data: { isServiceable: false, state: "XX" } }; + }); + + await wrapper.setData({ registrationZip: "00000" }); + navigateToHeritage.navigateAfterSaveToHeritageFunnel = jest.fn(); + + // Act + await wrapper.vm.forwardButtonAction(); + + // Assert + const serviceZipField = wrapper.findComponent("[cmsWidgetName='ServiceZip']"); + expect(serviceZipField.exists()).toBe(true); + expect(serviceZipField.isVisible()).toBe(true); + }) + + test("registrationZip is not serviceable so serviceZip field is shown, continue clicked => user cannot continue", async () => { + // Arrange + const { wrapper } = setupMocks({}); + wrapper.vm.validateZip = jest.fn().mockImplementation(() => { + return { data: { isServiceable: false, state: "XX" } }; + }); + + await wrapper.setData({ registrationZip: "00000" }); + navigateToHeritage.navigateAfterSaveToHeritageFunnel = jest.fn(); + await wrapper.vm.forwardButtonAction(); + wrapper.vm.$router.navigateAfterSave = jest.fn(); + // At this point, serviceZip field is shown + + // Act + // Continue without entering anything into service zip field + await wrapper.vm.forwardButtonAction(); + + // Assert + const serviceZipField = wrapper.findComponent("[cmsWidgetName='ServiceZip']"); + expect(serviceZipField.exists()).toBe(true); + expect(serviceZipField.isVisible()).toBe(true); 3 + expect(navigateToHeritage.navigateAfterSaveToHeritageFunnel).not.toHaveBeenCalled(); + expect(wrapper.vm.$router.navigateAfterSave).not.toHaveBeenCalled(); + }); + + test("registrationZip is not serviceable so serviceZip field is shown, user enters serviceZip => user can continue", async () => { + // Arrange + const { wrapper } = setupMocks({}); + const registrationZip = "00000"; + const serviceZip = "99999"; + const mockCarId = "TestCarId"; + store.commit(storeMutations.UPDATE_CAR_ID, mockCarId); + wrapper.vm.validateZip = jest.fn().mockImplementation((zip) => { + return { data: { isServiceable: zip == registrationZip ? false : true, state: "XX" } }; + }); + const vinLookup = { data: { vehicle: { carId: mockCarId } } } + wrapper.vm.lookupVin = jest.fn().mockImplementation(() => { + return new Promise(resolve => resolve(vinLookup)); + }); + wrapper.vm.navigateForward = jest.fn(); + await wrapper.setData({ registrationZip: registrationZip }); + await wrapper.vm.forwardButtonAction(); + // At this point, serviceZip field is shown + + await wrapper.setData({ serviceZip: serviceZip }); + + // Act + // Continue after entering input into service zip field + await wrapper.vm.forwardButtonAction(); + + // Assert + const serviceZipField = wrapper.findComponent("[cmsWidgetName='ServiceZip']"); + expect(serviceZipField.exists()).toBe(true); + expect(serviceZipField.isVisible()).toBe(true); + expect(wrapper.vm.navigateForward).toHaveBeenCalled(); + }); + + test("registrationZip is not serviceable so serviceZip field is shown, user enters serviceZip => service and registration zips/states saved", async () => { + // Arrange + const { wrapper } = setupMocks({}); + const registrationZip = "00000"; + const serviceZip = "99999"; + const mockCarId = "TestCarId"; + store.commit(storeMutations.UPDATE_CAR_ID, mockCarId); + wrapper.vm.validateZip = jest.fn().mockImplementation((zip) => { + return { data: { isServiceable: zip == registrationZip ? false : true, state: "XX" } }; + }); + const vinLookup = { data: { vehicle: { carId: mockCarId } } } + wrapper.vm.lookupVin = jest.fn().mockImplementation(() => { + return new Promise(resolve => resolve(vinLookup)); + }); + wrapper.vm.navigateForward = jest.fn(); + await wrapper.setData({ registrationZip: registrationZip }); + await wrapper.vm.forwardButtonAction(); + // At this point, serviceZip field is shown + + await wrapper.setData({ serviceZip: serviceZip }); + + // Act + // Continue after entering value into service zip field + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(store.getters.vehicle.registration.zipCode).toEqual(registrationZip); + expect(store.getters.order.serviceLocation.zipCode).toEqual(serviceZip); + expect(wrapper.vm.navigateForward).toHaveBeenCalled(); + }); + }) + describe("miscellaneous", () => { test("CarId set, arePagePrerequisitesValid should be true ", async () => { //Arrange const { wrapper } = setupMocks({}); - + store.commit(storeMutations.UPDATE_CAR_ID, "TESTCARID"); + //Act licensePlateLookup.beforeRouteEnter.call( wrapper.vm, @@ -338,10 +457,10 @@ describe("license-plate-lookup.vue", () => { undefined, (c) => c(wrapper.vm) ); - + let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); await nextTick(); - + //Assert expect(arePagePrerequisitesValid).toBe(true); }); @@ -350,7 +469,7 @@ describe("license-plate-lookup.vue", () => { // Arrange const { wrapper } = setupMocks({}); - + //Act wrapper.vm.isCarIdDifferent = true; wrapper.vm.isSelectedGlassAvailableForVehicle = false; @@ -359,23 +478,23 @@ describe("license-plate-lookup.vue", () => { }); store.commit = jest.fn(); store.dispatch = jest.fn(); - + const vehicleInfo = { year: "2020", make: "honda", model: "civic", style: "2 door", carId: "TestId", category: "testCat", imageUrl: "image.jpg", imageVifNumber: "123", imageColor: "blue" } await wrapper.vm.updateCustomerInfo('vin', vehicleInfo, 'registrationState'); - + //Assert expect(store.dispatch).toHaveBeenCalled(); - }); + }) test("dispatch non blocking store action called on validate zip", async () => { // Arrange const { wrapper } = setupMocks({}); - + //Act await wrapper.vm.validateZip("12345"); - - + + //Assert expect(baseMixin.methods.dispatchStoreAction).toHaveBeenCalled(); }); @@ -384,11 +503,11 @@ describe("license-plate-lookup.vue", () => { // Arrange const { wrapper } = setupMocks({}); - + //Act await wrapper.vm.lookupVin("zzz123fqsfwg"); - - + + //Assert expect(baseMixin.methods.dispatchStoreAction).toHaveBeenCalled(); }); @@ -401,10 +520,9 @@ function setupMocks({ router: { navigate: jest.fn(), }, - licensePlate: "TESTPLATE", - registrationZip: "12345" }, }) { + store.commit(storeMutations.RESET_STATE); //Mock api responses baseMixin.methods.dispatchStoreAction = jest.fn(); const apiResponses = { @@ -426,13 +544,16 @@ function setupMocks({ settleAllPromises.mockImplementation(() => apiPromise); fetchCmsContentForPage.mockImplementation(() => Promise.resolve()); - const mountOptions = getMountOptions(mountOptionsMockData); mountOptions['attachTo'] = document.body; // append wrapper to document.body to test DOM methods const wrapper = shallowMount(licensePlateLookup, mountOptions); wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent; + wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => ""); + wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); + wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn(); + wrapper.vm.$refs.loadingModal.showModal = jest.fn(); return { wrapper, apiPromise }; }