yuzhva / react-leaflet-markercluster

React wrapper of the official Leaflet.markercluster for react-leaflet
https://yuzhva.github.io/react-leaflet-markercluster/
MIT License
284 stars 101 forks source link

Testing with Jest and React Testing Library (RTL) cannot find markers in DOM #175

Closed butters16 closed 2 years ago

butters16 commented 2 years ago

I created a repo that reproduces the problem: https://github.com/butters16/cluster-testing

From the Readme in that repo:

npm test

This is the problem

<MarkerClusterGroup>
    <Marker position={[51.5074, -0.0901]} alt="Solo" />
</MarkerClusterGroup>

because this passes the test

<Marker position={[51.5074, -0.0901]} alt="Solo" />

by itself without the MarkerClusterGroup.

Also note that this passes the test

<MarkerClusterGroup>
    <Marker position={[0, 0]} alt="Solo" />
</MarkerClusterGroup>

but only as long as the map is also centered at 0,0

center={[0, 0]}

and again fails the test if moved even a tiny bit

<MarkerClusterGroup>
    <Marker position={[0.001, 0]} alt="Solo" />
</MarkerClusterGroup>

Also note that I needed to include this fix https://stackoverflow.com/a/54384719 to even get this far with testing.

butters16 commented 2 years ago

This seems like a clue. If I reformat and debug the dist code, I can see where the ctx.map._size is 0, 0, which seems odd. If I change them at testing runtime to 1000, 1000, the test passes. I've not yet found where those values come from, but maybe somebody here does.

Screen Shot 2022-02-07 at 5 49 46 PM
butters16 commented 2 years ago

This post https://stackoverflow.com/a/57646705 seems related, especially since I can observe the map container clientWidth and clientHeight as zero. However, the suggestion there of manually setting those values and then calling map.fitBounds does not seem to work for me. I switched to map.fitWorld() because it seemed more universal, but still no luck.

butters16 commented 2 years ago

This seemed to work: https://github.com/butters16/cluster-testing/commit/3d7ef5a1cc30e8c5c2a40a1a82f243a68f5f9486

In a nutshell, the code needs to make the underlying leaflet map available

<MapContainer
    whenCreated={map => window.map = map}

the test needs to set the width and height on the map

// inspired by https://stackoverflow.com/a/57646705
Object.defineProperty(window.map.getContainer(), "clientWidth", { value: 800 });
Object.defineProperty(window.map.getContainer(), "clientHeight", { value: 600 });
window.map.invalidateSize(true);

and needs to wait for the assertion

await screen.findByAltText('Solo');