diff --git a/src/iss-components/google-map/__snapshots__/google-map.spec.js.snap b/src/iss-components/google-map/__snapshots__/google-map.spec.js.snap index 74a1d74d..87f5298e 100644 --- a/src/iss-components/google-map/__snapshots__/google-map.spec.js.snap +++ b/src/iss-components/google-map/__snapshots__/google-map.spec.js.snap @@ -20,5 +20,6 @@ Object { ], }, }, + "infoWindow": null, } `; diff --git a/src/iss-components/google-map/google-map.spec.js b/src/iss-components/google-map/google-map.spec.js index b26d36a2..331c78e1 100644 --- a/src/iss-components/google-map/google-map.spec.js +++ b/src/iss-components/google-map/google-map.spec.js @@ -21,12 +21,19 @@ const mockGeocoderInstance2 = { }; const mockGeocoder = jest.fn(() => (mockGeocoderInstance1)); -const mockAdvancedMarkerElement = jest.fn(); +const mockAdvancedMarkerInstance = { + addListener: jest.fn() +}; + +const mockAdvancedMarkerElement = jest.fn(() => (mockAdvancedMarkerInstance)); +const mockPinElement = jest.fn(); +const mockInfoWindow = jest.fn(); const mockImportLibrary = jest.fn().mockImplementation(() => (Promise.resolve({ Map: mockMap, Geocoder: mockGeocoder, - AdvancedMarkerElement: mockAdvancedMarkerElement + AdvancedMarkerElement: mockAdvancedMarkerElement, + PinElement: mockPinElement }))); const mockExtend = jest.fn(); @@ -36,7 +43,8 @@ const setupGoogleMock = () => { global.window.google = { maps: { importLibrary: mockImportLibrary, - LatLngBounds: jest.fn(() => (mockLatLngBound)) + LatLngBounds: jest.fn(() => (mockLatLngBound)), + InfoWindow: mockInfoWindow } }; }; @@ -46,6 +54,7 @@ beforeEach(() => { mockMap.mockClear(); mockGeocoder.mockClear(); mockAdvancedMarkerElement.mockClear(); + mockPinElement.mockClear(); // clear methods mockExtend.mockClear(); @@ -150,7 +159,13 @@ describe('Google Map', () => { const zipCode = '00882'; const [address1, address2, position1, position2] = ['a1', 'a2', 'p1', 'p2']; - const addresses = [address1, address2]; + const markers = [ + { + fullAddress: address1 + }, + { + fullAddress: address2 + }]; mockGeocode.mockImplementation((obj) => { let result = {}; if (obj.address.includes(zipCode)) { @@ -171,7 +186,7 @@ describe('Google Map', () => { return Promise.resolve(result); }); - const propsData = { addresses, zipCode }; + const propsData = { markers, zipCode }; const { wrapper } = getMountedComponent({}, {}, propsData); await awaitingSetupTicks(wrapper); @@ -198,8 +213,6 @@ describe('Google Map', () => { test('watch addresses creates map with expected markers', async () => { // Arrange const zipCode = '00882'; - const { wrapper } = getMountedComponent({}, { zipCode }); - await awaitingSetupTicks(wrapper); const mockGetCenter = jest.fn(); const mockNorthEast = jest.fn(); @@ -238,10 +251,18 @@ describe('Google Map', () => { } return Promise.resolve(result); }); - const newAddresses = [address1, address2]; + const markers = [ + { + fullAddress: address1 + }, + { + fullAddress: address2 + }]; // Act - await wrapper.vm.$options.watch.addresses.call(wrapper.vm, newAddresses); + const { wrapper } = getMountedComponent({}, { zipCode }); + await awaitingSetupTicks(wrapper); + await wrapper.vm.$options.watch.markers.call(wrapper.vm, markers); await awaitingSetupTicks(wrapper); // Assert @@ -260,9 +281,9 @@ describe('Google Map', () => { expect(mockExtend).toBeCalledTimes(6); expect(mockFitBounds).toBeCalledTimes(2); - expect(mockGetCenter).toBeCalledTimes(1); - expect(mockNorthEast).toBeCalledTimes(1); - expect(mockSouthWest).toBeCalledTimes(1); + expect(mockGetCenter).toBeCalledTimes(2); + expect(mockNorthEast).toBeCalledTimes(2); + expect(mockSouthWest).toBeCalledTimes(2); }); describe('method', () => { test('getMap calls map constructor with expected parameters', async () => { @@ -295,12 +316,20 @@ describe('Google Map', () => { await awaitingSetupTicks(wrapper); const numberOfExtendCallsDuringMount = 2; + mockGeocode.mockImplementation(() => { + const result = { + results: [ + { geometry: { location: 'p1' } } + ] + }; + return Promise.resolve(result); + }); + // Act const result = wrapper.vm.getBounds(locations); // Assert - expect(mockExtend).toHaveBeenCalledTimes( - numberOfExtendCallsDuringMount + numberOfExtendCallsPostMount); + expect(mockExtend).toHaveBeenCalledTimes(numberOfExtendCallsDuringMount + numberOfExtendCallsPostMount); expect(result).toBe(mockLatLngBound); } ); @@ -362,7 +391,7 @@ describe('Google Map', () => { expect(mockGeocode).toHaveBeenCalledTimes(numberOfCallsFromMount); // Act - await wrapper.vm.getLocationsFromAddresses(addresses); + await wrapper.vm.getLocationsFromAddresses(addresses?.map((a) => ({ fullAddress: a }))); await wrapper.vm.$nextTick(); // Assert @@ -374,7 +403,7 @@ describe('Google Map', () => { // Arrange 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'].map((a) => ({ fullAddress: a })); mockGeocode.mockImplementationOnce(() => null) .mockImplementationOnce(() => ({ results: null })) .mockImplementationOnce(() => ({ results: [] })) @@ -402,7 +431,7 @@ describe('Google Map', () => { const expectedResult = ['some value', 'some other value']; // Act - const result = await wrapper.vm.getLocationsFromAddresses(addresses); + const result = (await wrapper.vm.getLocationsFromAddresses(addresses)).map((a) => a.position); // Assert expect(result.length).toBe(2); @@ -477,7 +506,7 @@ describe('Google Map', () => { Promise.resolve(obj.address.includes(zipCode) ? zipCodeGeocodeResult : shopGeocodeResult)); - const addresses = ['a1', 'a2']; + const addresses = [{ fullAddress: 'a1' }, { fullAddress: 'a2' }]; const { wrapper } = getMountedComponent({}, { zipCode }); await awaitingSetupTicks(wrapper); diff --git a/src/iss-components/google-map/google-map.vue b/src/iss-components/google-map/google-map.vue index 0c901dec..b3de8c7d 100644 --- a/src/iss-components/google-map/google-map.vue +++ b/src/iss-components/google-map/google-map.vue @@ -8,13 +8,14 @@ export default { name: 'google-map', props: { - addresses: Array, + markers: Array, zipCode: String }, data() { return { country: 'USA', - geocoder: null + geocoder: null, + infoWindow: null }; }, computed: { @@ -23,12 +24,12 @@ export default { } }, watch: { - async addresses(newAddresses) { - this.createMapWithMarkersForAddresses(newAddresses); + async markers(newMarkers) { + await this.createMapWithMarkersForAddresses(newMarkers); } }, - beforeMount() { - this.createMapWithMarkersForAddresses(this.addresses); + async beforeMount() { + await this.createMapWithMarkersForAddresses(this.markers); }, methods: { async getMap(center) { @@ -50,20 +51,58 @@ export default { this.geocoder = new Geocoder(); } }, - async addMarkersToMap(map, positions) { - const { AdvancedMarkerElement } = await window.google.maps.importLibrary('marker'); - positions?.forEach((position) => new AdvancedMarkerElement({ map, position })); + async addMarkersToMap(map, markers) { + const { AdvancedMarkerElement, PinElement } = await window.google.maps.importLibrary('marker'); + markers?.forEach((marker, index) => { + const pinElement = new PinElement({ + glyph: String.fromCharCode('A'.charCodeAt(0) + index), + glyphColor: '#000000', + borderColor: '#000000' + }); + const markerElement = new AdvancedMarkerElement({ + map, + position: marker.position, + title: marker.title, + content: pinElement.element, + zIndex: 1000 - index + }); + this.createMarkerInfoWindows(markerElement, marker); + }); }, - async getLocationsFromAddresses(addresses) { + createMarkerInfoWindows(markerElement, marker) { + const directionsUrl = this.createGetDirectionsUrl(marker); + const content = `