diff --git a/src/layouts/scheduling/scheduling-zip-search/scheduling-zip-search.spec.js b/src/layouts/scheduling/scheduling-zip-search/scheduling-zip-search.spec.js index e75a76a17..a384b1603 100644 --- a/src/layouts/scheduling/scheduling-zip-search/scheduling-zip-search.spec.js +++ b/src/layouts/scheduling/scheduling-zip-search/scheduling-zip-search.spec.js @@ -1,6 +1,7 @@ import { shallowMount } from "@vue/test-utils"; import schedulingZipSearch from "./scheduling-zip-search"; import store from "@/store"; +import { errorMessages } from "@/constants/error-messages"; import { getBillToAccountNumber, getZipCodeData, @@ -21,77 +22,72 @@ jest.mock( }) ); -function mountComponent(props = {}) { +function createWrapper(props = {}) { return shallowMount(schedulingZipSearch, { props: { - modelValue: "43235", + modelValue: "", pageNameToLog: "scheduling", ...props, }, + global: { + mocks: { + $root: { + cmsContentByWidget: { + ServiceZipQuestionWidget: { + QuestionText: "Service ZIP code:", + }, + }, + }, + }, + }, }); } describe("scheduling-zip-search.vue", () => { - test("renders serviceZipQuestion with search icon", () => { - const wrapper = mountComponent(); - const zipQuestion = wrapper.find("service-zip-question-stub"); - expect(zipQuestion.exists()).toBe(true); - expect(zipQuestion.attributes("includesearchicon")).toBeDefined(); - wrapper.unmount(); + beforeEach(() => { + jest.clearAllMocks(); }); - test("validates zip on search when field is blank", async () => { - const validate = jest.fn().mockResolvedValue({ valid: false }); - const wrapper = mountComponent({ modelValue: "" }); - Object.defineProperty(wrapper.vm.$refs, "zipCodeSearch", { - configurable: true, - value: { - $refs: { - zipInputTextQuestion: { validate }, - }, - }, - }); + test("prefills the zip input and CMS label from modelValue / ServiceZipQuestionWidget", () => { + const wrapper = createWrapper({ modelValue: "43235" }); + + expect(wrapper.find("#sz-service-zip").element.value).toBe("43235"); + expect(wrapper.vm.zipLabelText).toBe("Service ZIP code:"); + expect(wrapper.find("label").html()).toContain("Service ZIP code:"); + }); + + test("shows required error when searching with a blank zip", async () => { + const wrapper = createWrapper({ modelValue: "" }); await wrapper.vm.onZipSearch({ preventDefault: jest.fn() }); - expect(validate).toHaveBeenCalled(); + expect(wrapper.vm.errorMessage).toBe(errorMessages.SERVICE_ZIP_REQUIRED); + expect(wrapper.find(".scheduling-zip-search__error").classes()).toContain("active"); + expect(getZipCodeData).not.toHaveBeenCalled(); + expect(wrapper.emitted("zip-searched")).toBeUndefined(); + }); + + test("shows format error when zip is invalid", async () => { + const wrapper = createWrapper({ modelValue: "123" }); + + await wrapper.vm.onZipSearch({ preventDefault: jest.fn() }); + + expect(wrapper.vm.errorMessage).toBe(errorMessages.SERVICE_ZIP_FORMAT); expect(getZipCodeData).not.toHaveBeenCalled(); expect(wrapper.emitted("zip-searched")).toBeUndefined(); - wrapper.unmount(); }); test("does not search when disabled", async () => { - const validate = jest.fn().mockResolvedValue({ valid: true }); - const wrapper = mountComponent({ disabled: true }); - Object.defineProperty(wrapper.vm.$refs, "zipCodeSearch", { - configurable: true, - value: { - $refs: { - zipInputTextQuestion: { validate }, - }, - }, - }); + const wrapper = createWrapper({ modelValue: "44101", disabled: true }); await wrapper.vm.onZipSearch({ preventDefault: jest.fn() }); - expect(validate).toHaveBeenCalled(); expect(getZipCodeData).not.toHaveBeenCalled(); - wrapper.unmount(); + expect(wrapper.emitted("zip-searched")).toBeUndefined(); }); test("saves zip info and emits billToAccountNumber when a valid zip is searched", async () => { - store.dispatch.mockClear(); - const wrapper = mountComponent({ modelValue: "44101" }); - Object.defineProperty(wrapper.vm.$refs, "zipCodeSearch", { - configurable: true, - value: { - $refs: { - zipInputTextQuestion: { - validate: jest.fn().mockResolvedValue({ valid: true }), - }, - }, - }, - }); + const wrapper = createWrapper({ modelValue: "44101" }); await wrapper.vm.onZipSearch({ preventDefault: jest.fn() }); @@ -105,6 +101,20 @@ describe("scheduling-zip-search.vue", () => { expect(wrapper.emitted("zip-searched")).toEqual([ [{ zipCode: "44101", billToAccountNumber: "87291" }], ]); - wrapper.unmount(); + }); + + test("focusZipInput scrolls and focuses the zip input", () => { + const wrapper = createWrapper({ modelValue: "43235" }); + const zipInput = wrapper.find("#sz-service-zip").element; + zipInput.scrollIntoView = jest.fn(); + zipInput.focus = jest.fn(); + + wrapper.vm.focusZipInput(); + + expect(zipInput.scrollIntoView).toHaveBeenCalledWith({ + behavior: "smooth", + block: "center", + }); + expect(zipInput.focus).toHaveBeenCalledWith({ preventScroll: true }); }); }); diff --git a/src/layouts/scheduling/scheduling-zip-search/scheduling-zip-search.vue b/src/layouts/scheduling/scheduling-zip-search/scheduling-zip-search.vue index 75aad0029..25203fd28 100644 --- a/src/layouts/scheduling/scheduling-zip-search/scheduling-zip-search.vue +++ b/src/layouts/scheduling/scheduling-zip-search/scheduling-zip-search.vue @@ -1,37 +1,47 @@ diff --git a/src/layouts/scheduling/scheduling.spec.js b/src/layouts/scheduling/scheduling.spec.js index aa5cc4a78..60347ace7 100644 --- a/src/layouts/scheduling/scheduling.spec.js +++ b/src/layouts/scheduling/scheduling.spec.js @@ -185,15 +185,11 @@ describe("scheduling.vue", () => { }); describe("service zip", () => { - test("prefills zipSearchCode and billToAccountNumber from store on mount", () => { + test("prefills zipSearchCode and billToAccountNumber from store and renders zip search", () => { const { wrapper } = setupMocks(); + expect(wrapper.vm.zipSearchCode).toBe("43235"); expect(wrapper.vm.billToAccountNumber).toBe("12345"); - wrapper.unmount(); - }); - - test("renders schedulingZipSearch", () => { - const { wrapper } = setupMocks(); expect(wrapper.find("scheduling-zip-search-stub").exists()).toBe(true); wrapper.unmount(); }); @@ -228,16 +224,10 @@ describe("scheduling.vue", () => { await wrapper.vm.onZipSearched({ zipCode: "44101", billToAccountNumber: "87291" }); - const getProvidersDispatch = store.dispatch.mock.calls.find( - ([actionName]) => actionName === "getProviders" - ); - expect(getProvidersDispatch).toEqual([ - "getProviders", - { - payload: { serviceZipCode: "44101" }, - pageNameToLog: undefined, - }, - ]); + expect(store.dispatch).toHaveBeenCalledWith("getProviders", { + payload: { serviceZipCode: "44101" }, + pageNameToLog: undefined, + }); expect(wrapper.vm.billToAccountNumber).toBe("87291"); expect(settleAllPromises).toHaveBeenCalled(); expect(wrapper.vm.datePickerKey).toBe(initialDatePickerKey + 1); @@ -248,5 +238,16 @@ describe("scheduling.vue", () => { expect(wrapper.vm.mobileProviderAndTimeSlot.providerNumber).toBe("12345"); wrapper.unmount(); }); + + test("anchors to zip search when mobile zip is clicked", () => { + const { wrapper } = setupMocks(); + const focusZipInput = jest.fn(); + wrapper.vm.$refs.schedulingZipSearch = { focusZipInput }; + + wrapper.vm.onMobileZipCodeClicked(); + + expect(focusZipInput).toHaveBeenCalled(); + wrapper.unmount(); + }); }); }); diff --git a/src/layouts/scheduling/scheduling.vue b/src/layouts/scheduling/scheduling.vue index a0f67df4a..b9d11a8bc 100644 --- a/src/layouts/scheduling/scheduling.vue +++ b/src/layouts/scheduling/scheduling.vue @@ -12,6 +12,7 @@