googlemaps / js-jest-mocks

Jest mocks for Google Maps Platform
Apache License 2.0
33 stars 29 forks source link

Library does not work with react testing library #706

Closed KrzysztofWelc closed 2 months ago

KrzysztofWelc commented 3 months ago

I have a react application with google maps loaded by dynamic library import. I test test with jest and rtl running on jest-environment-jsdom. I wanted to integrate js-jest-mocks to my tests. however when i run test like this:

import { initialize, mockInstances, Map } from "@googlemaps/jest-mocks";

describe('component', ()==>{

beforeEach(() => {
  initialize();
});

it('should x', ()=>{
   render(<MapComponent/>);
   const map = mockInstances.get(Map)
   ...
})

})

the value returned by mockInstances.get(...) is undefined. I checked everything and it seems like mock library does not recognize api calls inside the component.

usefulthink commented 3 months ago

I can confidently say that it works quite well together with the jest/rtl stack, but it takes some time getting used to the specifics of how to write the tests. See for example the tests here, using the same stack: https://github.com/visgl/react-google-maps/blob/main/src/components/__tests__/api-provider.test.tsx

I'd like to know more about how your MapComponent is structured, without seeing that it's pretty difficult to figure out what's going wrong there. It would be expected that there's something in the component waiting for the maps-API to load, something like await google.maps.importLibrary('maps') for example.

In that case, the google.maps.Map constructor is likely being called in an effect that hasn't been run when you try to retrieve the map instance (render is synchronous, and the promise returned from importLibrary will not resolve until the next microtask run, so you'd have to wait for that at least).

KrzysztofWelc commented 3 months ago

I cannot really show the code, but i checked with both debugger and console.log and the mock map object is created, but is not available by mockInstances.get

usefulthink commented 3 months ago

Hmm, it could it be that the class returned from google.maps.importLibrary isn't the one you're expecting? For example, if you create an extended version of the Map mock for your tests, the importLibrary function will still return the unmodified version of the class. In that case, you might need to mock/extend the google.maps.importLibrary function as well..

KrzysztofWelc commented 3 months ago

I checked that and global.google.maps in test scope and in component are the same object

usefulthink commented 3 months ago

Without any more details I'm afraid I won't be able to help you any further. Please post an update here once you found out what was going wrong. Maybe there's something that could be improved in this library or at least it might help someone else..

KrzysztofWelc commented 3 months ago

It turns out that due to app architecture, all mockInstances.get() call had to be wrapped in waitfor()