Merge branch 'develop' into feature/SSR-862
This commit is contained in:
commit
e9df2ed6ee
15 changed files with 1100 additions and 112 deletions
|
|
@ -88,6 +88,7 @@ stages:
|
||||||
indexDeployVariables:
|
indexDeployVariables:
|
||||||
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
||||||
__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
|
__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
|
||||||
|
__VUE_APP_GOOGLE_MAPS_API_SCRIPT__: $(__VUE_APP_GOOGLE_MAPS_API_SCRIPT__)
|
||||||
- template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
|
- template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
|
||||||
parameters:
|
parameters:
|
||||||
awsCliContainer: awscli
|
awsCliContainer: awscli
|
||||||
|
|
@ -137,6 +138,7 @@ stages:
|
||||||
indexDeployVariables:
|
indexDeployVariables:
|
||||||
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
||||||
__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
|
__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
|
||||||
|
__VUE_APP_GOOGLE_MAPS_API_SCRIPT__: $(__VUE_APP_GOOGLE_MAPS_API_SCRIPT__)
|
||||||
- template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
|
- template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
|
||||||
parameters:
|
parameters:
|
||||||
awsCliContainer: awscli
|
awsCliContainer: awscli
|
||||||
|
|
@ -186,6 +188,7 @@ stages:
|
||||||
indexDeployVariables:
|
indexDeployVariables:
|
||||||
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
||||||
__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
|
__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
|
||||||
|
__VUE_APP_GOOGLE_MAPS_API_SCRIPT__: $(__VUE_APP_GOOGLE_MAPS_API_SCRIPT__)
|
||||||
- template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
|
- template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
|
||||||
parameters:
|
parameters:
|
||||||
awsCliContainer: awscli
|
awsCliContainer: awscli
|
||||||
|
|
@ -235,6 +238,7 @@ stages:
|
||||||
indexDeployVariables:
|
indexDeployVariables:
|
||||||
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
||||||
__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
|
__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
|
||||||
|
__VUE_APP_GOOGLE_MAPS_API_SCRIPT__: $(__VUE_APP_GOOGLE_MAPS_API_SCRIPT__)
|
||||||
- template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
|
- template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
|
||||||
parameters:
|
parameters:
|
||||||
awsCliContainer: awscli
|
awsCliContainer: awscli
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
window.dataLayer = [{}];
|
window.dataLayer = [{}];
|
||||||
</script>
|
</script>
|
||||||
<script><%= process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY %></script>
|
<script><%= process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY %></script>
|
||||||
|
<script><%= process.env.VUE_APP_GOOGLE_MAPS_API_SCRIPT %></script>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ const endpoints = Object.freeze({
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
},
|
},
|
||||||
GooglePlaces: {
|
GooglePlaces: {
|
||||||
url: 'https://maps.googleapis.com/maps/api/js?key={apiKey}&libraries=places'
|
url: (apiKey) => `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places`
|
||||||
},
|
},
|
||||||
ValidateClientTag: {
|
ValidateClientTag: {
|
||||||
url: '/clientauth/api/v1/clientauth/validate-client-tag',
|
url: '/clientauth/api/v1/clientauth/validate-client-tag',
|
||||||
|
|
|
||||||
|
|
@ -196,7 +196,7 @@ export default {
|
||||||
const addressField1 = document.getElementById('autocomplete');
|
const addressField1 = document.getElementById('autocomplete');
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
const url = endpoints.GooglePlaces.url.replace('{apiKey}', applicationConfig.GOOGLE_PLACES_API_KEY);
|
const url = endpoints.GooglePlaces.url(applicationConfig.GOOGLE_PLACES_API_KEY);
|
||||||
|
|
||||||
this.$loadScript(url)
|
this.$loadScript(url)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Google Map should render expected initial data 1`] = `
|
||||||
|
Object {
|
||||||
|
"country": "USA",
|
||||||
|
"geocoder": null,
|
||||||
|
}
|
||||||
|
`;
|
||||||
428
src/iss-components/google-map/google-map.spec.js
Normal file
428
src/iss-components/google-map/google-map.spec.js
Normal file
|
|
@ -0,0 +1,428 @@
|
||||||
|
import { shallowMount } from '@vue/test-utils';
|
||||||
|
import googleMap from '@/iss-components/google-map/google-map.vue';
|
||||||
|
|
||||||
|
const mockFitBounds = jest.fn();
|
||||||
|
const mockMapInstance = {
|
||||||
|
fitBounds: mockFitBounds
|
||||||
|
};
|
||||||
|
const mockMap = jest.fn(() => mockMapInstance);
|
||||||
|
|
||||||
|
const mockGeocode = jest.fn();
|
||||||
|
const mockGeocoderInstance = {
|
||||||
|
geocode: mockGeocode
|
||||||
|
};
|
||||||
|
const mockGeocoder = jest.fn(() => (mockGeocoderInstance));
|
||||||
|
|
||||||
|
const mockAdvancedMarkerElement = jest.fn();
|
||||||
|
|
||||||
|
const mockImportLibrary = jest.fn().mockImplementation(() => (Promise.resolve({
|
||||||
|
Map: mockMap,
|
||||||
|
Geocoder: mockGeocoder,
|
||||||
|
AdvancedMarkerElement: mockAdvancedMarkerElement
|
||||||
|
})));
|
||||||
|
|
||||||
|
const mockExtend = jest.fn();
|
||||||
|
const mockLatLngBound = { extend: mockExtend };
|
||||||
|
|
||||||
|
const setupGoogleMock = () => {
|
||||||
|
global.window.google = {
|
||||||
|
maps: {
|
||||||
|
importLibrary: mockImportLibrary,
|
||||||
|
LatLngBounds: jest.fn(() => (mockLatLngBound))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// clear constructors
|
||||||
|
mockMap.mockClear();
|
||||||
|
mockGeocoder.mockClear();
|
||||||
|
mockAdvancedMarkerElement.mockClear();
|
||||||
|
|
||||||
|
// clear methods
|
||||||
|
mockExtend.mockClear();
|
||||||
|
mockGeocode.mockClear();
|
||||||
|
mockFitBounds.mockClear();
|
||||||
|
|
||||||
|
setupGoogleMock();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Google Map', () => {
|
||||||
|
describe('should render', () => {
|
||||||
|
test('expected initial data', async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.$data).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
test('map', () => {
|
||||||
|
// Arrange
|
||||||
|
const mapReference = '#map';
|
||||||
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const map = wrapper.find(mapReference);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(map.exists()).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
test.each([
|
||||||
|
['13001', '13001 USA'],
|
||||||
|
['9', '9 USA'],
|
||||||
|
['', ' USA'],
|
||||||
|
[null, ' USA']
|
||||||
|
])(
|
||||||
|
'given that zipcode set to "%p", computed zipCodeAddress should return "%p"',
|
||||||
|
async (zipCode, expected) => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
await wrapper.setData({ zipCode });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.zipCodeAddress;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toBe(expected);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test('watch addresses creates map with expected markers', async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
const zipCode = '00882';
|
||||||
|
await wrapper.setData({ zipCode });
|
||||||
|
|
||||||
|
const mockGetCenter = jest.fn();
|
||||||
|
const mockNorthEast = jest.fn();
|
||||||
|
const mockSouthWest = jest.fn();
|
||||||
|
const zipCodeGeocodeResult = {
|
||||||
|
results: [
|
||||||
|
{
|
||||||
|
geometry: {
|
||||||
|
bounds:
|
||||||
|
{
|
||||||
|
getCenter: mockGetCenter,
|
||||||
|
getNorthEast: mockNorthEast,
|
||||||
|
getSouthWest: mockSouthWest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const [address1, address2, position1, position2] = ['a1', 'a2', 'p1', 'p2'];
|
||||||
|
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 newAddresses = [address1, address2];
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.$options.watch.addresses.call(wrapper.vm, newAddresses);
|
||||||
|
|
||||||
|
for (let i = 0; i < 11; i++) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
});
|
||||||
|
describe('method', () => {
|
||||||
|
test('getMap calls map constructor with expected parameters', async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
const center = { lat: 90, lng: -5 };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = await wrapper.vm.getMap(center);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mockMap).toHaveBeenCalledWith(
|
||||||
|
null,
|
||||||
|
expect.objectContaining({ center, mapId: 'map_id', mapTypeControl: false })
|
||||||
|
);
|
||||||
|
expect(result).toBe(mockMapInstance);
|
||||||
|
});
|
||||||
|
test.each([
|
||||||
|
[undefined, 0],
|
||||||
|
[null, 0],
|
||||||
|
[[], 0],
|
||||||
|
[['loc1'], 1],
|
||||||
|
[['loc1', 'loc1', 'loc1', 'loc1'], 4]
|
||||||
|
])(
|
||||||
|
'given parameter %p, getBounds calls extend %p time(s)',
|
||||||
|
(locations, numberOfExtendCalls) => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.getBounds(locations);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mockExtend).toHaveBeenCalledTimes(numberOfExtendCalls);
|
||||||
|
expect(result).toBe(mockLatLngBound);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test.each([
|
||||||
|
[1, null, mockGeocoderInstance],
|
||||||
|
[1, undefined, mockGeocoderInstance],
|
||||||
|
[0, {}, {}],
|
||||||
|
[0, { value: 'any value' }, { value: 'any value' }]
|
||||||
|
])(
|
||||||
|
'setGeocoder calls Geocoder constructor %p time(s) when original geocoder %p and geocoder set to %p',
|
||||||
|
async (numberOfCalls, originalGeocoder, newGeocoder) => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
await wrapper.setData({ geocoder: originalGeocoder });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.setGeocoder();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mockGeocoder).toHaveBeenCalledTimes(numberOfCalls);
|
||||||
|
expect(wrapper.vm.geocoder).toEqual(newGeocoder);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test.each([
|
||||||
|
[null, 0],
|
||||||
|
[undefined, 0],
|
||||||
|
[[], 0],
|
||||||
|
[['p1'], 1],
|
||||||
|
[['p1', 'p2', 'p3'], 3]
|
||||||
|
])(
|
||||||
|
'addMarkersToMap given positions argument %p, creates AdvancedMarkerElement %p time(s)',
|
||||||
|
async (positions, numberOfCalls) => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
const map = jest.fn();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.addMarkersToMap(map, positions);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mockAdvancedMarkerElement).toHaveBeenCalledTimes(numberOfCalls);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
describe('getLocationsFromAddresses', () => {
|
||||||
|
test.each([
|
||||||
|
[null, 0],
|
||||||
|
[undefined, 0],
|
||||||
|
[[], 0],
|
||||||
|
[['a1'], 1],
|
||||||
|
[['a1', 'a2', 'a3'], 3]
|
||||||
|
])(
|
||||||
|
'given address(es) %p calls geocode %p times',
|
||||||
|
async (addresses, numberOfCalls) => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.getLocationsFromAddresses(addresses);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mockGeocode).toHaveBeenCalledTimes(numberOfCalls);
|
||||||
|
expect(wrapper.vm.geocoder).not.toBeNull();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test('only returns geocode results that are not null', async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
const addresses = ['a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8'];
|
||||||
|
mockGeocode.mockImplementationOnce(() => null)
|
||||||
|
.mockImplementationOnce(() => ({ results: null }))
|
||||||
|
.mockImplementationOnce(() => ({ results: [] }))
|
||||||
|
.mockImplementationOnce(() => ({ results: [{}] }))
|
||||||
|
.mockImplementationOnce(() => (
|
||||||
|
{ results: [{ geometry: undefined }] }
|
||||||
|
))
|
||||||
|
.mockImplementationOnce(() => (
|
||||||
|
{ results: [{ geometry: {} }] }
|
||||||
|
))
|
||||||
|
.mockImplementationOnce(() => (
|
||||||
|
{
|
||||||
|
results: [
|
||||||
|
{ geometry: { location: 'some value' } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
))
|
||||||
|
.mockImplementationOnce(() => (
|
||||||
|
{
|
||||||
|
results: [
|
||||||
|
{ geometry: { location: 'some other value' } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
));
|
||||||
|
const expectedResult = ['some value', 'some other value'];
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = await wrapper.vm.getLocationsFromAddresses(addresses);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result.length).toBe(2);
|
||||||
|
expect(result).toEqual(expectedResult);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('getBoundsFromAddress', () => {
|
||||||
|
test('returns expected when geocode returns valid result', async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
const address = 'random address';
|
||||||
|
const expectedResult = 'bounds returned';
|
||||||
|
const geocodeResult = {
|
||||||
|
results: [
|
||||||
|
{
|
||||||
|
geometry: { bounds: expectedResult }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
mockGeocode.mockImplementationOnce(() => Promise.resolve(geocodeResult));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = await wrapper.vm.getBoundsFromAddress(address);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toBe(expectedResult);
|
||||||
|
expect(wrapper.vm.geocoder).not.toBeNull();
|
||||||
|
});
|
||||||
|
test('returns null when geocode returns invalid result', async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
const address = 'random address';
|
||||||
|
mockGeocode.mockImplementationOnce(() => Promise.resolve({}));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = await wrapper.vm.getBoundsFromAddress(address);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toBeNull();
|
||||||
|
expect(wrapper.vm.geocoder).not.toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('createMapWithMarkersForAddresses', () => {
|
||||||
|
test('calls expected when addresses provided', async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
const zipCode = '00882';
|
||||||
|
await wrapper.setData({ zipCode });
|
||||||
|
const mockGetCenter = jest.fn();
|
||||||
|
const mockNorthEast = jest.fn();
|
||||||
|
const mockSouthWest = jest.fn();
|
||||||
|
const zipCodeGeocodeResult = {
|
||||||
|
results: [
|
||||||
|
{
|
||||||
|
geometry: {
|
||||||
|
bounds:
|
||||||
|
{
|
||||||
|
getCenter: mockGetCenter,
|
||||||
|
getNorthEast: mockNorthEast,
|
||||||
|
getSouthWest: mockSouthWest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const shopGeocodeResult = {
|
||||||
|
results: [
|
||||||
|
{ geometry: { location: 'valid location' } }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
mockGeocode.mockImplementation((obj) =>
|
||||||
|
Promise.resolve(obj.address.includes(zipCode)
|
||||||
|
? zipCodeGeocodeResult
|
||||||
|
: shopGeocodeResult));
|
||||||
|
const addresses = ['a1', 'a2'];
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.createMapWithMarkersForAddresses(addresses);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mockMap).toBeCalledTimes(1);
|
||||||
|
expect(mockAdvancedMarkerElement).toBeCalledTimes(2);
|
||||||
|
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.each([null, undefined, []])(
|
||||||
|
'calls expected when addresses argument is "%p"',
|
||||||
|
async (addresses) => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(googleMap, {});
|
||||||
|
const zipCode = '00882';
|
||||||
|
await wrapper.setData({ zipCode });
|
||||||
|
const mockGetCenter = jest.fn();
|
||||||
|
const mockNorthEast = jest.fn();
|
||||||
|
const mockSouthWest = jest.fn();
|
||||||
|
const zipCodeGeocodeResult = {
|
||||||
|
results: [
|
||||||
|
{
|
||||||
|
geometry: {
|
||||||
|
bounds:
|
||||||
|
{
|
||||||
|
getCenter: mockGetCenter,
|
||||||
|
getNorthEast: mockNorthEast,
|
||||||
|
getSouthWest: mockSouthWest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
mockGeocode.mockImplementation(() => Promise.resolve(zipCodeGeocodeResult));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.createMapWithMarkersForAddresses(addresses);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mockMap).toBeCalledTimes(1);
|
||||||
|
expect(mockAdvancedMarkerElement).toBeCalledTimes(0);
|
||||||
|
expect(mockGeocoder).toBeCalledTimes(1);
|
||||||
|
|
||||||
|
expect(mockExtend).toBeCalledTimes(2);
|
||||||
|
expect(mockFitBounds).toBeCalledTimes(1);
|
||||||
|
|
||||||
|
expect(mockGetCenter).toBeCalledTimes(1);
|
||||||
|
expect(mockNorthEast).toBeCalledTimes(1);
|
||||||
|
expect(mockSouthWest).toBeCalledTimes(1);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
93
src/iss-components/google-map/google-map.vue
Normal file
93
src/iss-components/google-map/google-map.vue
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div id="map" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'google-map',
|
||||||
|
props: {
|
||||||
|
addresses: Array,
|
||||||
|
zipCode: String
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
country: 'USA',
|
||||||
|
geocoder: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
zipCodeAddress() {
|
||||||
|
return `${this.zipCode ?? ''} ${this.country}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
async addresses(newAddresses) {
|
||||||
|
this.createMapWithMarkersForAddresses(newAddresses);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async getMap(center) {
|
||||||
|
const { Map } = await window.google.maps.importLibrary('maps');
|
||||||
|
return new Map(document.getElementById('map'), {
|
||||||
|
center,
|
||||||
|
mapId: 'map_id',
|
||||||
|
mapTypeControl: false
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getBounds(locations) {
|
||||||
|
const bounds = new window.google.maps.LatLngBounds();
|
||||||
|
locations?.forEach((location) => bounds.extend(location));
|
||||||
|
return bounds;
|
||||||
|
},
|
||||||
|
async setGeocoder() {
|
||||||
|
if (this.geocoder == null) {
|
||||||
|
const { Geocoder } = await window.google.maps.importLibrary('geocoding');
|
||||||
|
this.geocoder = new Geocoder();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async addMarkersToMap(map, positions) {
|
||||||
|
const { AdvancedMarkerElement } = await window.google.maps.importLibrary('marker');
|
||||||
|
positions?.forEach((position) => new AdvancedMarkerElement({ map, position }));
|
||||||
|
},
|
||||||
|
async getLocationsFromAddresses(addresses) {
|
||||||
|
await this.setGeocoder();
|
||||||
|
|
||||||
|
const geocodeShopAddressPromises = addresses?.map((address) => this.geocoder.geocode({ address })) ?? [];
|
||||||
|
const geocodeShopAddressResults = await Promise.all(geocodeShopAddressPromises);
|
||||||
|
return geocodeShopAddressResults.map((result) =>
|
||||||
|
(result?.results?.length > 0
|
||||||
|
? result.results[0].geometry?.location
|
||||||
|
: null))
|
||||||
|
.filter((loc) => loc != null);
|
||||||
|
},
|
||||||
|
async getBoundsFromAddress(address) {
|
||||||
|
await this.setGeocoder();
|
||||||
|
const result = await this.geocoder.geocode({ address });
|
||||||
|
return result?.results?.length > 0
|
||||||
|
? result.results[0].geometry?.bounds
|
||||||
|
: null;
|
||||||
|
},
|
||||||
|
async createMapWithMarkersForAddresses(addresses) {
|
||||||
|
const shopPositions = await this.getLocationsFromAddresses(addresses);
|
||||||
|
const zipBounds = await this.getBoundsFromAddress(this.zipCodeAddress);
|
||||||
|
const map = await this.getMap(zipBounds.getCenter());
|
||||||
|
|
||||||
|
await this.addMarkersToMap(map, shopPositions);
|
||||||
|
|
||||||
|
const positionsToDisplay = shopPositions.concat(zipBounds.getNorthEast(), zipBounds.getSouthWest());
|
||||||
|
const bounds = this.getBounds(positionsToDisplay);
|
||||||
|
map.fitBounds(bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
#map {
|
||||||
|
height: 250px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -152,7 +152,7 @@ describe('Shop list button', () => {
|
||||||
expect(buttonLabelSubCopy.classes().length).toBe(4);
|
expect(buttonLabelSubCopy.classes().length).toBe(4);
|
||||||
expect(buttonLabelSubCopy.classes()).toContain('m-0');
|
expect(buttonLabelSubCopy.classes()).toContain('m-0');
|
||||||
expect(buttonLabelSubCopy.classes()).toContain('caption');
|
expect(buttonLabelSubCopy.classes()).toContain('caption');
|
||||||
expect(buttonLabelSubCopy.classes()).toContain('ms-1');
|
expect(buttonLabelSubCopy.classes()).toContain('ms-2');
|
||||||
expect(buttonLabelSubCopy.classes()).toContain(textPosition);
|
expect(buttonLabelSubCopy.classes()).toContain(textPosition);
|
||||||
});
|
});
|
||||||
test('when "textPosition" prop not provided', async () => {
|
test('when "textPosition" prop not provided', async () => {
|
||||||
|
|
@ -176,7 +176,7 @@ describe('Shop list button', () => {
|
||||||
expect(buttonLabelSubCopy.classes().length).toBe(3);
|
expect(buttonLabelSubCopy.classes().length).toBe(3);
|
||||||
expect(buttonLabelSubCopy.classes()).toContain('m-0');
|
expect(buttonLabelSubCopy.classes()).toContain('m-0');
|
||||||
expect(buttonLabelSubCopy.classes()).toContain('caption');
|
expect(buttonLabelSubCopy.classes()).toContain('caption');
|
||||||
expect(buttonLabelSubCopy.classes()).toContain('ms-1');
|
expect(buttonLabelSubCopy.classes()).toContain('ms-2');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('availability indicator block with expected when displayAvailabilityIndicators true', () => {
|
describe('availability indicator block with expected when displayAvailabilityIndicators true', () => {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
id="buttonLabelSubCopySpan"
|
id="buttonLabelSubCopySpan"
|
||||||
class="m-0 caption ms-1"
|
class="m-0 caption ms-2"
|
||||||
:class="textPosition">{{ buttonLabelSubCopy }}
|
:class="textPosition">{{ buttonLabelSubCopy }}
|
||||||
</span>
|
</span>
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ Object {
|
||||||
"displayAvailabilityIndicators": false,
|
"displayAvailabilityIndicators": false,
|
||||||
},
|
},
|
||||||
"filter": "",
|
"filter": "",
|
||||||
|
"mapZipCode": "12663",
|
||||||
"providers": Array [],
|
"providers": Array [],
|
||||||
"rules": Object {
|
"rules": Object {
|
||||||
"filter": "option-required",
|
"filter": "option-required",
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRu
|
||||||
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
|
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
|
||||||
|
|
||||||
const wrapper = shallowMount(tpaSearch, mountOptions);
|
const wrapper = shallowMount(tpaSearch, mountOptions);
|
||||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => cmsContent);
|
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {});
|
||||||
wrapper.vm.setCmsContent = jest.fn();
|
wrapper.vm.setCmsContent = jest.fn();
|
||||||
return { wrapper };
|
return { wrapper };
|
||||||
}
|
}
|
||||||
|
|
@ -149,16 +149,31 @@ describe('TPA search page', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(providerSelectionForm.exists()).toBeTruthy();
|
expect(providerSelectionForm.exists()).toBeTruthy();
|
||||||
});
|
});
|
||||||
test('map', () => {
|
test('map', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
const zipCode = '12345';
|
||||||
|
const { wrapper } = getMountedComponent();
|
||||||
|
await wrapper.setData({
|
||||||
|
providers: [{
|
||||||
|
address: {
|
||||||
|
streetAddress: '123 Lane Ave',
|
||||||
|
city: 'New York',
|
||||||
|
state: 'NY',
|
||||||
|
zipCode: '99230'
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
mapZipCode: zipCode
|
||||||
|
});
|
||||||
|
const expectedAddresses = ['123 Lane Ave, New York, NY 99230'];
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const map = wrapper.find('#map');
|
const map = wrapper.findComponent('#map');
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(map.exists()).toBeTruthy();
|
expect(map.exists()).toBeTruthy();
|
||||||
expect(map.classes()).toContain('mb-4');
|
expect(map.classes()).toContain('mb-4');
|
||||||
|
expect(map.props().addresses).toEqual(expectedAddresses);
|
||||||
|
expect(map.props().zipCode).toBe(zipCode);
|
||||||
});
|
});
|
||||||
test('search radius filter', () => {
|
test('search radius filter', () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
|
|
@ -173,9 +188,32 @@ 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', () => {
|
test('select provider question', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
await wrapper.setData({
|
||||||
|
providers: [{
|
||||||
|
name: 'Shop Auto Glass',
|
||||||
|
phoneNumber: '740-555-1234',
|
||||||
|
distanceInMiles: 1.2345,
|
||||||
|
providerNumber: '232209',
|
||||||
|
address: {
|
||||||
|
streetAddress: '123 Lane Ave',
|
||||||
|
city: 'New York',
|
||||||
|
state: 'NY',
|
||||||
|
zipCode: '99230'
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
const expectedAnswers = [{
|
||||||
|
buttonLabel: 'Shop Auto Glass',
|
||||||
|
buttonLabelSubCopy: '1.2 mi',
|
||||||
|
buttonBodyCopy: '123 Lane Ave, New York, NY 99230<br>740-555-1234',
|
||||||
|
value: '232209'
|
||||||
|
}];
|
||||||
|
const expectedAdditionalButtonData = {
|
||||||
|
displayAvailabilityIndicators: false
|
||||||
|
};
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const selectProviderQuestion = wrapper.findComponent('#selectProviderQuestion');
|
const selectProviderQuestion = wrapper.findComponent('#selectProviderQuestion');
|
||||||
|
|
@ -188,6 +226,8 @@ describe('TPA search page', () => {
|
||||||
expect(selectProviderQuestion.props().textPosition).toBe('text-start');
|
expect(selectProviderQuestion.props().textPosition).toBe('text-start');
|
||||||
expect(selectProviderQuestion.props().isRequired).toBeTruthy();
|
expect(selectProviderQuestion.props().isRequired).toBeTruthy();
|
||||||
expect(selectProviderQuestion.props().validationRules).toBe(globalRules.OPTION_REQUIRED);
|
expect(selectProviderQuestion.props().validationRules).toBe(globalRules.OPTION_REQUIRED);
|
||||||
|
expect(selectProviderQuestion.props().answers).toEqual(expectedAnswers);
|
||||||
|
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',
|
||||||
|
|
@ -447,12 +487,143 @@ describe('TPA search page', () => {
|
||||||
expect(result).toEqual(expected);
|
expect(result).toEqual(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('providerAddresses', () => {
|
||||||
|
test.each([null, undefined, []])(
|
||||||
|
'returns empty list when providers empty',
|
||||||
|
async (providers) => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
await wrapper.setData({ providers });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.providerAddresses;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toEqual([]);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test('returns expected when providers not empty', async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
await wrapper.setData({
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
name: 'Shop Auto Glass',
|
||||||
|
phoneNumber: '740-555-1234',
|
||||||
|
distanceInMiles: 1.2345,
|
||||||
|
providerNumber: '232209',
|
||||||
|
address: {
|
||||||
|
streetAddress: '123 Lane Ave',
|
||||||
|
city: 'New York',
|
||||||
|
state: 'NY',
|
||||||
|
zipCode: '99230'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Safelite AutoGlass',
|
||||||
|
phoneNumber: '676-555-0099',
|
||||||
|
distanceInMiles: 123.9452,
|
||||||
|
providerNumber: '123456',
|
||||||
|
address: {
|
||||||
|
streetAddress: '2003 Coral Ln',
|
||||||
|
city: 'Birmingham',
|
||||||
|
state: 'AL',
|
||||||
|
zipCode: '43001'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
const expectedResult = [
|
||||||
|
'123 Lane Ave, New York, NY 99230',
|
||||||
|
'2003 Coral Ln, Birmingham, AL 43001'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.providerAddresses;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toEqual(expectedResult);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('providerButtonData', () => {
|
||||||
|
test.each([null, undefined, []])(
|
||||||
|
'returns empty list when providers empty',
|
||||||
|
async (providers) => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
await wrapper.setData({ providers });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.providerButtonData;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toEqual([]);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test('returns expected when providers not empty', async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
await wrapper.setData({
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
name: 'Shop Auto Glass',
|
||||||
|
phoneNumber: '740-555-1234',
|
||||||
|
distanceInMiles: 1.2345,
|
||||||
|
providerNumber: '232209',
|
||||||
|
address: {
|
||||||
|
streetAddress: '123 Lane Ave',
|
||||||
|
city: 'New York',
|
||||||
|
state: 'NY',
|
||||||
|
zipCode: '99230'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Safelite AutoGlass',
|
||||||
|
phoneNumber: '676-555-0099',
|
||||||
|
distanceInMiles: 123.9452,
|
||||||
|
providerNumber: '123456',
|
||||||
|
address: {
|
||||||
|
streetAddress: '2003 Coral Ln',
|
||||||
|
city: 'Birmingham',
|
||||||
|
state: 'AL',
|
||||||
|
zipCode: '43001'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
const expectedResult = [
|
||||||
|
{
|
||||||
|
buttonLabel: 'Shop Auto Glass',
|
||||||
|
buttonLabelSubCopy: '1.2 mi',
|
||||||
|
buttonBodyCopy: '123 Lane Ave, New York, NY 99230<br>740-555-1234',
|
||||||
|
value: '232209'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
buttonLabel: 'Safelite AutoGlass',
|
||||||
|
buttonLabelSubCopy: '123.9 mi',
|
||||||
|
buttonBodyCopy: '2003 Coral Ln, Birmingham, AL 43001<br>676-555-0099',
|
||||||
|
value: '123456'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.providerButtonData;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toEqual(expectedResult);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe('watch', () => {
|
describe('watch', () => {
|
||||||
test('on filter calls getTpaProviders and sets providers', async () => {
|
test('on filter calls getTpaProviders and sets providers', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = getMountedComponent();
|
const zipCode = '78220';
|
||||||
const providers = { data: ['some data', 'some more data'] };
|
const initialMapZipCode = '88800';
|
||||||
|
const { wrapper } = getMountedComponent({}, {
|
||||||
|
zipCode,
|
||||||
|
mapZipCode: initialMapZipCode
|
||||||
|
});
|
||||||
|
const providers = { data: { shopProviders: ['some data', 'some more data']} };
|
||||||
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (providers));
|
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (providers));
|
||||||
const newFilter = 'new filter';
|
const newFilter = 'new filter';
|
||||||
|
|
||||||
|
|
@ -461,7 +632,8 @@ describe('TPA search page', () => {
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(useMainStore().getTpaProviders).toBeCalled();
|
expect(useMainStore().getTpaProviders).toBeCalled();
|
||||||
expect(wrapper.vm.providers).toEqual(providers.data);
|
expect(wrapper.vm.providers).toEqual(providers.data.shopProviders);
|
||||||
|
expect(wrapper.vm.mapZipCode).toBe(zipCode);
|
||||||
});
|
});
|
||||||
describe('on providers', () => {
|
describe('on providers', () => {
|
||||||
test.each([null, undefined, []])(
|
test.each([null, undefined, []])(
|
||||||
|
|
@ -481,7 +653,7 @@ describe('TPA search page', () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = getMountedComponent();
|
const { wrapper } = getMountedComponent();
|
||||||
const value = 'some value';
|
const value = 'some value';
|
||||||
const newProviders = [{ value }];
|
const newProviders = [{ providerNumber: value }];
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
wrapper.vm.$options.watch.providers.call(wrapper.vm, newProviders);
|
wrapper.vm.$options.watch.providers.call(wrapper.vm, newProviders);
|
||||||
|
|
@ -503,7 +675,35 @@ describe('TPA search page', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('method', () => {
|
describe('method', () => {
|
||||||
describe('getProviders', () => {
|
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'],
|
||||||
|
[null, null, null, null, '']
|
||||||
|
])(
|
||||||
|
'getProviderAddress returns expected',
|
||||||
|
(streetAddress, city, state, zipCode, expected) => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = getMountedComponent();
|
||||||
|
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (newProviders));
|
||||||
|
const provider = {
|
||||||
|
address: {
|
||||||
|
streetAddress,
|
||||||
|
city,
|
||||||
|
state,
|
||||||
|
zipCode
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.getProviderAddress(provider);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
describe('getProviderButtonData', () => {
|
||||||
test.each([null, undefined, {}])(
|
test.each([null, undefined, {}])(
|
||||||
'returns empty list when getTpaProviders returns no data',
|
'returns empty list when getTpaProviders returns no data',
|
||||||
async (newProviders) => {
|
async (newProviders) => {
|
||||||
|
|
@ -512,7 +712,7 @@ describe('TPA search page', () => {
|
||||||
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (newProviders));
|
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (newProviders));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = await wrapper.vm.getProviders();
|
const result = await wrapper.vm.getProviderButtonData();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(result).toEqual([]);
|
expect(result).toEqual([]);
|
||||||
|
|
@ -521,14 +721,18 @@ describe('TPA search page', () => {
|
||||||
test('returns expected when getTpaProviders returns data', async () => {
|
test('returns expected when getTpaProviders returns data', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = getMountedComponent();
|
const { wrapper } = getMountedComponent();
|
||||||
const providers = { data: [{ name: 'foo' }] };
|
const providers = {
|
||||||
|
data: {
|
||||||
|
shopProviders: [{ name: 'foo' }]
|
||||||
|
}
|
||||||
|
};
|
||||||
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (providers));
|
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (providers));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = await wrapper.vm.getProviders();
|
const result = await wrapper.vm.getProviderButtonData();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(result).toEqual(providers.data);
|
expect(result).toEqual(providers.data.shopProviders);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
test('doNotSeeMyShopLinkClick invokes navigate method', () => {
|
test('doNotSeeMyShopLinkClick invokes navigate method', () => {
|
||||||
|
|
@ -546,7 +750,12 @@ describe('TPA search page', () => {
|
||||||
'sets providers to empty list when no data returned from getProviders',
|
'sets providers to empty list when no data returned from getProviders',
|
||||||
async (newProviders) => {
|
async (newProviders) => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = getMountedComponent();
|
const zipCode = '28331';
|
||||||
|
const initialMapZipCode = '10022';
|
||||||
|
const { wrapper } = getMountedComponent({}, {
|
||||||
|
zipCode,
|
||||||
|
mapZipCode: initialMapZipCode
|
||||||
|
});
|
||||||
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (newProviders));
|
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (newProviders));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -554,19 +763,28 @@ describe('TPA search page', () => {
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.providers).toEqual([]);
|
expect(wrapper.vm.providers).toEqual([]);
|
||||||
|
expect(wrapper.vm.mapZipCode).toEqual(zipCode);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
test('returns value from getProviders', async () => {
|
test('returns value from getProviders', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = getMountedComponent();
|
const zipCode = '12990';
|
||||||
const newProviders = { data: [{ name: 'foo' }] };
|
const initialMapZipCode = '00981';
|
||||||
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => (newProviders));
|
const { wrapper } = getMountedComponent({}, {
|
||||||
|
zipCode,
|
||||||
|
mapZipCode: initialMapZipCode
|
||||||
|
});
|
||||||
|
const shopProviders = [{ name: 'foo' }];
|
||||||
|
useMainStore().getTpaProviders = jest.fn().mockImplementationOnce(() => ({
|
||||||
|
data: { shopProviders }
|
||||||
|
}));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await wrapper.vm.searchClick();
|
await wrapper.vm.searchClick();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.providers).toEqual(newProviders.data);
|
expect(wrapper.vm.providers).toEqual(shopProviders);
|
||||||
|
expect(wrapper.vm.mapZipCode).toEqual(zipCode);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
test('backButtonAction invokes navigate method', () => {
|
test('backButtonAction invokes navigate method', () => {
|
||||||
|
|
@ -613,32 +831,162 @@ describe('TPA search page', () => {
|
||||||
expect(result).toBeNull();
|
expect(result).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
test.each([undefined, null, 'some value', ''])(
|
describe('getShopButtonDataFromProvider', () => {
|
||||||
'setFilter sets value of filter',
|
test.each([null, undefined, {}])(
|
||||||
(filter) => {
|
'returns empty list given parameter with no provider',
|
||||||
|
(provider) => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
const expectedResult = {
|
||||||
|
buttonLabel: '',
|
||||||
|
buttonLabelSubCopy: '',
|
||||||
|
buttonBodyCopy: '<br>',
|
||||||
|
value: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.getShopButtonDataFromProvider(provider);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toEqual(expectedResult);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test('returns expected given provider', () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = getMountedComponent();
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
const provider = {
|
||||||
|
name: 'Shop Auto Glass',
|
||||||
|
phoneNumber: '740-555-1234',
|
||||||
|
distanceInMiles: 1.2345,
|
||||||
|
providerNumber: '232209',
|
||||||
|
address: {
|
||||||
|
streetAddress: '123 Lane Ave',
|
||||||
|
city: 'New York',
|
||||||
|
state: 'NY',
|
||||||
|
zipCode: '99230'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const expectedResult = {
|
||||||
|
buttonLabel: 'Shop Auto Glass',
|
||||||
|
buttonLabelSubCopy: '1.2 mi',
|
||||||
|
buttonBodyCopy: '123 Lane Ave, New York, NY 99230<br>740-555-1234',
|
||||||
|
value: '232209'
|
||||||
|
};
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
wrapper.vm.setFilter(filter);
|
const result = wrapper.vm.getShopButtonDataFromProvider(provider);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.filter).toEqual(filter);
|
expect(result).toEqual(expectedResult);
|
||||||
}
|
});
|
||||||
);
|
describe('returns result with button label', () => {
|
||||||
test.each([undefined, null, ['some value'], []])(
|
test.each(['', undefined, null])(
|
||||||
'setProviders sets value of providers',
|
'equal to empty string when name is empty',
|
||||||
(providers) => {
|
(name) => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
const provider = { name };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.getShopButtonDataFromProvider(provider);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result.buttonLabel).toEqual('');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test('returns provider name when exists', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
const name = 'Some Shop Name';
|
||||||
|
const provider = { name };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.getShopButtonDataFromProvider(provider);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result.buttonLabel).toEqual(name);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('returns result with button label sub copy', () => {
|
||||||
|
test.each([null, undefined, 'random string'])(
|
||||||
|
'as empty string when distanceInMiles is not a number',
|
||||||
|
(distanceInMiles) => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
const provider = { distanceInMiles };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.getShopButtonDataFromProvider(provider);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result.buttonLabelSubCopy).toEqual('');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test.each([[0, 0], [0, 0.000], [-7.89, -7.9], [109, 109], [1.234, 1.2], [2.99, 3]])(
|
||||||
|
'displays expected distance value',
|
||||||
|
(distanceInMiles, displayedDistance) => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
const provider = { distanceInMiles };
|
||||||
|
const expectedSubCopy = `${displayedDistance} mi`;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.getShopButtonDataFromProvider(provider);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result.buttonLabelSubCopy).toEqual(expectedSubCopy);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
test('returns result with button body copy showing expected address and phone number', () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = getMountedComponent();
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
const provider = {
|
||||||
|
phoneNumber: '123-555-0099',
|
||||||
|
address: {
|
||||||
|
streetAddress: '434 Up Down Blvd',
|
||||||
|
city: 'San Francisco',
|
||||||
|
state: 'CA',
|
||||||
|
zipCode: '90887'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const expected = '434 Up Down Blvd, San Francisco, CA 90887<br>123-555-0099';
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
wrapper.vm.setProviders(providers);
|
const result = wrapper.vm.getShopButtonDataFromProvider(provider);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.providers).toEqual(providers);
|
expect(result.buttonBodyCopy).toEqual(expected);
|
||||||
}
|
});
|
||||||
);
|
describe('returns result with value', () => {
|
||||||
|
test.each(['', undefined, null])(
|
||||||
|
'equal to empty string when providerNumber is empty',
|
||||||
|
(providerNumber) => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
const provider = { providerNumber };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.getShopButtonDataFromProvider(provider);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result.value).toEqual('');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test('returns provider number when exists', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(tpaSearch, getMountOptions());
|
||||||
|
const providerNumber = '123391';
|
||||||
|
const provider = { providerNumber };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = wrapper.vm.getShopButtonDataFromProvider(provider);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result.value).toEqual(providerNumber);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe('before route enter', () => {
|
describe('before route enter', () => {
|
||||||
test('when providers exist at 25 mile radius, filter is set to "25 miles" and providers set to expected', async () => {
|
test('when providers exist at 25 mile radius, filter is set to "25 miles" and providers set to expected', async () => {
|
||||||
|
|
@ -646,8 +994,9 @@ 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 = { data: [{ name: 'provider' }] };
|
const providers = [{ name: 'provider' }];
|
||||||
useMainStore().getTpaProviders = jest.fn().mockImplementation((_, radius) => (radius === 25 ? providers : []));
|
useMainStore().getTpaProviders = jest.fn().mockImplementation((_, radius) =>
|
||||||
|
({ data: { shopProviders: radius === 25 ? providers : [] } }));
|
||||||
const expectedFilter = '25 miles';
|
const expectedFilter = '25 miles';
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -658,6 +1007,9 @@ describe('TPA search page', () => {
|
||||||
(c) => c(wrapper.vm)
|
(c) => c(wrapper.vm)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
@ -667,8 +1019,9 @@ 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 = { data: [{ name: 'provider' }] };
|
const providers = [{ name: 'provider' }];
|
||||||
useMainStore().getTpaProviders = jest.fn().mockImplementation((_, radius) => (radius === 50 ? providers : []));
|
useMainStore().getTpaProviders = jest.fn().mockImplementation((_, radius) =>
|
||||||
|
({ data: { shopProviders: radius === 50 ? providers : [] } }));
|
||||||
const expectedFilter = '50 miles';
|
const expectedFilter = '50 miles';
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -679,6 +1032,9 @@ describe('TPA search page', () => {
|
||||||
(c) => c(wrapper.vm)
|
(c) => c(wrapper.vm)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
@ -690,8 +1046,9 @@ 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 = { data: [{ name: 'provider' }] };
|
const providers = [{ name: 'provider' }];
|
||||||
useMainStore().getTpaProviders = jest.fn().mockImplementation((_, radius) => (radius === 100 ? providers : []));
|
useMainStore().getTpaProviders = jest.fn().mockImplementation((_, radius) =>
|
||||||
|
({ data: { shopProviders: radius === 100 ? providers : [] } }));
|
||||||
const expectedFilter = '100 miles';
|
const expectedFilter = '100 miles';
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -702,6 +1059,9 @@ describe('TPA search page', () => {
|
||||||
(c) => c(wrapper.vm)
|
(c) => c(wrapper.vm)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
@ -725,6 +1085,9 @@ describe('TPA search page', () => {
|
||||||
(c) => c(wrapper.vm)
|
(c) => c(wrapper.vm)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.filter).toBe(expectedFilter);
|
expect(wrapper.vm.filter).toBe(expectedFilter);
|
||||||
expect(wrapper.vm.providers).toEqual([]);
|
expect(wrapper.vm.providers).toEqual([]);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="page-container-grouped-styles">
|
||||||
|
<div class="fade-on-route-transition">
|
||||||
<siteHeader
|
<siteHeader
|
||||||
ref="siteHeader"
|
ref="siteHeader"
|
||||||
:cmsWidgetName="widget.siteHeader" />
|
:cmsWidgetName="widget.siteHeader" />
|
||||||
|
|
@ -36,18 +37,17 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
<googleMap
|
||||||
|
id="map"
|
||||||
|
class="mb-4"
|
||||||
|
:addresses="providerAddresses"
|
||||||
|
:zipCode="mapZipCode"></googleMap>
|
||||||
<Form
|
<Form
|
||||||
id="providerSelectionForm"
|
id="providerSelectionForm"
|
||||||
v-slot="{ meta }"
|
v-slot="{ meta }"
|
||||||
@submit="onSubmit"
|
@submit="onSubmit"
|
||||||
@invalidSubmit="onInvalidSubmit">
|
@invalidSubmit="onInvalidSubmit">
|
||||||
<div class="container-fluid pb-2">
|
<div class="container-fluid pb-2">
|
||||||
<p
|
|
||||||
id="map"
|
|
||||||
class="mb-4">
|
|
||||||
Placeholder for Map
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="mx-5">
|
<div class="mx-5">
|
||||||
<dropdownQuestion
|
<dropdownQuestion
|
||||||
id="searchRadiusFilter"
|
id="searchRadiusFilter"
|
||||||
|
|
@ -65,7 +65,7 @@
|
||||||
buttonTypeString="shopListButton"
|
buttonTypeString="shopListButton"
|
||||||
:buttonTypeObject="shopListButton"
|
:buttonTypeObject="shopListButton"
|
||||||
class="radioQuestion"
|
class="radioQuestion"
|
||||||
:answers="providers"
|
:answers="providerButtonData"
|
||||||
groupName="chooseShop"
|
groupName="chooseShop"
|
||||||
textPosition="text-start"
|
textPosition="text-start"
|
||||||
isRequired
|
isRequired
|
||||||
|
|
@ -98,6 +98,7 @@
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
|
|
@ -105,11 +106,12 @@ import { Form } from 'vee-validate';
|
||||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||||
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
|
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
|
||||||
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
|
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
|
||||||
import buttonQuestion from '@/digital-components/button-question/button-question.vue'
|
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||||
import shopListButton from '@/iss-components/shop-list-button/shop-list-button.vue'
|
|
||||||
import textLink from '@/ux-components/text-link/text-link.vue';
|
import textLink from '@/ux-components/text-link/text-link.vue';
|
||||||
import alert from '@/ux-components/alert/alert.vue';
|
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 shopListButton from '@/iss-components/shop-list-button/shop-list-button.vue';
|
||||||
|
|
||||||
// Supporting files
|
// Supporting files
|
||||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||||
|
|
@ -118,7 +120,6 @@ 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 routerParams from '@/router/router-constants/router-params';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'tpa-search',
|
name: 'tpa-search',
|
||||||
|
|
@ -129,6 +130,7 @@ export default {
|
||||||
buttonQuestion,
|
buttonQuestion,
|
||||||
textLink,
|
textLink,
|
||||||
alert,
|
alert,
|
||||||
|
googleMap,
|
||||||
siteFooter,
|
siteFooter,
|
||||||
// eslint-disable-next-line vue/no-reserved-component-names
|
// eslint-disable-next-line vue/no-reserved-component-names
|
||||||
Form
|
Form
|
||||||
|
|
@ -144,34 +146,16 @@ export default {
|
||||||
];
|
];
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
||||||
const radiusOptions = [25, 50, 100];
|
next(async (vm) => {
|
||||||
const { zipCode } = useMainStore().order.customer.address;
|
|
||||||
|
|
||||||
const tpaProvidersRadius25 = await useMainStore().getTpaProviders(zipCode, radiusOptions[0]);
|
|
||||||
const tpaProvidersRadius50 = await useMainStore().getTpaProviders(zipCode, radiusOptions[1]);
|
|
||||||
const tpaProvidersRadius100 = await useMainStore().getTpaProviders(zipCode, radiusOptions[2]);
|
|
||||||
let radius = '25 miles';
|
|
||||||
|
|
||||||
let providers = tpaProvidersRadius25;
|
|
||||||
if ((tpaProvidersRadius25?.data ?? []).length === 0) {
|
|
||||||
radius = '50 miles';
|
|
||||||
providers = tpaProvidersRadius50;
|
|
||||||
if ((tpaProvidersRadius50?.data ?? []).length === 0) {
|
|
||||||
radius = '100 miles';
|
|
||||||
providers = tpaProvidersRadius100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
next((vm) => {
|
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
vm.setFilter(radius);
|
await vm.setInitialFilterAndProviders();
|
||||||
vm.setProviders(providers);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const { zipCode } = useMainStore().order.customer.address;
|
const { zipCode } = useMainStore().order.customer.address;
|
||||||
return {
|
return {
|
||||||
zipCode,
|
zipCode,
|
||||||
|
mapZipCode: zipCode,
|
||||||
filter: '',
|
filter: '',
|
||||||
providers: [],
|
providers: [],
|
||||||
selectedProviderNumber: '',
|
selectedProviderNumber: '',
|
||||||
|
|
@ -242,24 +226,79 @@ export default {
|
||||||
this.widget.noNetworkShopsAlert,
|
this.widget.noNetworkShopsAlert,
|
||||||
widgetFields.ALERT_WIDGET.HEADLINE_TEXT
|
widgetFields.ALERT_WIDGET.HEADLINE_TEXT
|
||||||
)?.replaceAll('{custom:radiusInMiles}', this.radiusInMiles);
|
)?.replaceAll('{custom:radiusInMiles}', this.radiusInMiles);
|
||||||
|
},
|
||||||
|
providerAddresses() {
|
||||||
|
return this.providers?.map((provider) => this.getProviderAddress(provider)) ?? [];
|
||||||
|
},
|
||||||
|
providerButtonData() {
|
||||||
|
return this.providers?.map((provider) => this.getShopButtonDataFromProvider(provider)) ?? [];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
async filter() {
|
async filter() {
|
||||||
// TODO right now this results in getProviders being called once more than it needs to be
|
// TODO right now this results in getProviders being called once more than it needs to be
|
||||||
this.providers = await this.getProviders();
|
this.providers = await this.getProviderButtonData();
|
||||||
|
this.mapZipCode = this.zipCode;
|
||||||
},
|
},
|
||||||
providers(newProviders) {
|
providers(newProviders) {
|
||||||
this.selectedProviderNumber = newProviders?.length === 1 ?? false
|
this.selectedProviderNumber = newProviders?.length === 1 ?? false
|
||||||
? newProviders[0].value
|
? newProviders[0].providerNumber
|
||||||
: '';
|
: '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods:
|
methods:
|
||||||
{
|
{
|
||||||
async getProviders() {
|
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() {
|
||||||
|
const radiusOptions = [25, 50, 100];
|
||||||
|
const { zipCode } = useMainStore().order.customer.address;
|
||||||
|
|
||||||
|
const tpaProvidersRadius25 = await useMainStore().getTpaProviders(zipCode, radiusOptions[0]);
|
||||||
|
const tpaProvidersRadius50 = await useMainStore().getTpaProviders(zipCode, radiusOptions[1]);
|
||||||
|
const tpaProvidersRadius100 = await useMainStore().getTpaProviders(zipCode, radiusOptions[2]);
|
||||||
|
let radius = '25 miles';
|
||||||
|
|
||||||
|
let providers = tpaProvidersRadius25;
|
||||||
|
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.providers = providers?.data?.shopProviders ?? [];
|
||||||
|
},
|
||||||
|
async getProviderButtonData() {
|
||||||
const getTpaProvidersResult = await useMainStore().getTpaProviders(this.zipCode, this.radiusInMiles);
|
const getTpaProvidersResult = await useMainStore().getTpaProviders(this.zipCode, this.radiusInMiles);
|
||||||
return getTpaProvidersResult?.data ?? [];
|
return getTpaProvidersResult?.data?.shopProviders ?? [];
|
||||||
},
|
},
|
||||||
doNotSeeMyShopLinkClick() {
|
doNotSeeMyShopLinkClick() {
|
||||||
this.$router.navigate(
|
this.$router.navigate(
|
||||||
|
|
@ -268,7 +307,8 @@ export default {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
async searchClick() {
|
async searchClick() {
|
||||||
this.providers = await this.getProviders();
|
this.providers = await this.getProviderButtonData();
|
||||||
|
this.mapZipCode = this.zipCode;
|
||||||
},
|
},
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
|
|
@ -287,11 +327,20 @@ export default {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setFilter(filter) {
|
getShopButtonDataFromProvider(provider) {
|
||||||
this.filter = filter;
|
const cellNumber = provider?.phoneNumber ?? '';
|
||||||
},
|
const distance = provider?.distanceInMiles !== null && !Number.isNaN(parseFloat(provider?.distanceInMiles))
|
||||||
setProviders(providers) {
|
? +provider.distanceInMiles.toFixed(1)
|
||||||
this.providers = providers;
|
: null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
buttonLabel: provider?.name ?? '',
|
||||||
|
buttonLabelSubCopy: distance === null
|
||||||
|
? ''
|
||||||
|
: `${distance} mi`,
|
||||||
|
buttonBodyCopy: `${this.getProviderAddress(provider)}<br>${cellNumber ?? ''}`,
|
||||||
|
value: provider?.providerNumber ?? ''
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -848,38 +848,76 @@ export const useMainStore = defineStore({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO what info is returned here
|
// TODO update with real endpoint
|
||||||
getTpaProviders(zipCode, radius) {
|
getTpaProviders(zipCode, radius) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (radius === 25) {
|
if (radius === 25) {
|
||||||
resolve({});
|
resolve({
|
||||||
|
data: {
|
||||||
|
mobileProviderNumber: null,
|
||||||
|
shopProviders: null
|
||||||
|
}
|
||||||
|
});
|
||||||
} else if (radius === 50) {
|
} else if (radius === 50) {
|
||||||
resolve({
|
resolve({
|
||||||
data: [
|
data: {
|
||||||
{
|
mobileProviderNumber: null,
|
||||||
buttonLabel: 'USA Auto Glass',
|
shopProviders: [
|
||||||
buttonLabelSubCopy: '1.5 mi',
|
{
|
||||||
buttonBodyCopy: '760 Dearborn Park Ln, Worthington, OH 43085<br>614-123-5555',
|
name: 'USA Auto Glass',
|
||||||
value: '000123'
|
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 {
|
} else {
|
||||||
resolve({
|
resolve({
|
||||||
data: [
|
data: {
|
||||||
{
|
mobileProviderNumber: null,
|
||||||
buttonLabel: 'USA Auto Glass',
|
shopProviders: [
|
||||||
buttonLabelSubCopy: '1.5 mi',
|
{
|
||||||
buttonBodyCopy: '760 Dearborn Park Ln, Worthington, OH 43085<br>614-123-5555',
|
name: 'USA Auto Glass',
|
||||||
value: '000123'
|
address: {
|
||||||
},
|
city: 'WESTERVILLE',
|
||||||
{
|
country: 'US',
|
||||||
buttonLabel: 'USA Auto Glass',
|
state: 'OH',
|
||||||
buttonLabelSubCopy: '1.5 mi',
|
streetAddress: '4403 EXECUTIVE PKWY',
|
||||||
buttonBodyCopy: '760 Dearborn Park Ln, Worthington, OH 43085<br>614-123-5555',
|
streetAddress2: '',
|
||||||
value: '000123'
|
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'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY =
|
||||||
"(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-KKNWZ3');";
|
"(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-KKNWZ3');";
|
||||||
process.env.VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC =
|
process.env.VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC =
|
||||||
'https://www.googletagmanager.com/ns.html?id=GTM-KKNWZ3>m_auth=amlAYNhxUxuskQo7jmjadg>m_preview=env-38>m_cookies_win=x';
|
'https://www.googletagmanager.com/ns.html?id=GTM-KKNWZ3>m_auth=amlAYNhxUxuskQo7jmjadg>m_preview=env-38>m_cookies_win=x';
|
||||||
|
process.env.VUE_APP_GOOGLE_MAPS_API_SCRIPT =
|
||||||
|
"(g=>{var h,a,k,p='The Google Maps JavaScript API',c='google',l='importLibrary',q='__ib__',m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement('script'));e.set('libraries',[...r]+'');for(k in g)e.set(k.replace(/[A-Z]/g,t=>'_'+t[0].toLowerCase()),g[k]);e.set('callback',c+'.maps.'+q);a.src=`https://maps.googleapis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+' could not load.'));a.nonce=m.querySelector('script[nonce]')?.nonce||'';m.head.append(a)}));d[l]?console.warn(p+' only loads once. Ignoring:',g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({key: 'AIzaSyCuLhQcDdZTTb4JzpUFms1OCch2dk5lHF0', v: 'weekly'});";
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
publicPath: '/',
|
publicPath: '/',
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ process.env.VUE_APP_GOOGLE_PLACES_API_KEY = "__VUE_APP_GOOGLE_PLACES_API_KEY__";
|
||||||
// GA & GTM
|
// GA & GTM
|
||||||
process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY = "__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__";
|
process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY = "__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__";
|
||||||
process.env.VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC = "__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__"
|
process.env.VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC = "__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__"
|
||||||
|
process.env.VUE_APP_GOOGLE_MAPS_API_SCRIPT = "__VUE_APP_GOOGLE_MAPS_API_SCRIPT__";
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
publicPath: "/",
|
publicPath: "/",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue