From d7fcadb1f0d0d3eab40581b34fbe5fa8ee2bf8d1 Mon Sep 17 00:00:00 2001 From: Michaela Brydon Date: Thu, 30 Nov 2023 11:14:31 -0500 Subject: [PATCH 01/15] Partial fixes --- src/layouts/tpa-search/tpa-search.vue | 261 ++++++++++++++------------ 1 file changed, 142 insertions(+), 119 deletions(-) diff --git a/src/layouts/tpa-search/tpa-search.vue b/src/layouts/tpa-search/tpa-search.vue index 6c3941e0..e52d7116 100644 --- a/src/layouts/tpa-search/tpa-search.vue +++ b/src/layouts/tpa-search/tpa-search.vue @@ -37,14 +37,14 @@ - -
+ :height="4" /> --> +
@@ -134,13 +134,41 @@ import loader from '@/ux-components/loader/loader.vue'; // Supporting files import { fetchCmsContentForPage } from '@/helpers/cms-content-helper'; -import settleAllPromises from '@/helpers/layout-helper'; import { useMainStore } from '@/store'; import BaseFormMixin from '@/mixins/base-form-mixin.js'; import globalRules from '@/constants/global-rules.js'; import widgetFields from '@/constants/cms-widget-fields.js'; import { shallowRef } from 'vue'; +async function getInitialFilterAndProviders() { + const radiusOptions = [15, 25, 50, 100]; + const { zipCode } = useMainStore().order.customer.address; + + const tpaProvidersRadius15 = useMainStore().getTpaProviders(zipCode, radiusOptions[0]); + const tpaProvidersRadius25 = useMainStore().getTpaProviders(zipCode, radiusOptions[1]); + const tpaProvidersRadius50 = useMainStore().getTpaProviders(zipCode, radiusOptions[2]); + const tpaProvidersRadius100 = useMainStore().getTpaProviders(zipCode, radiusOptions[3]); + + let filter = '15 miles'; + let providers = await tpaProvidersRadius15; + if ((providers?.data?.shopProviders ?? []).length === 0) { + filter = '25 miles'; + providers = await tpaProvidersRadius25; + if ((providers?.data?.shopProviders ?? []).length === 0) { + filter = '50 miles'; + providers = await tpaProvidersRadius50; + if ((providers?.data?.shopProviders ?? []).length === 0) { + filter = '100 miles'; + providers = await tpaProvidersRadius100; + } + } + } + return [ + filter, + providers?.data?.shopProviders ?? [] + ]; +} + export default { name: 'tpa-search', components: { @@ -158,29 +186,24 @@ export default { }, mixins: [BaseFormMixin], async beforeRouteEnter(to, from, next) { - const cmsContentPromise = fetchCmsContentForPage(to.query.issPage); - const promiseResultMap = [ - { - resultKey: 'cmsContent', - promise: cmsContentPromise - } - ]; - const resultMap = await settleAllPromises(promiseResultMap); + const [filter, providers] = await getInitialFilterAndProviders(); + const cmsContent = await fetchCmsContentForPage(to.query.issPage); next(async (vm) => { - vm.setCmsContent(resultMap.cmsContent); - await vm.setInitialFilterAndProviders(); + vm.setCmsContent(cmsContent); + vm.setFilter(filter); + vm.setProviders(providers); }); }, data() { const { zipCode } = useMainStore().order.customer.address; return { + dataLoaded: false, zipCode, mapZipCode: zipCode, filter: '', providers: [], selectedProviderNumber: '', - initialLoading: false, reloadProviders: false, additionalButtonData: { displayAvailabilityIndicators: false @@ -234,6 +257,8 @@ export default { }, radiusInMiles() { switch (this.filter) { + case '15 miles': + return 15; case '25 miles': return 25; case '50 miles': @@ -262,15 +287,13 @@ export default { }, watch: { async filter() { - if (!this.initialLoading) { + if (this.dataLoaded) { this.reloadProviders = true; await this.getProviderButtonData().then((providers) => { this.providers = providers; }); this.mapZipCode = this.zipCode; this.reloadProviders = false; - } else { - this.initialLoading = false; } }, async providers(newProviders) { @@ -279,106 +302,106 @@ export default { } } }, - methods: - { - getProviderAddress(provider) { - const city = provider?.address?.city ?? ''; - const state = provider?.address?.state ?? ''; - const zipCode = provider?.address?.zipCode ?? ''; - let addressLine2 = ''; - if (city) { - addressLine2 = city; - if (state || zipCode) { - if (state) { - addressLine2 += ','; - } - addressLine2 += ' '; - } - } - if (state) { - addressLine2 += `${state}`; - if (zipCode) { - addressLine2 += ' '; - } - } - if (zipCode) { - addressLine2 += `${zipCode}`; - } - return provider?.address?.streetAddress - ? `${provider.address.streetAddress}, ${addressLine2}` - : addressLine2; - }, - async setInitialFilterAndProviders() { - this.initialLoading = true; - const radiusOptions = [25, 50, 100]; - const { zipCode } = useMainStore().order.customer.address; - - const tpaProvidersRadius25 = useMainStore().getTpaProviders(zipCode, radiusOptions[0]); - const tpaProvidersRadius50 = useMainStore().getTpaProviders(zipCode, radiusOptions[1]); - const tpaProvidersRadius100 = useMainStore().getTpaProviders(zipCode, radiusOptions[2]); - - let radius = '25 miles'; - let providers = await tpaProvidersRadius25; - if ((providers?.data?.shopProviders ?? []).length === 0) { - radius = '50 miles'; - providers = await tpaProvidersRadius50; - if ((providers?.data?.shopProviders ?? []).length === 0) { - radius = '100 miles'; - providers = await tpaProvidersRadius100; - } - } - this.filter = radius; - this.providers = providers?.data?.shopProviders ?? []; - }, - async getProviderButtonData() { - const getTpaProvidersResult = await useMainStore().getTpaProviders(this.zipCode, this.radiusInMiles); - return getTpaProvidersResult?.data?.shopProviders ?? []; - }, - doNotSeeMyShopLinkClick() { - this.$router.navigate( - this.navigationScenarios.CLICKED_DO_NOT_SEE_MY_SHOP_LINK, - this.$route - ); - }, - async searchClick() { - this.reloadProviders = true; - this.providers = await this.getProviderButtonData(); - this.mapZipCode = this.zipCode; - this.reloadProviders = false; - }, - backButtonAction() { - this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); - }, - forwardButtonAction() { - const scenario = this.selectedProviderIsSafeliteShop - ? this.navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE_SHOP - : this.navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP; - this.$router.navigate(scenario, this.$route); - }, - getCustomValueFromString(str) { - switch (str) { - case 'radiusInMiles': - return this.radiusInMiles; - default: - return null; - } - }, - getShopButtonDataFromProvider(provider) { - const cellNumber = provider?.phoneNumber ?? ''; - const distance = provider?.distanceInMiles !== null && !Number.isNaN(parseFloat(provider?.distanceInMiles)) - ? +provider.distanceInMiles.toFixed(1) - : null; - - return { - buttonLabel: provider?.companyName ?? '', - buttonLabelSubCopy: distance === null - ? '' - : `${distance} mi`, - buttonBodyCopy: `${this.getProviderAddress(provider)}
${cellNumber ?? ''}`, - value: provider?.providerNumber ?? '' - }; - } + beforeUpdate() { + if (!this.dataLoaded) { + this.dataLoaded = true; } + }, + methods: { + getProviderAddress(provider) { + const city = provider?.address?.city ?? ''; + const state = provider?.address?.state ?? ''; + const zipCode = provider?.address?.zipCode ?? ''; + let addressLine2 = ''; + if (city) { + addressLine2 = city; + if (state || zipCode) { + if (state) { + addressLine2 += ','; + } + addressLine2 += ' '; + } + } + if (state) { + addressLine2 += `${state}`; + if (zipCode) { + addressLine2 += ' '; + } + } + if (zipCode) { + addressLine2 += `${zipCode}`; + } + return provider?.address?.streetAddress + ? `${provider.address.streetAddress}, ${addressLine2}` + : addressLine2; + }, + setFilter(filter) { + this.filter = filter; + }, + setProviders(providers) { + this.providers = providers; + }, + async getProviderButtonData() { + const getTpaProvidersResult = await useMainStore().getTpaProviders(this.zipCode, this.radiusInMiles); + return getTpaProvidersResult?.data?.shopProviders ?? []; + }, + doNotSeeMyShopLinkClick() { + this.$router.navigate( + this.navigationScenarios.CLICKED_DO_NOT_SEE_MY_SHOP_LINK, + this.$route + ); + }, + async searchClick() { + this.reloadProviders = true; + this.providers = await this.getProviderButtonData(); + this.mapZipCode = this.zipCode; + this.reloadProviders = false; + }, + backButtonAction() { + this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); + }, + forwardButtonAction() { + const scenario = this.selectedProviderIsSafeliteShop + ? this.navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE_SHOP + : this.navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP; + this.$router.navigate(scenario, this.$route); + }, + getCustomValueFromString(str) { + switch (str) { + case 'radiusInMiles': + return this.radiusInMiles; + default: + return null; + } + }, + getShopButtonDataFromProvider(provider) { + const cellNumber = this.getDisplayPhoneNumber(provider?.phoneNumber ?? ''); + const distance = provider?.distanceInMiles !== null && !Number.isNaN(parseFloat(provider?.distanceInMiles)) + ? +provider.distanceInMiles.toFixed(1) + : null; + + return { + buttonLabel: provider?.companyName ?? '', + buttonLabelSubCopy: distance === null + ? '' + : `${distance} mi`, + buttonBodyCopy: `${this.getProviderAddress(provider)}
${cellNumber ?? ''}`, + value: provider?.providerNumber ?? '' + }; + }, + getDisplayPhoneNumber(phoneNumber) { + let result = ''; + let remainingDigits = phoneNumber; + if (phoneNumber.length === 11) { + result += `${remainingDigits[0]}-`; + remainingDigits = remainingDigits.substring(1); + } + if (phoneNumber.length > 9) { + result += remainingDigits.replace(/^(\d{3})(\d{3})(\d{4})/, '$1-$2-$3'); + } + return result; + } + } }; From 0ee833f584cffb18d87292dafd4e459a3b5dbd5c Mon Sep 17 00:00:00 2001 From: Michaela Brydon Date: Thu, 30 Nov 2023 11:15:59 -0500 Subject: [PATCH 02/15] Starting to title case --- src/layouts/tpa-search/tpa-search.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/layouts/tpa-search/tpa-search.vue b/src/layouts/tpa-search/tpa-search.vue index e52d7116..ba346dff 100644 --- a/src/layouts/tpa-search/tpa-search.vue +++ b/src/layouts/tpa-search/tpa-search.vue @@ -400,7 +400,10 @@ export default { result += remainingDigits.replace(/^(\d{3})(\d{3})(\d{4})/, '$1-$2-$3'); } return result; - } + }// , + // toTitleCase(word) { + // const first = word[0]. + // } } }; From 7764556e563336f026b52bbcc4d1df63472b33b4 Mon Sep 17 00:00:00 2001 From: Michaela Brydon Date: Thu, 30 Nov 2023 13:01:03 -0500 Subject: [PATCH 03/15] Adding fourth case --- src/layouts/tpa-search/tpa-search.spec.js | 55 +++++++++++++++++-- src/layouts/tpa-search/tpa-search.vue | 67 +++++++++++++---------- 2 files changed, 88 insertions(+), 34 deletions(-) diff --git a/src/layouts/tpa-search/tpa-search.spec.js b/src/layouts/tpa-search/tpa-search.spec.js index d8185733..ccc056ec 100644 --- a/src/layouts/tpa-search/tpa-search.spec.js +++ b/src/layouts/tpa-search/tpa-search.spec.js @@ -1238,8 +1238,55 @@ describe('TPA search page', () => { }); }); }); + test.each([ + [undefined, ''], + [null, ''], + ['', ''], + ['hello world', 'Hello World'], + ['hello world', 'Hello World'], + ['HEllO worLD', 'Hello World'], + ['a991,,:A froG FAMILY', 'A991,,:a Frog Family'] + ])( + 'toTitleCase given "%p" returns "%p"', + (input, expected) => { + // Arrange + const { wrapper } = getMountedComponent(); + + // Act + const result = wrapper.vm.toTitleCase(input); + + // Assert + expect(result).toEqual(expected); + } + ); }); describe('before route enter', () => { + test('when providers exist at 15 mile radius, filter is set to "15 miles" and providers set to expected', async () => { + // Arrange + const { wrapper } = getMountedComponent(); + const zipCode = '18394'; + useMainStore().order.customer.address.zipCode = zipCode; + const providers = [{ companyName: 'provider' }]; + useMainStore().getTpaProviders = jest.fn().mockImplementation((_, radius) => + ({ data: { shopProviders: radius === 15 ? providers : [] } })); + const expectedFilter = '15 miles'; + + // Act + await tpaSearch.beforeRouteEnter.call( + wrapper.vm, + { query: { issPage: 'tpa-search' } }, + undefined, + (c) => c(wrapper.vm) + ); + + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.filter).toBe(expectedFilter); + expect(wrapper.vm.providers).toEqual(providers); + expect(useMainStore().getTpaProviders).toBeCalledTimes(1); + }); test('when providers exist at 25 mile radius, filter is set to "25 miles" and providers set to expected', async () => { // Arrange const { wrapper } = getMountedComponent(); @@ -1264,7 +1311,7 @@ describe('TPA search page', () => { // Assert expect(wrapper.vm.filter).toBe(expectedFilter); expect(wrapper.vm.providers).toEqual(providers); - expect(useMainStore().getTpaProviders).toBeCalledTimes(1); + expect(useMainStore().getTpaProviders).toBeCalledTimes(2); }); test('when providers exist at 50 mile radius but not 25, filter is set to "50 miles" and providers set to expected', async () => { // Arrange @@ -1290,7 +1337,7 @@ describe('TPA search page', () => { // Assert expect(wrapper.vm.filter).toBe(expectedFilter); expect(wrapper.vm.providers).toEqual(providers); - expect(useMainStore().getTpaProviders).toBeCalledTimes(2); + expect(useMainStore().getTpaProviders).toBeCalledTimes(3); }); test( 'when providers exist at 100 mile radius but not 50 or 25, filter is set to "100 miles" and providers set to expected', @@ -1318,7 +1365,7 @@ describe('TPA search page', () => { // Assert expect(wrapper.vm.filter).toBe(expectedFilter); expect(wrapper.vm.providers).toEqual(providers); - expect(useMainStore().getTpaProviders).toBeCalledTimes(3); + expect(useMainStore().getTpaProviders).toBeCalledTimes(4); } ); test( @@ -1345,7 +1392,7 @@ describe('TPA search page', () => { // Assert expect(wrapper.vm.filter).toBe(expectedFilter); expect(wrapper.vm.providers).toEqual([]); - expect(useMainStore().getTpaProviders).toBeCalledTimes(3); + expect(useMainStore().getTpaProviders).toBeCalledTimes(4); } ); }); diff --git a/src/layouts/tpa-search/tpa-search.vue b/src/layouts/tpa-search/tpa-search.vue index a2ec4231..5b7d84fc 100644 --- a/src/layouts/tpa-search/tpa-search.vue +++ b/src/layouts/tpa-search/tpa-search.vue @@ -140,14 +140,21 @@ import globalRules from '@/constants/global-rules.js'; import widgetFields from '@/constants/cms-widget-fields.js'; import { shallowRef } from 'vue'; +const radiusFilterPairs = [ + { radius: 15, filter: '15 miles' }, + { radius: 25, filter: '25 miles' }, + { radius: 50, filter: '50 miles' }, + { radius: 100, filter: '100 miles' } +]; + async function getInitialFilterAndProviders() { const { zipCode } = useMainStore().order.customer.address; let pairIndex = 0; let providers = []; let filter = ''; - while (providers.length === 0 && pairIndex < this.radiusFilterPairs.length) { - const pair = this.radiusFilterPairs[pairIndex]; + while (providers.length === 0 && pairIndex < radiusFilterPairs.length) { + const pair = radiusFilterPairs[pairIndex]; const { radius } = pair; filter = pair.filter; // eslint-disable-next-line no-await-in-loop @@ -157,7 +164,7 @@ async function getInitialFilterAndProviders() { pairIndex += 1; } - return {filter, providers}; + return { filter, providers }; } export default { @@ -213,13 +220,7 @@ export default { filter: globalRules.OPTION_REQUIRED, // TODO do we even need this? provider: globalRules.OPTION_REQUIRED }, - shopListButton: shallowRef(shopListButton), - radiusFilterPairs: [ - { radius: 15, filter: '15 miles' }, - { radius: 25, filter: '25 miles' }, - { radius: 50, filter: '50 miles' }, - { radius: 100, filter: '100 miles' } - ] + shopListButton: shallowRef(shopListButton) }; }, computed: { @@ -253,7 +254,7 @@ export default { ); }, radiusInMiles() { - const pair = this.radiusFilterPairs.find((p) => p.filter === this.filter); + const pair = radiusFilterPairs.find((p) => p.filter === this.filter); return pair?.radius ?? 0; }, noNetworkShopsAlertHeaderText() { @@ -302,31 +303,27 @@ export default { this.providers = providers; }, getProviderAddress(provider) { - const city = provider?.address?.city ?? ''; + const city = this.toTitleCase(provider?.address?.city); const state = provider?.address?.state ?? ''; const zipCode = provider?.address?.zipCode ?? ''; let addressLine2 = ''; if (city) { - addressLine2 = city; + addressLine2 += city; if (state || zipCode) { - if (state) { - addressLine2 += ','; - } - addressLine2 += ' '; + addressLine2 += state ? ',' : ' '; } } if (state) { - addressLine2 += `${state}`; - if (zipCode) { - addressLine2 += ' '; - } + addressLine2 += state; + addressLine2 += zipCode ? ' ' : ''; } if (zipCode) { - addressLine2 += `${zipCode}`; + addressLine2 += zipCode; } - return provider?.address?.streetAddress - ? `${provider.address.streetAddress}, ${addressLine2}` - : addressLine2; + + const addressLine1 = this.toTitleCase(provider?.address?.streetAddress); + const joinString = addressLine1.length > 0 && addressLine2.length > 0 ? ', ' : ''; + return [addressLine1, addressLine2].join(joinString); }, async getProviderButtonData() { const getTpaProvidersResult = await useMainStore().getTpaProviders(this.zipCode, this.radiusInMiles); @@ -362,7 +359,7 @@ export default { } }, getShopButtonDataFromProvider(provider) { - const cellNumber = this.getDisplayPhoneNumber(provider?.phoneNumber ?? ''); + const cellNumber = this.getDisplayPhoneNumber(provider?.phoneNumber); const distance = provider?.distanceInMiles !== null && !Number.isNaN(parseFloat(provider?.distanceInMiles)) ? +provider.distanceInMiles.toFixed(1) : null; @@ -378,6 +375,7 @@ export default { }, getDisplayPhoneNumber(phoneNumber) { let result = ''; + if (!phoneNumber) { return result; } let remainingDigits = phoneNumber; if (phoneNumber.length === 11) { result += `${remainingDigits[0]}-`; @@ -387,10 +385,19 @@ export default { result += remainingDigits.replace(/^(\d{3})(\d{3})(\d{4})/, '$1-$2-$3'); } return result; - }// , - // toTitleCase(word) { - // const first = word[0]. - // } + }, + toTitleCase(text) { + if ((text?.length ?? 0) === 0) { + return ''; + } + const wordList = text.split(' '); + const titleCaseWordList = wordList.map((word) => { + const first = word[0].toUpperCase(); + const rest = word.substring(1).toLowerCase(); + return first + rest; + }); + return titleCaseWordList.join(' '); + } } }; From c43065a6326c799410c7b2fbcf1805c1395faf9e Mon Sep 17 00:00:00 2001 From: Michaela Brydon Date: Thu, 30 Nov 2023 13:23:55 -0500 Subject: [PATCH 04/15] Fixing tests --- .../__snapshots__/tpa-search.spec.js.snap | 16 +- src/layouts/tpa-search/tpa-search.spec.js | 193 +++++++----------- src/layouts/tpa-search/tpa-search.vue | 11 +- 3 files changed, 77 insertions(+), 143 deletions(-) diff --git a/src/layouts/tpa-search/__snapshots__/tpa-search.spec.js.snap b/src/layouts/tpa-search/__snapshots__/tpa-search.spec.js.snap index fc429c1b..5f9f27f5 100644 --- a/src/layouts/tpa-search/__snapshots__/tpa-search.spec.js.snap +++ b/src/layouts/tpa-search/__snapshots__/tpa-search.spec.js.snap @@ -5,24 +5,10 @@ Object { "additionalButtonData": Object { "displayAvailabilityIndicators": false, }, + "dataLoaded": false, "filter": "", - "initialLoading": false, "mapZipCode": "12663", "providers": Array [], - "radiusFilterPairs": Array [ - Object { - "filter": "25 miles", - "radius": 25, - }, - Object { - "filter": "50 miles", - "radius": 50, - }, - Object { - "filter": "100 miles", - "radius": 100, - }, - ], "reloadProviders": false, "rules": Object { "filter": "option-required", diff --git a/src/layouts/tpa-search/tpa-search.spec.js b/src/layouts/tpa-search/tpa-search.spec.js index ccc056ec..de95fdb8 100644 --- a/src/layouts/tpa-search/tpa-search.spec.js +++ b/src/layouts/tpa-search/tpa-search.spec.js @@ -150,18 +150,7 @@ describe('TPA search page', () => { // Assert expect(providerSelectionForm.exists()).toBeTruthy(); }); - test('map loader when initialLoading is true', async () => { - // Arrange - const wrapper = shallowMount(tpaSearch, getMountOptions()); - await wrapper.setData({ initialLoading: true }); - - // Act - const mapLoader = wrapper.findComponent('#mapLoader'); - - // Assert - expect(mapLoader.exists()).toBeTruthy(); - }); - test('map when initialLoading is false', async () => { + test('map', async () => { // Arrange const zipCode = '12345'; const { wrapper } = getMountedComponent(); @@ -174,8 +163,7 @@ describe('TPA search page', () => { zipCode: '99230' } }], - mapZipCode: zipCode, - initialLoading: false + mapZipCode: zipCode }); const expectedAddresses = ['123 Lane Ave, New York, NY 99230']; @@ -188,10 +176,9 @@ describe('TPA search page', () => { expect(map.props().addresses).toEqual(expectedAddresses); expect(map.props().zipCode).toBe(zipCode); }); - test('search radius filter when initialLoading is false', async () => { + test('search radius filter', async () => { // Arrange const wrapper = shallowMount(tpaSearch, getMountOptions()); - await wrapper.setData({ initialLoading: false }); const expectedWidgetName = 'FilterByQuestion'; // Act @@ -202,10 +189,10 @@ describe('TPA search page', () => { expect(searchRadiusFilter.props().cmsWidgetName).toBe(expectedWidgetName); expect(searchRadiusFilter.props().validationRules).toBe(globalRules.OPTION_REQUIRED); }); - test('providers loader when initialLoading is false and reloadProviders is true', async () => { + test('providers loader when reloadProviders is true', async () => { // Arrange const wrapper = shallowMount(tpaSearch, getMountOptions()); - await wrapper.setData({ initialLoading: false, reloadProviders: true }); + await wrapper.setData({ reloadProviders: true }); // Act const providersLoader = wrapper.findComponent('#providersLoader'); @@ -213,7 +200,7 @@ describe('TPA search page', () => { // Assert expect(providersLoader.exists()).toBeTruthy(); }); - test('select provider question when initialLoading and reloadProviders are false', async () => { + test('select provider question when reloadProviders are false', async () => { // Arrange const wrapper = shallowMount(tpaSearch, getMountOptions()); await wrapper.setData({ @@ -229,7 +216,6 @@ describe('TPA search page', () => { zipCode: '99230' } }], - initialLoading: false, reloadProviders: false }); const expectedAnswers = [{ @@ -257,17 +243,14 @@ describe('TPA search page', () => { expect(selectProviderQuestion.props().additionalButtonData).toEqual(expectedAdditionalButtonData); }); test.each([[], null, undefined])( - 'no network providers alert when providers length is 0, undefined, or null and initialLoading and reloadProviders are false', + 'no network providers alert when providers length is 0, undefined, or null and reloadProviders is false', async (providers) => { // Arrange const initialData = { providers }; const wrapper = shallowMount(tpaSearch, getMountOptions({}, initialData)); - await wrapper.setData({ - initialLoading: false, - reloadProviders: false - }); + await wrapper.setData({ reloadProviders: false }); // Act const noNetworkProvidersAlert = wrapper.findComponent('#alertNoNetworkProviders'); @@ -279,13 +262,10 @@ describe('TPA search page', () => { expect(noNetworkProvidersAlert.props().isDismissible).toBeFalsy(); } ); - test('preferred shop not listed link when initialLoading and reloadProviders are false', async () => { + test('preferred shop not listed link when reloadProviders is false', async () => { // Arrange const wrapper = shallowMount(tpaSearch, getMountOptions()); - await wrapper.setData({ - initialLoading: false, - reloadProviders: false - }); + await wrapper.setData({ reloadProviders: false }); // Act const preferredShopNotListedLink = wrapper.findComponent('#preferredShopNotListedLink'); @@ -308,62 +288,16 @@ describe('TPA search page', () => { }); }); describe('should not render', () => { - test('map loader when initialLoading is false', async () => { - // Arrange - const wrapper = shallowMount(tpaSearch, getMountOptions()); - await wrapper.setData({ initialLoading: false }); - - // Act - const mapLoader = wrapper.findComponent('#mapLoader'); - - // Assert - expect(mapLoader.exists()).toBeFalsy(); - }); - test('map when initialLoading is true', async () => { + test('select provider question when reloadProviders is true', async () => { // Arrange const { wrapper } = getMountedComponent(); - await wrapper.setData({ initialLoading: true }); + await wrapper.setData({ reloadProviders: true }); // Act - const map = wrapper.findComponent('#map'); + const selectProviderQuestion = wrapper.findComponent('#selectProviderQuestion'); // Assert - expect(map.exists()).toBeFalsy(); - }); - test('search radius filter when initialLoading is true', async () => { - // Arrange - const { wrapper } = getMountedComponent(); - await wrapper.setData({ initialLoading: true }); - - // Act - const searchRadiusFilter = wrapper.findComponent('#searchRadiusFilter'); - - // Assert - expect(searchRadiusFilter.exists()).toBeFalsy(); - }); - describe('select provider question', () => { - test('when initialLoading is true', async () => { - // Arrange - const { wrapper } = getMountedComponent(); - await wrapper.setData({ initialLoading: true }); - - // Act - const selectProviderQuestion = wrapper.findComponent('#selectProviderQuestion'); - - // Assert - expect(selectProviderQuestion.exists()).toBeFalsy(); - }); - test('when reloadProviders is true', async () => { - // Arrange - const { wrapper } = getMountedComponent(); - await wrapper.setData({ reloadProviders: true }); - - // Act - const selectProviderQuestion = wrapper.findComponent('#selectProviderQuestion'); - - // Assert - expect(selectProviderQuestion.exists()).toBeFalsy(); - }); + expect(selectProviderQuestion.exists()).toBeFalsy(); }); describe('no network providers alert', () => { test('when providers length is not 0', async () => { @@ -377,17 +311,6 @@ describe('TPA search page', () => { // Assert expect(noNetworkProvidersAlert.exists()).toBeFalsy(); }); - test('when initialLoading is true', async () => { - // Arrange - const wrapper = shallowMount(tpaSearch, getMountOptions()); - await wrapper.setData({ providers: [], initialLoading: true }); - - // Act - const noNetworkProvidersAlert = wrapper.findComponent('#alertNoNetworkProviders'); - - // Assert - expect(noNetworkProvidersAlert.exists()).toBeFalsy(); - }); test('when reloadProviders is true', async () => { // Arrange const wrapper = shallowMount(tpaSearch, getMountOptions()); @@ -400,29 +323,16 @@ describe('TPA search page', () => { expect(noNetworkProvidersAlert.exists()).toBeFalsy(); }); }); - describe('preferred shop not listed link', () => { - test('when initialLoading is true', async () => { - // Arrange - const { wrapper } = getMountedComponent(); - await wrapper.setData({ initialLoading: true }); + test('preferred shop not listed link when reloadProviders is true', async () => { + // Arrange + const { wrapper } = getMountedComponent(); + await wrapper.setData({ reloadProviders: true }); - // Act - const preferredShopNotListedLink = wrapper.findComponent('#preferredShopNotListedLink'); + // Act + const preferredShopNotListedLink = wrapper.findComponent('#preferredShopNotListedLink'); - // Assert - expect(preferredShopNotListedLink.exists()).toBeFalsy(); - }); - test('when reloadProviders is true', async () => { - // Arrange - const { wrapper } = getMountedComponent(); - await wrapper.setData({ reloadProviders: true }); - - // Act - const preferredShopNotListedLink = wrapper.findComponent('#preferredShopNotListedLink'); - - // Assert - expect(preferredShopNotListedLink.exists()).toBeFalsy(); - }); + // Assert + expect(preferredShopNotListedLink.exists()).toBeFalsy(); }); }); describe('computed', () => { @@ -835,15 +745,16 @@ describe('TPA search page', () => { }); describe('watch', () => { // TODO update/add to filter watch tests - test('on filter calls getTpaProviders and sets providers', async () => { + test.only('on filter calls getTpaProviders and sets providers', async () => { // Arrange const zipCode = '78220'; const initialMapZipCode = '88800'; const { wrapper } = getMountedComponent({}, { zipCode, - mapZipCode: initialMapZipCode + mapZipCode: initialMapZipCode, + dataLoaded: true }); - const providers = { data: { shopProviders: ['some data', 'some more data']} }; + const providers = { data: { shopProviders: ['some data', 'some more data'] } }; useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (providers)); const newFilter = 'new filter'; @@ -855,6 +766,50 @@ describe('TPA search page', () => { expect(wrapper.vm.providers).toEqual(providers.data.shopProviders); expect(wrapper.vm.mapZipCode).toBe(zipCode); }); + describe('on filter', () => { + test('calls getTpaProviders once and sets providers when dataLoaded is true', async () => { + // Arrange + const zipCode = '78220'; + const initialMapZipCode = '88800'; + const { wrapper } = getMountedComponent({}, { + zipCode, + mapZipCode: initialMapZipCode, + dataLoaded: true + }); + const providers = { data: { shopProviders: ['some data', 'some more data'] } }; + useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (providers)); + const newFilter = 'new filter'; + + // Act + await wrapper.vm.$options.watch.filter.call(wrapper.vm, newFilter); + + // Assert + expect(useMainStore().getTpaProviders).toBeCalled(); + expect(wrapper.vm.providers).toEqual(providers.data.shopProviders); + expect(wrapper.vm.mapZipCode).toBe(zipCode); + }); + test('never calls getTpaProviders and does not set providers when dataLoaded is false', async () => { + // Arrange + const zipCode = '78220'; + const initialMapZipCode = '88800'; + const { wrapper } = getMountedComponent({}, { + zipCode, + mapZipCode: initialMapZipCode, + dataLoaded: false + }); + const providers = { data: { shopProviders: ['some data', 'some more data'] } }; + useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (providers)); + const newFilter = 'new filter'; + + // Act + await wrapper.vm.$options.watch.filter.call(wrapper.vm, newFilter); + + // Assert + expect(useMainStore().getTpaProviders).not.toBeCalled(); + expect(wrapper.vm.providers).not.toEqual(providers.data.shopProviders); + expect(wrapper.vm.mapZipCode).toBe(initialMapZipCode); + }); + }); // TODO confirm tests appropriate. Also should this method be async? describe('on providers', () => { test.each([null, undefined, []])( @@ -897,10 +852,10 @@ describe('TPA search page', () => { }); describe('method', () => { test.each([ - ['address', 'city', 'ST', 'zip', 'address, city, ST zip'], - ['address', null, 'ST', 'zip', 'address, ST zip'], - ['address', 'city', null, 'zip', 'address, city zip'], - ['address', 'city', 'ST', null, 'address, city, ST'], + ['address', 'city', 'ST', 'zip', 'Address, City, ST zip'], + ['address', null, 'ST', 'zip', 'Address, ST zip'], + ['address', 'city', null, 'zip', 'Address, City zip'], + ['address', 'city', 'ST', null, 'Address, City, ST'], [null, null, null, null, ''] ])( 'getProviderAddress returns expected', diff --git a/src/layouts/tpa-search/tpa-search.vue b/src/layouts/tpa-search/tpa-search.vue index 5b7d84fc..f35ee59f 100644 --- a/src/layouts/tpa-search/tpa-search.vue +++ b/src/layouts/tpa-search/tpa-search.vue @@ -37,13 +37,6 @@
-
Date: Thu, 30 Nov 2023 13:40:55 -0500 Subject: [PATCH 05/15] Adding tests for getDisplayPhoneNumber --- src/layouts/tpa-search/tpa-search.spec.js | 37 ++++++++++++++++++----- src/layouts/tpa-search/tpa-search.vue | 13 ++++---- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/layouts/tpa-search/tpa-search.spec.js b/src/layouts/tpa-search/tpa-search.spec.js index de95fdb8..f1f5c412 100644 --- a/src/layouts/tpa-search/tpa-search.spec.js +++ b/src/layouts/tpa-search/tpa-search.spec.js @@ -745,7 +745,7 @@ describe('TPA search page', () => { }); describe('watch', () => { // TODO update/add to filter watch tests - test.only('on filter calls getTpaProviders and sets providers', async () => { + test('on filter calls getTpaProviders and sets providers', async () => { // Arrange const zipCode = '78220'; const initialMapZipCode = '88800'; @@ -1197,18 +1197,41 @@ describe('TPA search page', () => { [undefined, ''], [null, ''], ['', ''], - ['hello world', 'Hello World'], - ['hello world', 'Hello World'], - ['HEllO worLD', 'Hello World'], - ['a991,,:A froG FAMILY', 'A991,,:a Frog Family'] + ['119', ''], + ['1111999900', '111-199-9900'], + ['111199-9900', '111-199-9900'], + ['111-199-9900', '111-199-9900'], + ['01111999900', '0-111-199-9900'], + ['0-111-199-9900', '0-111-199-9900'] ])( - 'toTitleCase given "%p" returns "%p"', + 'getDisplayPhoneNumber', (input, expected) => { // Arrange const { wrapper } = getMountedComponent(); // Act - const result = wrapper.vm.toTitleCase(input); + const result = wrapper.vm.getDisplayPhoneNumber(input); + + // Assert + expect(result).toEqual(expected); + } + ); + test.each([ + [undefined, ''], + [null, ''], + ['', ''], + ['hello world', 'Hello World'], + ['hello world', 'Hello World'], + ['HEllO worLD', 'Hello World'], + ['a991,,:A froG FAMILY', 'A991,,:a Frog Family'] + ])( + 'getTitleCase given "%p" returns "%p"', + (input, expected) => { + // Arrange + const { wrapper } = getMountedComponent(); + + // Act + const result = wrapper.vm.getTitleCase(input); // Assert expect(result).toEqual(expected); diff --git a/src/layouts/tpa-search/tpa-search.vue b/src/layouts/tpa-search/tpa-search.vue index f35ee59f..8eb12c90 100644 --- a/src/layouts/tpa-search/tpa-search.vue +++ b/src/layouts/tpa-search/tpa-search.vue @@ -296,7 +296,7 @@ export default { this.providers = providers; }, getProviderAddress(provider) { - const city = this.toTitleCase(provider?.address?.city); + const city = this.getTitleCase(provider?.address?.city); const state = provider?.address?.state ?? ''; const zipCode = provider?.address?.zipCode ?? ''; let addressLine2 = ''; @@ -314,7 +314,7 @@ export default { addressLine2 += zipCode; } - const addressLine1 = this.toTitleCase(provider?.address?.streetAddress); + const addressLine1 = this.getTitleCase(provider?.address?.streetAddress); const joinString = addressLine1.length > 0 && addressLine2.length > 0 ? ', ' : ''; return [addressLine1, addressLine2].join(joinString); }, @@ -369,17 +369,18 @@ export default { getDisplayPhoneNumber(phoneNumber) { let result = ''; if (!phoneNumber) { return result; } - let remainingDigits = phoneNumber; - if (phoneNumber.length === 11) { + let remainingDigits = phoneNumber.match(/\d+/g).join(''); + console.log(remainingDigits); + if (remainingDigits.length === 11) { result += `${remainingDigits[0]}-`; remainingDigits = remainingDigits.substring(1); } - if (phoneNumber.length > 9) { + if (remainingDigits.length === 10) { result += remainingDigits.replace(/^(\d{3})(\d{3})(\d{4})/, '$1-$2-$3'); } return result; }, - toTitleCase(text) { + getTitleCase(text) { if ((text?.length ?? 0) === 0) { return ''; } From db8a34298651fce19d9d893f2f50a2e0426084db Mon Sep 17 00:00:00 2001 From: Michaela Brydon Date: Thu, 30 Nov 2023 13:46:02 -0500 Subject: [PATCH 06/15] Updating get radius by filter tests --- src/layouts/tpa-search/tpa-search.spec.js | 50 ++++++++--------------- src/layouts/tpa-search/tpa-search.vue | 1 - 2 files changed, 18 insertions(+), 33 deletions(-) diff --git a/src/layouts/tpa-search/tpa-search.spec.js b/src/layouts/tpa-search/tpa-search.spec.js index f1f5c412..5545b58b 100644 --- a/src/layouts/tpa-search/tpa-search.spec.js +++ b/src/layouts/tpa-search/tpa-search.spec.js @@ -448,41 +448,27 @@ describe('TPA search page', () => { } ); describe('radiusInMiles', () => { - test('returns 25 when filter is "25 miles"', async () => { - // Arrange - const { wrapper } = getMountedComponent(); - await wrapper.setData({ filter: '25 miles' }); + test.each([ + [15, '15 miles'], + [25, '25 miles'], + [50, '50 miles'], + [100, '100 miles'] + ])( + 'returns %p when filter is "%p"', + async (expectedRadius, filter) => { + // Arrange + const { wrapper } = getMountedComponent(); + await wrapper.setData({ filter }); - // Act - const result = wrapper.vm.radiusInMiles; + // Act + const result = wrapper.vm.radiusInMiles; - // Assert - expect(result).toEqual(25); - }); - test('returns 50 when filter is "50 miles"', async () => { - // Arrange - const { wrapper } = getMountedComponent(); - await wrapper.setData({ filter: '50 miles' }); - - // Act - const result = wrapper.vm.radiusInMiles; - - // Assert - expect(result).toEqual(50); - }); - test('returns 100 when filter is "100 miles"', async () => { - // Arrange - const { wrapper } = getMountedComponent(); - await wrapper.setData({ filter: '100 miles' }); - - // Act - const result = wrapper.vm.radiusInMiles; - - // Assert - expect(result).toEqual(100); - }); + // Assert + expect(result).toEqual(expectedRadius); + } + ); test.each([null, undefined, 'some random string'])( - 'returns 0 when filter is not "25 miles", "50 miles", or "100 miles"', + 'returns 0 when filter is "%p"', async (filter) => { // Arrange const { wrapper } = getMountedComponent(); diff --git a/src/layouts/tpa-search/tpa-search.vue b/src/layouts/tpa-search/tpa-search.vue index 8eb12c90..6d68ea41 100644 --- a/src/layouts/tpa-search/tpa-search.vue +++ b/src/layouts/tpa-search/tpa-search.vue @@ -370,7 +370,6 @@ export default { let result = ''; if (!phoneNumber) { return result; } let remainingDigits = phoneNumber.match(/\d+/g).join(''); - console.log(remainingDigits); if (remainingDigits.length === 11) { result += `${remainingDigits[0]}-`; remainingDigits = remainingDigits.substring(1); From e52046f7ab85d3fd1330d78632be9acc5335b8bb Mon Sep 17 00:00:00 2001 From: Michaela Brydon Date: Thu, 30 Nov 2023 14:11:19 -0500 Subject: [PATCH 07/15] adding reloadingProviders flag toggle to getProviderButtonData --- .../__snapshots__/tpa-search.spec.js.snap | 2 +- src/layouts/tpa-search/tpa-search.spec.js | 28 +++++++++---------- src/layouts/tpa-search/tpa-search.vue | 10 +++---- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/layouts/tpa-search/__snapshots__/tpa-search.spec.js.snap b/src/layouts/tpa-search/__snapshots__/tpa-search.spec.js.snap index 5f9f27f5..b34c010c 100644 --- a/src/layouts/tpa-search/__snapshots__/tpa-search.spec.js.snap +++ b/src/layouts/tpa-search/__snapshots__/tpa-search.spec.js.snap @@ -9,7 +9,7 @@ Object { "filter": "", "mapZipCode": "12663", "providers": Array [], - "reloadProviders": false, + "reloadingProviders": false, "rules": Object { "filter": "option-required", "provider": "option-required", diff --git a/src/layouts/tpa-search/tpa-search.spec.js b/src/layouts/tpa-search/tpa-search.spec.js index 5545b58b..68f6516f 100644 --- a/src/layouts/tpa-search/tpa-search.spec.js +++ b/src/layouts/tpa-search/tpa-search.spec.js @@ -189,10 +189,10 @@ describe('TPA search page', () => { expect(searchRadiusFilter.props().cmsWidgetName).toBe(expectedWidgetName); expect(searchRadiusFilter.props().validationRules).toBe(globalRules.OPTION_REQUIRED); }); - test('providers loader when reloadProviders is true', async () => { + test('providers loader when reloadingProviders is true', async () => { // Arrange const wrapper = shallowMount(tpaSearch, getMountOptions()); - await wrapper.setData({ reloadProviders: true }); + await wrapper.setData({ reloadingProviders: true }); // Act const providersLoader = wrapper.findComponent('#providersLoader'); @@ -200,7 +200,7 @@ describe('TPA search page', () => { // Assert expect(providersLoader.exists()).toBeTruthy(); }); - test('select provider question when reloadProviders are false', async () => { + test('select provider question when reloadingProviders are false', async () => { // Arrange const wrapper = shallowMount(tpaSearch, getMountOptions()); await wrapper.setData({ @@ -216,7 +216,7 @@ describe('TPA search page', () => { zipCode: '99230' } }], - reloadProviders: false + reloadingProviders: false }); const expectedAnswers = [{ buttonLabel: 'Shop Auto Glass', @@ -243,14 +243,14 @@ describe('TPA search page', () => { expect(selectProviderQuestion.props().additionalButtonData).toEqual(expectedAdditionalButtonData); }); test.each([[], null, undefined])( - 'no network providers alert when providers length is 0, undefined, or null and reloadProviders is false', + 'no network providers alert when providers length is 0, undefined, or null and reloadingProviders is false', async (providers) => { // Arrange const initialData = { providers }; const wrapper = shallowMount(tpaSearch, getMountOptions({}, initialData)); - await wrapper.setData({ reloadProviders: false }); + await wrapper.setData({ reloadingProviders: false }); // Act const noNetworkProvidersAlert = wrapper.findComponent('#alertNoNetworkProviders'); @@ -262,10 +262,10 @@ describe('TPA search page', () => { expect(noNetworkProvidersAlert.props().isDismissible).toBeFalsy(); } ); - test('preferred shop not listed link when reloadProviders is false', async () => { + test('preferred shop not listed link when reloadingProviders is false', async () => { // Arrange const wrapper = shallowMount(tpaSearch, getMountOptions()); - await wrapper.setData({ reloadProviders: false }); + await wrapper.setData({ reloadingProviders: false }); // Act const preferredShopNotListedLink = wrapper.findComponent('#preferredShopNotListedLink'); @@ -288,10 +288,10 @@ describe('TPA search page', () => { }); }); describe('should not render', () => { - test('select provider question when reloadProviders is true', async () => { + test('select provider question when reloadingProviders is true', async () => { // Arrange const { wrapper } = getMountedComponent(); - await wrapper.setData({ reloadProviders: true }); + await wrapper.setData({ reloadingProviders: true }); // Act const selectProviderQuestion = wrapper.findComponent('#selectProviderQuestion'); @@ -311,10 +311,10 @@ describe('TPA search page', () => { // Assert expect(noNetworkProvidersAlert.exists()).toBeFalsy(); }); - test('when reloadProviders is true', async () => { + test('when reloadingProviders is true', async () => { // Arrange const wrapper = shallowMount(tpaSearch, getMountOptions()); - await wrapper.setData({ providers: [], reloadProviders: true }); + await wrapper.setData({ providers: [], reloadingProviders: true }); // Act const noNetworkProvidersAlert = wrapper.findComponent('#alertNoNetworkProviders'); @@ -323,10 +323,10 @@ describe('TPA search page', () => { expect(noNetworkProvidersAlert.exists()).toBeFalsy(); }); }); - test('preferred shop not listed link when reloadProviders is true', async () => { + test('preferred shop not listed link when reloadingProviders is true', async () => { // Arrange const { wrapper } = getMountedComponent(); - await wrapper.setData({ reloadProviders: true }); + await wrapper.setData({ reloadingProviders: true }); // Act const preferredShopNotListedLink = wrapper.findComponent('#preferredShopNotListedLink'); diff --git a/src/layouts/tpa-search/tpa-search.vue b/src/layouts/tpa-search/tpa-search.vue index 6d68ea41..77ab0c30 100644 --- a/src/layouts/tpa-search/tpa-search.vue +++ b/src/layouts/tpa-search/tpa-search.vue @@ -59,7 +59,7 @@ disableAutoFill :validationRules="rules.filter" /> { this.providers = providers; }); this.mapZipCode = this.zipCode; - this.reloadProviders = false; } }, providers(newProviders) { @@ -319,7 +317,9 @@ export default { return [addressLine1, addressLine2].join(joinString); }, async getProviderButtonData() { + this.reloadingProviders = true; const getTpaProvidersResult = await useMainStore().getTpaProviders(this.zipCode, this.radiusInMiles); + this.reloadingProviders = false; return getTpaProvidersResult?.data?.shopProviders ?? []; }, doNotSeeMyShopLinkClick() { @@ -329,10 +329,8 @@ export default { ); }, async searchClick() { - this.reloadProviders = true; this.providers = await this.getProviderButtonData(); this.mapZipCode = this.zipCode; - this.reloadProviders = false; }, backButtonAction() { this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); From 9b438991b393b8b40ac673e839b1327acb1c11f8 Mon Sep 17 00:00:00 2001 From: Michaela Brydon Date: Thu, 30 Nov 2023 14:19:59 -0500 Subject: [PATCH 08/15] Fixing bug with single shop selection not being unset --- src/layouts/tpa-search/tpa-search.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/layouts/tpa-search/tpa-search.vue b/src/layouts/tpa-search/tpa-search.vue index 77ab0c30..41d80dc6 100644 --- a/src/layouts/tpa-search/tpa-search.vue +++ b/src/layouts/tpa-search/tpa-search.vue @@ -276,9 +276,9 @@ export default { } }, providers(newProviders) { - if (newProviders?.length === 1 ?? false) { - this.selectedProviderNumber = newProviders[0]?.providerNumber ?? ''; - } + this.selectedProviderNumber = newProviders?.length === 1 ?? false + ? newProviders[0]?.providerNumber ?? '' + : ''; } }, beforeUpdate() { From fff280ceaf9ad64a422f7c97c100ab697e65555b Mon Sep 17 00:00:00 2001 From: Michaela Brydon Date: Thu, 30 Nov 2023 14:45:57 -0500 Subject: [PATCH 09/15] Fixing paste issue --- .../textbox-question/textbox-question.vue | 23 +-- src/layouts/tpa-search/tpa-search.vue | 136 +++++++++--------- 2 files changed, 71 insertions(+), 88 deletions(-) diff --git a/src/digital-components/textbox-question/textbox-question.vue b/src/digital-components/textbox-question/textbox-question.vue index 86bcfeea..7d74278f 100644 --- a/src/digital-components/textbox-question/textbox-question.vue +++ b/src/digital-components/textbox-question/textbox-question.vue @@ -201,27 +201,10 @@ export default { evt.stopPropagation(); evt.preventDefault(); - const input = document.getElementById(evt.srcElement.id); - const originalValue = input.value; - const startPosition = input.selectionStart; - const endPosition = input.selectionEnd; - const selectionLength = endPosition - startPosition; + const data = evt.type === 'paste' ? (evt.clipboardData || window.clipboardData) : evt.dataTransfer; + const value = data.getData('Text')?.trim(); - let data = null; - if (evt.type === 'paste') { - data = evt.clipboardData || window.clipboardData; - } else { - data = evt.dataTransfer; - } - - const textValue = data.getData('Text'); - - // Insert the pasted/dropped string at the index position - const arrOriginalString = originalValue.split(''); - arrOriginalString.splice(startPosition, selectionLength, textValue); - const blendedString = arrOriginalString.join(''); - - this.$emit('update:modelValue', blendedString); + this.$emit('update:modelValue', this.modelValue + value); }, clickedSearch() { if (this.meta.valid) { diff --git a/src/layouts/tpa-search/tpa-search.vue b/src/layouts/tpa-search/tpa-search.vue index 41d80dc6..be446bde 100644 --- a/src/layouts/tpa-search/tpa-search.vue +++ b/src/layouts/tpa-search/tpa-search.vue @@ -31,83 +31,83 @@ :includeSearchIcon="true" :displayQuestionText="false" isRequired + :isDisabled="reloadingProviders" :validationRules="rules.zipCode" @clickEvent="searchClick" />
-
- -
-
-
- - -
-
- - -
-
- -
+ + +
+
+ + +
+
+ + +
+
+
-
- -
+ +
+
From 436c286c62af6164a5beaa60c2147a65cb1f60bf Mon Sep 17 00:00:00 2001 From: Michaela Brydon Date: Thu, 30 Nov 2023 15:19:23 -0500 Subject: [PATCH 10/15] Setting router parameter --- src/layouts/tpa-search/tpa-search.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/layouts/tpa-search/tpa-search.vue b/src/layouts/tpa-search/tpa-search.vue index be446bde..537aa0e4 100644 --- a/src/layouts/tpa-search/tpa-search.vue +++ b/src/layouts/tpa-search/tpa-search.vue @@ -132,6 +132,7 @@ import BaseFormMixin from '@/mixins/base-form-mixin.js'; import globalRules from '@/constants/global-rules.js'; import widgetFields from '@/constants/cms-widget-fields.js'; import { shallowRef } from 'vue'; +import routerParams from '@/router/router-constants/router-params'; const radiusFilterPairs = [ { radius: 15, filter: '15 miles' }, @@ -325,7 +326,10 @@ export default { doNotSeeMyShopLinkClick() { this.$router.navigate( this.navigationScenarios.CLICKED_DO_NOT_SEE_MY_SHOP_LINK, - this.$route + this.$route, + {}, + {}, + { [routerParams.NOT_SEEING_PREFERRED_SHOP]: true } ); }, async searchClick() { From 0c47b89f7834b146a25c04bdb0196e835ec633d0 Mon Sep 17 00:00:00 2001 From: Michaela Brydon Date: Thu, 30 Nov 2023 15:21:48 -0500 Subject: [PATCH 11/15] Setting optional page data default value --- src/router/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/router/index.js b/src/router/index.js index 06c209b1..e9945601 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -186,7 +186,7 @@ router.overrideNavigation = ( isSavingNavigation, optionalQuery = {}, optionalParams = {}, - optionalPageData + optionalPageData = {} ) => { navigate( scenario, From 990935d07ca11ae4e206aac3c35bc1ba7bcd74e9 Mon Sep 17 00:00:00 2001 From: Michaela Brydon Date: Thu, 30 Nov 2023 15:32:14 -0500 Subject: [PATCH 12/15] Fixing test --- src/layouts/tpa-search/tpa-search.spec.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/layouts/tpa-search/tpa-search.spec.js b/src/layouts/tpa-search/tpa-search.spec.js index 68f6516f..85213788 100644 --- a/src/layouts/tpa-search/tpa-search.spec.js +++ b/src/layouts/tpa-search/tpa-search.spec.js @@ -683,7 +683,10 @@ describe('TPA search page', () => { expect(result).toEqual(false); } ); - test.each([[true, true], [false, false]])( + test.each([ + [true, true], + [false, false] + ])( 'returns %p when first instance of multiple matching providerNumbers has isSafeliteShop value %p', async (expectedOutput, isSafeliteShop) => { // Arrange @@ -699,7 +702,8 @@ describe('TPA search page', () => { } ]; const wrapper = shallowMount(tpaSearch, getMountOptions()); - await wrapper.setData({ selectedProviderNumber, providers }); + await wrapper.setData({ providers }); + await wrapper.setData({ selectedProviderNumber }); // Act const result = wrapper.vm.selectedProviderIsSafeliteShop; From 10104b849497e2d96542469b8133035f94ee9842 Mon Sep 17 00:00:00 2001 From: Michaela Brydon Date: Thu, 30 Nov 2023 15:55:56 -0500 Subject: [PATCH 13/15] input id must differ from all other ids --- .../textbox-question/textbox-question.vue | 23 ++++++++++++++++--- src/layouts/tpa-search/tpa-search.vue | 4 ++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/digital-components/textbox-question/textbox-question.vue b/src/digital-components/textbox-question/textbox-question.vue index 7d74278f..86bcfeea 100644 --- a/src/digital-components/textbox-question/textbox-question.vue +++ b/src/digital-components/textbox-question/textbox-question.vue @@ -201,10 +201,27 @@ export default { evt.stopPropagation(); evt.preventDefault(); - const data = evt.type === 'paste' ? (evt.clipboardData || window.clipboardData) : evt.dataTransfer; - const value = data.getData('Text')?.trim(); + const input = document.getElementById(evt.srcElement.id); + const originalValue = input.value; + const startPosition = input.selectionStart; + const endPosition = input.selectionEnd; + const selectionLength = endPosition - startPosition; - this.$emit('update:modelValue', this.modelValue + value); + let data = null; + if (evt.type === 'paste') { + data = evt.clipboardData || window.clipboardData; + } else { + data = evt.dataTransfer; + } + + const textValue = data.getData('Text'); + + // Insert the pasted/dropped string at the index position + const arrOriginalString = originalValue.split(''); + arrOriginalString.splice(startPosition, selectionLength, textValue); + const blendedString = arrOriginalString.join(''); + + this.$emit('update:modelValue', blendedString); }, clickedSearch() { if (this.meta.valid) { diff --git a/src/layouts/tpa-search/tpa-search.vue b/src/layouts/tpa-search/tpa-search.vue index 537aa0e4..65e41ca0 100644 --- a/src/layouts/tpa-search/tpa-search.vue +++ b/src/layouts/tpa-search/tpa-search.vue @@ -26,7 +26,7 @@ Date: Thu, 30 Nov 2023 15:59:11 -0500 Subject: [PATCH 14/15] Fixing bug --- src/layouts/tpa-search/tpa-search.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layouts/tpa-search/tpa-search.spec.js b/src/layouts/tpa-search/tpa-search.spec.js index 85213788..9a6f4734 100644 --- a/src/layouts/tpa-search/tpa-search.spec.js +++ b/src/layouts/tpa-search/tpa-search.spec.js @@ -132,7 +132,7 @@ describe('TPA search page', () => { // Assert expect(searchQuestionField.exists()).toBeTruthy(); - expect(searchQuestionField.props().inputId).toBe('tpaSearchQuestionField'); + expect(searchQuestionField.props().inputId).toBe('tpaSearchQuestionFieldInput'); expect(searchQuestionField.props().isRequired).toBeTruthy(); expect(searchQuestionField.props().cmsWidgetName).toBe(expectedWidgetName); expect(searchQuestionField.props().includeSearchIcon).toBeTruthy(); From e58601bab4b6a1af1eb0e857bac9dbec21233afb Mon Sep 17 00:00:00 2001 From: Michaela Brydon Date: Mon, 4 Dec 2023 20:54:28 -0500 Subject: [PATCH 15/15] Moving general methods to shared file --- src/helpers/text-helper.js | 23 +++++++++++- src/helpers/text-helper.spec.js | 42 ++++++++++++++++++++++ src/layouts/tpa-search/tpa-search.spec.js | 44 ----------------------- src/layouts/tpa-search/tpa-search.vue | 34 ++++-------------- 4 files changed, 70 insertions(+), 73 deletions(-) create mode 100644 src/helpers/text-helper.spec.js diff --git a/src/helpers/text-helper.js b/src/helpers/text-helper.js index d08e0c04..41e19a66 100644 --- a/src/helpers/text-helper.js +++ b/src/helpers/text-helper.js @@ -17,9 +17,30 @@ export function stripRteStyle(stringWithStyleTag) { * @returns {string} */ export function toTitleCase(text) { - const temp = text.toLowerCase().split(' '); + const temp = text?.toLowerCase()?.split(' ') ?? []; for (let i = 0; i < temp.length; i++) { temp[i] = temp[i].charAt(0).toUpperCase() + temp[i].slice(1); } return temp.join(' '); } + +/** + * @function toDisplayPhoneNumber + * @summary If 10 or 11 digits are in phoneNumber, then the expected number including dashes will be returned + * in either d-ddd-ddd-dddd or ddd-ddd-dddd format. Otherwise, an empty string will be returned. + * @param {string} phoneNumber + * @returns {string} + */ +export function toDisplayPhoneNumber(phoneNumber) { + let result = ''; + if (!phoneNumber) { return result; } + let remainingDigits = phoneNumber.match(/\d+/g).join(''); + if (remainingDigits.length === 11) { + result += `${remainingDigits[0]}-`; + remainingDigits = remainingDigits.substring(1); + } + if (remainingDigits.length === 10) { + result += remainingDigits.replace(/^(\d{3})(\d{3})(\d{4})/, '$1-$2-$3'); + } + return result; +} diff --git a/src/helpers/text-helper.spec.js b/src/helpers/text-helper.spec.js new file mode 100644 index 00000000..1b2daf64 --- /dev/null +++ b/src/helpers/text-helper.spec.js @@ -0,0 +1,42 @@ +import { toTitleCase, toDisplayPhoneNumber } from '@/helpers/text-helper.js'; + +describe('text-helper', () => { + test.each([ + [undefined, ''], + [null, ''], + ['', ''], + ['hello world', 'Hello World'], + ['hello world', 'Hello World'], + ['HEllO worLD', 'Hello World'], + ['a991,,:A froG FAMILY', 'A991,,:a Frog Family'] + ])( + 'toTitleCase given "%p" returns "%p"', + (input, expected) => { + // Act + const result = toTitleCase(input); + + // Assert + expect(result).toEqual(expected); + } + ); + test.each([ + [undefined, ''], + [null, ''], + ['', ''], + ['119', ''], + ['1111999900', '111-199-9900'], + ['111199-9900', '111-199-9900'], + ['111-199-9900', '111-199-9900'], + ['01111999900', '0-111-199-9900'], + ['0-111-199-9900', '0-111-199-9900'] + ])( + 'getDisplayPhoneNumber', + (input, expected) => { + // Act + const result = toDisplayPhoneNumber(input); + + // Assert + expect(result).toEqual(expected); + } + ); +}); diff --git a/src/layouts/tpa-search/tpa-search.spec.js b/src/layouts/tpa-search/tpa-search.spec.js index 9a6f4734..99754c6b 100644 --- a/src/layouts/tpa-search/tpa-search.spec.js +++ b/src/layouts/tpa-search/tpa-search.spec.js @@ -1183,50 +1183,6 @@ describe('TPA search page', () => { }); }); }); - test.each([ - [undefined, ''], - [null, ''], - ['', ''], - ['119', ''], - ['1111999900', '111-199-9900'], - ['111199-9900', '111-199-9900'], - ['111-199-9900', '111-199-9900'], - ['01111999900', '0-111-199-9900'], - ['0-111-199-9900', '0-111-199-9900'] - ])( - 'getDisplayPhoneNumber', - (input, expected) => { - // Arrange - const { wrapper } = getMountedComponent(); - - // Act - const result = wrapper.vm.getDisplayPhoneNumber(input); - - // Assert - expect(result).toEqual(expected); - } - ); - test.each([ - [undefined, ''], - [null, ''], - ['', ''], - ['hello world', 'Hello World'], - ['hello world', 'Hello World'], - ['HEllO worLD', 'Hello World'], - ['a991,,:A froG FAMILY', 'A991,,:a Frog Family'] - ])( - 'getTitleCase given "%p" returns "%p"', - (input, expected) => { - // Arrange - const { wrapper } = getMountedComponent(); - - // Act - const result = wrapper.vm.getTitleCase(input); - - // Assert - expect(result).toEqual(expected); - } - ); }); describe('before route enter', () => { test('when providers exist at 15 mile radius, filter is set to "15 miles" and providers set to expected', async () => { diff --git a/src/layouts/tpa-search/tpa-search.vue b/src/layouts/tpa-search/tpa-search.vue index 65e41ca0..8ec7742e 100644 --- a/src/layouts/tpa-search/tpa-search.vue +++ b/src/layouts/tpa-search/tpa-search.vue @@ -133,6 +133,7 @@ import globalRules from '@/constants/global-rules.js'; import widgetFields from '@/constants/cms-widget-fields.js'; import { shallowRef } from 'vue'; import routerParams from '@/router/router-constants/router-params'; +import { toTitleCase, toDisplayPhoneNumber } from '@/helpers/text-helper.js'; const radiusFilterPairs = [ { radius: 15, filter: '15 miles' }, @@ -295,7 +296,7 @@ export default { this.providers = providers; }, getProviderAddress(provider) { - const city = this.getTitleCase(provider?.address?.city); + const city = toTitleCase(provider?.address?.city); const state = provider?.address?.state ?? ''; const zipCode = provider?.address?.zipCode ?? ''; let addressLine2 = ''; @@ -313,7 +314,7 @@ export default { addressLine2 += zipCode; } - const addressLine1 = this.getTitleCase(provider?.address?.streetAddress); + const addressLine1 = this.toTitleCase(provider?.address?.streetAddress); const joinString = addressLine1.length > 0 && addressLine2.length > 0 ? ', ' : ''; return [addressLine1, addressLine2].join(joinString); }, @@ -354,7 +355,7 @@ export default { } }, getShopButtonDataFromProvider(provider) { - const cellNumber = this.getDisplayPhoneNumber(provider?.phoneNumber); + const cellNumber = this.toDisplayPhoneNumber(provider?.phoneNumber); const distance = provider?.distanceInMiles !== null && !Number.isNaN(parseFloat(provider?.distanceInMiles)) ? +provider.distanceInMiles.toFixed(1) : null; @@ -368,31 +369,8 @@ export default { value: provider?.providerNumber ?? '' }; }, - getDisplayPhoneNumber(phoneNumber) { - let result = ''; - if (!phoneNumber) { return result; } - let remainingDigits = phoneNumber.match(/\d+/g).join(''); - if (remainingDigits.length === 11) { - result += `${remainingDigits[0]}-`; - remainingDigits = remainingDigits.substring(1); - } - if (remainingDigits.length === 10) { - result += remainingDigits.replace(/^(\d{3})(\d{3})(\d{4})/, '$1-$2-$3'); - } - return result; - }, - getTitleCase(text) { - if ((text?.length ?? 0) === 0) { - return ''; - } - const wordList = text.split(' '); - const titleCaseWordList = wordList.map((word) => { - const first = word[0].toUpperCase(); - const rest = word.substring(1).toLowerCase(); - return first + rest; - }); - return titleCaseWordList.join(' '); - } + toDisplayPhoneNumber, + toTitleCase } };