Finishing unit tests
This commit is contained in:
parent
612a2f8b7b
commit
352f3acb43
4 changed files with 418 additions and 11 deletions
|
|
@ -1,6 +1,6 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Google Maps should render expected initial data 1`] = `
|
||||
exports[`Google Map should render expected initial data 1`] = `
|
||||
Object {
|
||||
"country": "USA",
|
||||
"geocoder": null,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,53 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import googleMap from '@/iss-components/google-map/google-map.vue';
|
||||
|
||||
describe('Google Maps', () => {
|
||||
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
|
||||
|
|
@ -15,7 +61,6 @@ describe('Google Maps', () => {
|
|||
// Arrange
|
||||
const mapReference = '#map';
|
||||
const wrapper = shallowMount(googleMap, {});
|
||||
// await wrapper.vm.$nextTick();
|
||||
|
||||
// Act
|
||||
const map = wrapper.find(mapReference);
|
||||
|
|
@ -24,4 +69,360 @@ describe('Google Maps', () => {
|
|||
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);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,12 +7,10 @@
|
|||
<script>
|
||||
export default {
|
||||
name: 'google-map',
|
||||
components: { },
|
||||
props: {
|
||||
addresses: Array,
|
||||
zipCode: String
|
||||
},
|
||||
emits: [],
|
||||
data() {
|
||||
return {
|
||||
country: 'USA',
|
||||
|
|
@ -21,7 +19,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
zipCodeAddress() {
|
||||
return `${this.zipCode} ${this.country}`;
|
||||
return `${this.zipCode ?? ''} ${this.country}`;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
@ -40,7 +38,7 @@ export default {
|
|||
},
|
||||
getBounds(locations) {
|
||||
const bounds = new window.google.maps.LatLngBounds();
|
||||
locations.forEach((location) => bounds.extend(location));
|
||||
locations?.forEach((location) => bounds.extend(location));
|
||||
return bounds;
|
||||
},
|
||||
async setGeocoder() {
|
||||
|
|
@ -51,19 +49,25 @@ export default {
|
|||
},
|
||||
async addMarkersToMap(map, positions) {
|
||||
const { AdvancedMarkerElement } = await window.google.maps.importLibrary('marker');
|
||||
positions.forEach((position) => new AdvancedMarkerElement({ map, position }));
|
||||
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[0].geometry.location);
|
||||
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[0].geometry.bounds;
|
||||
return result?.results?.length > 0
|
||||
? result.results[0].geometry?.bounds
|
||||
: null;
|
||||
},
|
||||
async createMapWithMarkersForAddresses(addresses) {
|
||||
const shopPositions = await this.getLocationsFromAddresses(addresses);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition">
|
||||
<siteHeader
|
||||
ref="siteHeader"
|
||||
:cmsWidgetName="widget.siteHeader" />
|
||||
|
|
@ -97,6 +98,7 @@
|
|||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
// Components
|
||||
|
|
|
|||
Loading…
Reference in a new issue