Merge branch 'develop' into feature/SSR-1023
This commit is contained in:
commit
a0e60c1de2
6 changed files with 398 additions and 390 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
42
src/helpers/text-helper.spec.js
Normal file
42
src/helpers/text-helper.spec.js
Normal file
|
|
@ -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);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
@ -5,25 +5,11 @@ 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,
|
||||
"reloadingProviders": false,
|
||||
"rules": Object {
|
||||
"filter": "option-required",
|
||||
"provider": "option-required",
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
@ -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 reloadingProviders is true', async () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||
await wrapper.setData({ initialLoading: false, reloadProviders: true });
|
||||
await wrapper.setData({ reloadingProviders: 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 reloadingProviders are false', async () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||
await wrapper.setData({
|
||||
|
|
@ -229,8 +216,7 @@ describe('TPA search page', () => {
|
|||
zipCode: '99230'
|
||||
}
|
||||
}],
|
||||
initialLoading: false,
|
||||
reloadProviders: false
|
||||
reloadingProviders: false
|
||||
});
|
||||
const expectedAnswers = [{
|
||||
buttonLabel: 'Shop Auto Glass',
|
||||
|
|
@ -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 reloadingProviders is false',
|
||||
async (providers) => {
|
||||
// Arrange
|
||||
const initialData = {
|
||||
providers
|
||||
};
|
||||
const wrapper = shallowMount(tpaSearch, getMountOptions({}, initialData));
|
||||
await wrapper.setData({
|
||||
initialLoading: false,
|
||||
reloadProviders: false
|
||||
});
|
||||
await wrapper.setData({ reloadingProviders: 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 reloadingProviders is false', async () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||
await wrapper.setData({
|
||||
initialLoading: false,
|
||||
reloadProviders: false
|
||||
});
|
||||
await wrapper.setData({ reloadingProviders: 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 reloadingProviders is true', async () => {
|
||||
// Arrange
|
||||
const { wrapper } = getMountedComponent();
|
||||
await wrapper.setData({ initialLoading: true });
|
||||
await wrapper.setData({ reloadingProviders: 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,21 +311,10 @@ describe('TPA search page', () => {
|
|||
// Assert
|
||||
expect(noNetworkProvidersAlert.exists()).toBeFalsy();
|
||||
});
|
||||
test('when initialLoading is true', async () => {
|
||||
test('when reloadingProviders 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());
|
||||
await wrapper.setData({ providers: [], reloadProviders: true });
|
||||
await wrapper.setData({ providers: [], reloadingProviders: true });
|
||||
|
||||
// Act
|
||||
const noNetworkProvidersAlert = wrapper.findComponent('#alertNoNetworkProviders');
|
||||
|
|
@ -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 reloadingProviders is true', async () => {
|
||||
// Arrange
|
||||
const { wrapper } = getMountedComponent();
|
||||
await wrapper.setData({ reloadingProviders: 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', () => {
|
||||
|
|
@ -538,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();
|
||||
|
|
@ -787,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
|
||||
|
|
@ -803,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;
|
||||
|
|
@ -841,9 +741,10 @@ describe('TPA search page', () => {
|
|||
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 +756,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 +842,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',
|
||||
|
|
@ -1240,6 +1185,32 @@ describe('TPA search page', () => {
|
|||
});
|
||||
});
|
||||
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 +1235,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 +1261,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 +1289,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 +1316,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);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -26,95 +26,88 @@
|
|||
<textboxQuestion
|
||||
id="tpaSearchQuestionField"
|
||||
v-model="zipCode"
|
||||
inputId="tpaSearchQuestionField"
|
||||
inputId="tpaSearchQuestionFieldInput"
|
||||
:cmsWidgetName="widget.tpaSearchQuestion"
|
||||
:includeSearchIcon="true"
|
||||
:displayQuestionText="false"
|
||||
isRequired
|
||||
:isDisabled="reloadingProviders"
|
||||
:validationRules="rules.zipCode"
|
||||
@clickEvent="searchClick" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
<loader
|
||||
v-if="initialLoading"
|
||||
id="mapLoader"
|
||||
loaderPosition="center"
|
||||
loaderColor="blue"
|
||||
:width="4"
|
||||
:height="4" />
|
||||
<div v-else>
|
||||
<googleMap
|
||||
id="map"
|
||||
class="mb-4"
|
||||
:addresses="providerAddresses"
|
||||
:zipCode="mapZipCode"></googleMap>
|
||||
<Form
|
||||
id="providerSelectionForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid pb-2">
|
||||
<div class="mx-5">
|
||||
<dropdownQuestion
|
||||
id="searchRadiusFilter"
|
||||
v-model="filter"
|
||||
:cmsWidgetName="widget.filterByQuestion"
|
||||
inputId="filterByQuestionField"
|
||||
:options="filterOptions"
|
||||
disableAutoFill
|
||||
:validationRules="rules.filter" />
|
||||
<loader
|
||||
v-if="reloadProviders"
|
||||
id="providersLoader"
|
||||
loaderPosition="center"
|
||||
loaderColor="blue"
|
||||
:width="4"
|
||||
:height="4"
|
||||
class="my-4" />
|
||||
<div v-else>
|
||||
<div class="my-4">
|
||||
<buttonQuestion
|
||||
id="selectProviderQuestion"
|
||||
v-model="selectedProviderNumber"
|
||||
buttonTypeString="shopListButton"
|
||||
:buttonTypeObject="shopListButton"
|
||||
class="radioQuestion"
|
||||
:answers="providerButtonData"
|
||||
groupName="chooseShop"
|
||||
textPosition="text-start"
|
||||
isRequired
|
||||
:validationRules="rules.provider"
|
||||
:additionalButtonData="additionalButtonData" />
|
||||
<alert
|
||||
v-if="providers?.length === 0 ?? true"
|
||||
id="alertNoNetworkProviders"
|
||||
:cmsWidgetName="widget.noNetworkShopsAlert"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false"
|
||||
:manualHeadline="noNetworkShopsAlertHeaderText" />
|
||||
</div>
|
||||
<div
|
||||
class="text-center">
|
||||
<textLink
|
||||
id="preferredShopNotListedLink"
|
||||
linkType="navigation"
|
||||
href="#!"
|
||||
:text="shopNotListedModalLink"
|
||||
@clickEvent="doNotSeeMyShopLinkClick" />
|
||||
</div>
|
||||
<googleMap
|
||||
id="map"
|
||||
class="mb-4"
|
||||
:addresses="providerAddresses"
|
||||
:zipCode="mapZipCode"></googleMap>
|
||||
<Form
|
||||
id="providerSelectionForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid pb-2">
|
||||
<div class="mx-5">
|
||||
<dropdownQuestion
|
||||
id="searchRadiusFilter"
|
||||
v-model="filter"
|
||||
:cmsWidgetName="widget.filterByQuestion"
|
||||
inputId="searchRadiusFilterInput"
|
||||
:options="filterOptions"
|
||||
disableAutoFill
|
||||
:isDisabled="reloadingProviders"
|
||||
:validationRules="rules.filter" />
|
||||
<loader
|
||||
v-if="reloadingProviders"
|
||||
id="providersLoader"
|
||||
loaderPosition="center"
|
||||
loaderColor="blue"
|
||||
:width="2"
|
||||
:height="2"
|
||||
class="my-4" />
|
||||
<div v-else>
|
||||
<div class="my-4">
|
||||
<buttonQuestion
|
||||
id="selectProviderQuestion"
|
||||
v-model="selectedProviderNumber"
|
||||
buttonTypeString="shopListButton"
|
||||
:buttonTypeObject="shopListButton"
|
||||
class="radioQuestion"
|
||||
:answers="providerButtonData"
|
||||
groupName="chooseShop"
|
||||
textPosition="text-start"
|
||||
isRequired
|
||||
:validationRules="rules.provider"
|
||||
:additionalButtonData="additionalButtonData" />
|
||||
<alert
|
||||
v-if="providers?.length === 0 ?? true"
|
||||
id="alertNoNetworkProviders"
|
||||
:cmsWidgetName="widget.noNetworkShopsAlert"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false"
|
||||
:manualHeadline="noNetworkShopsAlertHeaderText" />
|
||||
</div>
|
||||
<div
|
||||
class="text-center">
|
||||
<textLink
|
||||
id="preferredShopNotListedLink"
|
||||
linkType="navigation"
|
||||
href="#!"
|
||||
:text="shopNotListedModalLink"
|
||||
@clickEvent="doNotSeeMyShopLinkClick" />
|
||||
</div>
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
:cmsWidgetName="widget.siteFooter"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@backClicked="backButtonAction" />
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
:cmsWidgetName="widget.siteFooter"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@backClicked="backButtonAction" />
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -134,12 +127,40 @@ 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';
|
||||
import routerParams from '@/router/router-constants/router-params';
|
||||
import { toTitleCase, toDisplayPhoneNumber } from '@/helpers/text-helper.js';
|
||||
|
||||
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 < radiusFilterPairs.length) {
|
||||
const pair = radiusFilterPairs[pairIndex];
|
||||
const { radius } = pair;
|
||||
filter = pair.filter;
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const result = await useMainStore().getTpaProviders(zipCode, radius);
|
||||
providers = result?.data?.shopProviders ?? [];
|
||||
|
||||
pairIndex += 1;
|
||||
}
|
||||
|
||||
return { filter, providers };
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'tpa-search',
|
||||
|
|
@ -158,30 +179,25 @@ 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,
|
||||
reloadingProviders: false,
|
||||
additionalButtonData: {
|
||||
displayAvailabilityIndicators: false
|
||||
},
|
||||
|
|
@ -199,21 +215,7 @@ export default {
|
|||
filter: globalRules.OPTION_REQUIRED, // TODO do we even need this?
|
||||
provider: globalRules.OPTION_REQUIRED
|
||||
},
|
||||
shopListButton: shallowRef(shopListButton),
|
||||
radiusFilterPairs: [
|
||||
{
|
||||
radius: 25,
|
||||
filter: '25 miles'
|
||||
},
|
||||
{
|
||||
radius: 50,
|
||||
filter: '50 miles'
|
||||
},
|
||||
{
|
||||
radius: 100,
|
||||
filter: '100 miles'
|
||||
}
|
||||
]
|
||||
shopListButton: shallowRef(shopListButton)
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -247,7 +249,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() {
|
||||
|
|
@ -268,122 +270,108 @@ export default {
|
|||
},
|
||||
watch: {
|
||||
async filter() {
|
||||
if (!this.initialLoading) {
|
||||
this.reloadProviders = true;
|
||||
if (this.dataLoaded) {
|
||||
await this.getProviderButtonData().then((providers) => {
|
||||
this.providers = providers;
|
||||
});
|
||||
this.mapZipCode = this.zipCode;
|
||||
this.reloadProviders = false;
|
||||
} else {
|
||||
this.initialLoading = false;
|
||||
}
|
||||
},
|
||||
async providers(newProviders) {
|
||||
if (newProviders?.length === 1 ?? false) {
|
||||
this.selectedProviderNumber = newProviders[0]?.providerNumber ?? '';
|
||||
}
|
||||
providers(newProviders) {
|
||||
this.selectedProviderNumber = newProviders?.length === 1 ?? false
|
||||
? newProviders[0]?.providerNumber ?? ''
|
||||
: '';
|
||||
}
|
||||
},
|
||||
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 { 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];
|
||||
const { radius } = pair;
|
||||
filter = pair.filter;
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const result = await useMainStore().getTpaProviders(zipCode, radius);
|
||||
providers = result?.data?.shopProviders ?? [];
|
||||
|
||||
pairIndex += 1;
|
||||
}
|
||||
|
||||
this.filter = filter;
|
||||
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 = 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)}<br>${cellNumber ?? ''}`,
|
||||
value: provider?.providerNumber ?? ''
|
||||
};
|
||||
}
|
||||
beforeUpdate() {
|
||||
if (!this.dataLoaded) {
|
||||
this.dataLoaded = true;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setFilter(filter) {
|
||||
this.filter = filter;
|
||||
},
|
||||
setProviders(providers) {
|
||||
this.providers = providers;
|
||||
},
|
||||
getProviderAddress(provider) {
|
||||
const city = toTitleCase(provider?.address?.city);
|
||||
const state = provider?.address?.state ?? '';
|
||||
const zipCode = provider?.address?.zipCode ?? '';
|
||||
let addressLine2 = '';
|
||||
if (city) {
|
||||
addressLine2 += city;
|
||||
if (state || zipCode) {
|
||||
addressLine2 += state ? ', ' : ' ';
|
||||
}
|
||||
}
|
||||
if (state) {
|
||||
addressLine2 += state;
|
||||
addressLine2 += zipCode ? ' ' : '';
|
||||
}
|
||||
if (zipCode) {
|
||||
addressLine2 += zipCode;
|
||||
}
|
||||
|
||||
const addressLine1 = this.toTitleCase(provider?.address?.streetAddress);
|
||||
const joinString = addressLine1.length > 0 && addressLine2.length > 0 ? ', ' : '';
|
||||
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() {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_DO_NOT_SEE_MY_SHOP_LINK,
|
||||
this.$route,
|
||||
{},
|
||||
{},
|
||||
{ [routerParams.NOT_SEEING_PREFERRED_SHOP]: true }
|
||||
);
|
||||
},
|
||||
async searchClick() {
|
||||
this.providers = await this.getProviderButtonData();
|
||||
this.mapZipCode = this.zipCode;
|
||||
},
|
||||
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.toDisplayPhoneNumber(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)}<br>${cellNumber ?? ''}`,
|
||||
value: provider?.providerNumber ?? ''
|
||||
};
|
||||
},
|
||||
toDisplayPhoneNumber,
|
||||
toTitleCase
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ router.overrideNavigation = (
|
|||
isSavingNavigation,
|
||||
optionalQuery = {},
|
||||
optionalParams = {},
|
||||
optionalPageData
|
||||
optionalPageData = {}
|
||||
) => {
|
||||
navigate(
|
||||
scenario,
|
||||
|
|
|
|||
Loading…
Reference in a new issue