We have been banging our heads against the wall trying to test the AdvancedMarkerElement from the google maps api. We replaced google.maps.Markers with AdvancedMarkerElement. The tests we had originally were using @googlemaps/jest-mocks'
and we mocked the listener and then called it directly using addListenerSpy.mock.calls[0][1]()
and then assert that the proper calls were made. Below is the test which was working with Markers
/* global jest context */
import { render, waitFor } from '@testing-library/react'
import { initialize } from '@googlemaps/jest-mocks'
import '@googlemaps/react-wrapper'
import { useSessionContext } from 'hooks/SessionContext'
import Map from 'pages/Dashboard/CriticalAndMajorAlertsMapCard/Map'
jest.mock('hooks/SessionContext')
jest.mock('@googlemaps/markerclusterer', () => ({
...jest.requireActual('@googlemaps/markerclusterer'),
MarkerClusterer: jest.fn().mockImplementation(() => {})
}))
// mocking useLayoutEffect to use useEffect useLayoutEffect is intended to be used within a browser like environment
// and jest runs test in node .env by default which doesn't provide a browser DOM.
// https://stackoverflow.com/questions/58070996/how-to-fix-the-warning-uselayouteffect-does-nothing-on-the-server
// https://react.dev/reference/react/useLayoutEffect#im-getting-an-error-uselayouteffect-does-nothing-on-the-server
jest.mock('react', () => ({
...jest.requireActual('react'),
useLayoutEffect: jest.requireActual('react').useEffect
}))
const dealer = Object.freeze({
dealerId: 1,
latitude: 40.15,
longitude: -111.11
})
const devices = Object.freeze({
deviceId: '12345ABCD',
criticalAlertCount: 1,
majorAlertCount: 1,
sdaMajorAlertCount: 0
})
const customersWithLocation = Object.freeze(
[{
customerId: 1,
dealerId: 2,
latitude: 35.01,
longitude: -113.45,
devices: [devices]
}]
)
describe('Map', () => {
context('when map loads', () => {
const addListenerSpy = jest.fn()
const openInfoWindowSpy = jest.fn()
const setContentinfoWindowSpy = jest.fn()
beforeEach(() => {
useSessionContext.mockReturnValue({
session: dealer
})
initialize()
window.google.maps.Marker = jest.fn().mockImplementation(() => {
return {
addListener: addListenerSpy
}
})
window.google.maps.InfoWindow = jest.fn().mockImplementation(() => {
return {
setContent: setContentinfoWindowSpy,
open: openInfoWindowSpy
}
})
})
describe('when user clicks on the customer marker', () => {
it('opens info window for customer ', async () => {
render(<Map customersWithLocation={customersWithLocation} />)
addListenerSpy.mock.calls[0][1]()
await waitFor(() => {
expect(setContentinfoWindowSpy).toHaveBeenCalledTimes(1)
expect(openInfoWindowSpy).toHaveBeenCalledTimes(1)
})
})
})
})
})
When we switched to using AdvancedMarkerElement we had to import the library like so:
const { AdvancedMarkerElement } = (await google.maps.importLibrary('marker')) as google.maps.MarkerLibrary
We could not figure out how to mock this using jest mocks so what we wound up doing is creating a file that contains this functionality and then are trying to mock the file we just implemented. The AdvancedMarkerElement importer file is:
export const importAdvancedMarkerElement = async () => {
const { AdvancedMarkerElement } = (await google.maps.importLibrary('marker')) as google.maps.MarkerLibrary
return AdvancedMarkerElement
}
We have tried mocking the above like so:
jest.mock('pages/Dashboard/CriticalAndMajorAlertsMapCard/AdvancedMarkerElement', () => {
return {
importAdvancedMarkerElement: jest.fn().mockImplementation(() => {
return {
addListener: jest.fn()
}
})
}
})
But are now getting the following error when running:
TypeError: AdvancedMarkerElement is not a constructor
54 | }
55 |
> 56 | const marker = new AdvancedMarkerElement({
Any help with testing this functionality would be greatly appreciated.