Merge pull request #508 from Safelite/feature/digital/SSR-755
Feature/digital/ssr 755
This commit is contained in:
commit
e7a8f55f38
11 changed files with 839 additions and 306 deletions
|
|
@ -3,6 +3,22 @@
|
||||||
exports[`Google Map should render expected initial data 1`] = `
|
exports[`Google Map should render expected initial data 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"country": "USA",
|
"country": "USA",
|
||||||
"geocoder": null,
|
"geocoder": Object {
|
||||||
|
"geocode": [MockFunction] {
|
||||||
|
"calls": Array [
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"address": " USA",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
"results": Array [
|
||||||
|
Object {
|
||||||
|
"type": "return",
|
||||||
|
"value": undefined,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
import { shallowMount } from '@vue/test-utils';
|
import { shallowMount } from '@vue/test-utils';
|
||||||
|
import { createTestingPinia } from '@pinia/testing';
|
||||||
import googleMap from '@/iss-components/google-map/google-map.vue';
|
import googleMap from '@/iss-components/google-map/google-map.vue';
|
||||||
|
|
||||||
|
// Supporting Files
|
||||||
|
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||||
|
import { useMainStore } from '@/store';
|
||||||
|
|
||||||
const mockFitBounds = jest.fn();
|
const mockFitBounds = jest.fn();
|
||||||
const mockMapInstance = {
|
const mockMapInstance = {
|
||||||
fitBounds: mockFitBounds
|
fitBounds: mockFitBounds
|
||||||
|
|
@ -8,10 +13,13 @@ const mockMapInstance = {
|
||||||
const mockMap = jest.fn(() => mockMapInstance);
|
const mockMap = jest.fn(() => mockMapInstance);
|
||||||
|
|
||||||
const mockGeocode = jest.fn();
|
const mockGeocode = jest.fn();
|
||||||
const mockGeocoderInstance = {
|
const mockGeocoderInstance1 = {
|
||||||
geocode: mockGeocode
|
geocode: mockGeocode
|
||||||
};
|
};
|
||||||
const mockGeocoder = jest.fn(() => (mockGeocoderInstance));
|
const mockGeocoderInstance2 = {
|
||||||
|
geocode: mockGeocode
|
||||||
|
};
|
||||||
|
const mockGeocoder = jest.fn(() => (mockGeocoderInstance1));
|
||||||
|
|
||||||
const mockAdvancedMarkerElement = jest.fn();
|
const mockAdvancedMarkerElement = jest.fn();
|
||||||
|
|
||||||
|
|
@ -47,20 +55,52 @@ beforeEach(() => {
|
||||||
setupGoogleMock();
|
setupGoogleMock();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getMountedComponent(mainInitialState = {}, initialData = {}, propsData = {}) {
|
||||||
|
const mountOptions = getMountOptions({
|
||||||
|
router: {
|
||||||
|
navigate: jest.fn()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const testingPinia = createTestingPinia({
|
||||||
|
initialState: {
|
||||||
|
main: mainInitialState
|
||||||
|
}
|
||||||
|
});
|
||||||
|
useMainStore(testingPinia);
|
||||||
|
|
||||||
|
mountOptions.global.plugins = [testingPinia];
|
||||||
|
mountOptions.data = () => (initialData);
|
||||||
|
mountOptions.propsData = propsData;
|
||||||
|
|
||||||
|
const wrapper = shallowMount(googleMap, mountOptions);
|
||||||
|
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {});
|
||||||
|
wrapper.vm.setCmsContent = jest.fn();
|
||||||
|
return { wrapper };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function awaitingSetupTicks(wrapper) {
|
||||||
|
for (let i = 0; i < 11; i++) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
describe('Google Map', () => {
|
describe('Google Map', () => {
|
||||||
describe('should render', () => {
|
describe('should render', () => {
|
||||||
test('expected initial data', async () => {
|
test('expected initial data', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(googleMap, {});
|
const wrapper = shallowMount(googleMap, {});
|
||||||
await wrapper.vm.$nextTick();
|
await awaitingSetupTicks(wrapper);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.$data).toMatchSnapshot();
|
expect(wrapper.vm.$data).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('map', () => {
|
test('map', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const mapReference = '#map';
|
const mapReference = '#map';
|
||||||
const wrapper = shallowMount(googleMap, {});
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const map = wrapper.find(mapReference);
|
const map = wrapper.find(mapReference);
|
||||||
|
|
@ -78,8 +118,8 @@ describe('Google Map', () => {
|
||||||
'given that zipcode set to "%p", computed zipCodeAddress should return "%p"',
|
'given that zipcode set to "%p", computed zipCodeAddress should return "%p"',
|
||||||
async (zipCode, expected) => {
|
async (zipCode, expected) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(googleMap, {});
|
const { wrapper } = getMountedComponent({}, {}, { zipCode });
|
||||||
await wrapper.setData({ zipCode });
|
await awaitingSetupTicks(wrapper);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = wrapper.vm.zipCodeAddress;
|
const result = wrapper.vm.zipCodeAddress;
|
||||||
|
|
@ -88,11 +128,78 @@ describe('Google Map', () => {
|
||||||
expect(result).toBe(expected);
|
expect(result).toBe(expected);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
test('before mount addresses creates map with expected markers', async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockGetCenter = jest.fn();
|
||||||
|
const mockNorthEast = jest.fn();
|
||||||
|
const mockSouthWest = jest.fn();
|
||||||
|
const zipCodeGeocodeResult = {
|
||||||
|
results: [
|
||||||
|
{
|
||||||
|
geometry: {
|
||||||
|
bounds:
|
||||||
|
{
|
||||||
|
getCenter: mockGetCenter,
|
||||||
|
getNorthEast: mockNorthEast,
|
||||||
|
getSouthWest: mockSouthWest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const zipCode = '00882';
|
||||||
|
const [address1, address2, position1, position2] = ['a1', 'a2', 'p1', 'p2'];
|
||||||
|
const addresses = [address1, address2];
|
||||||
|
mockGeocode.mockImplementation((obj) => {
|
||||||
|
let result = {};
|
||||||
|
if (obj.address.includes(zipCode)) {
|
||||||
|
result = zipCodeGeocodeResult;
|
||||||
|
} else if (obj.address === address1) {
|
||||||
|
result = {
|
||||||
|
results: [
|
||||||
|
{ geometry: { location: position1 } }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
} else if (obj.address === address2) {
|
||||||
|
result = {
|
||||||
|
results: [
|
||||||
|
{ geometry: { location: position2 } }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return Promise.resolve(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
const propsData = { addresses, zipCode };
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, propsData);
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mockMap).toBeCalledTimes(1);
|
||||||
|
expect(mockAdvancedMarkerElement).toBeCalledTimes(2);
|
||||||
|
expect(mockAdvancedMarkerElement).toBeCalledWith(expect.objectContaining({
|
||||||
|
map: expect.anything(),
|
||||||
|
position: position1
|
||||||
|
}));
|
||||||
|
expect(mockAdvancedMarkerElement).toBeCalledWith(expect.objectContaining({
|
||||||
|
map: expect.anything(),
|
||||||
|
position: position2
|
||||||
|
}));
|
||||||
|
expect(mockGeocoder).toBeCalledTimes(1);
|
||||||
|
|
||||||
|
expect(mockExtend).toBeCalledTimes(4);
|
||||||
|
expect(mockFitBounds).toBeCalledTimes(1);
|
||||||
|
|
||||||
|
expect(mockGetCenter).toBeCalledTimes(1);
|
||||||
|
expect(mockNorthEast).toBeCalledTimes(1);
|
||||||
|
expect(mockSouthWest).toBeCalledTimes(1);
|
||||||
|
});
|
||||||
test('watch addresses creates map with expected markers', async () => {
|
test('watch addresses creates map with expected markers', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(googleMap, {});
|
|
||||||
const zipCode = '00882';
|
const zipCode = '00882';
|
||||||
await wrapper.setData({ zipCode });
|
const { wrapper } = getMountedComponent({}, { zipCode });
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
|
|
||||||
const mockGetCenter = jest.fn();
|
const mockGetCenter = jest.fn();
|
||||||
const mockNorthEast = jest.fn();
|
const mockNorthEast = jest.fn();
|
||||||
|
|
@ -135,14 +242,10 @@ describe('Google Map', () => {
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await wrapper.vm.$options.watch.addresses.call(wrapper.vm, newAddresses);
|
await wrapper.vm.$options.watch.addresses.call(wrapper.vm, newAddresses);
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
for (let i = 0; i < 11; i++) {
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
await wrapper.vm.$nextTick();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(mockMap).toBeCalledTimes(1);
|
expect(mockMap).toBeCalledTimes(2);
|
||||||
expect(mockAdvancedMarkerElement).toBeCalledTimes(2);
|
expect(mockAdvancedMarkerElement).toBeCalledTimes(2);
|
||||||
expect(mockAdvancedMarkerElement).toBeCalledWith(expect.objectContaining({
|
expect(mockAdvancedMarkerElement).toBeCalledWith(expect.objectContaining({
|
||||||
map: expect.anything(),
|
map: expect.anything(),
|
||||||
|
|
@ -154,8 +257,8 @@ describe('Google Map', () => {
|
||||||
}));
|
}));
|
||||||
expect(mockGeocoder).toBeCalledTimes(1);
|
expect(mockGeocoder).toBeCalledTimes(1);
|
||||||
|
|
||||||
expect(mockExtend).toBeCalledTimes(4);
|
expect(mockExtend).toBeCalledTimes(6);
|
||||||
expect(mockFitBounds).toBeCalledTimes(1);
|
expect(mockFitBounds).toBeCalledTimes(2);
|
||||||
|
|
||||||
expect(mockGetCenter).toBeCalledTimes(1);
|
expect(mockGetCenter).toBeCalledTimes(1);
|
||||||
expect(mockNorthEast).toBeCalledTimes(1);
|
expect(mockNorthEast).toBeCalledTimes(1);
|
||||||
|
|
@ -165,6 +268,7 @@ describe('Google Map', () => {
|
||||||
test('getMap calls map constructor with expected parameters', async () => {
|
test('getMap calls map constructor with expected parameters', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(googleMap, {});
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
const center = { lat: 90, lng: -5 };
|
const center = { lat: 90, lng: -5 };
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -185,32 +289,35 @@ describe('Google Map', () => {
|
||||||
[['loc1', 'loc1', 'loc1', 'loc1'], 4]
|
[['loc1', 'loc1', 'loc1', 'loc1'], 4]
|
||||||
])(
|
])(
|
||||||
'given parameter %p, getBounds calls extend %p time(s)',
|
'given parameter %p, getBounds calls extend %p time(s)',
|
||||||
(locations, numberOfExtendCalls) => {
|
async (locations, numberOfExtendCallsPostMount) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(googleMap, {});
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
|
const numberOfExtendCallsDuringMount = 2;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = wrapper.vm.getBounds(locations);
|
const result = wrapper.vm.getBounds(locations);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(mockExtend).toHaveBeenCalledTimes(numberOfExtendCalls);
|
expect(mockExtend).toHaveBeenCalledTimes(
|
||||||
|
numberOfExtendCallsDuringMount + numberOfExtendCallsPostMount);
|
||||||
expect(result).toBe(mockLatLngBound);
|
expect(result).toBe(mockLatLngBound);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
test.each([
|
test.each([
|
||||||
[1, null, mockGeocoderInstance],
|
[1, null, mockGeocoderInstance1],
|
||||||
[1, undefined, mockGeocoderInstance],
|
[1, undefined, mockGeocoderInstance1],
|
||||||
[0, {}, {}],
|
[0, mockGeocoderInstance2, mockGeocoderInstance2]
|
||||||
[0, { value: 'any value' }, { value: 'any value' }]
|
|
||||||
])(
|
])(
|
||||||
'setGeocoder calls Geocoder constructor %p time(s) when original geocoder %p and geocoder set to %p',
|
'setGeocoder calls Geocoder constructor %p time(s) when original geocoder %p and geocoder set to %p',
|
||||||
async (numberOfCalls, originalGeocoder, newGeocoder) => {
|
async (numberOfCalls, originalGeocoder, newGeocoder) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(googleMap, {});
|
const { wrapper } = getMountedComponent({}, { geocoder: originalGeocoder }, {});
|
||||||
await wrapper.setData({ geocoder: originalGeocoder });
|
await awaitingSetupTicks(wrapper);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await wrapper.vm.setGeocoder();
|
await wrapper.vm.setGeocoder();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(mockGeocoder).toHaveBeenCalledTimes(numberOfCalls);
|
expect(mockGeocoder).toHaveBeenCalledTimes(numberOfCalls);
|
||||||
|
|
@ -228,6 +335,7 @@ describe('Google Map', () => {
|
||||||
async (positions, numberOfCalls) => {
|
async (positions, numberOfCalls) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(googleMap, {});
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
const map = jest.fn();
|
const map = jest.fn();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -246,21 +354,26 @@ describe('Google Map', () => {
|
||||||
[['a1', 'a2', 'a3'], 3]
|
[['a1', 'a2', 'a3'], 3]
|
||||||
])(
|
])(
|
||||||
'given address(es) %p calls geocode %p times',
|
'given address(es) %p calls geocode %p times',
|
||||||
async (addresses, numberOfCalls) => {
|
async (addresses, numberOfCallsPostMount) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(googleMap, {});
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
|
const numberOfCallsFromMount = 1;
|
||||||
|
expect(mockGeocode).toHaveBeenCalledTimes(numberOfCallsFromMount);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await wrapper.vm.getLocationsFromAddresses(addresses);
|
await wrapper.vm.getLocationsFromAddresses(addresses);
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(mockGeocode).toHaveBeenCalledTimes(numberOfCalls);
|
expect(mockGeocode).toHaveBeenCalledTimes(numberOfCallsFromMount + numberOfCallsPostMount);
|
||||||
expect(wrapper.vm.geocoder).not.toBeNull();
|
expect(wrapper.vm.geocoder).not.toBeNull();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
test('only returns geocode results that are not null', async () => {
|
test('only returns geocode results that are not null', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(googleMap, {});
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
const addresses = ['a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8'];
|
const addresses = ['a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8'];
|
||||||
mockGeocode.mockImplementationOnce(() => null)
|
mockGeocode.mockImplementationOnce(() => null)
|
||||||
.mockImplementationOnce(() => ({ results: null }))
|
.mockImplementationOnce(() => ({ results: null }))
|
||||||
|
|
@ -300,6 +413,7 @@ describe('Google Map', () => {
|
||||||
test('returns expected when geocode returns valid result', async () => {
|
test('returns expected when geocode returns valid result', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(googleMap, {});
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
const address = 'random address';
|
const address = 'random address';
|
||||||
const expectedResult = 'bounds returned';
|
const expectedResult = 'bounds returned';
|
||||||
const geocodeResult = {
|
const geocodeResult = {
|
||||||
|
|
@ -321,6 +435,7 @@ describe('Google Map', () => {
|
||||||
test('returns null when geocode returns invalid result', async () => {
|
test('returns null when geocode returns invalid result', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(googleMap, {});
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
const address = 'random address';
|
const address = 'random address';
|
||||||
mockGeocode.mockImplementationOnce(() => Promise.resolve({}));
|
mockGeocode.mockImplementationOnce(() => Promise.resolve({}));
|
||||||
|
|
||||||
|
|
@ -335,9 +450,6 @@ describe('Google Map', () => {
|
||||||
describe('createMapWithMarkersForAddresses', () => {
|
describe('createMapWithMarkersForAddresses', () => {
|
||||||
test('calls expected when addresses provided', async () => {
|
test('calls expected when addresses provided', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(googleMap, {});
|
|
||||||
const zipCode = '00882';
|
|
||||||
await wrapper.setData({ zipCode });
|
|
||||||
const mockGetCenter = jest.fn();
|
const mockGetCenter = jest.fn();
|
||||||
const mockNorthEast = jest.fn();
|
const mockNorthEast = jest.fn();
|
||||||
const mockSouthWest = jest.fn();
|
const mockSouthWest = jest.fn();
|
||||||
|
|
@ -360,34 +472,35 @@ describe('Google Map', () => {
|
||||||
{ geometry: { location: 'valid location' } }
|
{ geometry: { location: 'valid location' } }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
const zipCode = '00882';
|
||||||
mockGeocode.mockImplementation((obj) =>
|
mockGeocode.mockImplementation((obj) =>
|
||||||
Promise.resolve(obj.address.includes(zipCode)
|
Promise.resolve(obj.address.includes(zipCode)
|
||||||
? zipCodeGeocodeResult
|
? zipCodeGeocodeResult
|
||||||
: shopGeocodeResult));
|
: shopGeocodeResult));
|
||||||
const addresses = ['a1', 'a2'];
|
const addresses = ['a1', 'a2'];
|
||||||
|
const { wrapper } = getMountedComponent({}, { zipCode });
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await wrapper.vm.createMapWithMarkersForAddresses(addresses);
|
await wrapper.vm.createMapWithMarkersForAddresses(addresses);
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(mockMap).toBeCalledTimes(1);
|
expect(mockMap).toBeCalledTimes(2);
|
||||||
expect(mockAdvancedMarkerElement).toBeCalledTimes(2);
|
expect(mockAdvancedMarkerElement).toBeCalledTimes(2);
|
||||||
expect(mockGeocoder).toBeCalledTimes(1);
|
expect(mockGeocoder).toBeCalledTimes(1);
|
||||||
|
|
||||||
expect(mockExtend).toBeCalledTimes(4);
|
expect(mockExtend).toBeCalledTimes(6);
|
||||||
expect(mockFitBounds).toBeCalledTimes(1);
|
expect(mockFitBounds).toBeCalledTimes(2);
|
||||||
|
|
||||||
expect(mockGetCenter).toBeCalledTimes(1);
|
expect(mockGetCenter).toBeCalledTimes(2);
|
||||||
expect(mockNorthEast).toBeCalledTimes(1);
|
expect(mockNorthEast).toBeCalledTimes(2);
|
||||||
expect(mockSouthWest).toBeCalledTimes(1);
|
expect(mockSouthWest).toBeCalledTimes(2);
|
||||||
});
|
});
|
||||||
test.each([null, undefined, []])(
|
test.each([null, undefined, []])(
|
||||||
'calls expected when addresses argument is "%p"',
|
'calls expected when addresses argument is "%p"',
|
||||||
async (addresses) => {
|
async (addresses) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(googleMap, {});
|
|
||||||
const zipCode = '00882';
|
|
||||||
await wrapper.setData({ zipCode });
|
|
||||||
const mockGetCenter = jest.fn();
|
const mockGetCenter = jest.fn();
|
||||||
const mockNorthEast = jest.fn();
|
const mockNorthEast = jest.fn();
|
||||||
const mockSouthWest = jest.fn();
|
const mockSouthWest = jest.fn();
|
||||||
|
|
@ -406,21 +519,25 @@ describe('Google Map', () => {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
mockGeocode.mockImplementation(() => Promise.resolve(zipCodeGeocodeResult));
|
mockGeocode.mockImplementation(() => Promise.resolve(zipCodeGeocodeResult));
|
||||||
|
const zipCode = '00882';
|
||||||
|
const { wrapper } = getMountedComponent({}, { zipCode });
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await wrapper.vm.createMapWithMarkersForAddresses(addresses);
|
await wrapper.vm.createMapWithMarkersForAddresses(addresses);
|
||||||
|
await awaitingSetupTicks(wrapper);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(mockMap).toBeCalledTimes(1);
|
expect(mockMap).toBeCalledTimes(2);
|
||||||
expect(mockAdvancedMarkerElement).toBeCalledTimes(0);
|
expect(mockAdvancedMarkerElement).toBeCalledTimes(0);
|
||||||
expect(mockGeocoder).toBeCalledTimes(1);
|
expect(mockGeocoder).toBeCalledTimes(1);
|
||||||
|
|
||||||
expect(mockExtend).toBeCalledTimes(2);
|
expect(mockExtend).toBeCalledTimes(4);
|
||||||
expect(mockFitBounds).toBeCalledTimes(1);
|
expect(mockFitBounds).toBeCalledTimes(2);
|
||||||
|
|
||||||
expect(mockGetCenter).toBeCalledTimes(1);
|
expect(mockGetCenter).toBeCalledTimes(2);
|
||||||
expect(mockNorthEast).toBeCalledTimes(1);
|
expect(mockNorthEast).toBeCalledTimes(2);
|
||||||
expect(mockSouthWest).toBeCalledTimes(1);
|
expect(mockSouthWest).toBeCalledTimes(2);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,9 @@ export default {
|
||||||
this.createMapWithMarkersForAddresses(newAddresses);
|
this.createMapWithMarkersForAddresses(newAddresses);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
beforeMount() {
|
||||||
|
this.createMapWithMarkersForAddresses(this.addresses);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getMap(center) {
|
async getMap(center) {
|
||||||
const { Map } = await window.google.maps.importLibrary('maps');
|
const { Map } = await window.google.maps.importLibrary('maps');
|
||||||
|
|
@ -72,13 +75,13 @@ export default {
|
||||||
async createMapWithMarkersForAddresses(addresses) {
|
async createMapWithMarkersForAddresses(addresses) {
|
||||||
const shopPositions = await this.getLocationsFromAddresses(addresses);
|
const shopPositions = await this.getLocationsFromAddresses(addresses);
|
||||||
const zipBounds = await this.getBoundsFromAddress(this.zipCodeAddress);
|
const zipBounds = await this.getBoundsFromAddress(this.zipCodeAddress);
|
||||||
const map = await this.getMap(zipBounds.getCenter());
|
const map = await this.getMap(zipBounds?.getCenter());
|
||||||
|
|
||||||
await this.addMarkersToMap(map, shopPositions);
|
await this.addMarkersToMap(map, shopPositions);
|
||||||
|
|
||||||
const positionsToDisplay = shopPositions.concat(zipBounds.getNorthEast(), zipBounds.getSouthWest());
|
const positionsToDisplay = shopPositions.concat(zipBounds?.getNorthEast(), zipBounds?.getSouthWest());
|
||||||
const bounds = this.getBounds(positionsToDisplay);
|
const bounds = this.getBounds(positionsToDisplay);
|
||||||
map.fitBounds(bounds);
|
map?.fitBounds(bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,24 @@ Object {
|
||||||
"displayAvailabilityIndicators": false,
|
"displayAvailabilityIndicators": false,
|
||||||
},
|
},
|
||||||
"filter": "",
|
"filter": "",
|
||||||
|
"initialLoading": false,
|
||||||
"mapZipCode": "12663",
|
"mapZipCode": "12663",
|
||||||
"providers": Array [],
|
"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 {
|
"rules": Object {
|
||||||
"filter": "option-required",
|
"filter": "option-required",
|
||||||
"provider": "option-required",
|
"provider": "option-required",
|
||||||
|
|
@ -89,14 +105,25 @@ Object {
|
||||||
"setup": [Function],
|
"setup": [Function],
|
||||||
},
|
},
|
||||||
"loader": Object {
|
"loader": Object {
|
||||||
|
"computed": Object {
|
||||||
|
"cssProps": [Function],
|
||||||
|
},
|
||||||
"name": "loader",
|
"name": "loader",
|
||||||
"props": Object {
|
"props": Object {
|
||||||
|
"height": Object {
|
||||||
|
"default": 1,
|
||||||
|
"type": [Function],
|
||||||
|
},
|
||||||
"loaderColor": Object {
|
"loaderColor": Object {
|
||||||
"type": [Function],
|
"type": [Function],
|
||||||
},
|
},
|
||||||
"loaderPosition": Object {
|
"loaderPosition": Object {
|
||||||
"type": [Function],
|
"type": [Function],
|
||||||
},
|
},
|
||||||
|
"width": Object {
|
||||||
|
"default": 1,
|
||||||
|
"type": [Function],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"render": [Function],
|
"render": [Function],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||||
import settleAllPromises from '@/helpers/layout-helper.js';
|
import settleAllPromises from '@/helpers/layout-helper.js';
|
||||||
import globalRules from '@/constants/global-rules.js';
|
import globalRules from '@/constants/global-rules.js';
|
||||||
import widgetFields from '@/constants/cms-widget-fields.js';
|
import widgetFields from '@/constants/cms-widget-fields.js';
|
||||||
|
import navigationScenarios from '@/router/router-constants/navigation-scenarios';
|
||||||
|
|
||||||
// Mock fetchCmsContentForPage
|
// Mock fetchCmsContentForPage
|
||||||
jest.mock('@/helpers/cms-content-helper', () => ({
|
jest.mock('@/helpers/cms-content-helper', () => ({
|
||||||
|
|
@ -149,7 +150,18 @@ describe('TPA search page', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(providerSelectionForm.exists()).toBeTruthy();
|
expect(providerSelectionForm.exists()).toBeTruthy();
|
||||||
});
|
});
|
||||||
test('map', async () => {
|
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 () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const zipCode = '12345';
|
const zipCode = '12345';
|
||||||
const { wrapper } = getMountedComponent();
|
const { wrapper } = getMountedComponent();
|
||||||
|
|
@ -162,7 +174,8 @@ describe('TPA search page', () => {
|
||||||
zipCode: '99230'
|
zipCode: '99230'
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
mapZipCode: zipCode
|
mapZipCode: zipCode,
|
||||||
|
initialLoading: false
|
||||||
});
|
});
|
||||||
const expectedAddresses = ['123 Lane Ave, New York, NY 99230'];
|
const expectedAddresses = ['123 Lane Ave, New York, NY 99230'];
|
||||||
|
|
||||||
|
|
@ -175,9 +188,10 @@ describe('TPA search page', () => {
|
||||||
expect(map.props().addresses).toEqual(expectedAddresses);
|
expect(map.props().addresses).toEqual(expectedAddresses);
|
||||||
expect(map.props().zipCode).toBe(zipCode);
|
expect(map.props().zipCode).toBe(zipCode);
|
||||||
});
|
});
|
||||||
test('search radius filter', () => {
|
test('search radius filter when initialLoading is false', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
await wrapper.setData({ initialLoading: false });
|
||||||
const expectedWidgetName = 'FilterByQuestion';
|
const expectedWidgetName = 'FilterByQuestion';
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -188,12 +202,23 @@ describe('TPA search page', () => {
|
||||||
expect(searchRadiusFilter.props().cmsWidgetName).toBe(expectedWidgetName);
|
expect(searchRadiusFilter.props().cmsWidgetName).toBe(expectedWidgetName);
|
||||||
expect(searchRadiusFilter.props().validationRules).toBe(globalRules.OPTION_REQUIRED);
|
expect(searchRadiusFilter.props().validationRules).toBe(globalRules.OPTION_REQUIRED);
|
||||||
});
|
});
|
||||||
test('select provider question', async () => {
|
test('providers loader when initialLoading is false and reloadProviders is true', async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
await wrapper.setData({ initialLoading: false, reloadProviders: true });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const providersLoader = wrapper.findComponent('#providersLoader');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(providersLoader.exists()).toBeTruthy();
|
||||||
|
});
|
||||||
|
test('select provider question when initialLoading and reloadProviders are false', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
await wrapper.setData({
|
await wrapper.setData({
|
||||||
providers: [{
|
providers: [{
|
||||||
name: 'Shop Auto Glass',
|
companyName: 'Shop Auto Glass',
|
||||||
phoneNumber: '740-555-1234',
|
phoneNumber: '740-555-1234',
|
||||||
distanceInMiles: 1.2345,
|
distanceInMiles: 1.2345,
|
||||||
providerNumber: '232209',
|
providerNumber: '232209',
|
||||||
|
|
@ -203,7 +228,9 @@ describe('TPA search page', () => {
|
||||||
state: 'NY',
|
state: 'NY',
|
||||||
zipCode: '99230'
|
zipCode: '99230'
|
||||||
}
|
}
|
||||||
}]
|
}],
|
||||||
|
initialLoading: false,
|
||||||
|
reloadProviders: false
|
||||||
});
|
});
|
||||||
const expectedAnswers = [{
|
const expectedAnswers = [{
|
||||||
buttonLabel: 'Shop Auto Glass',
|
buttonLabel: 'Shop Auto Glass',
|
||||||
|
|
@ -230,13 +257,17 @@ describe('TPA search page', () => {
|
||||||
expect(selectProviderQuestion.props().additionalButtonData).toEqual(expectedAdditionalButtonData);
|
expect(selectProviderQuestion.props().additionalButtonData).toEqual(expectedAdditionalButtonData);
|
||||||
});
|
});
|
||||||
test.each([[], null, undefined])(
|
test.each([[], null, undefined])(
|
||||||
'no network providers alert when providers length is 0, undefined, or null',
|
'no network providers alert when providers length is 0, undefined, or null and initialLoading and reloadProviders are false',
|
||||||
(providers) => {
|
async (providers) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const initialData = {
|
const initialData = {
|
||||||
providers
|
providers
|
||||||
};
|
};
|
||||||
const wrapper = shallowMount(tpaSearch, getMountOptions({}, initialData));
|
const wrapper = shallowMount(tpaSearch, getMountOptions({}, initialData));
|
||||||
|
await wrapper.setData({
|
||||||
|
initialLoading: false,
|
||||||
|
reloadProviders: false
|
||||||
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const noNetworkProvidersAlert = wrapper.findComponent('#alertNoNetworkProviders');
|
const noNetworkProvidersAlert = wrapper.findComponent('#alertNoNetworkProviders');
|
||||||
|
|
@ -248,9 +279,13 @@ describe('TPA search page', () => {
|
||||||
expect(noNetworkProvidersAlert.props().isDismissible).toBeFalsy();
|
expect(noNetworkProvidersAlert.props().isDismissible).toBeFalsy();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
test('preferred shop not listed link', () => {
|
test('preferred shop not listed link when initialLoading and reloadProviders are false', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
await wrapper.setData({
|
||||||
|
initialLoading: false,
|
||||||
|
reloadProviders: false
|
||||||
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const preferredShopNotListedLink = wrapper.findComponent('#preferredShopNotListedLink');
|
const preferredShopNotListedLink = wrapper.findComponent('#preferredShopNotListedLink');
|
||||||
|
|
@ -272,7 +307,66 @@ describe('TPA search page', () => {
|
||||||
expect(footer.props().cmsWidgetName).toBe('SiteFooterWidget');
|
expect(footer.props().cmsWidgetName).toBe('SiteFooterWidget');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
test('should not render no network providers alert when providers length is not 0', async () => {
|
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 () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = getMountedComponent();
|
||||||
|
await wrapper.setData({ initialLoading: true });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const map = wrapper.findComponent('#map');
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('no network providers alert', () => {
|
||||||
|
test('when providers length is not 0', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
await wrapper.setData({ providers: ['p1', 'p2'] });
|
await wrapper.setData({ providers: ['p1', 'p2'] });
|
||||||
|
|
@ -283,6 +377,54 @@ describe('TPA search page', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(noNetworkProvidersAlert.exists()).toBeFalsy();
|
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());
|
||||||
|
await wrapper.setData({ providers: [], reloadProviders: true });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const noNetworkProvidersAlert = wrapper.findComponent('#alertNoNetworkProviders');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
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 });
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
describe('computed', () => {
|
describe('computed', () => {
|
||||||
describe('filterOptions', () => {
|
describe('filterOptions', () => {
|
||||||
test.each([[], null, undefined])(
|
test.each([[], null, undefined])(
|
||||||
|
|
@ -330,7 +472,7 @@ describe('TPA search page', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
test.each([null, undefined, '', 'non empty string'])(
|
test.each([null, undefined, '', 'non empty string'])(
|
||||||
'tpaSearchQuestionLabel returns value from getCmsContent',
|
'tpaSearchQuestionLabel returns "%p" from getCmsContent',
|
||||||
(cmsContent) => {
|
(cmsContent) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const mountOptions = getMountOptions();
|
const mountOptions = getMountOptions();
|
||||||
|
|
@ -352,7 +494,7 @@ describe('TPA search page', () => {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
test.each([null, undefined, '', 'non empty string'])(
|
test.each([null, undefined, '', 'non empty string'])(
|
||||||
'searchInstructionsText returns value from getCmsContent',
|
'searchInstructionsText returns "%p" from getCmsContent',
|
||||||
(cmsContent) => {
|
(cmsContent) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const mountOptions = getMountOptions();
|
const mountOptions = getMountOptions();
|
||||||
|
|
@ -374,7 +516,7 @@ describe('TPA search page', () => {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
test.each([null, undefined, '', 'non empty string'])(
|
test.each([null, undefined, '', 'non empty string'])(
|
||||||
'shopNotListedModalLink returns value from getCmsContent',
|
'shopNotListedModalLink returns "%p" from getCmsContent',
|
||||||
(cmsContent) => {
|
(cmsContent) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const mountOptions = getMountOptions();
|
const mountOptions = getMountOptions();
|
||||||
|
|
@ -508,7 +650,7 @@ describe('TPA search page', () => {
|
||||||
await wrapper.setData({
|
await wrapper.setData({
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
name: 'Shop Auto Glass',
|
companyName: 'Shop Auto Glass',
|
||||||
phoneNumber: '740-555-1234',
|
phoneNumber: '740-555-1234',
|
||||||
distanceInMiles: 1.2345,
|
distanceInMiles: 1.2345,
|
||||||
providerNumber: '232209',
|
providerNumber: '232209',
|
||||||
|
|
@ -520,7 +662,7 @@ describe('TPA search page', () => {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Safelite AutoGlass',
|
companyName: 'Safelite AutoGlass',
|
||||||
phoneNumber: '676-555-0099',
|
phoneNumber: '676-555-0099',
|
||||||
distanceInMiles: 123.9452,
|
distanceInMiles: 123.9452,
|
||||||
providerNumber: '123456',
|
providerNumber: '123456',
|
||||||
|
|
@ -547,7 +689,7 @@ describe('TPA search page', () => {
|
||||||
});
|
});
|
||||||
describe('providerButtonData', () => {
|
describe('providerButtonData', () => {
|
||||||
test.each([null, undefined, []])(
|
test.each([null, undefined, []])(
|
||||||
'returns empty list when providers empty',
|
'returns empty list when providers equals "%p"',
|
||||||
async (providers) => {
|
async (providers) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
|
@ -566,7 +708,7 @@ describe('TPA search page', () => {
|
||||||
await wrapper.setData({
|
await wrapper.setData({
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
name: 'Shop Auto Glass',
|
companyName: 'Shop Auto Glass',
|
||||||
phoneNumber: '740-555-1234',
|
phoneNumber: '740-555-1234',
|
||||||
distanceInMiles: 1.2345,
|
distanceInMiles: 1.2345,
|
||||||
providerNumber: '232209',
|
providerNumber: '232209',
|
||||||
|
|
@ -578,7 +720,7 @@ describe('TPA search page', () => {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Safelite AutoGlass',
|
companyName: 'Safelite AutoGlass',
|
||||||
phoneNumber: '676-555-0099',
|
phoneNumber: '676-555-0099',
|
||||||
distanceInMiles: 123.9452,
|
distanceInMiles: 123.9452,
|
||||||
providerNumber: '123456',
|
providerNumber: '123456',
|
||||||
|
|
@ -613,8 +755,86 @@ describe('TPA search page', () => {
|
||||||
expect(result).toEqual(expectedResult);
|
expect(result).toEqual(expectedResult);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('selectedProviderIsSafeliteShop', () => {
|
||||||
|
test('no issue when provider in providers with no provider number', async () => {
|
||||||
|
// Arrange
|
||||||
|
const selectedProviderNumber = '10099';
|
||||||
|
const providers = [
|
||||||
|
{ isSafeliteShop: false },
|
||||||
|
{ isSafeliteShop: true }
|
||||||
|
];
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
await wrapper.setData({ selectedProviderNumber, providers });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.selectedProviderIsSafeliteShop;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toEqual(false);
|
||||||
|
});
|
||||||
|
test.each([null, undefined, []])(
|
||||||
|
'returns false when providers %s',
|
||||||
|
async (providers) => {
|
||||||
|
// Arrange
|
||||||
|
const selectedProviderNumber = '10099';
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
await wrapper.setData({ selectedProviderNumber, providers });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.selectedProviderIsSafeliteShop;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toEqual(false);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test.each([[true, true], [false, false]])(
|
||||||
|
'returns %p when first instance of multiple matching providerNumbers has isSafeliteShop value %p',
|
||||||
|
async (expectedOutput, isSafeliteShop) => {
|
||||||
|
// Arrange
|
||||||
|
const selectedProviderNumber = '29987';
|
||||||
|
const providers = [
|
||||||
|
{
|
||||||
|
providerNumber: selectedProviderNumber,
|
||||||
|
isSafeliteShop
|
||||||
|
},
|
||||||
|
{
|
||||||
|
providerNumber: selectedProviderNumber,
|
||||||
|
isSafeliteShop: !isSafeliteShop
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
await wrapper.setData({ selectedProviderNumber, providers });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.selectedProviderIsSafeliteShop;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toEqual(expectedOutput);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test.each([[false, false], [true, true]])(
|
||||||
|
'returns %p when providerNumber match has isSafeliteShop equal to %p',
|
||||||
|
async (expectedOutput, isSafeliteShop) => {
|
||||||
|
// Arrange
|
||||||
|
const selectedProviderNumber = '19274';
|
||||||
|
const providers = [{
|
||||||
|
providerNumber: selectedProviderNumber,
|
||||||
|
isSafeliteShop
|
||||||
|
}];
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
await wrapper.setData({ selectedProviderNumber, providers });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.selectedProviderIsSafeliteShop;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toEqual(expectedOutput);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe('watch', () => {
|
describe('watch', () => {
|
||||||
|
// TODO update/add to filter watch tests
|
||||||
test('on filter calls getTpaProviders and sets providers', async () => {
|
test('on filter calls getTpaProviders and sets providers', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const zipCode = '78220';
|
const zipCode = '78220';
|
||||||
|
|
@ -635,6 +855,7 @@ describe('TPA search page', () => {
|
||||||
expect(wrapper.vm.providers).toEqual(providers.data.shopProviders);
|
expect(wrapper.vm.providers).toEqual(providers.data.shopProviders);
|
||||||
expect(wrapper.vm.mapZipCode).toBe(zipCode);
|
expect(wrapper.vm.mapZipCode).toBe(zipCode);
|
||||||
});
|
});
|
||||||
|
// TODO confirm tests appropriate. Also should this method be async?
|
||||||
describe('on providers', () => {
|
describe('on providers', () => {
|
||||||
test.each([null, undefined, []])(
|
test.each([null, undefined, []])(
|
||||||
'sets selected provider number to "" when there are no providers',
|
'sets selected provider number to "" when there are no providers',
|
||||||
|
|
@ -686,7 +907,6 @@ describe('TPA search page', () => {
|
||||||
(streetAddress, city, state, zipCode, expected) => {
|
(streetAddress, city, state, zipCode, expected) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = getMountedComponent();
|
const { wrapper } = getMountedComponent();
|
||||||
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (newProviders));
|
|
||||||
const provider = {
|
const provider = {
|
||||||
address: {
|
address: {
|
||||||
streetAddress,
|
streetAddress,
|
||||||
|
|
@ -723,7 +943,7 @@ describe('TPA search page', () => {
|
||||||
const { wrapper } = getMountedComponent();
|
const { wrapper } = getMountedComponent();
|
||||||
const providers = {
|
const providers = {
|
||||||
data: {
|
data: {
|
||||||
shopProviders: [{ name: 'foo' }]
|
shopProviders: [{ companyName: 'foo' }]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (providers));
|
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (providers));
|
||||||
|
|
@ -774,7 +994,7 @@ describe('TPA search page', () => {
|
||||||
zipCode,
|
zipCode,
|
||||||
mapZipCode: initialMapZipCode
|
mapZipCode: initialMapZipCode
|
||||||
});
|
});
|
||||||
const shopProviders = [{ name: 'foo' }];
|
const shopProviders = [{ companyName: 'foo' }];
|
||||||
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => ({
|
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => ({
|
||||||
data: { shopProviders }
|
data: { shopProviders }
|
||||||
}));
|
}));
|
||||||
|
|
@ -797,15 +1017,46 @@ describe('TPA search page', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
|
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
test('forwardButtonAction invokes navigate method', () => {
|
describe('forwardButtonAction', () => {
|
||||||
|
test('invokes navigate method with safelite shop scenario when selectedProviderIsSafeliteShop true', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = getMountedComponent();
|
const { wrapper } = getMountedComponent();
|
||||||
|
const providerNumber = '1109';
|
||||||
|
await wrapper.setData({
|
||||||
|
selectedProviderNumber: providerNumber,
|
||||||
|
providers: [{
|
||||||
|
providerNumber,
|
||||||
|
isSafeliteShop: true
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
wrapper.vm.backButtonAction();
|
wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
|
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE_SHOP, undefined);
|
||||||
|
});
|
||||||
|
test('invokes navigate method with non safelite shop scenario when selectedProviderIsSafeliteShop false', async () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = getMountedComponent();
|
||||||
|
const providerNumber = '928';
|
||||||
|
await wrapper.setData({
|
||||||
|
selectedProviderNumber: providerNumber,
|
||||||
|
providers: [{
|
||||||
|
providerNumber,
|
||||||
|
isSafeliteShop: false
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||||
|
navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe('getCustomValueFromString', () => {
|
describe('getCustomValueFromString', () => {
|
||||||
test('returns radius in miles value if "radiusInMiles"', () => {
|
test('returns radius in miles value if "radiusInMiles"', () => {
|
||||||
|
|
@ -855,7 +1106,7 @@ describe('TPA search page', () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
const provider = {
|
const provider = {
|
||||||
name: 'Shop Auto Glass',
|
companyName: 'Shop Auto Glass',
|
||||||
phoneNumber: '740-555-1234',
|
phoneNumber: '740-555-1234',
|
||||||
distanceInMiles: 1.2345,
|
distanceInMiles: 1.2345,
|
||||||
providerNumber: '232209',
|
providerNumber: '232209',
|
||||||
|
|
@ -882,10 +1133,10 @@ describe('TPA search page', () => {
|
||||||
describe('returns result with button label', () => {
|
describe('returns result with button label', () => {
|
||||||
test.each(['', undefined, null])(
|
test.each(['', undefined, null])(
|
||||||
'equal to empty string when name is empty',
|
'equal to empty string when name is empty',
|
||||||
(name) => {
|
(companyName) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
const provider = { name };
|
const provider = { companyName };
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = wrapper.vm.getShopButtonDataFromProvider(provider);
|
const result = wrapper.vm.getShopButtonDataFromProvider(provider);
|
||||||
|
|
@ -897,14 +1148,14 @@ describe('TPA search page', () => {
|
||||||
test('returns provider name when exists', () => {
|
test('returns provider name when exists', () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
const name = 'Some Shop Name';
|
const companyName = 'Some Shop Name';
|
||||||
const provider = { name };
|
const provider = { companyName };
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = wrapper.vm.getShopButtonDataFromProvider(provider);
|
const result = wrapper.vm.getShopButtonDataFromProvider(provider);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(result.buttonLabel).toEqual(name);
|
expect(result.buttonLabel).toEqual(companyName);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('returns result with button label sub copy', () => {
|
describe('returns result with button label sub copy', () => {
|
||||||
|
|
@ -994,7 +1245,7 @@ describe('TPA search page', () => {
|
||||||
const { wrapper } = getMountedComponent();
|
const { wrapper } = getMountedComponent();
|
||||||
const zipCode = '18394';
|
const zipCode = '18394';
|
||||||
useMainStore().order.customer.address.zipCode = zipCode;
|
useMainStore().order.customer.address.zipCode = zipCode;
|
||||||
const providers = [{ name: 'provider' }];
|
const providers = [{ companyName: 'provider' }];
|
||||||
useMainStore().getTpaProviders = jest.fn().mockImplementation((_, radius) =>
|
useMainStore().getTpaProviders = jest.fn().mockImplementation((_, radius) =>
|
||||||
({ data: { shopProviders: radius === 25 ? providers : [] } }));
|
({ data: { shopProviders: radius === 25 ? providers : [] } }));
|
||||||
const expectedFilter = '25 miles';
|
const expectedFilter = '25 miles';
|
||||||
|
|
@ -1013,13 +1264,14 @@ describe('TPA search page', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.filter).toBe(expectedFilter);
|
expect(wrapper.vm.filter).toBe(expectedFilter);
|
||||||
expect(wrapper.vm.providers).toEqual(providers);
|
expect(wrapper.vm.providers).toEqual(providers);
|
||||||
|
expect(useMainStore().getTpaProviders).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
test('when providers exist at 50 mile radius but not 25, filter is set to "50 miles" and providers set to expected', async () => {
|
test('when providers exist at 50 mile radius but not 25, filter is set to "50 miles" and providers set to expected', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = getMountedComponent();
|
const { wrapper } = getMountedComponent();
|
||||||
const zipCode = '18394';
|
const zipCode = '18394';
|
||||||
useMainStore().order.customer.address.zipCode = zipCode;
|
useMainStore().order.customer.address.zipCode = zipCode;
|
||||||
const providers = [{ name: 'provider' }];
|
const providers = [{ companyName: 'provider' }];
|
||||||
useMainStore().getTpaProviders = jest.fn().mockImplementation((_, radius) =>
|
useMainStore().getTpaProviders = jest.fn().mockImplementation((_, radius) =>
|
||||||
({ data: { shopProviders: radius === 50 ? providers : [] } }));
|
({ data: { shopProviders: radius === 50 ? providers : [] } }));
|
||||||
const expectedFilter = '50 miles';
|
const expectedFilter = '50 miles';
|
||||||
|
|
@ -1038,6 +1290,7 @@ describe('TPA search page', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.filter).toBe(expectedFilter);
|
expect(wrapper.vm.filter).toBe(expectedFilter);
|
||||||
expect(wrapper.vm.providers).toEqual(providers);
|
expect(wrapper.vm.providers).toEqual(providers);
|
||||||
|
expect(useMainStore().getTpaProviders).toBeCalledTimes(2);
|
||||||
});
|
});
|
||||||
test(
|
test(
|
||||||
'when providers exist at 100 mile radius but not 50 or 25, filter is set to "100 miles" and providers set to expected',
|
'when providers exist at 100 mile radius but not 50 or 25, filter is set to "100 miles" and providers set to expected',
|
||||||
|
|
@ -1046,7 +1299,7 @@ describe('TPA search page', () => {
|
||||||
const { wrapper } = getMountedComponent();
|
const { wrapper } = getMountedComponent();
|
||||||
const zipCode = '18394';
|
const zipCode = '18394';
|
||||||
useMainStore().order.customer.address.zipCode = zipCode;
|
useMainStore().order.customer.address.zipCode = zipCode;
|
||||||
const providers = [{ name: 'provider' }];
|
const providers = [{ companyName: 'provider' }];
|
||||||
useMainStore().getTpaProviders = jest.fn().mockImplementation((_, radius) =>
|
useMainStore().getTpaProviders = jest.fn().mockImplementation((_, radius) =>
|
||||||
({ data: { shopProviders: radius === 100 ? providers : [] } }));
|
({ data: { shopProviders: radius === 100 ? providers : [] } }));
|
||||||
const expectedFilter = '100 miles';
|
const expectedFilter = '100 miles';
|
||||||
|
|
@ -1065,6 +1318,7 @@ describe('TPA search page', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.filter).toBe(expectedFilter);
|
expect(wrapper.vm.filter).toBe(expectedFilter);
|
||||||
expect(wrapper.vm.providers).toEqual(providers);
|
expect(wrapper.vm.providers).toEqual(providers);
|
||||||
|
expect(useMainStore().getTpaProviders).toBeCalledTimes(3);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
test(
|
test(
|
||||||
|
|
@ -1091,6 +1345,7 @@ describe('TPA search page', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.filter).toBe(expectedFilter);
|
expect(wrapper.vm.filter).toBe(expectedFilter);
|
||||||
expect(wrapper.vm.providers).toEqual([]);
|
expect(wrapper.vm.providers).toEqual([]);
|
||||||
|
expect(useMainStore().getTpaProviders).toBeCalledTimes(3);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
<loader
|
||||||
|
v-if="initialLoading"
|
||||||
|
id="mapLoader"
|
||||||
|
loaderPosition="center"
|
||||||
|
loaderColor="blue"
|
||||||
|
:width="4"
|
||||||
|
:height="4" />
|
||||||
|
<div v-else>
|
||||||
<googleMap
|
<googleMap
|
||||||
id="map"
|
id="map"
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
|
|
@ -57,7 +65,15 @@
|
||||||
:options="filterOptions"
|
:options="filterOptions"
|
||||||
disableAutoFill
|
disableAutoFill
|
||||||
:validationRules="rules.filter" />
|
: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">
|
<div class="my-4">
|
||||||
<buttonQuestion
|
<buttonQuestion
|
||||||
id="selectProviderQuestion"
|
id="selectProviderQuestion"
|
||||||
|
|
@ -89,6 +105,7 @@
|
||||||
@clickEvent="doNotSeeMyShopLinkClick" />
|
@clickEvent="doNotSeeMyShopLinkClick" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<siteFooter
|
<siteFooter
|
||||||
ref="siteFooter"
|
ref="siteFooter"
|
||||||
:cmsWidgetName="widget.siteFooter"
|
:cmsWidgetName="widget.siteFooter"
|
||||||
|
|
@ -99,6 +116,7 @@
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
|
|
@ -112,6 +130,7 @@ import alert from '@/ux-components/alert/alert.vue';
|
||||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||||
import googleMap from '@/iss-components/google-map/google-map.vue';
|
import googleMap from '@/iss-components/google-map/google-map.vue';
|
||||||
import shopListButton from '@/iss-components/shop-list-button/shop-list-button.vue';
|
import shopListButton from '@/iss-components/shop-list-button/shop-list-button.vue';
|
||||||
|
import loader from '@/ux-components/loader/loader.vue';
|
||||||
|
|
||||||
// Supporting files
|
// Supporting files
|
||||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||||
|
|
@ -120,6 +139,7 @@ import { useMainStore } from '@/store';
|
||||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||||
import globalRules from '@/constants/global-rules.js';
|
import globalRules from '@/constants/global-rules.js';
|
||||||
import widgetFields from '@/constants/cms-widget-fields.js';
|
import widgetFields from '@/constants/cms-widget-fields.js';
|
||||||
|
import { shallowRef } from 'vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'tpa-search',
|
name: 'tpa-search',
|
||||||
|
|
@ -130,6 +150,7 @@ export default {
|
||||||
buttonQuestion,
|
buttonQuestion,
|
||||||
textLink,
|
textLink,
|
||||||
alert,
|
alert,
|
||||||
|
loader,
|
||||||
googleMap,
|
googleMap,
|
||||||
siteFooter,
|
siteFooter,
|
||||||
// eslint-disable-next-line vue/no-reserved-component-names
|
// eslint-disable-next-line vue/no-reserved-component-names
|
||||||
|
|
@ -159,6 +180,8 @@ export default {
|
||||||
filter: '',
|
filter: '',
|
||||||
providers: [],
|
providers: [],
|
||||||
selectedProviderNumber: '',
|
selectedProviderNumber: '',
|
||||||
|
initialLoading: false,
|
||||||
|
reloadProviders: false,
|
||||||
additionalButtonData: {
|
additionalButtonData: {
|
||||||
displayAvailabilityIndicators: false
|
displayAvailabilityIndicators: false
|
||||||
},
|
},
|
||||||
|
|
@ -176,7 +199,21 @@ export default {
|
||||||
filter: globalRules.OPTION_REQUIRED, // TODO do we even need this?
|
filter: globalRules.OPTION_REQUIRED, // TODO do we even need this?
|
||||||
provider: globalRules.OPTION_REQUIRED
|
provider: globalRules.OPTION_REQUIRED
|
||||||
},
|
},
|
||||||
shopListButton
|
shopListButton: shallowRef(shopListButton),
|
||||||
|
radiusFilterPairs: [
|
||||||
|
{
|
||||||
|
radius: 25,
|
||||||
|
filter: '25 miles'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
radius: 50,
|
||||||
|
filter: '50 miles'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
radius: 100,
|
||||||
|
filter: '100 miles'
|
||||||
|
}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -210,16 +247,8 @@ export default {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
radiusInMiles() {
|
radiusInMiles() {
|
||||||
switch (this.filter) {
|
const pair = this.radiusFilterPairs.find((p) => p.filter === this.filter);
|
||||||
case '25 miles':
|
return pair?.radius ?? 0;
|
||||||
return 25;
|
|
||||||
case '50 miles':
|
|
||||||
return 50;
|
|
||||||
case '100 miles':
|
|
||||||
return 100;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
noNetworkShopsAlertHeaderText() {
|
noNetworkShopsAlertHeaderText() {
|
||||||
return this.getCmsContent(
|
return this.getCmsContent(
|
||||||
|
|
@ -232,18 +261,28 @@ export default {
|
||||||
},
|
},
|
||||||
providerButtonData() {
|
providerButtonData() {
|
||||||
return this.providers?.map((provider) => this.getShopButtonDataFromProvider(provider)) ?? [];
|
return this.providers?.map((provider) => this.getShopButtonDataFromProvider(provider)) ?? [];
|
||||||
|
},
|
||||||
|
selectedProviderIsSafeliteShop() {
|
||||||
|
return this.providers?.find((p) => p.providerNumber === this.selectedProviderNumber)?.isSafeliteShop ?? false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
async filter() {
|
async filter() {
|
||||||
// TODO right now this results in getProviders being called once more than it needs to be
|
if (!this.initialLoading) {
|
||||||
this.providers = await this.getProviderButtonData();
|
this.reloadProviders = true;
|
||||||
|
await this.getProviderButtonData().then((providers) => {
|
||||||
|
this.providers = providers;
|
||||||
|
});
|
||||||
this.mapZipCode = this.zipCode;
|
this.mapZipCode = this.zipCode;
|
||||||
|
this.reloadProviders = false;
|
||||||
|
} else {
|
||||||
|
this.initialLoading = false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
providers(newProviders) {
|
async providers(newProviders) {
|
||||||
this.selectedProviderNumber = newProviders?.length === 1 ?? false
|
if (newProviders?.length === 1 ?? false) {
|
||||||
? newProviders[0].providerNumber
|
this.selectedProviderNumber = newProviders[0]?.providerNumber ?? '';
|
||||||
: '';
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods:
|
methods:
|
||||||
|
|
@ -276,25 +315,25 @@ export default {
|
||||||
: addressLine2;
|
: addressLine2;
|
||||||
},
|
},
|
||||||
async setInitialFilterAndProviders() {
|
async setInitialFilterAndProviders() {
|
||||||
const radiusOptions = [25, 50, 100];
|
this.initialLoading = true;
|
||||||
const { zipCode } = useMainStore().order.customer.address;
|
const { zipCode } = useMainStore().order.customer.address;
|
||||||
|
|
||||||
const tpaProvidersRadius25 = await useMainStore().getTpaProviders(zipCode, radiusOptions[0]);
|
let pairIndex = 0;
|
||||||
const tpaProvidersRadius50 = await useMainStore().getTpaProviders(zipCode, radiusOptions[1]);
|
let providers = [];
|
||||||
const tpaProvidersRadius100 = await useMainStore().getTpaProviders(zipCode, radiusOptions[2]);
|
let filter = '';
|
||||||
let radius = '25 miles';
|
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 ?? [];
|
||||||
|
|
||||||
let providers = tpaProvidersRadius25;
|
pairIndex += 1;
|
||||||
if ((tpaProvidersRadius25?.data?.shopProviders ?? []).length === 0) {
|
|
||||||
radius = '50 miles';
|
|
||||||
providers = tpaProvidersRadius50;
|
|
||||||
if ((tpaProvidersRadius50?.data?.shopProviders ?? []).length === 0) {
|
|
||||||
radius = '100 miles';
|
|
||||||
providers = tpaProvidersRadius100;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
this.filter = radius;
|
this.filter = filter;
|
||||||
this.providers = providers?.data?.shopProviders ?? [];
|
this.providers = providers;
|
||||||
},
|
},
|
||||||
async getProviderButtonData() {
|
async getProviderButtonData() {
|
||||||
const getTpaProvidersResult = await useMainStore().getTpaProviders(this.zipCode, this.radiusInMiles);
|
const getTpaProvidersResult = await useMainStore().getTpaProviders(this.zipCode, this.radiusInMiles);
|
||||||
|
|
@ -307,17 +346,19 @@ export default {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
async searchClick() {
|
async searchClick() {
|
||||||
|
this.reloadProviders = true;
|
||||||
this.providers = await this.getProviderButtonData();
|
this.providers = await this.getProviderButtonData();
|
||||||
this.mapZipCode = this.zipCode;
|
this.mapZipCode = this.zipCode;
|
||||||
|
this.reloadProviders = false;
|
||||||
},
|
},
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
},
|
},
|
||||||
forwardButtonAction() {
|
forwardButtonAction() {
|
||||||
this.$router.navigate(
|
const scenario = this.selectedProviderIsSafeliteShop
|
||||||
this.navigationScenarios.CLICKED_FORWARD,
|
? this.navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE_SHOP
|
||||||
this.$route
|
: this.navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP;
|
||||||
);
|
this.$router.navigate(scenario, this.$route);
|
||||||
},
|
},
|
||||||
getCustomValueFromString(str) {
|
getCustomValueFromString(str) {
|
||||||
switch (str) {
|
switch (str) {
|
||||||
|
|
@ -334,7 +375,7 @@ export default {
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
buttonLabel: provider?.name ?? '',
|
buttonLabel: provider?.companyName ?? '',
|
||||||
buttonLabelSubCopy: distance === null
|
buttonLabelSubCopy: distance === null
|
||||||
? ''
|
? ''
|
||||||
: `${distance} mi`,
|
: `${distance} mi`,
|
||||||
|
|
@ -347,7 +388,6 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
.search-question {
|
.search-question {
|
||||||
font-size: $h5-font-size;
|
font-size: $h5-font-size;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,8 @@ const navigationScenarios = Object.freeze({
|
||||||
|
|
||||||
// TPA Search
|
// TPA Search
|
||||||
CLICKED_DO_NOT_SEE_MY_SHOP_LINK: 'CLICKED_DO_NOT_SEE_MY_SHOP_LINK',
|
CLICKED_DO_NOT_SEE_MY_SHOP_LINK: 'CLICKED_DO_NOT_SEE_MY_SHOP_LINK',
|
||||||
|
CLICKED_FORWARD_WITH_SAFELITE_SHOP: 'CLICKED_FORWARD_WITH_SAFELITE_SHOP',
|
||||||
|
CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP: 'CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP',
|
||||||
|
|
||||||
// Provider Preference
|
// Provider Preference
|
||||||
CLICKED_FORWARD_WITH_SAFELITE: 'CLICKED_FORWARD_WITH_SAFELITE',
|
CLICKED_FORWARD_WITH_SAFELITE: 'CLICKED_FORWARD_WITH_SAFELITE',
|
||||||
|
|
|
||||||
|
|
@ -664,7 +664,11 @@ const routingTable = () => [
|
||||||
destinationIssPageValue: issPageValues.PROVIDER_PREFERENCE
|
destinationIssPageValue: issPageValues.PROVIDER_PREFERENCE
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
scenario: navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE_SHOP,
|
||||||
|
destinationIssPageValue: issPageValues.SERVICE_LOCATION
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP,
|
||||||
destinationIssPageValue: issPageValues.TPA_SUBMIT
|
destinationIssPageValue: issPageValues.TPA_SUBMIT
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -857,78 +857,15 @@ export const useMainStore = defineStore({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO update with real endpoint
|
|
||||||
getTpaProviders(zipCode, radius) {
|
getTpaProviders(zipCode, radius) {
|
||||||
|
const damageType = this.damage.isRepair ? 'Repair' : 'Replace';
|
||||||
|
const { parentAccountNumber } = this.issConfig;
|
||||||
|
const safeliteOnly = false;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (radius === 25) {
|
globalMethods.callHttpClient({
|
||||||
resolve({
|
method: endpoints.GetProviders.method,
|
||||||
data: {
|
endpoint: `${endpoints.GetProviders.url}/${zipCode}/${damageType}/${radius}/${parentAccountNumber}/${safeliteOnly}`
|
||||||
mobileProviderNumber: null,
|
}).then((response) => resolve(response), (error) => reject(error));
|
||||||
shopProviders: null
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (radius === 50) {
|
|
||||||
resolve({
|
|
||||||
data: {
|
|
||||||
mobileProviderNumber: null,
|
|
||||||
shopProviders: [
|
|
||||||
{
|
|
||||||
name: 'USA Auto Glass',
|
|
||||||
address: {
|
|
||||||
city: 'WESTERVILLE',
|
|
||||||
country: 'US',
|
|
||||||
state: 'OH',
|
|
||||||
streetAddress: '4403 EXECUTIVE PKWY',
|
|
||||||
streetAddress2: '',
|
|
||||||
zipCode: '43081',
|
|
||||||
zipCodeCtu: '01820'
|
|
||||||
},
|
|
||||||
distanceInMiles: 8.393453111956896,
|
|
||||||
providerNumber: '003335',
|
|
||||||
phoneNumber: '614-123-5555'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
resolve({
|
|
||||||
data: {
|
|
||||||
mobileProviderNumber: null,
|
|
||||||
shopProviders: [
|
|
||||||
{
|
|
||||||
name: 'USA Auto Glass',
|
|
||||||
address: {
|
|
||||||
city: 'WESTERVILLE',
|
|
||||||
country: 'US',
|
|
||||||
state: 'OH',
|
|
||||||
streetAddress: '4403 EXECUTIVE PKWY',
|
|
||||||
streetAddress2: '',
|
|
||||||
zipCode: '43081',
|
|
||||||
zipCodeCtu: '01820'
|
|
||||||
},
|
|
||||||
distanceInMiles: 8.393453111956896,
|
|
||||||
providerNumber: '003335',
|
|
||||||
phoneNumber: '614-123-5555'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Safelite AutoGlass',
|
|
||||||
address: {
|
|
||||||
city: 'WORTHINGTON',
|
|
||||||
country: 'US',
|
|
||||||
state: 'OH',
|
|
||||||
streetAddress: '760 DEARBORN PARK LN',
|
|
||||||
streetAddress2: '',
|
|
||||||
zipCode: '43085',
|
|
||||||
zipCodeCtu: '01820'
|
|
||||||
},
|
|
||||||
distanceInMiles: 8.704336770196678,
|
|
||||||
providerNumber: '001820',
|
|
||||||
phoneNumber: '740-555-1234'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1961,4 +1961,120 @@ describe('Store', () => {
|
||||||
expect(store.order.currentDeductible).toEqual(finalDeductible);
|
expect(store.order.currentDeductible).toEqual(finalDeductible);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getTpaProviders method', () => {
|
||||||
|
describe('successful method call', () => {
|
||||||
|
it.each([[true, 'Repair'], [false, 'Replace']])(
|
||||||
|
'calls getProviders api endpoint',
|
||||||
|
async (isRepair, damageType) => {
|
||||||
|
// Arrange
|
||||||
|
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
|
||||||
|
|
||||||
|
const parentAccountNumber = getRandomString(6, 6);
|
||||||
|
store.issConfig.parentAccountNumber = parentAccountNumber;
|
||||||
|
store.order.damage.isRepair = isRepair;
|
||||||
|
const zipCode = getRandomString(6, 6);
|
||||||
|
const radius = getRandomInt(5, 100);
|
||||||
|
const expectedEndpoint = [
|
||||||
|
endpoints.GetProviders.url,
|
||||||
|
zipCode,
|
||||||
|
damageType,
|
||||||
|
radius,
|
||||||
|
parentAccountNumber,
|
||||||
|
'false'
|
||||||
|
].join('/');
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await store.getTpaProviders(zipCode, radius);
|
||||||
|
|
||||||
|
// Asserts
|
||||||
|
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining({
|
||||||
|
method: endpoints.GetProviders.method,
|
||||||
|
endpoint: expectedEndpoint
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
it('Returns expected response object', async () => {
|
||||||
|
// Arrange
|
||||||
|
const response = { ReferralNumber: getRandomString(6, 6) };
|
||||||
|
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(response));
|
||||||
|
const zipCode = getRandomString(6, 6);
|
||||||
|
const radius = getRandomInt(5, 100);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = store.getTpaProviders(zipCode, radius);
|
||||||
|
|
||||||
|
// Asserts
|
||||||
|
await expect(result).resolves.toBe(response);
|
||||||
|
});
|
||||||
|
it('null response by api => no exceptions thrown', async () => {
|
||||||
|
// Arrange
|
||||||
|
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(null));
|
||||||
|
const zipCode = getRandomString(6, 6);
|
||||||
|
const radius = getRandomInt(5, 100);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await store.getTpaProviders(zipCode, radius);
|
||||||
|
});
|
||||||
|
it('no providers returned by api => promise resolves to empty list', async () => {
|
||||||
|
// Arrange
|
||||||
|
const responseNoProviders = {
|
||||||
|
data: {
|
||||||
|
shopProviders: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(responseNoProviders));
|
||||||
|
const zipCode = getRandomString(6, 6);
|
||||||
|
const radius = getRandomInt(5, 100);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = await store.getTpaProviders(zipCode, radius);
|
||||||
|
|
||||||
|
// Asserts
|
||||||
|
expect(result.data.shopProviders).toHaveLength(0);
|
||||||
|
});
|
||||||
|
it('multiple providers returned by api => promise resolves to expected', async () => {
|
||||||
|
// Arrange
|
||||||
|
const provider1 = {
|
||||||
|
companyName: getRandomString(6, 6)
|
||||||
|
};
|
||||||
|
const provider2 = {
|
||||||
|
companyName: getRandomString(6, 6)
|
||||||
|
};
|
||||||
|
|
||||||
|
const responseProviders = {
|
||||||
|
data: {
|
||||||
|
shopProviders: [provider1, provider2]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(responseProviders));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = await store.getTpaProviders();
|
||||||
|
|
||||||
|
// Asserts
|
||||||
|
expect(result.data.shopProviders).toHaveLength(2);
|
||||||
|
expect(result.data.shopProviders[0]).toBe(provider1);
|
||||||
|
expect(result.data.shopProviders[1]).toBe(provider2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('api call throws exception => policyLookupSuccessful false', async () => {
|
||||||
|
expect.assertions(3);
|
||||||
|
const error = 'get coverage policy info error';
|
||||||
|
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject(error));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await store.getCoveragePolicyInfo().catch((e) => {
|
||||||
|
expect(e).toEqual(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Asserts
|
||||||
|
expect(globalMethods.callHttpClient)
|
||||||
|
.toHaveBeenCalledWith(expect.objectContaining({
|
||||||
|
method: endpoints.CoveragePolicyInfo.method,
|
||||||
|
endpoint: endpoints.CoveragePolicyInfo.url
|
||||||
|
}));
|
||||||
|
expect(store.order.policy.policyLookupSuccessful).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
|
:style="cssProps"
|
||||||
class="loader"
|
class="loader"
|
||||||
role="alert"
|
role="alert"
|
||||||
aria-label="Loading new page"
|
aria-label="Loading new page"
|
||||||
|
|
@ -18,6 +19,22 @@ export default {
|
||||||
/* Position options: center, right, left (OPTIONAL, do NOT use on btn-* classes) */
|
/* Position options: center, right, left (OPTIONAL, do NOT use on btn-* classes) */
|
||||||
loaderPosition: {
|
loaderPosition: {
|
||||||
type: String
|
type: String
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: Number,
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
cssProps() {
|
||||||
|
return {
|
||||||
|
'--loader-width': `${this.width}rem`,
|
||||||
|
'--loader-height': `${this.height}rem`
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -45,8 +62,8 @@ export default {
|
||||||
mask: url(../../assets/img/icons/spinner.svg);
|
mask: url(../../assets/img/icons/spinner.svg);
|
||||||
mask-size: cover;
|
mask-size: cover;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 1rem;
|
width: var(--loader-width);
|
||||||
height: 1rem;
|
height: var(--loader-height);
|
||||||
border-radius:50%;
|
border-radius:50%;
|
||||||
animation: rotation 1s infinite linear;
|
animation: rotation 1s infinite linear;
|
||||||
@keyframes rotation {
|
@keyframes rotation {
|
||||||
|
|
@ -57,8 +74,7 @@ export default {
|
||||||
}
|
}
|
||||||
//Spinner position
|
//Spinner position
|
||||||
&.center {
|
&.center {
|
||||||
right: 50%;
|
justify-content: center;
|
||||||
transform: translateX(50%);
|
|
||||||
}
|
}
|
||||||
&.right {
|
&.right {
|
||||||
right: 1rem;
|
right: 1rem;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue