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 00000000..b9cd7e02 --- /dev/null +++ b/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.spec.js @@ -0,0 +1,77 @@ +import addressVehiclesQuestion from "@/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue"; +import { shallowMount } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; + +describe("address-vehicles-question.vue", () => { + test("Selected vehicle is emitted upon selection", async () => { + //Arrange + const { wrapper } = setupMocks({ modelValueProp: "2020 Audi A6" }); + const vehicleToSelect = "2016 Jaguar F-Type"; + + //Act + wrapper.setValue({ selectedVehicle: vehicleToSelect }); + await wrapper.vm.$nextTick(); + + //Assert + expect(wrapper.emitted()["update:modelValue"][0]).toEqual([ + { selectedVehicle: "2016 Jaguar F-Type" }, + ]); + }); + test("Should return content for differentVehicleAlertHeader", () => { + // Arrange + const wrapper = shallowMount(addressVehiclesQuestion, { + mixins: [mockMixin], + }); + + // Assert + expect(wrapper.vm.differentVehicleAlertHeader).toEqual("FoundWindshieldTestReturn"); + }); + test("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"); + }); +}); + +const mockMixin = { + methods: { + getCmsContent: jest.fn((contentName) => { + if (contentName === "FoundWindshield") { + return "FoundWindshieldTestReturn"; + } + return null; + }), + vehicles: jest.fn(() => { + return [{ vehicle: "test" }]; + }), + }, +}; + +function setupMocks({ + modelValueProp = "TESTCAR", + cmsQuestionText = "CMS text goes here", +}) { + + const mountOptions = getMountOptions(); + + //Mock props + mountOptions.propsData = { + modelValue: modelValueProp, + }; + + const wrapper = shallowMount(addressVehiclesQuestion, mountOptions); + + //Mock CMS content + const cmsContent = { + QuestionText: cmsQuestionText, + }; + return { wrapper, cmsContent }; +} \ No newline at end of file diff --git a/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue b/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue new file mode 100644 index 00000000..0ab1512e --- /dev/null +++ b/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue @@ -0,0 +1,86 @@ + + + + \ 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 00000000..76aebdf0 --- /dev/null +++ b/src/layouts/address-vehicles/address-vehicles.spec.js @@ -0,0 +1,252 @@ +import addressVehicles from "@/layouts/address-vehicles/address-vehicles"; +import { settleAllPromises } from "@/helpers/layout-helper.js"; +import { shallowMount } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import { useMainStore } from "@/store"; +import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; + +jest.mock("@/helpers/damage-helper", () => ({ + isGlassAvailableForCarId: jest.fn().mockImplementation(() => true), + getDamageString: jest.fn(), +})); + +// Mock fetchCmsContentForPage +jest.mock("@/helpers/cms-content-helper", () => ({ + fetchCmsContentForPage: jest.fn(), + doesCopyContainRouterLink: jest.fn(), + splitCopyOnCMSPlaceHolder: jest.fn().mockImplementation(() => "test"), + getRouterLinkRouteFromCopy: jest.fn(), + getRouterLinkDisplayTextFromCopy: jest.fn(), + splitCMSCopyOnParagraphTag: jest.fn(), +})); + +// Mock our module for promises. +jest.mock("@/helpers/layout-helper.js", () => ({ + settleAllPromises: jest.fn(), +})); + +describe("address-vehicles.vue", () => { + test("Should navigate to CLICKED_BACK if backButtonAction is run", async () => { + // Arrange + const { wrapper } = setupMocks({}); + + // Act + await wrapper.vm.backButtonAction(); + + //Assert + expect(wrapper.vm.$router.navigate).toBeCalled(); + }); + + test("navigateForward should be called if forwardButtonAction is run", async () => { + // Arrange + const { wrapper } = setupMocks({}); + const lookupVinResponse = { + data: { + carId: "456" + } + } + + wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn(); + wrapper.vm.$refs.siteFooter.removeLoader = jest.fn(); + wrapper.vm.lookupVin = jest.fn(() => Promise.resolve(lookupVinResponse)); + wrapper.vm.$router.navigate = jest.fn(); + wrapper.vm.saveVin = jest.fn().mockImplementation(() => {}); + wrapper.vm.navigateForward = jest.fn().mockImplementation(() => {}); + + // Act + await wrapper.setData({ + selectedVehicleVin: "5NMS3CADXLH233004", + }); + + await wrapper.vm.forwardButtonAction(); + wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.navigateForward).toHaveBeenCalled(); + }); + + test("Should return out of forwardButtonAction is lookupVin returns an error", async () => { + // Arrange + const { wrapper } = setupMocks({}); + wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn(); + + const lookupVinResponse = { + error: "there is an error", + }; + + wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn(); + wrapper.vm.$refs.siteFooter.removeLoader = jest.fn(); + wrapper.vm.lookupVin = jest.fn(() => Promise.reject(lookupVinResponse)); + wrapper.vm.$router.navigate = jest.fn(); + wrapper.vm.saveVin = jest.fn().mockImplementation(() => {}); + + // Act + await wrapper.setData({ + selectedVehicleVin: "5NMS3CADXLH233004", + }); + + await wrapper.vm.forwardButtonAction(); + wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.forwardButtonAction).toReturn; + }); + + 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.siteFooter.updateButtonText = jest.fn(); + wrapper.vm.$router.navigate = jest.fn(); + + // Act + await wrapper.setData({ + selectedVehicleVin: "5NMS3CADXLH233004", + isSelectedGlassAvailableForVehicle: false, + isCarIdDifferent: true, + }); + await wrapper.vm.navigateForward(); + + //Assert + expect(wrapper.vm.$router.navigate).toBeCalledTimes(1); + }); + + test("carId is not different on navigateForward (car was found) => Should handle navigating forward with car match", async () => { + // Arrange + const { wrapper } = setupMocks({}); + wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn(); + wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn(); + + // Act + await wrapper.setData({ + isCarIdDifferent: false, + }); + await wrapper.vm.navigateForward(); + + //Assert + expect(wrapper.vm.navigateForwardWithSingleCarMatch).toBeCalledTimes(1); + + }); + + test("Should return true for valid page requisites if carId exists", async () => { + // Arrange + const { wrapper } = setupMocks({}); + useMainStore().order.vehicle.carId = "CR00000395"; + + // Act + addressVehicles.beforeRouteEnter.call( + wrapper.vm, + { query: { issPage: "address-vehicles" } }, + undefined, + (c) => c(wrapper.vm) + ); + + let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); + + // Assert + expect(arePagePrerequisitesValid).toBe(true); + }); +}); + +function setupMocks({ + route = null, + lookupVehicleByVinResponse, +}) +{ + useMainStore().applicationUser = { + pageData: { + "address-vehicles": + [ + { + vehicle: { + carId: "CR00069309", + category: "SUV", + imageUrl: + "https://dbhdyzvm8lm25.cloudfront.net/color_0320_032/MY2020/13769/13769_cc0320_032_WW8.jpg", + imageVifColor: "white", + imageVifNumber: "13769", + make: "Hyundai", + model: "Santa Fe", + style: "4 door utility", + year: 2020, + }, + vin: "5NMS3CADXLH233004", + }, + ], + } + }; + + useMainStore().lookupVehicleByVin = jest.fn().mockImplementation(() => { + return Promise.resolve({ + data: lookupVehicleByVinResponse + ? lookupVehicleByVinResponse : { + vehicle: { + carId: "CARID" + }, + }, + }) + }); + + const mountOptions = getMountOptions({ + route: route ? route : undefined, + router: { + navigate: jest.fn(), + }, + mainStore: { + order: { + vehicle: { + carId: "CR00069309", + category: "SUV", + imageUrl: + "https://dbhdyzvm8lm25.cloudfront.net/color_0320_032/MY2020/13769/13769_cc0320_032_WW8.jpg", + imageVifColor: "white", + imageVifNumber: "13769", + make: "Hyundai", + model: "Santa Fe", + style: "4 door utility", + year: 2020, + }, + vin: "5NMS3CADXLH233004", + }, + }, + }, + ); + + const apiResponses = { + cmsContent: {}, + }; + + settleAllPromises.mockImplementation(() => apiResponses); + fetchCmsContentForPage.mockImplementation(() => Promise.resolve()); + + + //Mock props + const mockMixin = { + methods: { + getCmsContent: jest.fn((contentName) => { + if (contentName === "FoundMultipleVehicles") { + return "FoundMultipleVehiclesTestReturn"; + } + if (contentName === "ProvideVinAlert") { + return "ProvideVinAlertTestReturn"; + } + return null; + }), + }, + computed: { + dynamicStrings() { + return { ROUTER_LINK: "routerLink:" }; + }, + }, + }; + + mountOptions.mixins = [mockMixin]; + + const wrapper = shallowMount(addressVehicles, mountOptions); + + wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => ""); + wrapper.vm.setCmsContent = jest.fn(); + wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn(); + wrapper.vm.$refs.siteFooter.removeLoader = jest.fn(); + + return { wrapper }; +} diff --git a/src/layouts/address-vehicles/address-vehicles.vue b/src/layouts/address-vehicles/address-vehicles.vue index b6e1835b..8f6cbb2e 100644 --- a/src/layouts/address-vehicles/address-vehicles.vue +++ b/src/layouts/address-vehicles/address-vehicles.vue @@ -2,66 +2,103 @@
- + - + -
-

Placeholder for address-vehicles page

- - + +
+ + + {{ getRouterLinkDisplayTextFromCopy(copy) }} + + +
+
+ + + \ No newline at end of file diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js index 2e2c9d19..342ef39a 100644 --- a/src/router/router-constants/routing-table.js +++ b/src/router/router-constants/routing-table.js @@ -321,6 +321,39 @@ const routingTable = function(store) { }, ], }, + { + issPageValue: issPageValues.ADDRESS_VEHICLES, + maps: [ + { + scenario: navigationScenarios.CLICKED_BACK, + destinationIssPageValue: issPageValues.ADDRESS_LOOKUP, + }, + { + scenario: navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS, + destinationIssPageValue: issPageValues.VEHICLE_DAMAGE, + }, + { + scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS, + destinationIssPageValue: issPageValues.PART_QUESTIONS, + }, + { + scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE, + destinationIssPageValue: issPageValues.VEHICLE_PARTS, + }, + { + scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS, + destinationIssPageValue: issPageValues.MOLDING_QUESTIONS, + }, + { + scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS, + destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS, + }, + { + scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS, + destinationIssPageValue: issPageValues.COVERAGE_STATEMENT, + }, + ], + }, { issPageValue: issPageValues.WELCOME_PAGE, maps: [ diff --git a/src/store/index.js b/src/store/index.js index 2c760f84..abb22d83 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -893,7 +893,20 @@ export const useMainStore = defineStore({ this.updateRegistration(registrationInfo); } }, + saveVin({ isSelectedGlassAvailableForVehicle, vehicleInfo }) { + //Reset dependent state when changing + if (vehicleInfo.vin !== this.order.vehicle.vin) { + this.resetRegistrationAndDependencies(); + if (!isSelectedGlassAvailableForVehicle) { + this.resetDamageAndDependencies(); + this.resetPartsAndDependencies(); + } + + //Save new values + this.updateVehicle(vehicleInfo); + } + }, saveRegistrationLicensePlateLookup({ isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }) { //Reset dependent state when changing if