From 8d8d253bfcd1e9d782fe0f8609183e13f8925b58 Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Wed, 1 Mar 2023 09:11:31 -0500 Subject: [PATCH 1/9] Preparing for additional unit tests of page and mobile location component --- src/helpers/service-location-helper.js | 10 +-- src/helpers/service-location-helper.spec.js | 79 ++++++++++++++++++- .../mobile-location-modal-questions.vue | 15 +++- .../service-location/service-location.vue | 36 +++++---- 4 files changed, 113 insertions(+), 27 deletions(-) diff --git a/src/helpers/service-location-helper.js b/src/helpers/service-location-helper.js index 1f4a12f51..41f4be147 100644 --- a/src/helpers/service-location-helper.js +++ b/src/helpers/service-location-helper.js @@ -1,20 +1,20 @@ import { storeActions } from "@/constants/store-actions"; import baseMixin from "@/mixins/base-mixin.js"; -export async function getMobileFee(serviceZipCode) { +export async function getPricedMobileFeePart(serviceZipCode) { if (!serviceZipCode) { - return 0; + return Promise.resolve(null); } const zipCodeData = await baseMixin.methods.getZipCodeData(serviceZipCode); - + // Get the Mobile Fee Part const mobileFeePart = await baseMixin.methods.dispatchStoreAction( storeActions.GET_MOBILE_FEE_PART, null, false ); - + // Get the Mobile Fee Part Price const pricingResults = await baseMixin.methods.dispatchStoreAction( storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA, @@ -26,5 +26,5 @@ export async function getMobileFee(serviceZipCode) { false ); - return Promise.resolve(baseMixin.methods.getTotalLineItemPrice(pricingResults[0])); + return Promise.resolve(pricingResults[0]); } diff --git a/src/helpers/service-location-helper.spec.js b/src/helpers/service-location-helper.spec.js index 66012402c..9b1920fba 100644 --- a/src/helpers/service-location-helper.spec.js +++ b/src/helpers/service-location-helper.spec.js @@ -1 +1,78 @@ -test.todo("some test to be written in the future"); \ No newline at end of file +import { getPricedMobileFeePart } from "./service-location-helper"; +import { storeActions } from "@/constants/store-actions"; + +const mockStoreActionGetMobileFeePart = storeActions.GET_MOBILE_FEE_PART; +const mockStoreActionPriceOrderItemsAndSaveServerData = storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA; + +jest.mock("@/mixins/base-mixin.js", () => ({ + methods: { + getZipCodeData: jest.fn().mockImplementation(() => { + return Promise.resolve({ + containsMilitaryBase: false, + isServiceable: true, + isValid: true, + state: "OH", + zipCodeCtu: "01820", + }); + }), + + dispatchStoreAction: jest.fn().mockImplementation((actionName) => { + if (actionName === mockStoreActionGetMobileFeePart) { + return Promise.resolve({ + data: { + partNumber: "MOBILE FEE", + description: "MOBILE FEE", + partType: "FEE", + }, + }); + } + + if (actionName === mockStoreActionPriceOrderItemsAndSaveServerData) { + return Promise.resolve([ + { + partNumber: "MOBILE FEE", + description: "MOBILE FEE", + partType: "FEE", + laborAmount: 49.99, + sellingPrice: 0, + kitPrice: 0, + }, + ]); + } + }), + + }, +})); + +describe("service-location-helper.js", () => { + it("Should return the null if no service zip code is passed in", async() => { + // Arrange / Act + const serviceZipCode = null; + const expected = null; + + const result = await getPricedMobileFeePart(serviceZipCode); + + // Assert + expect(result).toEqual(expected); + }); + + it("Should return the priced mobile fee part", async() => { + // Arrange / Act + const serviceZipCode = "43235"; + const expected = { + partNumber: "MOBILE FEE", + description: "MOBILE FEE", + partType: "FEE", + laborAmount: 49.99, + sellingPrice: 0, + kitPrice: 0, + } + + const result = await getPricedMobileFeePart(serviceZipCode); + + // Assert + expect(result).toEqual(expected); + }); +}) + +//test.todo("some test to be written in the future"); diff --git a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue index a15709f67..ba7cc2fab 100644 --- a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue +++ b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue @@ -109,14 +109,21 @@ export default { }, mobileFeeText() { const cmsContentText = this.getCmsContent("MobileFeeDisclaimerWidget", "Text"); - if (this.modelValue.mobileFee === undefined) { - return cmsContentText.replaceAll("{custom:mobileFee}", 0); - } - return cmsContentText.replaceAll("{custom:mobileFee}", this.modelValue.mobileFee); + return cmsContentText.replaceAll("{custom:mobileFee}", this.mobileFee); }, modalFooterText() { return this.getCmsContent(this.modalWidgetName, "FooterText"); }, + mobileFee() { + if (!this.modelValue.mobileFeePart) { + return 0; + } + return ( + this.modelValue.mobileFeePart.laborAmount + + this.modelValue.mobileFeePart.sellingPrice + + this.modelValue.mobileFeePart.kitPrice + ); + }, addressModel: { get: function () { return this.modelValue.addressQuestions; diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index f2339b218..6c7849216 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -6,7 +6,7 @@ @@ -38,7 +38,7 @@ import { Form } from "vee-validate"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper"; -import { getMobileFee } from "@/helpers/service-location-helper"; +import { getPricedMobileFeePart } from "@/helpers/service-location-helper"; import store from "@/store"; export default { @@ -66,13 +66,13 @@ export default { }, }; }, - async beforeRouteEnter(to, from, next) { + async beforeRouteEnter(to, from, next) { // Call APIs const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage); - const serviceZipCode = store.getters.order.serviceLocation.zipCode; - const mobileFeePromise = getMobileFee(serviceZipCode); - + const serviceZipCode = store.getters.order.serviceLocation.zipCode; + const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode); + // Settle promises and get results const promiseResultMap = [ { @@ -80,17 +80,19 @@ export default { promise: cmsContentPromise, }, { - resultKey: "mobileFee", - promise: mobileFeePromise, + resultKey: "mobileFeePart", + promise: mobileFeePartPromise, }, ]; const resultMap = await settleAllPromises(promiseResultMap); - + console.log(resultMap); + console.log(resultMap.cmsContent); + console.log(resultMap.mobileFeePart); // Call the "next" function to complete the transition to this page. next((vm) => { vm.setCmsContent(resultMap.cmsContent); - vm.setData(resultMap.mobileFee); + vm.setData(resultMap.mobileFeePart); }); }, methods: { @@ -102,9 +104,9 @@ export default { // store.getters.payment.isInsurance !== null // ); }, - setData(mobileFee) { - if (mobileFee) { - this.mobileLocationQuestions.mobileFee = mobileFee + setData(mobileFeePart) { + if (mobileFeePart) { + this.mobileLocationQuestions.mobileFeePart = mobileFeePart; } }, getRegistrationAddressFromStore() { @@ -128,9 +130,9 @@ export default { getIsServiceableFromStore() { return store.getters.order.serviceLocation.isServiceable; }, - recalculateMobileFee(serviceZipCode) { - getMobileFee(serviceZipCode).then((mobileFee) => { - this.mobileLocationQuestions.mobileFee = mobileFee; + resetMobileFeePart(serviceZipCode) { + getPricedMobileFeePart(serviceZipCode).then((pricedMobileFeePart) => { + this.mobileLocationQuestions.mobileFeePart = pricedMobileFeePart; }); }, resetMobileLocation(updatedServiceZipCode) { @@ -153,7 +155,7 @@ export default { this.serviceZipCodeQuestion.zipCode = newValue.zipCode; this.serviceZipCodeQuestion.isServiceable = newValue.isServiceable; - this.recalculateMobileFee(this.serviceZipCodeQuestion.zipCode); + this.resetMobileFeePart(this.serviceZipCodeQuestion.zipCode); }, backButtonAction() { this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route); From 7304729717eea21de083d3614078205e631004c7 Mon Sep 17 00:00:00 2001 From: CarlNation Date: Wed, 1 Mar 2023 10:09:45 -0500 Subject: [PATCH 2/9] CSR-969 Hide the home address lookup if a provided zip is in a state that prohibits it --- src/constants/endpoints.js | 4 ++++ src/constants/store-actions.js | 1 + src/layouts/estimate/estimate.vue | 21 +++++++++++++++++++++ src/store/index.js | 7 +++++++ 4 files changed, 33 insertions(+) diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index 9f4c60d61..1fc6c2b8f 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -54,6 +54,10 @@ const endpoints = { url: "/vehicle/api/v1/vehicle/lookup-vin-by-address", method: "POST", }, + IsVinByAddressPermissible: { + url: "/vehicle/api/v1/vehicle/is-vin-by-address-permissible", + method: "GET", + }, GetPartsOrQuestions: { url: "/parts/api/v1/parts/parts-or-questions", method: "POST", diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js index 428280d40..c11356d69 100644 --- a/src/constants/store-actions.js +++ b/src/constants/store-actions.js @@ -13,6 +13,7 @@ const storeActions = { GET_DAMAGE_OPTIONS: "getDamageOptions", GET_EVOX_IMAGE: "getEvoxImage", IS_VIN_OPTIONAL_VEHICLE: "isVinOptionalVehicle", + IS_VIN_BY_ADDRESS_PERMISSIBLE: "isVinByAddressPermissible", // Lookup Actions LOOKUP_VEHICLE_BY_YMMS: "lookupVehicleByYmms", diff --git a/src/layouts/estimate/estimate.vue b/src/layouts/estimate/estimate.vue index 4eafab25e..893f76cb8 100644 --- a/src/layouts/estimate/estimate.vue +++ b/src/layouts/estimate/estimate.vue @@ -112,6 +112,8 @@ import { experimentSettings } from "@/constants/experiments"; import vinPagesMixin from "@/mixins/vin-pages-mixin"; import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper"; import { saveSession } from "@/helpers/heritage-integration/order-helper.js"; +import baseMixin from "@/mixins/base-mixin.js"; +import { queryStrings } from "@/constants/query-strings"; // Define Validation Rules defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED)); @@ -145,12 +147,25 @@ export default { //Call APIs const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage); + const zip = Object.hasOwn(to.query, queryStrings.ZIP_CODE) ? to.query.zipCode : null; + var vinByAddressPromise; + if (zip) { + vinByAddressPromise = baseMixin.methods.dispatchStoreAction( + storeActions.IS_VIN_BY_ADDRESS_PERMISSIBLE, + zip, false + ); + } + //Settle promises and get results const promiseResultMap = [ { resultKey: "cmsContent", promise: cmsContentPromise, }, + (zip != null && zip != undefined) && { + resultKey: "vinByAddress", + promise: vinByAddressPromise, + }, ]; const resultMap = await settleAllPromises(promiseResultMap); @@ -172,6 +187,12 @@ export default { } } + if (zip){ + var indexToRemove = resultMap.cmsContent.VinLookupMethod.Answers.findIndex(answer => answer.Name === 'HomeAddress') + if (indexToRemove){ + resultMap.cmsContent.VinLookupMethod.Answers.splice(indexToRemove, 1); + } + } vm.setCmsContent(resultMap.cmsContent); }); }, diff --git a/src/store/index.js b/src/store/index.js index 93a3e5a25..f42a950ea 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -530,6 +530,13 @@ export const actions = { }, }); }, + isVinByAddressPermissible(context, zip) { + return globalMethods.callHttpClient({ + method: endpoints.IsVinByAddressPermissible.method, + endpoint: `${endpoints.IsVinByAddressPermissible.url}?zipcode=${zip}`, + payload: {}, + }); + }, getVehicleMakes(context, { year }) { return globalMethods.callHttpClient({ method: endpoints.GetVehicleMakes.method, From afcd713fdba5ef835c86245d8979d2dfb9ae2a56 Mon Sep 17 00:00:00 2001 From: CarlNation Date: Wed, 1 Mar 2023 11:35:40 -0500 Subject: [PATCH 3/9] CSR-969 prettier --- src/layouts/estimate/estimate.vue | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/layouts/estimate/estimate.vue b/src/layouts/estimate/estimate.vue index 893f76cb8..722357e62 100644 --- a/src/layouts/estimate/estimate.vue +++ b/src/layouts/estimate/estimate.vue @@ -152,7 +152,8 @@ export default { if (zip) { vinByAddressPromise = baseMixin.methods.dispatchStoreAction( storeActions.IS_VIN_BY_ADDRESS_PERMISSIBLE, - zip, false + zip, + false ); } @@ -162,10 +163,11 @@ export default { resultKey: "cmsContent", promise: cmsContentPromise, }, - (zip != null && zip != undefined) && { - resultKey: "vinByAddress", - promise: vinByAddressPromise, - }, + zip != null && + zip != undefined && { + resultKey: "vinByAddress", + promise: vinByAddressPromise, + }, ]; const resultMap = await settleAllPromises(promiseResultMap); @@ -187,9 +189,11 @@ export default { } } - if (zip){ - var indexToRemove = resultMap.cmsContent.VinLookupMethod.Answers.findIndex(answer => answer.Name === 'HomeAddress') - if (indexToRemove){ + if (zip) { + var indexToRemove = resultMap.cmsContent.VinLookupMethod.Answers.findIndex( + (answer) => answer.Name === "HomeAddress" + ); + if (indexToRemove) { resultMap.cmsContent.VinLookupMethod.Answers.splice(indexToRemove, 1); } } From 9ec12c81bdc9e70005edb0d638f0a9003d5c5c80 Mon Sep 17 00:00:00 2001 From: CarlNation Date: Thu, 2 Mar 2023 09:43:00 -0500 Subject: [PATCH 4/9] CSR-945 CSR-969 use lower case for querystring parms --- src/constants/query-strings.js | 2 +- src/layouts/estimate/estimate.vue | 12 ++++++++---- .../license-plate-lookup/license-plate-lookup.vue | 2 +- src/layouts/vin-lookup/vin-lookup.vue | 2 +- src/router/index.js | 14 +++++++++++--- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/constants/query-strings.js b/src/constants/query-strings.js index d2dbcf976..5ff1f636c 100644 --- a/src/constants/query-strings.js +++ b/src/constants/query-strings.js @@ -1,7 +1,7 @@ const queryStrings = { FMG_PAGE: "fmgPage", START_TYPE: "start_type", - ZIP_CODE: "zipCode", + ZIP_CODE: "zipcode", }; export { queryStrings }; diff --git a/src/layouts/estimate/estimate.vue b/src/layouts/estimate/estimate.vue index 722357e62..cfec5923d 100644 --- a/src/layouts/estimate/estimate.vue +++ b/src/layouts/estimate/estimate.vue @@ -134,7 +134,7 @@ export default { data() { return { selectedVinLookupMethod: null, - serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipCode, + serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode, emailAddress: this.getEmailFromStore(), displayInvalidZipAlert: false, displayNonServiceableZipAlert: false, @@ -147,9 +147,13 @@ export default { //Call APIs const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage); - const zip = Object.hasOwn(to.query, queryStrings.ZIP_CODE) ? to.query.zipCode : null; + const queryString = window.location.search; + const urlParams = new URLSearchParams(queryString); + const hasZip = urlParams.has(queryStrings.ZIP_CODE); + const zip = urlParams.get(queryStrings.ZIP_CODE); + var vinByAddressPromise; - if (zip) { + if (hasZip) { vinByAddressPromise = baseMixin.methods.dispatchStoreAction( storeActions.IS_VIN_BY_ADDRESS_PERMISSIBLE, zip, @@ -189,7 +193,7 @@ export default { } } - if (zip) { + if (zip && resultMap.vinByAddress === false) { var indexToRemove = resultMap.cmsContent.VinLookupMethod.Answers.findIndex( (answer) => answer.Name === "HomeAddress" ); diff --git a/src/layouts/license-plate-lookup/license-plate-lookup.vue b/src/layouts/license-plate-lookup/license-plate-lookup.vue index ec54fd4f7..c97791937 100644 --- a/src/layouts/license-plate-lookup/license-plate-lookup.vue +++ b/src/layouts/license-plate-lookup/license-plate-lookup.vue @@ -152,7 +152,7 @@ export default { data() { return { licensePlate: this.getLicensePlateFromStore(), - registrationZipCode: this.getRegistrationZipFromStore() ?? this.$route.query.zipCode, + registrationZipCode: this.getRegistrationZipFromStore() ?? this.$route.query.zipcode, email: this.getEmailFromStore(), serviceZipCode: this.getServiceZipFromStore(), displayNonServiceableZipAlert: false, diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue index 17e981bc8..e42187b12 100644 --- a/src/layouts/vin-lookup/vin-lookup.vue +++ b/src/layouts/vin-lookup/vin-lookup.vue @@ -176,7 +176,7 @@ export default { data() { return { vin: this.getVinFromStore(), - serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipCode, + serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode, emailAddress: this.getEmailFromStore(), isCarIdDifferent: false, customAlertData: {}, diff --git a/src/router/index.js b/src/router/index.js index 409ce0419..c94ef65e3 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -265,14 +265,22 @@ async function navigate( fmgPage: destinationFmgPageValue, }; - if ( - Object.hasOwn(currentRoute.query, queryStrings.ZIP_CODE) && + const queryString = window.location.search; + const urlParams = new URLSearchParams(queryString); + const lowerCaseParams = new URLSearchParams(); + for (const [name, value] of urlParams) { + lowerCaseParams.append(name.toLowerCase(), value); + } + const hasZip = lowerCaseParams.has(queryStrings.ZIP_CODE); + const zip = lowerCaseParams.get(queryStrings.ZIP_CODE); + + if (hasZip && (store.getters.order.serviceLocation.zipCode === undefined || store.getters.order.serviceLocation.zipCode == null) && (store.getters.order.vehicle.registration.zipCode === undefined || store.getters.order.vehicle.registration.zipCode == null) ) { - queryStringsObject[queryStrings.ZIP_CODE] = currentRoute.query.zipCode; + queryStringsObject[queryStrings.ZIP_CODE] = zip; } router.push({ From a29fb2b2a4b9ee3d05eea087d90784178d589d63 Mon Sep 17 00:00:00 2001 From: CarlNation Date: Thu, 2 Mar 2023 09:46:53 -0500 Subject: [PATCH 5/9] CSR-945 CSR-946 prettier --- src/router/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/router/index.js b/src/router/index.js index c94ef65e3..eb8e3947c 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -274,7 +274,8 @@ async function navigate( const hasZip = lowerCaseParams.has(queryStrings.ZIP_CODE); const zip = lowerCaseParams.get(queryStrings.ZIP_CODE); - if (hasZip && + if ( + hasZip && (store.getters.order.serviceLocation.zipCode === undefined || store.getters.order.serviceLocation.zipCode == null) && (store.getters.order.vehicle.registration.zipCode === undefined || From e6625aeb341d657eaf4a9afbe86e7177d238620c Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Thu, 2 Mar 2023 14:04:55 -0500 Subject: [PATCH 6/9] Addl unit tests for service-location and tests for mobile-location-modal-question --- src/helpers/service-location-helper.spec.js | 14 +- .../mobile-location-modal-questions.spec.js | 210 ++++++++++++++++- .../mobile-location-modal-questions.vue | 7 +- .../service-location/service-location.spec.js | 217 ++++++++++++++---- .../service-location/service-location.vue | 42 ++-- 5 files changed, 407 insertions(+), 83 deletions(-) diff --git a/src/helpers/service-location-helper.spec.js b/src/helpers/service-location-helper.spec.js index 9b1920fba..ac3eace06 100644 --- a/src/helpers/service-location-helper.spec.js +++ b/src/helpers/service-location-helper.spec.js @@ -2,7 +2,8 @@ import { getPricedMobileFeePart } from "./service-location-helper"; import { storeActions } from "@/constants/store-actions"; const mockStoreActionGetMobileFeePart = storeActions.GET_MOBILE_FEE_PART; -const mockStoreActionPriceOrderItemsAndSaveServerData = storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA; +const mockStoreActionPriceOrderItemsAndSaveServerData = + storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA; jest.mock("@/mixins/base-mixin.js", () => ({ methods: { @@ -40,12 +41,11 @@ jest.mock("@/mixins/base-mixin.js", () => ({ ]); } }), - }, })); describe("service-location-helper.js", () => { - it("Should return the null if no service zip code is passed in", async() => { + it("Should return the null if no service zip code is passed in", async () => { // Arrange / Act const serviceZipCode = null; const expected = null; @@ -54,9 +54,9 @@ describe("service-location-helper.js", () => { // Assert expect(result).toEqual(expected); - }); + }); - it("Should return the priced mobile fee part", async() => { + it("Should return the priced mobile fee part", async () => { // Arrange / Act const serviceZipCode = "43235"; const expected = { @@ -66,13 +66,13 @@ describe("service-location-helper.js", () => { laborAmount: 49.99, sellingPrice: 0, kitPrice: 0, - } + }; const result = await getPricedMobileFeePart(serviceZipCode); // Assert expect(result).toEqual(expected); }); -}) +}); //test.todo("some test to be written in the future"); diff --git a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.spec.js b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.spec.js index 7e5aaff8c..f7a2238c8 100644 --- a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.spec.js +++ b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.spec.js @@ -2,6 +2,7 @@ import mobileLocationModalQuestions from "./mobile-location-modal-questions"; import { mount, shallowMount } from "@vue/test-utils"; import { storeActions } from "@/constants/store-actions"; import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import modal from "@/digital-components/modal/modal"; import crypto from "crypto"; @@ -42,7 +43,7 @@ const mockMixin = { }), getZipCodeData: jest.fn((zip) => { - if (zip === "43235") { + if (zip === "43235" || zip === "55555") { return Promise.resolve({ containsMilitaryBase: false, isServiceable: true, @@ -128,6 +129,213 @@ describe("mobile-location-modal-questions.vue", () => { expect(wrapper.vm.internalModel.isVehicleProtected).toEqual(true); expect(wrapper.vm.internalModel.serviceZipCode).toEqual("55555"); }); + + it("Should open the modal when the 'Enter your service address' link is clicked", async () => { + // Arrange + const mobileLocationQuestions = { + addressQuestions: { + streetAddress: "555 Some St", + apartmentNumberOrBusinessName: "Apt 1", + city: "Funkytown", + state: "OH", + zipCode: "55555", + }, + isVehicleProtected: true, + serviceZipCode: "55555", + }; + + const { wrapper } = setupMocks({ + mixins: [mockMixin], + props: { + modelValue: mobileLocationQuestions, + }, + mountOptions: { + attachTo: document.body, + }, + }); + + wrapper.vm.$refs.MobileLocationModalWidget.openModal = jest.fn(); + const mobileLocationLink = wrapper.findComponent({ ref: "mobileLocationLink" }); + + // // Act + await mobileLocationLink.trigger("click-event"); + + // // Assert + expect(wrapper.vm.$refs.MobileLocationModalWidget.openModal).toHaveBeenCalled(); + }); + + it("Should emit update:modelValue on setMobileLocation for a valid address and vehicle protection answer", async () => { + // Arrange + const mobileLocationQuestions = { + addressQuestions: { + streetAddress: "", + apartmentNumberOrBusinessName: "", + city: "", + state: "", + zipCode: "", + }, + isVehicleProtected: true, + serviceZipCode: "", + }; + + const newMobileLocationQuestions = { + addressQuestions: { + streetAddress: "555 Some St", + apartmentNumberOrBusinessName: "Apt 1", + city: "Funkytown", + state: "OH", + zipCode: "55555", + }, + isVehicleProtected: true, + serviceZipCode: "55555", + }; + + const wrapper = shallowMount(mobileLocationModalQuestions, { + mixins: [mockMixin], + props: { + modelValue: mobileLocationQuestions, + linkWidgetName: linkWidgetName, + modalWidgetName: modalWidgetName, + }, + attachTo: document.body, + }); + wrapper.vm.$refs.MobileLocationModalWidget.closeModal = jest.fn(); + + // Act + wrapper.vm.internalModel = newMobileLocationQuestions; + await wrapper.vm.setMobileLocation(); + + let expectedEmit = [[newMobileLocationQuestions]]; + + // Assert + expect(wrapper.emitted("update:modelValue")).toEqual(expectedEmit); + }); + + it("Should not emit update:modelValue on setMobileLocation for an invalid address zip code", async () => { + // Arrange + const mobileLocationQuestions = { + addressQuestions: { + streetAddress: "", + apartmentNumberOrBusinessName: "", + city: "", + state: "", + zipCode: "", + }, + isVehicleProtected: true, + serviceZipCode: "", + }; + + const newMobileLocationQuestions = { + addressQuestions: { + streetAddress: "555 Some St", + apartmentNumberOrBusinessName: "Apt 1", + city: "Funkytown", + state: "OH", + zipCode: "61000", + }, + isVehicleProtected: true, + serviceZipCode: "61000", + }; + + const wrapper = shallowMount(mobileLocationModalQuestions, { + mixins: [mockMixin], + props: { + modelValue: mobileLocationQuestions, + linkWidgetName: linkWidgetName, + modalWidgetName: modalWidgetName, + }, + attachTo: document.body, + }); + wrapper.vm.$refs.MobileLocationModalWidget.closeModal = jest.fn(); + + // Act + wrapper.vm.internalModel = newMobileLocationQuestions; + await wrapper.vm.setMobileLocation(); + + // Assert + expect(wrapper.emitted("update:modelValue")).not.toBeTruthy(); + }); + + it("Should display invalid zip alert for invalid address zip inputs", async () => { + // Arrange + const mobileLocationQuestions = { + addressQuestions: { + streetAddress: "", + apartmentNumberOrBusinessName: "", + city: "", + state: "", + zipCode: "", + }, + isVehicleProtected: true, + serviceZipCode: "", + }; + + const newMobileLocationQuestions = { + addressQuestions: { + streetAddress: "555 Some St", + apartmentNumberOrBusinessName: "Apt 1", + city: "Funkytown", + state: "OH", + zipCode: "11111", + }, + isVehicleProtected: true, + serviceZipCode: "11111", + }; + + const wrapper = shallowMount(mobileLocationModalQuestions, { + mixins: [mockMixin], + props: { + modelValue: mobileLocationQuestions, + linkWidgetName: linkWidgetName, + modalWidgetName: modalWidgetName, + }, + attachTo: document.body, + }); + + wrapper.vm.internalModel = newMobileLocationQuestions; + + // Act + await wrapper.vm.setMobileLocation(); + + // Assert + expect(wrapper.vm.displayInvalidZipAlert).toBe(true); + }); + + it("Should clear the internal model when resetModel is called", async () => { + // Arrange + const mobileLocationQuestions = { + addressQuestions: { + streetAddress: "555 Some St", + apartmentNumberOrBusinessName: "Apt 1", + city: "Funkytown", + state: "OH", + zipCode: "55555", + }, + isVehicleProtected: true, + serviceZipCode: "55555", + }; + + const { wrapper } = setupMocks({ + mixins: [mockMixin], + props: { + modelValue: mobileLocationQuestions, + }, + mountOptions: { + attachTo: document.body, + }, + }); + + // Act + wrapper.vm.resetModel(); + + // Assert + expect(wrapper.vm.internalModel.addressQuestions.streetAddress).toEqual(""); + expect(wrapper.vm.internalModel.addressQuestions.apartmentNumberOrBusinessName).toEqual(""); + expect(wrapper.vm.internalModel.addressQuestions.city).toEqual(""); + expect(wrapper.vm.internalModel.addressQuestions.state).toEqual(""); + expect(wrapper.vm.internalModel.addressQuestions.zipCode).toEqual(""); + expect(wrapper.vm.internalModel.isVehicleProtected).toEqual(null); + }); }); function setupMocks({ mountOptions, mixins, props, isShallowMount = true }) { diff --git a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue index ba7cc2fab..644a875d3 100644 --- a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue +++ b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue @@ -7,6 +7,7 @@ v-html="mobileLocationLinkPromptText">