From d2b926f2f9a8698f1307a573955be184d3f93bdb Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Mon, 10 Apr 2023 08:38:52 -0400 Subject: [PATCH 01/17] Initial check-in --- .../shop-question/shop-question.spec.js | 1 + .../shop-question/shop-question.vue | 82 +++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 src/layouts/service-location/shop-question/shop-question.spec.js create mode 100644 src/layouts/service-location/shop-question/shop-question.vue diff --git a/src/layouts/service-location/shop-question/shop-question.spec.js b/src/layouts/service-location/shop-question/shop-question.spec.js new file mode 100644 index 000000000..66012402c --- /dev/null +++ b/src/layouts/service-location/shop-question/shop-question.spec.js @@ -0,0 +1 @@ +test.todo("some test to be written in the future"); \ No newline at end of file diff --git a/src/layouts/service-location/shop-question/shop-question.vue b/src/layouts/service-location/shop-question/shop-question.vue new file mode 100644 index 000000000..87f5349a8 --- /dev/null +++ b/src/layouts/service-location/shop-question/shop-question.vue @@ -0,0 +1,82 @@ + + + + + From 96133bc8ec1eea0a5d143aa07cb3ffb9a2438236 Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Tue, 11 Apr 2023 12:41:56 -0400 Subject: [PATCH 02/17] WIP --- .../shop-question/shop-question.vue | 95 +++++++++++++++++-- 1 file changed, 85 insertions(+), 10 deletions(-) diff --git a/src/layouts/service-location/shop-question/shop-question.vue b/src/layouts/service-location/shop-question/shop-question.vue index 87f5349a8..f5cbdba98 100644 --- a/src/layouts/service-location/shop-question/shop-question.vue +++ b/src/layouts/service-location/shop-question/shop-question.vue @@ -1,12 +1,18 @@ @@ -36,6 +45,7 @@ import { defineRule } from "vee-validate"; import { required } from "@/helpers/validation-rules"; import { errorMessages } from "@/constants/error-messages"; import baseMixin from "@/mixins/base-mixin.js"; +import textLink from '@/ux-components/text-link/text-link'; defineRule("option-required", required(errorMessages.OPTION_REQUIRED)); @@ -46,6 +56,9 @@ export default { return { shops: [], shopListButton: shopListButton, + availability: "high", + answers: [], + shopIndex: 0, }; }, props: { @@ -58,6 +71,7 @@ export default { components: { alert, buttonQuestion, + textLink, }, computed: { questionText() { @@ -71,23 +85,12 @@ export default { this.$emit("update:modelValue", newValue); }, }, - answers() { - // Map API result data - const mappedData = this.shops.map((shop) => { - return { - Name: shop.providerNumber, - buttonLabel: shop.city, - buttonLabelSubCopy: `${shop.distance} mi`, - buttonBodyCopy: `${shop.streetAddress}, ${shop.city}, ${shop.state} ${shop.zipCode}`, - buttonAuxillaryCopy: `foo` - }; - }); - - return mappedData; - }, displayDropoffInformation() { return this.isDropoff; }, + showMoreShopsLinkText() { + return this.getCmsContent("ShowMoreShopsLinkWidget", "Text"); + }, }, methods: { loadInitialData() { @@ -97,6 +100,7 @@ export default { }, initializeComponent(initialData) { this.shops = initialData; + this.getNextShopsFromList(); }, async updateShopList() { const result = await this.dispatchStoreAction(storeActions.GET_PROVIDER_LOCATIONS, { @@ -104,6 +108,38 @@ export default { }); return result.data; }, + shopIterator(array, n){ + let l = array.length; + return () => { + var end = this.shopIndex + n; + var part = array.slice(this.shopIndex, end); + this.shopIndex = end < l ? end : this.shopIndex.length - 1; + return part; + }; + }, + getNextShopsFromList() { + const nextShop = this.shopIterator(this.shops, 3); + + // Map API result data + const mappedData = nextShop().map((shop) => { + return { + Name: shop.providerNumber, + buttonLabel: shop.city, + buttonLabelSubCopy: `${shop.distance} mi`, + buttonBodyCopy: `${shop.streetAddress}, ${shop.city}, ${shop.state} ${shop.zipCode}`, + buttonAuxillaryCopy: `foo`, + }; + }); + + if (this.answers.length === 0) { + this.answers = mappedData; + } else { + mappedData.forEach(shop => { + this.answers.push(shop); + }) + } + + } }, watch: { serviceZipCode: { @@ -124,30 +160,70 @@ export default { } .button-content { - .button-label-copy { + .row-one { display: flex; - font-weight: 500; - line-height: 1.5rem; align-items: center; margin-bottom: 0.25rem !important; + .button-label-copy { + flex-grow: 0; + line-height: 1.5rem; + font-weight: 500; + } + .button-label-sub-copy { - margin-bottom: 0rem !important; + flex-grow: 1; + line-height: 1.25rem !important; + font-weight: 400; + font-size: 0.75rem; color: #727676; padding-left: 0.25rem; - font-weight: 400; - line-height: 1.25rem; - font-size: 0.75rem; } - .button-auxillary-copy { - display: flex; - align-items: right; + .availability-indicator { + display: none; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 0.125rem 1.5rem; + gap: 0.25rem; + background: #E3F2EA; + border-radius: 4.5rem; + + .button-auxillary-copy { + justify-content: right; + line-height: 1.25rem !important; + font-weight: 400; + font-size: 0.75rem; + } + + .green { + color: #006A36; + background: #E3F2EA; + } + + .red { + color: #AC160B; + background: #E3F2EA; + } + + } + } - - } + + // .button-question-overflow { + // height: 60vh; //calc(100vh - 274px); + + // // .overflow-scroll { + // // // Height will be determined by overall height of content above list + // // height: calc(100% - 314px); + // // overflow-x: hidden !important; + // // -webkit-overflow-scrolling: touch; + // // } + // } + } .drop-off-alert { diff --git a/src/store/index.js b/src/store/index.js index ca9aa4741..2fafa9214 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -941,7 +941,7 @@ export const actions = { return globalMethods.callMockHttpClient({ method: endpoints.GetProviderLocations.method, //TODO: Remove Mocky Endpoints - endpoint: "https://run.mocky.io/v3/2a82baf7-c6e8-40ac-8e2e-9d91800c7f9b", + endpoint: "https://run.mocky.io/v3/062bfed7-29a7-4001-b5e8-6135ec10494f", }); }, From 32d90ba74dc08b8db566b9a5a7b05c4754c37447 Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Fri, 14 Apr 2023 07:44:17 -0400 Subject: [PATCH 05/17] WIP --- .../shop-list-button/shop-list-button.vue | 62 ++++++++- .../shop-question/shop-question.vue | 120 +++++++----------- src/store/index.js | 2 +- 3 files changed, 102 insertions(+), 82 deletions(-) diff --git a/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue b/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue index 898194951..2fa1b1392 100644 --- a/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue +++ b/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue @@ -8,10 +8,14 @@ class="button-content list-button-content d-flex flex-column justify-content-center py-3 px-4">
{{ buttonLabel }} - {{ buttonLabelSubCopy }} -
- {{ buttonAuxillaryCopy }} -
+ {{ + buttonLabelSubCopy + }} +
+ {{ buttonAuxillaryCopy }} +
diff --git a/src/layouts/service-location/shop-question/shop-question.vue b/src/layouts/service-location/shop-question/shop-question.vue index c8066eb2f..5d6eaba7f 100644 --- a/src/layouts/service-location/shop-question/shop-question.vue +++ b/src/layouts/service-location/shop-question/shop-question.vue @@ -12,7 +12,6 @@ buttonTypeString="shopListButton" :buttonTypeObject="shopListButton" class="radioQuestion" - isOverflowScrollable :questionText="questionText" :answers="answers" groupName="ChooseShop" @@ -21,6 +20,7 @@ isRequired /> { var end = this.shopIndex + n; var part = array.slice(this.shopIndex, end); this.shopIndex = end < l ? end : this.shopIndex.length - 1; return part; - }; + }; }, - getNextShopsFromList() { + async getNextShopsFromList() { const nextShop = this.shopIterator(this.shops, 3); // Map API result data @@ -134,12 +134,18 @@ export default { if (this.answers.length === 0) { this.answers = mappedData; } else { - mappedData.forEach(shop => { + mappedData.forEach((shop) => { this.answers.push(shop); - }) + }); } - - } + + await this.$nextTick(); + window.scrollTo(0,document.body.scrollHeight); + + // const shopQuestion = document.getElementsByClassName("shop-question")[0]; + + // shopQuestion.scrollIntoView({ behavior: "smooth", block: "end", inline: "end"}); + }, }, watch: { serviceZipCode: { @@ -154,78 +160,38 @@ export default { From 86d7760d771e5432b78200d560695e980da66be5 Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Fri, 14 Apr 2023 15:57:49 -0400 Subject: [PATCH 08/17] Functionality mostly complete, need Bryan to take a stab at remaining styling --- .../service-location/service-location.vue | 4 +- .../shop-list-button/shop-list-button.vue | 60 ++++++++++--------- .../shop-question/shop-question.vue | 21 ++++--- 3 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index c5525ec54..422f5ba2f 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -66,7 +66,9 @@ modalWidgetName="MobileLocationModalWidget" /> - -
-
- {{ buttonLabel }} - {{ - buttonLabelSubCopy - }} -
- {{ buttonAuxillaryCopy }} + + +
+
+ {{ buttonLabel }} + {{ + buttonLabelSubCopy + }} +
+ {{ buttonAuxillaryCopy }} +
+ + + {{ screenReaderOnlyText }} + +
- - - {{ screenReaderOnlyText }} - - -
- + + @@ -176,7 +177,6 @@ export default { .question-text { margin-top: 0.5rem !important; } - } } @@ -191,5 +191,4 @@ export default { padding-left: 1.5rem !important; padding-right: 0.5rem !important; } - From 4def7c421e48f454076512111a20fda95346fda0 Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Mon, 17 Apr 2023 10:50:55 -0400 Subject: [PATCH 09/17] Working unit tests --- .../service-location/service-location.spec.js | 60 +++++++++++++++++++ .../shop-list-button/shop-list-button.vue | 4 +- .../shop-question/shop-question.vue | 28 +++++++-- 3 files changed, 86 insertions(+), 6 deletions(-) diff --git a/src/layouts/service-location/service-location.spec.js b/src/layouts/service-location/service-location.spec.js index 6f2443a49..95842e0c2 100644 --- a/src/layouts/service-location/service-location.spec.js +++ b/src/layouts/service-location/service-location.spec.js @@ -190,6 +190,8 @@ describe("service-location.vue", () => { // Arrange const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + const mobileFeePart = { partNumber: "MOBILE FEE", description: "MOBILE FEE", @@ -584,6 +586,8 @@ describe("service-location.vue", () => { ); const { wrapper } = setupMocks({}); + + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); // Act await serviceLocation.beforeRouteEnter.call( @@ -611,6 +615,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -637,6 +643,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -663,6 +671,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -689,6 +699,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -716,6 +728,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -743,6 +757,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -770,6 +786,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -797,6 +815,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -824,6 +844,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -851,6 +873,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -878,6 +902,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -905,6 +931,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -932,6 +960,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -959,6 +989,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -989,6 +1021,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -1015,6 +1049,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -1041,6 +1077,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -1068,6 +1106,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -1095,6 +1135,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -1122,6 +1164,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -1151,6 +1195,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -1178,6 +1224,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -1205,6 +1253,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -1232,6 +1282,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -1259,6 +1311,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -1286,6 +1340,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -1313,6 +1369,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, @@ -1342,6 +1400,8 @@ describe("service-location.vue", () => { const { wrapper } = setupMocks({}); + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); + // Act await serviceLocation.beforeRouteEnter.call( wrapper.vm, diff --git a/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue b/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue index 45a18280f..b8003148f 100644 --- a/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue +++ b/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue @@ -8,7 +8,9 @@ :aria-label="buttonLabel" class="button-content list-button-content d-flex flex-column justify-content-center py-3 px-4">
- {{ buttonLabel }} + {{ + buttonLabel + }} {{ buttonLabelSubCopy }} diff --git a/src/layouts/service-location/shop-question/shop-question.vue b/src/layouts/service-location/shop-question/shop-question.vue index 96d7debd8..c7dba4a5d 100644 --- a/src/layouts/service-location/shop-question/shop-question.vue +++ b/src/layouts/service-location/shop-question/shop-question.vue @@ -17,8 +17,9 @@ groupName="ChooseShop" textPosition="text-start" v-model="selectedValue" - isRequired /> - + + :aria-label="showMoreShopsLinkText" />
@@ -59,6 +60,7 @@ export default { availability: "high", answers: [], shopIndex: 0, + displaySeeMoreLocationsLink: true, }; }, props: { @@ -107,6 +109,9 @@ export default { const result = await this.dispatchStoreAction(storeActions.GET_PROVIDER_LOCATIONS, { serviceZipCode: this.serviceZipCode, }); + + this.resetShopList(); + return result.data; }, shopIterator(array, n) { @@ -114,7 +119,7 @@ export default { return () => { var end = this.shopIndex + n; var part = array.slice(this.shopIndex, end); - this.shopIndex = end < l ? end : this.shopIndex.length - 1; + this.shopIndex = end < l ? end : this.shops.length; return part; }; }, @@ -145,6 +150,18 @@ export default { const container = document.getElementsByClassName("page-container-grouped-styles")[0]; container.scrollTo({ top: container.scrollHeight, left: 0, behavior: "smooth" }); + + if (this.shopIndex == this.shops.length) { + this.displaySeeMoreLocationsLink = false; + } + }, + resetShopList() { + this.answers = []; + this.shopIndex = 0; + this.getNextShopsFromList(); + + this.displaySeeMoreLocationsLink = true; + }, }, watch: { @@ -160,8 +177,9 @@ export default { const container = document.getElementsByClassName( "page-container-grouped-styles" )[0]; - console.log(container.scrollHeight + 200); container.scrollTo({ top: container.scrollHeight, left: 0, behavior: "smooth" }); + + this.resetShopList(); }, }, }, From d2ed91e9199cc0ed2eccc7571e2fd4d7d01f90af Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Tue, 18 Apr 2023 08:32:43 -0400 Subject: [PATCH 10/17] Just needs styling tweaks and de-mocked --- .../service-location/service-location.spec.js | 2 +- .../service-location/service-location.vue | 34 +++++++++++------ .../shop-question/shop-question.vue | 37 +++++++++++++------ 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/src/layouts/service-location/service-location.spec.js b/src/layouts/service-location/service-location.spec.js index 95842e0c2..52239462c 100644 --- a/src/layouts/service-location/service-location.spec.js +++ b/src/layouts/service-location/service-location.spec.js @@ -586,7 +586,7 @@ describe("service-location.vue", () => { ); const { wrapper } = setupMocks({}); - + wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); // Act diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index 422f5ba2f..56cb88d80 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -66,12 +66,12 @@ modalWidgetName="MobileLocationModalWidget" /> item.partNumber === "RECAL STATIC" || item.partNumber === "RECAL DUAL" + // Specifically check for isRecalibrationServiceableMobile === false, not null or true. + requiresInshopRecalibration() { + return ( + this.isServiceableInshop && + this.isGlassServiceableMobile && + this.isRecalibrationServiceableMobile === false ); }, displayRecalibrationWarning() { - return this.isDualOrStaticRecalibration; + return this.requiresInshopRecalibration; }, displayServiceableInshopOnly() { return ( @@ -293,6 +296,9 @@ export default { isDropoff() { return this.selectedAppointmentType === "Dropoff"; }, + isMobile() { + return this.selectedAppointmentType === "Mobile"; + }, }, methods: { arePagePrerequisitesValid() { @@ -302,7 +308,7 @@ export default { store.getters.payment.isInsurance !== null ); }, - setData(zipCodeData, serviceabilityDetails, mobileFeePart) { + setData(zipCodeData, serviceabilityDetails, mobileFeePart, shopQuestionInitialData) { if (zipCodeData) { this.zipContainsMilitaryBase = zipCodeData.containsMilitaryBase; } @@ -314,6 +320,10 @@ export default { if (mobileFeePart) { this.mobileFeePart = mobileFeePart; } + + if (shopQuestionInitialData) { + this.shopQuestionInitialData = shopQuestionInitialData; + } }, setContainsMilitaryBase(val) { if (this.zipContainsMilitaryBase !== val) { diff --git a/src/layouts/service-location/shop-question/shop-question.vue b/src/layouts/service-location/shop-question/shop-question.vue index c7dba4a5d..ec6c0c18f 100644 --- a/src/layouts/service-location/shop-question/shop-question.vue +++ b/src/layouts/service-location/shop-question/shop-question.vue @@ -9,17 +9,19 @@ alertClass="alert-info" v-bind:isDismissible="false" /> - + Date: Tue, 18 Apr 2023 08:40:41 -0400 Subject: [PATCH 11/17] Small refactor --- .../service-location/shop-question/shop-question.vue | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/layouts/service-location/shop-question/shop-question.vue b/src/layouts/service-location/shop-question/shop-question.vue index ec6c0c18f..34441440d 100644 --- a/src/layouts/service-location/shop-question/shop-question.vue +++ b/src/layouts/service-location/shop-question/shop-question.vue @@ -162,7 +162,9 @@ export default { this.shopIndex = 0; this.getNextShopsFromList(); - this.displaySeeMoreLocationsLink = true; + this.displaySeeMoreLocationsLink = true; + this.selectedValue = ""; + this.$refs.buttonQuestion.resetField(); }, }, @@ -189,11 +191,6 @@ export default { container.scrollTo({ top: container.scrollHeight, left: 0, behavior: "smooth" }); this.resetShopList(); - - this.selectedValue = ""; - - this.$refs.buttonQuestion.resetField(); - }, immediate: true, }, From 7d0e2513be6cce80dca09c92a1729d119e872c07 Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Fri, 21 Apr 2023 07:12:26 -0400 Subject: [PATCH 12/17] WIP --- .../appointment-type-question.vue | 2 -- .../service-location/service-location.vue | 20 +++++++++---------- .../shop-question/shop-question.vue | 16 +++++++++------ 3 files changed, 20 insertions(+), 18 deletions(-) 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 6260df9d1..dc846f377 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 @@ -70,8 +70,6 @@ export default { handler(newValue) { if (newValue) { this.selectedValues = "Mobile"; - } else { - this.selectedValues = null; } }, }, diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index 56cb88d80..6dce8e985 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -71,7 +71,7 @@ :isDropoff="isDropoff" :serviceZipCode="zipCode" :selectedAppointmentType="selectedAppointmentType" - :shopQuestionInitialData="shopQuestionInitialData" + :shopQuestionData="shopQuestionData" cmsWidgetName="ShopQuestionWidget" /> Date: Mon, 24 Apr 2023 11:02:00 -0400 Subject: [PATCH 13/17] wip --- .../service-location/service-location.vue | 2 +- .../shop-question/shop-question.vue | 31 +++++++++++++------ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index 43f580efe..b17a91878 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -67,7 +67,7 @@ modalWidgetName="MobileLocationModalWidget" /> From 77ebdf1a7e0256556c6915196e5274451cf0e332 Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Tue, 25 Apr 2023 13:04:02 -0400 Subject: [PATCH 14/17] Checkpoint - needs additional testing / debugging --- .../service-location/service-location.vue | 38 +++--- .../shop-question/shop-question.vue | 124 ++++++++---------- src/mixins/analytics-mixin.js | 55 ++++---- 3 files changed, 104 insertions(+), 113 deletions(-) diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index b17a91878..42a8b92ad 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -46,7 +46,7 @@ alertClass="alert-warning" /> { - var end = this.shopIndex + n; - var part = array.slice(this.shopIndex, end); - this.shopIndex = end < l ? end : this.shops.length; - return part; + getNextShopsFromList(numberToGet = 3) { + const shopIterator = (array, n) => { + let l = array.length; + return () => { + var end = this.shopIndex + n; + var part = array.slice(this.shopIndex, end); + this.shopIndex = end < l ? end : this.shops.length; + return part; + }; }; - }, - async getNextShopsFromList() { - const nextShop = this.shopIterator(this.shops, 3); + + const nextShop = shopIterator(this.shops, numberToGet); // Map API result data const mappedData = nextShop().map((shop) => { @@ -147,70 +137,68 @@ export default { }); } - await this.$nextTick(); - - if (this.shopIndex == this.shops.length) { - this.displaySeeMoreLocationsLink = false; - } else { - this.displaySeeMoreLocationsLink = true; - } - - await this.$nextTick(); - - const container = document.getElementsByClassName("page-container-grouped-styles")[0]; - - container.scrollTo({ top: container.scrollHeight, left: 0, behavior: "smooth" }); - + this.$nextTick().then(() => { + if (this.shopIndex == this.shops.length) { + this.displaySeeMoreLocationsLink = false; + } else { + this.displaySeeMoreLocationsLink = true; + } + this.$nextTick().then(() => { + this.scrollToBottom(); + }); + }); }, resetShopList() { this.answers = []; this.shopIndex = 0; - this.getNextShopsFromList(); this.displaySeeMoreLocationsLink = true; this.selectedValue = ""; this.$refs.buttonQuestion.resetField(); }, + scrollToBottom() { + const container = document.getElementsByClassName("page-container-grouped-styles")[0]; + container.scrollTo({ top: container.scrollHeight, left: 0, behavior: "smooth" }); + }, }, - // mounted() { - // console.log(this.shopQuestionData); - // this.shops = this.shopQuestionData; - // this.getNextShopsFromList(); - // console.log(this.shops); - // }, watch: { serviceZipCode: { - async handler() { - this.shops = await this.updateShopList(); + handler(newValue) { + this.loadInitialData(newValue).then((result) => { + this.initializeComponent(result.data); + this.resetShopList(); + }); }, }, selectedAppointmentType: { - async handler(newValue, oldValue) { - if (oldValue == undefined) { - this.shops = this.shopQuestionData; - this.getNextShopsFromList(); - this.displaySeeMoreLocationsLink = true; - return; + handler(newValue) { + // If the validation has been previously triggered, clear it before displaying the component + this.$refs.buttonQuestion.resetField(); + + if (newValue != null) { + this.$nextTick().then(() => { + this.scrollToBottom(); + }); } - - await this.$nextTick(); - - const container = document.getElementsByClassName( - "page-container-grouped-styles" - )[0]; - container.scrollTo({ top: container.scrollHeight, left: 0, behavior: "smooth" }); - - this.resetShopList(); }, }, - shopQuestionData: { + shops: { handler(newValue) { - console.log(newValue) - this.shops = newValue; - this.getNextShopsFromList(); + this.$refs.buttonQuestion.resetField(); + const selectedShopIndex = newValue.findIndex((provider) => provider.providerNumber == this.modelValue); + if (selectedShopIndex >= 3) { + this.getNextShopsFromList(selectedShopIndex + 1); + } else { + this.getNextShopsFromList(); + } }, - } + }, + }, + components: { + alert, + buttonQuestion, + textLink, }, }; diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js index 3fbc9501d..3779b06c5 100644 --- a/src/mixins/analytics-mixin.js +++ b/src/mixins/analytics-mixin.js @@ -24,38 +24,35 @@ import { applicationConfig } from "../constants/application-config"; export default { methods: { logPageView(pageEvent) { - const currentPageName = getPageNameByQueryString(); - var payload = { - userId: getDeviceIdValue(), - sessionKey: getSessionKeyValue(), - pageName: currentPageName, - sessionId: getSessionIdValue(), - action: "", - event: pageEvent, - shouldUseSessionId: false, - experimentsForUser: store.getters.applicationUser.experiments, - }; - - baseMixin.methods.dispatchStoreAction(storeActions.LOG_PAGE_VIEW, payload, false); + // const currentPageName = getPageNameByQueryString(); + // var payload = { + // userId: getDeviceIdValue(), + // sessionKey: getSessionKeyValue(), + // pageName: currentPageName, + // sessionId: getSessionIdValue(), + // action: "", + // event: pageEvent, + // shouldUseSessionId: false, + // experimentsForUser: store.getters.applicationUser.experiments, + // }; + // baseMixin.methods.dispatchStoreAction(storeActions.LOG_PAGE_VIEW, payload, false); }, logCustomEvent(category, action, label, value) { - const currentPageName = getPageNameByQueryString(); - - var payload = { - userId: getDeviceIdValue(), - sessionKey: getSessionKeyValue(), - pageName: currentPageName, - sessionId: getSessionIdValue(), - category: category, - action: action, - label: label, - value: value, - shouldUseSessionId: false, - experimentsForUser: store.getters.applicationUser.experiments, - }; - - baseMixin.methods.dispatchStoreAction(storeActions.LOG_CUSTOM_EVENT, payload, false); + // const currentPageName = getPageNameByQueryString(); + // var payload = { + // userId: getDeviceIdValue(), + // sessionKey: getSessionKeyValue(), + // pageName: currentPageName, + // sessionId: getSessionIdValue(), + // category: category, + // action: action, + // label: label, + // value: value, + // shouldUseSessionId: false, + // experimentsForUser: store.getters.applicationUser.experiments, + // }; + // baseMixin.methods.dispatchStoreAction(storeActions.LOG_CUSTOM_EVENT, payload, false); }, pushEventToGA(category, action, label, pushToLogApp = false, valueToLogType = null) { From 97a9cfb37ffd5e3a499e2c18819090d1b0c1ea84 Mon Sep 17 00:00:00 2001 From: Bryan Mauger Date: Tue, 25 Apr 2023 13:57:49 -0400 Subject: [PATCH 15/17] Add to button group. --- src/layouts/service-location/service-location.vue | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index 42a8b92ad..2e4584c03 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -65,17 +65,17 @@ ref="mobileLocationQuestions" linkWidgetName="MobileLocationLinkWidget" modalWidgetName="MobileLocationModalWidget" /> + + Date: Tue, 25 Apr 2023 14:26:27 -0400 Subject: [PATCH 16/17] Checking in to work on defects --- .../service-location/service-location.vue | 25 +++++++++++-------- .../shop-question/shop-question.vue | 9 ++++--- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index 2e4584c03..63ed541e5 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -65,16 +65,19 @@ ref="mobileLocationQuestions" linkWidgetName="MobileLocationLinkWidget" modalWidgetName="MobileLocationModalWidget" /> - - + + { this.scrollToBottom(); }); @@ -186,7 +187,9 @@ export default { shops: { handler(newValue) { this.$refs.buttonQuestion.resetField(); - const selectedShopIndex = newValue.findIndex((provider) => provider.providerNumber == this.modelValue); + const selectedShopIndex = newValue.findIndex( + (provider) => provider.providerNumber == this.modelValue + ); if (selectedShopIndex >= 3) { this.getNextShopsFromList(selectedShopIndex + 1); } else { From 404c50d3a91aa4b1bdf856322f67b029741fbcd9 Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Mon, 1 May 2023 15:02:02 -0400 Subject: [PATCH 17/17] Completed some unit tests --- .../button-question/button-question.vue | 6 +- .../appointment-type-question.vue | 1 + .../service-location/service-location.vue | 15 +- .../shop-list-button/shop-list-button.spec.js | 71 ++- .../shop-question/shop-question.spec.js | 555 +++++++++++++++++- .../shop-question/shop-question.vue | 58 +- src/mixins/analytics-mixin.js | 55 +- 7 files changed, 687 insertions(+), 74 deletions(-) diff --git a/src/digital-components/button-question/button-question.vue b/src/digital-components/button-question/button-question.vue index 3dfa4489f..e98ef2901 100644 --- a/src/digital-components/button-question/button-question.vue +++ b/src/digital-components/button-question/button-question.vue @@ -256,8 +256,10 @@ export default { }, }, watch: { - modelValue() { - this.resetField(); + modelValue(newValue) { + this.resetField({ + value: newValue, + }); }, answers() { //once we get the answers to display from parent, see if we need a GA event to log what we showed 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 f1d684ffc..d6711f363 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 @@ -2,6 +2,7 @@
{ + it("Should include buttonLabel in html", async () => { + // Arrange + let { wrapper } = setupMocks({ + mountOptionsMockData: { + propsData: mockProps, + }, + }); + + // Act + const outputHtml = wrapper.html(); + + // Assert + expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonLabel"])); + }); + + it("Should include buttonLabelSubCopy in html", async () => { + // Arrange + let { wrapper } = setupMocks({ + mountOptionsMockData: { + propsData: mockProps, + }, + }); + + // Act + const outputHtml = wrapper.html(); + + // Assert + expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonLabelSubCopy"])); + }); + + it("Should include buttonLabelAuxillaryCopy in html", async () => { + // Arrange + let { wrapper } = setupMocks({ + mountOptionsMockData: { + propsData: mockProps, + }, + }); + + // Act + const outputHtml = wrapper.html(); + + // Assert + expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonLabelAuxillaryCopy"])); + }); +}); + +const mockProps = { + buttonLabel: "buttonLabel test copy", + buttonLabelSubCopy: "buttonLabelSubCopy test copy", + buttonBodyCopy: + "
  • buttonBodyCopy test copy
  • 2
  • 3
  • 4
  • 5
", + buttonLabelAuxillaryCopy: "buttonLabelAuxillaryCopy test copy", + value: 0, + modelValue: 0, + groupName: "mockGroup", +}; + +function setupMocks({ mountOptionsMockData = {} }) { + const wrapper = mount(shopListButton, { + ...mountOptionsMockData, + mixins: [inputButtonWrapperMixin], + }); + + return { wrapper }; +} diff --git a/src/layouts/service-location/shop-question/shop-question.spec.js b/src/layouts/service-location/shop-question/shop-question.spec.js index 3d0843e10..7f67737fa 100644 --- a/src/layouts/service-location/shop-question/shop-question.spec.js +++ b/src/layouts/service-location/shop-question/shop-question.spec.js @@ -1 +1,554 @@ -test.todo("some test to be written in the future"); +import { shallowMount } from "@vue/test-utils"; +import { storeActions } from "@/constants/store-actions"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import shopQuestion from "./shop-question"; + +jest.mock("@/mixins/base-mixin", () => ({ + methods: { + dispatchStoreAction(action, items, encode) { + if (action === mockGetProviderLocationsStoreAction) { + return new Promise((resolve) => { + resolve(mockNewShopList); + }); + } + }, + }, +})); + +const mockGetProviderLocationsStoreAction = storeActions.GET_PROVIDER_LOCATIONS; +const mockNewShopList = { + data: [ + { + city: "Far", + country: "United States", + distance: 100, + providerNumber: "129", + state: "OH", + streetAddress: "555 First Capital Ln", + zipCode: "45601", + }, + { + city: "Farther", + country: "United States", + distance: 200, + providerNumber: "130", + state: "OH", + streetAddress: "5486 N Grove Rd", + zipCode: "43215", + }, + { + city: "Farthest (Ever)", + country: "United States", + distance: 380.5, + providerNumber: "131", + state: "OH", + streetAddress: "1670 Bongo Ave D", + zipCode: "43223", + }, + ], +}; + +const mockCmsContent = { + QuestionText: "Select a shop:", +}; + +const cmsWidgetName = "AppointmentTypeQuestionWidget"; +const shopQuestionInitialData = [ + { + city: "Worthington", + country: "United States", + distance: 1.5, + providerNumber: "123", + state: "OH", + streetAddress: "760 Dearborn Park Ln", + zipCode: "43085", + }, + { + city: "Columbus", + country: "United States", + distance: 4.5, + providerNumber: "124", + state: "OH", + streetAddress: "5486 N Hamilton Rd", + zipCode: "43230", + }, + { + city: "Powell", + country: "United States", + distance: 7, + providerNumber: "125", + state: "OH", + streetAddress: "1670 Harmon Ave C", + zipCode: "43223", + }, + { + city: "Chillicothe", + country: "United States", + distance: 41.5, + providerNumber: "126", + state: "OH", + streetAddress: "555 First Capital Ln", + zipCode: "45601", + }, + { + city: "Grove City", + country: "United States", + distance: 4.5, + providerNumber: "127", + state: "OH", + streetAddress: "5486 N Grove Rd", + zipCode: "43215", + }, + { + city: "Dayton", + country: "United States", + distance: 80.5, + providerNumber: "128", + state: "OH", + streetAddress: "1670 Bongo Ave D", + zipCode: "43223", + }, + { + city: "Far", + country: "United States", + distance: 100, + providerNumber: "129", + state: "OH", + streetAddress: "555 First Capital Ln", + zipCode: "45601", + }, + { + city: "Farther", + country: "United States", + distance: 200, + providerNumber: "130", + state: "OH", + streetAddress: "5486 N Grove Rd", + zipCode: "43215", + }, + { + city: "Farthest (Ever)", + country: "United States", + distance: 380.5, + providerNumber: "131", + state: "OH", + streetAddress: "1670 Bongo Ave D", + zipCode: "43223", + }, +]; + +const mockMixin = { + methods: { + getCmsContent: jest.fn((widgetName, cmsFieldName) => { + if (widgetName === cmsWidgetName) { + return mockCmsContent[cmsFieldName]; + } + + return null; + }), + }, +}; + +describe("shop-question.vue", () => { + it("Should display first three shops when an appointment type has already been selected", async () => { + // Arrange/Act + const container = document.createElement("div"); + container.scrollTo = jest.fn(); + + container.classList.add("page-container-grouped-styles"); + document.body.appendChild(container); + + const { wrapper } = setupMocks({ + mixins: [mockMixin], + props: { + modelValue: null, + serviceZipCode: "43081", + selectedAppointmentType: "Dropoff", + cmsWidgetName: cmsWidgetName, + }, + mountOptions: { + attachTo: document.body, + }, + }); + + wrapper.vm.$refs.buttonQuestion.resetField = jest.fn(); + wrapper.vm.initializeComponent(shopQuestionInitialData); + + await wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.answers).toEqual([ + { + Name: "123", + buttonLabel: "Worthington", + buttonLabelSubCopy: "1.5 mi", + buttonBodyCopy: "760 Dearborn Park Ln, Worthington, OH 43085", + }, + { + Name: "124", + buttonLabel: "Columbus", + buttonLabelSubCopy: "4.5 mi", + buttonBodyCopy: "5486 N Hamilton Rd, Columbus, OH 43230", + }, + { + Name: "125", + buttonLabel: "Powell", + buttonLabelSubCopy: "7 mi", + buttonBodyCopy: "1670 Harmon Ave C, Powell, OH 43223", + }, + ]); + }); + + it("Should display the 'Show more locations' link when there are more than three locations to chose from", async () => { + // Arrange/Act + const container = document.createElement("div"); + container.scrollTo = jest.fn(); + + container.classList.add("page-container-grouped-styles"); + document.body.appendChild(container); + + const { wrapper } = setupMocks({ + mixins: [mockMixin], + props: { + modelValue: null, + serviceZipCode: "43081", + selectedAppointmentType: "Dropoff", + cmsWidgetName: cmsWidgetName, + }, + mountOptions: { + attachTo: document.body, + }, + }); + + wrapper.vm.$refs.buttonQuestion.resetField = jest.fn(); + wrapper.vm.initializeComponent(shopQuestionInitialData); + + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); + + const showMoreShopsLink = wrapper.findComponent({ ref: "showMoreShopsLink" }); + + // Assert + expect(showMoreShopsLink.exists()).toBe(true); + }); + + it("Should not display the 'Show more locations' link when there are fewer than three locations to chose from", async () => { + // Arrange/Act + const container = document.createElement("div"); + container.scrollTo = jest.fn(); + + container.classList.add("page-container-grouped-styles"); + document.body.appendChild(container); + + const alsoShopQuestionInitialData = [ + { + city: "Worthington", + country: "United States", + distance: 1.5, + providerNumber: "123", + state: "OH", + streetAddress: "760 Dearborn Park Ln", + zipCode: "43085", + }, + { + city: "Columbus", + country: "United States", + distance: 4.5, + providerNumber: "124", + state: "OH", + streetAddress: "5486 N Hamilton Rd", + zipCode: "43230", + }, + { + city: "Powell", + country: "United States", + distance: 7, + providerNumber: "125", + state: "OH", + streetAddress: "1670 Harmon Ave C", + zipCode: "43223", + }, + ]; + + const { wrapper } = setupMocks({ + mixins: [mockMixin], + props: { + modelValue: null, + serviceZipCode: "43081", + selectedAppointmentType: "Dropoff", + cmsWidgetName: cmsWidgetName, + }, + mountOptions: { + attachTo: document.body, + }, + }); + + wrapper.vm.$refs.buttonQuestion.resetField = jest.fn(); + wrapper.vm.initializeComponent(alsoShopQuestionInitialData); + + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); + + const showMoreShopsLink = wrapper.findComponent({ ref: "showMoreShopsLink" }); + + // Assert + expect(showMoreShopsLink.exists()).toBe(false); + }); + + it("Should display the next three shops when the 'Show more location' link is clicked", async () => { + const container = document.createElement("div"); + container.scrollTo = jest.fn(); + + container.classList.add("page-container-grouped-styles"); + document.body.appendChild(container); + + const displayedAnswers = [ + { + Name: "123", + buttonLabel: "Worthington", + buttonLabelSubCopy: "1.5 mi", + buttonBodyCopy: "760 Dearborn Park Ln, Worthington, OH 43085", + }, + { + Name: "124", + buttonLabel: "Columbus", + buttonLabelSubCopy: "4.5 mi", + buttonBodyCopy: "5486 N Hamilton Rd, Columbus, OH 43230", + }, + { + Name: "125", + buttonLabel: "Powell", + buttonLabelSubCopy: "7 mi", + buttonBodyCopy: "1670 Harmon Ave C, Powell, OH 43223", + }, + ]; + + // Arrange/Act + const { wrapper } = setupMocks({ + mixins: [mockMixin], + props: { + modelValue: null, + serviceZipCode: "43081", + selectedAppointmentType: "Dropoff", + cmsWidgetName: cmsWidgetName, + }, + mountOptions: { + attachTo: document.body, + }, + }); + + wrapper.vm.$refs.buttonQuestion.resetField = jest.fn(); + + wrapper.vm.shops = shopQuestionInitialData; + wrapper.vm.answers = displayedAnswers; + wrapper.vm.shopIndex = 3; + + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); + + const showMoreShopsLink = wrapper.findComponent({ ref: "showMoreShopsLink" }); + + showMoreShopsLink.trigger("click"); + + await wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.answers.length).toBe(6); + expect(wrapper.vm.answers).toEqual([ + { + Name: "123", + buttonLabel: "Worthington", + buttonLabelSubCopy: "1.5 mi", + buttonBodyCopy: "760 Dearborn Park Ln, Worthington, OH 43085", + }, + { + Name: "124", + buttonLabel: "Columbus", + buttonLabelSubCopy: "4.5 mi", + buttonBodyCopy: "5486 N Hamilton Rd, Columbus, OH 43230", + }, + { + Name: "125", + buttonLabel: "Powell", + buttonLabelSubCopy: "7 mi", + buttonBodyCopy: "1670 Harmon Ave C, Powell, OH 43223", + }, + { + Name: "126", + buttonLabel: "Chillicothe", + buttonLabelSubCopy: "41.5 mi", + buttonBodyCopy: "555 First Capital Ln, Chillicothe, OH 45601", + }, + { + Name: "127", + buttonLabel: "Grove City", + buttonLabelSubCopy: "4.5 mi", + buttonBodyCopy: "5486 N Grove Rd, Grove City, OH 43215", + }, + { + Name: "128", + buttonLabel: "Dayton", + buttonLabelSubCopy: "80.5 mi", + buttonBodyCopy: "1670 Bongo Ave D, Dayton, OH 43223", + }, + ]); + }); + + it("Should display the number of shops necessary to show a previously selected shop", async () => { + // Arrange/Act + const container = document.createElement("div"); + container.scrollTo = jest.fn(); + + container.classList.add("page-container-grouped-styles"); + document.body.appendChild(container); + + const { wrapper } = setupMocks({ + mixins: [mockMixin], + props: { + modelValue: "127", + serviceZipCode: "43081", + selectedAppointmentType: "Dropoff", + cmsWidgetName: cmsWidgetName, + }, + mountOptions: { + attachTo: document.body, + }, + }); + + wrapper.vm.$refs.buttonQuestion.resetField = jest.fn(); + wrapper.vm.initializeComponent(shopQuestionInitialData); + + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.answers.length).toEqual(5); + }); + + it("Should reset the answers when the selected appointment type changes", async () => { + // Arrange/Act + const container = document.createElement("div"); + container.scrollTo = jest.fn(); + + container.classList.add("page-container-grouped-styles"); + document.body.appendChild(container); + + const { wrapper } = setupMocks({ + mixins: [mockMixin], + props: { + modelValue: "127", + serviceZipCode: "43081", + selectedAppointmentType: "Dropoff", + cmsWidgetName: cmsWidgetName, + }, + mountOptions: { + attachTo: document.body, + }, + }); + + wrapper.vm.$refs.buttonQuestion.resetField = jest.fn(); + wrapper.vm.initializeComponent(shopQuestionInitialData); + + wrapper.setProps({ + selectedAppointmentType: "Inshop", + }); + + await wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.answers.length).toEqual(3); + }); + + it("Should reload the shops when the service zip code changes", async () => { + // Arrange/Act + const container = document.createElement("div"); + container.scrollTo = jest.fn(); + + container.classList.add("page-container-grouped-styles"); + document.body.appendChild(container); + + const { wrapper } = setupMocks({ + mixins: [mockMixin], + props: { + modelValue: "127", + serviceZipCode: "43081", + selectedAppointmentType: "Dropoff", + cmsWidgetName: cmsWidgetName, + }, + mountOptions: { + attachTo: document.body, + }, + }); + + wrapper.vm.$refs.buttonQuestion.resetField = jest.fn(); + wrapper.vm.shops = shopQuestionInitialData; + + await wrapper.vm.$nextTick(); + + wrapper.vm.$options.methods.loadInitialData = jest.fn().mockImplementation(() => { + return new Promise((resolve) => { + resolve(newShopList); + }); + }); + await wrapper.vm.$options.watch.serviceZipCode.handler.call(wrapper.vm, "43054"); + + await wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.shops.length).toEqual(3); + expect(wrapper.vm.shops).toEqual(mockNewShopList.data); + }); + + it("Should clear the existing answers when the service zip code changes", async () => { + // Arrange/Act + const container = document.createElement("div"); + container.scrollTo = jest.fn(); + + container.classList.add("page-container-grouped-styles"); + document.body.appendChild(container); + + const { wrapper } = setupMocks({ + mixins: [mockMixin], + props: { + modelValue: "127", + serviceZipCode: "43081", + selectedAppointmentType: "Dropoff", + cmsWidgetName: cmsWidgetName, + }, + mountOptions: { + attachTo: document.body, + }, + }); + + wrapper.vm.$refs.buttonQuestion.resetField = jest.fn(); + wrapper.vm.initializeComponent(shopQuestionInitialData); + + wrapper.setProps({ + selectedAppointmentType: "Inshop", + }); + + await wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.answers.length).toEqual(3); + }); +}); + +function setupMocks({ mountOptions, mixins, props, isShallowMount = true }) { + const resultingMountOptions = getMountOptions({ + ...mountOptions, + mixins, + }); + + if (props) resultingMountOptions.propsData = props; + + const wrapper = isShallowMount + ? shallowMount(shopQuestion, resultingMountOptions) + : mount(shopQuestion, resultingMountOptions); + + return { wrapper }; +} diff --git a/src/layouts/service-location/shop-question/shop-question.vue b/src/layouts/service-location/shop-question/shop-question.vue index 304651e81..2610fd787 100644 --- a/src/layouts/service-location/shop-question/shop-question.vue +++ b/src/layouts/service-location/shop-question/shop-question.vue @@ -67,14 +67,9 @@ export default { }, props: { modelValue: String, - isDropoff: Boolean, serviceZipCode: String, selectedAppointmentType: String, cmsWidgetName: String, - shopQuestionInitialData: { - type: Object, - required: true, - }, validationRules: String, }, computed: { @@ -90,7 +85,7 @@ export default { }, }, displayDropoffInformation() { - return this.isDropoff; + return this.selectedAppointmentType == "Dropoff"; }, showMoreShopsLinkText() { return this.getCmsContent("ShowMoreShopsLinkWidget", "Text"); @@ -105,7 +100,7 @@ export default { initializeComponent(shopQuestionInitialData) { this.shops = shopQuestionInitialData; }, - getNextShopsFromList(numberToGet = 3) { + async getNextShopsFromList(numberToGet = 3) { const shopIterator = (array, n) => { let l = array.length; return () => { @@ -125,7 +120,7 @@ export default { buttonLabel: shop.city, buttonLabelSubCopy: `${shop.distance} mi`, buttonBodyCopy: `${shop.streetAddress}, ${shop.city}, ${shop.state} ${shop.zipCode}`, - buttonAuxillaryCopy: `foo`, + //buttonAuxillaryCopy: `foo`, }; }); @@ -137,17 +132,17 @@ export default { }); } - this.$nextTick().then(() => { - if (this.shopIndex == this.shops.length) { - this.displaySeeMoreLocationsLink = false; - } else { - this.displaySeeMoreLocationsLink = true; - } + await this.$nextTick(); - this.$nextTick().then(() => { - this.scrollToBottom(); - }); - }); + if (this.shopIndex == this.shops.length) { + this.displaySeeMoreLocationsLink = false; + } else { + this.displaySeeMoreLocationsLink = true; + } + + await this.$nextTick(); + + this.scrollToBottom(); }, resetShopList() { this.answers = []; @@ -159,29 +154,29 @@ export default { const container = document.getElementsByClassName("page-container-grouped-styles")[0]; container.scrollTo({ top: container.scrollHeight, left: 0, behavior: "smooth" }); }, + async reloadShopData(serviceZipCode) { + const result = await this.loadInitialData(serviceZipCode); + this.initializeComponent(result.data); + this.resetShopList(); + }, }, watch: { serviceZipCode: { - handler(newValue) { - this.loadInitialData(newValue).then((result) => { - this.initializeComponent(result.data); - this.resetShopList(); - }); + async handler(newValue) { + await this.reloadShopData(newValue); }, }, selectedAppointmentType: { - handler(newValue) { + async handler(newValue) { // If the validation has been previously triggered, clear it before displaying the component this.$refs.buttonQuestion.resetField(); - if (newValue != null) { - this.resetShopList(); - this.getNextShopsFromList(); + this.resetShopList(); + await this.getNextShopsFromList(); - this.$nextTick().then(() => { - this.scrollToBottom(); - }); - } + await this.$nextTick(); + + this.scrollToBottom(); }, }, shops: { @@ -190,6 +185,7 @@ export default { const selectedShopIndex = newValue.findIndex( (provider) => provider.providerNumber == this.modelValue ); + if (selectedShopIndex >= 3) { this.getNextShopsFromList(selectedShopIndex + 1); } else { diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js index 12fea69dc..29eb76c3d 100644 --- a/src/mixins/analytics-mixin.js +++ b/src/mixins/analytics-mixin.js @@ -24,35 +24,38 @@ import { applicationConfig } from "../constants/application-config"; export default { methods: { logPageView(pageEvent) { - // const currentPageName = getPageNameByQueryString(); - // var payload = { - // userId: getDeviceIdValue(), - // sessionKey: getSessionKeyValue(), - // pageName: currentPageName, - // sessionId: getSessionIdValue(), - // action: "", - // event: pageEvent, - // shouldUseSessionId: false, - // experimentsForUser: store.getters.applicationUser.experiments, - // }; - // baseMixin.methods.dispatchStoreAction(storeActions.LOG_PAGE_VIEW, payload, false); + const currentPageName = getPageNameByQueryString(); + var payload = { + userId: getDeviceIdValue(), + sessionKey: getSessionKeyValue(), + pageName: currentPageName, + sessionId: getSessionIdValue(), + action: "", + event: pageEvent, + shouldUseSessionId: false, + experimentsForUser: store.getters.applicationUser.experiments, + }; + + baseMixin.methods.dispatchStoreAction(storeActions.LOG_PAGE_VIEW, payload, false); }, logCustomEvent(category, action, label, value) { - // const currentPageName = getPageNameByQueryString(); - // var payload = { - // userId: getDeviceIdValue(), - // sessionKey: getSessionKeyValue(), - // pageName: currentPageName, - // sessionId: getSessionIdValue(), - // category: category, - // action: action, - // label: label, - // value: value, - // shouldUseSessionId: false, - // experimentsForUser: store.getters.applicationUser.experiments, - // }; - // baseMixin.methods.dispatchStoreAction(storeActions.LOG_CUSTOM_EVENT, payload, false); + const currentPageName = getPageNameByQueryString(); + + var payload = { + userId: getDeviceIdValue(), + sessionKey: getSessionKeyValue(), + pageName: currentPageName, + sessionId: getSessionIdValue(), + category: category, + action: action, + label: label, + value: value, + shouldUseSessionId: false, + experimentsForUser: store.getters.applicationUser.experiments, + }; + + baseMixin.methods.dispatchStoreAction(storeActions.LOG_CUSTOM_EVENT, payload, false); }, pushEventToGA(category, action, label, pushToLogApp = false, valueToLogType = null) {