From 23d433931d792184a984a2b9029d6818ed364021 Mon Sep 17 00:00:00 2001 From: Chloe Herd Date: Wed, 29 Mar 2023 15:34:52 -0400 Subject: [PATCH 1/5] Pull serviceability logic up to service-location page. --- .../service-location/service-location.vue | 28 +++++++---- .../service-type-question.vue | 46 +++++-------------- 2 files changed, 31 insertions(+), 43 deletions(-) diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index d8167ad57..2b166e830 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -20,10 +20,8 @@ alertClass="alert-warning" /> 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; From e244e264199f82431ea407f7dce591ad4b6e550b Mon Sep 17 00:00:00 2001 From: Chloe Herd Date: Wed, 29 Mar 2023 15:43:56 -0400 Subject: [PATCH 2/5] Added non-cms version of the alert --- src/layouts/service-location/service-location.vue | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index 2b166e830..256ce6bc1 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -18,6 +18,12 @@ cmsWidgetName="AlertMilitaryBaseZipWidget" v-if="showMilitaryZipAlert" alertClass="alert-warning" /> + Date: Wed, 29 Mar 2023 15:53:16 -0400 Subject: [PATCH 3/5] Update to proper cms widget. --- src/layouts/service-location/service-location.vue | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index 256ce6bc1..774aafd87 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -20,8 +20,7 @@ alertClass="alert-warning" /> Date: Wed, 29 Mar 2023 16:50:46 -0400 Subject: [PATCH 4/5] Update tests based on changes to logic. --- .../service-type-question.spec.js | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/layouts/service-location/service-type-question/service-type-question.spec.js b/src/layouts/service-location/service-type-question/service-type-question.spec.js index 13b727c54..f4f48a77d 100644 --- a/src/layouts/service-location/service-type-question/service-type-question.spec.js +++ b/src/layouts/service-location/service-type-question/service-type-question.spec.js @@ -49,10 +49,8 @@ describe("service-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("service-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("service-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("service-type-question.vue", () => { mixins: [mockMixin], props: { cmsWidgetName: cmsWidgetName, - isGlassServiceableInshop: false, - isRecalibrationServiceableInshop: false, - isGlassServiceableMobile: false, - isRecalibrationServiceableMobile: false, + isServiceableInshop: false, + isServiceableMobile: false, }, mountOptions: { attachTo: document.body, From c94137f795bc6dbceef4da44ac214fbb5a662059 Mon Sep 17 00:00:00 2001 From: Chloe Herd Date: Thu, 30 Mar 2023 09:01:14 -0400 Subject: [PATCH 5/5] Add tests. --- .../service-location/service-location.spec.js | 381 ++++++++++++++++++ .../service-location/service-location.vue | 3 +- 2 files changed, 383 insertions(+), 1 deletion(-) diff --git a/src/layouts/service-location/service-location.spec.js b/src/layouts/service-location/service-location.spec.js index 2a056c4d1..4757c6a78 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("isServiceableMobileOnly 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.isServiceableMobileOnly).toEqual(true); + }); + + test("isServiceableMobileOnly 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.isServiceableMobileOnly).toEqual(false); + }); + + test("isServiceableMobileOnly 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.isServiceableMobileOnly).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("isServiceableMobileOnly 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.isServiceableMobileOnly).toEqual(true); + }); + + test("isServiceableMobileOnly 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.isServiceableMobileOnly).toEqual(false); + }); + + test("isServiceableMobileOnly 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.isServiceableMobileOnly).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('[data-test="mobileOnlyAlert"]'); + + // 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('[data-test="mobileOnlyAlert"]'); + + // 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 774aafd87..4d591edcc 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -22,7 +22,8 @@ class="my-4" cmsWidgetName="AlertMobileOnlyWidget" v-if="isServiceableMobileOnly" - alertClass="alert-warning" /> + alertClass="alert-warning" + data-test="mobileOnlyAlert" />