From f9dc366b84eb15d2e52dd2f3e35387b45ef95bd3 Mon Sep 17 00:00:00 2001 From: Chloe Herd Date: Wed, 19 Jun 2024 15:16:44 -0400 Subject: [PATCH] Update tests --- src/layouts/estimate/estimate.spec.js | 58 +-- src/layouts/service-zip/service-zip.spec.js | 423 ++++++++++++++++++ .../vehicle-damage/vehicle-damage.spec.js | 14 + 3 files changed, 449 insertions(+), 46 deletions(-) diff --git a/src/layouts/estimate/estimate.spec.js b/src/layouts/estimate/estimate.spec.js index b8517d833..a81ead0c3 100644 --- a/src/layouts/estimate/estimate.spec.js +++ b/src/layouts/estimate/estimate.spec.js @@ -86,15 +86,18 @@ describe("estimate.vue", () => { expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled(); }); - // TODO KO - describe("isRepair", () => { - test.todo("is repair and zip codes are valid/serviceable => go to quote page"); - test.todo( - "is repair and zip codes are valid but not serviceable => show correct alert, remove loader" - ); - test.todo( - "is repair and zip codes are not valid/serviceable => show correct alert, remove loader" - ); + test("Selecting no vin on ForwardButtonAction triggers a router.navigateWithSaving", async () => { + //Arrange + const { wrapper } = setupMocks({}); + await wrapper.setData({ + selectedVinLookupMethod: vinLookupMethodSelections.DECLINE, + }); + + //Act + wrapper.vm.forwardButtonAction(); + + //Assert + expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled(); }); }); @@ -207,43 +210,6 @@ describe("estimate.vue", () => { expect(arePagePrerequisitesValid).toBe(true); }); }); - - test("Changing zip should reset alert", async () => { - //Arrange - const { wrapper } = setupMocks({}); - - //Act - wrapper.vm.displayNonServiceableZipAlert = "true"; - wrapper.vm.serviceZipCode = "43015"; - - await wrapper.vm.$nextTick(); - - //Assert - expect(wrapper.vm.displayNonServiceableZipAlert).toEqual(false); - }); -}); - -describe("test alertInfo and isRepair", () => { - const skipOptions = [ - [true, false, "AlertQuoteReady"], - [false, true, "AlertQuoteVinOptional"], - [false, false, "AlertQuoteReady"], - [true, true, "AlertQuoteVinOptional"], - ]; - test.each(skipOptions)( - "isRepair %s, skipVinNotRepair %s alertInfo should return %s", - async (isRepair, skipVinNotRepair, expectedAlertInfo) => { - const { wrapper } = setupMocks({}); - await wrapper.setData({ - skipVinNotRepair: skipVinNotRepair, - }); - - store.commit(storeMutations.UPDATE_IS_REPAIR, isRepair); - - expect(wrapper.vm.alertInfo).toEqual(expectedAlertInfo); - expect(wrapper.vm.isRepair).toEqual(isRepair); - } - ); }); function setupMocks({ diff --git a/src/layouts/service-zip/service-zip.spec.js b/src/layouts/service-zip/service-zip.spec.js index e69de29bb..2e4f7ea48 100644 --- a/src/layouts/service-zip/service-zip.spec.js +++ b/src/layouts/service-zip/service-zip.spec.js @@ -0,0 +1,423 @@ +// Components +import serviceZip from "@/layouts/service-zip/service-zip"; + +// Supporting Files +import { shallowMount } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper"; +import baseMixin from "@/mixins/base-mixin"; +import store from "@/store"; +import router from "@/router"; +import { navigationScenarios } from "@/router/router-constants/navigation-scenarios"; +import { saveSession } from "@/helpers/heritage-integration/order-helper.js"; +import vinPagesMixin from "@/mixins/vin-pages-mixin"; + +// Constants + +// Setup global mocks +let mockCmsContent = { + AlertNonServiceableZipWidget: { + HeadlineText: "Test", + }, +}; + +let mockStoreActionData = {}; + +let mockStoreData = {}; + +function resetMockStoreData() { + mockStoreData = { + vehicle: { + year: "2000", + make: "TestMake", + model: "TestModel", + style: "TestStyle", + carId: "TestID", + vin: null, + registration: { + licensePlate: null, + }, + }, + serviceLocation: { + address: null, + address2: null, + city: null, + state: null, + zipCode: null, + zipCodeCtu: null, + appointmentType: null, + isVehicleProtected: null, + provider: { + providerNumber: null, + address: { + streetAddress: null, + city: null, + state: null, + zipCode: null, + zipCodeCtu: null, + }, + }, + techNotes: null, + }, + customer: { + firstName: null, + lastName: null, + emailAddress: null, + phoneNumber: null, + isSmsOptIn: null, + }, + damage: { + isRepair: false, + numberOfChips: null, + glassToReplace: [{ glassLocation: "Windshield", glassName: "windshield" }], + partQuestionAnswers: null, + moldingQuestionAnswers: null, + capabilityQuestionAnswers: null, + dateOfLoss: null, + damageCause: null, + }, + lineItems: { + glassParts: [{ + canSafeliteRecalibrate: true, + childParts: [ + { + kitPrice: 0, + laborAmount: 23.55, + partNumber: "GGG FW4896", + salesTax: 1.77, + sellingPrice: 0, + }, + ], + color: "Green Tint", + description: + "solar, soundproofing, lane keep assist, lane departure warning system, w/adaptive cruise control", + id: "db22fd44-10dd-456f-979b-ff88cf68cca6", + kitPrice: 0, + laborAmount: 60, + partNumber: "FW04896GTYN", + partType: "WINDSHIELD", + recalibrationType: "STATIC", + requiresCapabilityQuestions: false, + requiresRecalibration: true, + salesTax: 63.86, + sellingPrice: 791.46, + }], + supportingItems: null, + vaps: null, + serverData: null, + promos: null, + }, + payment: { + isInsurance: null, + insuranceCoverage: { + isVerified: null, + coverageStatus: null, + coverageType: null, + coverageVerificationType: null, + }, + parentAccountNumber: 0, + billToAccountNumber: null, + isPia: null, + piaType: null, + inactivePromos: null, + paypalToken: null, + nextGenSettledAmount: 0, + ccToken: { + subscriptionId: null, + expMonth: null, + expYear: null, + cardType: null, + billToPostalCode: null, + billToFirstName: null, + billToLastName: null, + referenceNumber: null, + authCode: null, + transactionId: null, + transReferenceNumber: null, + lastFour: null, + }, + }, + policy: { + currentDeductible: 0, + policyNumber: null, + isItac: false, + additionalAuthFlag: null, + isNoComp: false, + insuranceCompanyName: null, + }, + schedule: { + date: null, + startTime: null, + endTime: null, + routeCode: null, + jobMaxMinutes: null, + jobMinMinutes: null, + }, + }; +} + +function applyMockStoreDataToGetters() { + store.getters = { + order: mockStoreData, + damage: mockStoreData.damage, + payment: mockStoreData.payment, + policy: mockStoreData.policy, + }; + store.state.order = mockStoreData; +} + +async function mockDispatchStoreAction(actionName) { + return mockStoreActionData[actionName]; +} + +jest.mock("@/mixins/base-mixin.js", () => ({ + methods: { + dispatchStoreAction: jest.fn().mockImplementation(mockDispatchStoreAction), + dispatchStoreActionWithLogging: jest.fn().mockImplementation(mockDispatchStoreAction), + }, +})); + +jest.mock("@/helpers/cms-content-helper", () => ({ + fetchCmsContentForPage: () => Promise.resolve("content"), +})); + +jest.mock("@/helpers/heritage-integration/order-helper.js", () => ({ + saveSession: jest.fn(), +})); + +router.navigateWithoutSaving = jest.fn(); +router.navigateWithSaving = jest.fn(); + +// Tests +describe("service-zip.vue", () => { + beforeEach(() => { + resetMockStoreData(); + jest.clearAllMocks(); + }); + + describe("Pre-existing fields", () => { + test("No existing fields -> serviceZip & emailAdress undefined", () => { + // Arrange + // no changes to store + applyMockStoreDataToGetters(); + + // Act + const wrapper = setupMocks({}); + + // Assert + expect(wrapper.vm.serviceZipCode).toBeFalsy(); + expect(wrapper.vm.emailAddress).toBeFalsy(); + }); + + test("Fields in store -> autofilled to data", () => { + // Arrange + mockStoreData.serviceLocation.zipCode = "11111"; + mockStoreData.customer.emailAddress = "builddigitaltest@safelite.com"; + + applyMockStoreDataToGetters(); + + // Act + const wrapper = setupMocks({}); + + // Assert + expect(wrapper.vm.serviceZipCode).toEqual("11111"); + expect(wrapper.vm.emailAddress).toEqual("builddigitaltest@safelite.com"); + }); + + test("Zip in querystring -> pushed to data", () => { + // Arrange + // no changes to store + applyMockStoreDataToGetters(); + + // Act + const wrapper = setupMocks({ + customZipQuery: "11111", + }); + + // Assert + expect(wrapper.vm.serviceZipCode).toEqual("11111") + }); + }); + + describe("Navigation", () => { + describe("Back Nav", () => { + test("If skipvin eligable, go back to vehicle-damage", async () => { + // Arrange + mockStoreData.damage.isRepair = true; + mockStoreData.damage.numberOfChips = 1; + mockStoreData.damage.glassToReplace = null; + mockStoreData.lineItems.glassParts = null; + + applyMockStoreDataToGetters(); + + // Act + const wrapper = setupMocks({}); + await wrapper.vm.backButtonAction(); + + // Assert + expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(navigationScenarios.CLICKED_BACK_WITH_SKIP_VIN, wrapper.vm.$route); + }); + + test("If not skipvin eligable, go back to estimate", async () => { + // Arrange + // no changes to store + applyMockStoreDataToGetters(); + + // Act + const wrapper = setupMocks({}); + await wrapper.vm.backButtonAction(); + + // Assert + expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(navigationScenarios.CLICKED_BACK, wrapper.vm.$route); + }); + }); + + describe("Forward Nav", () => { + test("Repair skips questions flow", async () => { + // Arrange + mockStoreData.damage.isRepair = true; + mockStoreData.damage.numberOfChips = 1; + mockStoreData.damage.glassToReplace = null; + mockStoreData.lineItems.glassParts = null; + + applyMockStoreDataToGetters(); + + // Act + const wrapper = setupMocks({}); + + jest.spyOn(wrapper.vm, "navigateForwardWithSingleCarMatch").mockImplementation(); + + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.vm.$router.navigateWithSaving).toBeCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_NO_QUESTIONS, wrapper.vm.$route); + expect(wrapper.vm.navigateForwardWithSingleCarMatch).not.toBeCalled(); + }); + + test("Non-repair enters questions flow", async () => { + // Arrange + mockStoreData.damage.isRepair = false; + applyMockStoreDataToGetters(); + + // Act + const wrapper = setupMocks({}); + + jest.spyOn(wrapper.vm, "navigateForwardWithSingleCarMatch").mockImplementation(); + + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.vm.$router.navigateWithSaving).not.toBeCalled(); + expect(wrapper.vm.navigateForwardWithSingleCarMatch).toBeCalled(); + }); + }); + }); + + describe("Alerts", () => { + test("Invalid zip alert shown if indicated by endpoint", async () => { + // Arrange + // no changes to store + applyMockStoreDataToGetters(); + const invalidZipResponse = { + state: "OH", + zipCodeCtu: "TESTCTU", + isValid: false, + isServiceable: true, + }; + + // Act + const wrapper = setupMocks({customZipDataResponse: invalidZipResponse}); + + wrapper.vm.$refs.navbar.removeLoader = jest.fn(); + + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.vm.displayInvalidZipAlert).toBe(true); + }); + + test("Non-serviceable zip alert shown if indicated by endpoint", async () => { + // Arrange + // no changes to store + applyMockStoreDataToGetters(); + const invalidZipResponse = { + state: "OH", + zipCodeCtu: "TESTCTU", + isValid: true, + isServiceable: false, + }; + + // Act + const wrapper = setupMocks({customZipDataResponse: invalidZipResponse}); + + wrapper.vm.$refs.navbar.removeLoader = jest.fn(); + + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.vm.displayNonServiceableZipAlert).toBe(true); + }); + + test("Alerts cleared when valid zip is submitted", async () => { + // Arrange + // no changes to store + applyMockStoreDataToGetters(); + + // Act + const wrapper = setupMocks({}); + + wrapper.vm.displayInvalidZipAlert = true; + wrapper.vm.displayNonServiceableZipAlert = true; + + jest.spyOn(wrapper.vm, "navigateForwardWithSingleCarMatch").mockImplementation(); + + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.vm.displayInvalidZipAlert).toBe(false); + expect(wrapper.vm.displayNonServiceableZipAlert).toBe(false); + }); + }); +}); + +function setupMocks({ customMountOptions, customZipQuery, customZipDataResponse }) { + const route = { query: { fmgPage: "service-zip" }, params: {} }; + if(customZipQuery) { + route.query.zipcode = customZipQuery; + } + + const mountOptions = getMountOptions({ + ...customMountOptions, + route: route, + }); + + mountOptions.global.mocks["$store"] = store; + mountOptions.global.mocks["$router"] = router; + mountOptions.mixins = [ + { + methods: { + getCmsContent: jest.fn().mockImplementation((widgetName, fieldName) => { + if (mockCmsContent[widgetName] && mockCmsContent[widgetName][fieldName]) + return mockCmsContent[widgetName][fieldName]; + }), + setCmsContent: jest.fn(), + navigateForwardWithSingleCarMatch: jest.fn(), + getZipCodeData: jest.fn().mockImplementation(() => { + if(customZipDataResponse) { + return customZipDataResponse; + } else { + return { + state: "OH", + zipCodeCtu: "TESTCTU", + isValid: true, + isServiceable: true, + }; + } + }), + }, + }, + ]; + + const wrapper = shallowMount(serviceZip, mountOptions); + + return wrapper; +} diff --git a/src/layouts/vehicle-damage/vehicle-damage.spec.js b/src/layouts/vehicle-damage/vehicle-damage.spec.js index 36f694d5e..e0450fd80 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.spec.js +++ b/src/layouts/vehicle-damage/vehicle-damage.spec.js @@ -52,6 +52,20 @@ jest.mock("@/store", () => ({ damage: { glassToReplace: [], }, + order: { + vehicle: { + carId: "C00000000", + image: "test.jpg", + payment: { + insuranceCoverage: { + isVerified: false, + }, + }, + }, + damage: { + glassToReplace: [], + }, + }, }, }));