diff --git a/src/layouts/service-location/appointment-type-question/appointment-type-question.spec.js b/src/layouts/service-location/appointment-type-question/appointment-type-question.spec.js index b6487715e..cdbe474a2 100644 --- a/src/layouts/service-location/appointment-type-question/appointment-type-question.spec.js +++ b/src/layouts/service-location/appointment-type-question/appointment-type-question.spec.js @@ -49,10 +49,8 @@ describe("appointment-type-question.vue", () => { mixins: [mockMixin], props: { cmsWidgetName: cmsWidgetName, - isGlassServiceableInshop: true, - isRecalibrationServiceableInshop: true, - isGlassServiceableMobile: true, - isRecalibrationServiceableMobile: true, + isServiceableInshop: true, + isServiceableMobile: true, }, mountOptions: { attachTo: document.body, @@ -91,10 +89,8 @@ describe("appointment-type-question.vue", () => { mixins: [mockMixin], props: { cmsWidgetName: cmsWidgetName, - isGlassServiceableInshop: true, - isRecalibrationServiceableInshop: true, - isGlassServiceableMobile: false, - isRecalibrationServiceableMobile: false, + isServiceableInshop: true, + isServiceableMobile: false, }, mountOptions: { attachTo: document.body, @@ -126,10 +122,8 @@ describe("appointment-type-question.vue", () => { mixins: [mockMixin], props: { cmsWidgetName: cmsWidgetName, - isGlassServiceableInshop: false, - isRecalibrationServiceableInshop: false, - isGlassServiceableMobile: true, - isRecalibrationServiceableMobile: true, + isServiceableInshop: false, + isServiceableMobile: true, }, mountOptions: { attachTo: document.body, @@ -154,10 +148,8 @@ describe("appointment-type-question.vue", () => { mixins: [mockMixin], props: { cmsWidgetName: cmsWidgetName, - isGlassServiceableInshop: false, - isRecalibrationServiceableInshop: false, - isGlassServiceableMobile: false, - isRecalibrationServiceableMobile: false, + isServiceableInshop: false, + isServiceableMobile: false, }, mountOptions: { attachTo: document.body, diff --git a/src/layouts/service-location/appointment-type-question/appointment-type-question.vue b/src/layouts/service-location/appointment-type-question/appointment-type-question.vue index 8985f12e7..0394b8a84 100644 --- a/src/layouts/service-location/appointment-type-question/appointment-type-question.vue +++ b/src/layouts/service-location/appointment-type-question/appointment-type-question.vue @@ -26,10 +26,8 @@ export default { suppressError: Boolean, validationRules: String, cmsWidgetName: String, - isGlassServiceableMobile: Boolean, - isGlassServiceableInshop: Boolean, - isRecalibrationServiceableInshop: Boolean, - isRecalibrationServiceableMobile: Boolean, + isServiceableMobile: Boolean, + isServiceableInshop: Boolean, }, computed: { questionText() { @@ -40,45 +38,20 @@ export default { }, answersToDisplay() { let filteredAnswers; - if (this.serviceability == "All") { + if (this.isServiceableMobile && this.isServiceableInshop) { filteredAnswers = this.answersFromCms; - } else if (this.serviceability == "MobileOnly") { + } else if (this.isServiceableMobile) { filteredAnswers = this.answersFromCms.filter((answer) => answer.Name == "Mobile"); - } else if (this.serviceability == "InshopOnly") { + } else if (this.isServiceableInshop) { filteredAnswers = this.answersFromCms.filter( (answer) => answer.Name == "Inshop" || answer.Name == "DropOff" ); - } else if (this.serviceability == "None") { + } else { filteredAnswers = []; } return filteredAnswers; }, - serviceability() { - let mobileAvailable; - if (this.IsRecalibrationServiceableMobile == null) { - mobileAvailable = this.isGlassServiceableMobile; - } else { - mobileAvailable = - this.isGlassServiceableMobile && this.isRecalibrationServiceableMobile; - } - - const inshopAvailable = - this.isGlassServiceableInshop && this.isRecalibrationServiceableInshop; - - let result; - if (inshopAvailable && mobileAvailable) { - result = "All"; - } else if (inshopAvailable && !mobileAvailable) { - result = "InshopOnly"; - } else if (!inshopAvailable && mobileAvailable) { - result = "MobileOnly"; - } else if (!inshopAvailable && !mobileAvailable) { - result = "None"; - } - - return result; - }, selectedValues: { get: function () { return this.modelValue; @@ -87,11 +60,14 @@ export default { this.$emit("update:modelValue", newValue); }, }, + isMobileOnly() { + return this.isServiceableMobile && !this.isServiceableInshop; + }, }, watch: { - serviceability: { + isMobileOnly: { handler(newValue) { - if (newValue == "MobileOnly") { + if (newValue) { this.selectedValues = "Mobile"; } else { this.selectedValues = null; diff --git a/src/layouts/service-location/service-location.spec.js b/src/layouts/service-location/service-location.spec.js index 2a056c4d1..27f431884 100644 --- a/src/layouts/service-location/service-location.spec.js +++ b/src/layouts/service-location/service-location.spec.js @@ -7,6 +7,7 @@ import { getMountOptions } from "@/helpers/unit-test-helper"; import store from "@/store"; import baseMixin from "@/mixins/base-mixin"; +import { getServiceabilityDetails } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper"; // Define Mocks jest.mock("@/helpers/cms-content-helper", () => ({ @@ -437,6 +438,386 @@ describe("service-location.vue", () => { expect(wrapper.vm.serviceZipCodeQuestion).toStrictEqual(newServiceZipCodeInfo); }); }); + + describe("serviceability logic", () => { + describe("should be logical AND when recalibration is defined.", () => { + test("T & T => T", async () => { + // Arrange + getServiceabilityDetails.mockImplementation(() => + Promise.resolve({ + isGlassServiceableInshop: true, + isRecalibrationServiceableInshop: true, + isGlassServiceableMobile: true, + isRecalibrationServiceableMobile: true, + }) + ); + + const { wrapper } = setupMocks({}); + + // Act + await serviceLocation.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "serviceLocation" } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(wrapper.vm.isServiceableMobile).toEqual(true); + expect(wrapper.vm.isServiceableInshop).toEqual(true); + }); + + test("T & F => F", async () => { + // Arrange + getServiceabilityDetails.mockImplementation(() => + Promise.resolve({ + isGlassServiceableInshop: true, + isRecalibrationServiceableInshop: false, + isGlassServiceableMobile: true, + isRecalibrationServiceableMobile: false, + }) + ); + + const { wrapper } = setupMocks({}); + + // Act + await serviceLocation.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "serviceLocation" } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(wrapper.vm.isServiceableMobile).toEqual(false); + expect(wrapper.vm.isServiceableInshop).toEqual(false); + }); + + test("F & T => F", async () => { + // Arrange + getServiceabilityDetails.mockImplementation(() => + Promise.resolve({ + isGlassServiceableInshop: false, + isRecalibrationServiceableInshop: true, + isGlassServiceableMobile: false, + isRecalibrationServiceableMobile: true, + }) + ); + + const { wrapper } = setupMocks({}); + + // Act + await serviceLocation.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "serviceLocation" } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(wrapper.vm.isServiceableMobile).toEqual(false); + expect(wrapper.vm.isServiceableInshop).toEqual(false); + }); + + test("F & F => F", async () => { + // Arrange + getServiceabilityDetails.mockImplementation(() => + Promise.resolve({ + isGlassServiceableInshop: false, + isRecalibrationServiceableInshop: false, + isGlassServiceableMobile: false, + isRecalibrationServiceableMobile: false, + }) + ); + + const { wrapper } = setupMocks({}); + + // Act + await serviceLocation.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "serviceLocation" } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(wrapper.vm.isServiceableMobile).toEqual(false); + expect(wrapper.vm.isServiceableInshop).toEqual(false); + }); + + test("displayServiceableMobileOnly should be true if mobile is true and inshop is false.", async () => { + // Arrange + getServiceabilityDetails.mockImplementation(() => + Promise.resolve({ + isGlassServiceableInshop: false, + isRecalibrationServiceableInshop: false, + isGlassServiceableMobile: true, + isRecalibrationServiceableMobile: true, + }) + ); + + const { wrapper } = setupMocks({}); + + // Act + await serviceLocation.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "serviceLocation" } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(wrapper.vm.isServiceableMobile).toEqual(true); + expect(wrapper.vm.isServiceableInshop).toEqual(false); + expect(wrapper.vm.displayServiceableMobileOnly).toEqual(true); + }); + + test("displayServiceableMobileOnly should be false if mobile is false.", async () => { + // Arrange + getServiceabilityDetails.mockImplementation(() => + Promise.resolve({ + isGlassServiceableInshop: false, + isRecalibrationServiceableInshop: false, + isGlassServiceableMobile: false, + isRecalibrationServiceableMobile: false, + }) + ); + + const { wrapper } = setupMocks({}); + + // Act + await serviceLocation.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "serviceLocation" } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(wrapper.vm.isServiceableMobile).toEqual(false); + expect(wrapper.vm.isServiceableInshop).toEqual(false); + expect(wrapper.vm.displayServiceableMobileOnly).toEqual(false); + }); + + test("displayServiceableMobileOnly should be false if inShop is true", async () => { + // Arrange + getServiceabilityDetails.mockImplementation(() => + Promise.resolve({ + isGlassServiceableInshop: true, + isRecalibrationServiceableInshop: true, + isGlassServiceableMobile: true, + isRecalibrationServiceableMobile: true, + }) + ); + + const { wrapper } = setupMocks({}); + + // Act + await serviceLocation.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "serviceLocation" } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(wrapper.vm.isServiceableMobile).toEqual(true); + expect(wrapper.vm.isServiceableInshop).toEqual(true); + expect(wrapper.vm.displayServiceableMobileOnly).toEqual(false); + }); + }); + + describe("should be based only on glass serviceability if recalibration is not defined.", () => { + test("Should return true", async () => { + // Arrange + getServiceabilityDetails.mockImplementation(() => + Promise.resolve({ + isGlassServiceableInshop: true, + isRecalibrationServiceableInshop: null, + isGlassServiceableMobile: true, + isRecalibrationServiceableMobile: null, + }) + ); + + const { wrapper } = setupMocks({}); + + // Act + await serviceLocation.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "serviceLocation" } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(wrapper.vm.isServiceableMobile).toEqual(true); + expect(wrapper.vm.isServiceableInshop).toEqual(true); + }); + + test("Should return false", async () => { + // Arrange + getServiceabilityDetails.mockImplementation(() => + Promise.resolve({ + isGlassServiceableInshop: false, + isRecalibrationServiceableInshop: null, + isGlassServiceableMobile: false, + isRecalibrationServiceableMobile: null, + }) + ); + + const { wrapper } = setupMocks({}); + + // Act + await serviceLocation.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "serviceLocation" } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(wrapper.vm.isServiceableMobile).toEqual(false); + expect(wrapper.vm.isServiceableInshop).toEqual(false); + }); + + test("displayServiceableMobileOnly should be true if mobile is true and inshop is false.", async () => { + // Arrange + getServiceabilityDetails.mockImplementation(() => + Promise.resolve({ + isGlassServiceableInshop: false, + isRecalibrationServiceableInshop: null, + isGlassServiceableMobile: true, + isRecalibrationServiceableMobile: null, + }) + ); + + const { wrapper } = setupMocks({}); + + // Act + await serviceLocation.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "serviceLocation" } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(wrapper.vm.isServiceableMobile).toEqual(true); + expect(wrapper.vm.isServiceableInshop).toEqual(false); + expect(wrapper.vm.displayServiceableMobileOnly).toEqual(true); + }); + + test("displayServiceableMobileOnly should be false if mobile is false", async () => { + // Arrange + getServiceabilityDetails.mockImplementation(() => + Promise.resolve({ + isGlassServiceableInshop: false, + isRecalibrationServiceableInshop: null, + isGlassServiceableMobile: false, + isRecalibrationServiceableMobile: null, + }) + ); + + const { wrapper } = setupMocks({}); + + // Act + await serviceLocation.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "serviceLocation" } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(wrapper.vm.isServiceableMobile).toEqual(false); + expect(wrapper.vm.isServiceableInshop).toEqual(false); + expect(wrapper.vm.displayServiceableMobileOnly).toEqual(false); + }); + + test("displayServiceableMobileOnly should be false if inShop is true", async () => { + // Arrange + getServiceabilityDetails.mockImplementation(() => + Promise.resolve({ + isGlassServiceableInshop: true, + isRecalibrationServiceableInshop: null, + isGlassServiceableMobile: true, + isRecalibrationServiceableMobile: null, + }) + ); + + const { wrapper } = setupMocks({}); + + // Act + await serviceLocation.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "serviceLocation" } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(wrapper.vm.isServiceableMobile).toEqual(true); + expect(wrapper.vm.isServiceableInshop).toEqual(true); + expect(wrapper.vm.displayServiceableMobileOnly).toEqual(false); + }); + }); + + describe("should properly display alerts.", () => { + test("Should show mobile-only error if only mobile is available.", async () => { + // Arrange + getServiceabilityDetails.mockImplementation(() => + Promise.resolve({ + isGlassServiceableInshop: false, + isRecalibrationServiceableInshop: false, + isGlassServiceableMobile: true, + isRecalibrationServiceableMobile: true, + }) + ); + + const { wrapper } = setupMocks({}); + + // Act + await serviceLocation.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "serviceLocation" } }, + undefined, + (c) => c(wrapper.vm) + ); + + const alertComponent = wrapper.findComponent({ ref: "alertMobileOnly" }); + + // Assert + expect(alertComponent.exists()).toBe(true); + }); + + test("Should not show mobile-only error if not mobile-only.", async () => { + // Arrange + getServiceabilityDetails.mockImplementation(() => + Promise.resolve({ + isGlassServiceableInshop: true, + isRecalibrationServiceableInshop: true, + isGlassServiceableMobile: true, + isRecalibrationServiceableMobile: true, + }) + ); + + const { wrapper } = setupMocks({}); + + // Act + await serviceLocation.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "serviceLocation" } }, + undefined, + (c) => c(wrapper.vm) + ); + + const alertComponent = wrapper.findComponent({ ref: "alertMobileOnly" }); + + // Assert + expect(alertComponent.exists()).toBe(false); + }); + }); + }); }); function setupMocks({ mountOptionsMockData = {} }) { diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index e0a736a43..7f8430f04 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -14,21 +14,27 @@ linkWidgetName="ServiceZipLinkWidget" modalWidgetName="ServiceZipModalWidget" /> +