简体   繁体   中英

React-Leaflet: 'Invalid LatLng object' on running test when using boundsOptions

I built an simple app using react-leaflet to show a map. The app itself is working and the map is showing correctly in the browser. But when I try to write tests with react-testing-library, I receive Invalid LatLng object ' in execution when using boundsOptions . If I remove the boundsOptions property the test will pass.

Map.tsx

import "leaflet/dist/leaflet.css";
import React from "react";
import {
  LayersControl,
  Marker,
  Polyline,
  TileLayer,
  Tooltip,
  Map
} from "react-leaflet";
import './Map.css';

const { BaseLayer } = LayersControl;

const MapWrapper: React.FC = ({ ...props }) => {
  const layers = [
    {
      name: "OpenStreetMap.Mapnik",
      attribution:
        '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
      url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
    }
  ];

  const bounds: [number, number][] = [];

  [...] // Code that calculates the bounds to show (in production)

  if (bounds.length === 0) {
    bounds.push([35, -35]);
    bounds.push([65, 55]);
  }

  return (
      <Map bounds={bounds} boundsOptions={{ padding: [5, 5] }} className="map">
        <LayersControl position="topright">
          {layers.map(layer => {
            return (
              <BaseLayer
                key={layer.url}
                checked={true}
                name={layer.name}
              >
                <TileLayer attribution={layer.attribution} url={layer.url} />
              </BaseLayer>
            );
          })}
        </LayersControl>
      </Map>
  );
};

Map.css

.map {
  height: 400px;
  width: 640px;
}

Map.test.tsx

import React from 'react'
import MapWrapper from './Map';
import {render, fireEvent, cleanup} from '@testing-library/react';

afterEach(cleanup)

test('Simple test', () => {
  const { getByTestId } = render(<MapWrapper />)
})

Error occurred by test

    console.error node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/virtual-console.js:29
      Error: Uncaught [Error: Invalid LatLng object: (NaN, NaN)]
          at reportException (C:\Repos\react-leaflet-jest\node_modules\jest-environment-jsdom\node_modules\jsdom\lib\jsdom\living\helpers\runtime-script-errors.js:66:24)
    ...
    console.error node_modules/react-dom/cjs/react-dom.development.js:19814
      The above error occurred in the <TileLayer> component:
          in TileLayer (created by Context.Consumer)

You can find the code here: https://bitbucket.org/netcoding/react-leaflet-jest/src/master/

How can I setup react-leaflet to pass the test using the boundsOptions?

It appears to be a known issue and also could be reproduced, for example in Jest. The exception occurs since map container size could not be properly determined when map is rendered (in tests).

The solution would be to explicitly set map container size , in case of react-leaflet library map container size could be set like this:

const { leafletElement: map } = this.mapRef.current as Map;
const container = map.getContainer(); //get leaflet map container
Object.defineProperty(container, "clientWidth", { value: 800 });
Object.defineProperty(container, "clientHeight", { value: 600 });

Here is a complete example on how to test map bounds:

test("Map test bounds", () => {
  class TestComponent extends React.Component<any, any> {
    mapRef: React.RefObject<Map>;

    constructor(props: any) {
      super(props);
      this.mapRef = React.createRef();
    }

    componentDidMount() {
      this.updateBoundsOptions();
    }

    resizeContainer(container: HTMLElement) {
      Object.defineProperty(container, "clientWidth", { value: 800 });
      Object.defineProperty(container, "clientHeight", { value: 600 });
    }

    updateBoundsOptions() {
      const { leafletElement: map } = this.mapRef.current as Map;
      const container = map.getContainer(); //get leaflet map container
      this.resizeContainer(container);
      map.fitBounds(this.props.bounds, this.props.boundsOptions);
    }

    render() {
      return (
        <MapWrapper mapRef={this.mapRef}>
          <span />
        </MapWrapper>
      );
    }
  }

  render(
    <TestComponent
      bounds={[[35, -35], [65, 55]]}
      boundsOptions={{ padding: [5, 5] }}
    />
  );
});

where MapWrapper is a custom component:

export interface MapWrapperProps extends MapProps {
  mapRef?: React.RefObject<Map>;
}

const MapWrapper: React.FC<MapWrapperProps> = ({ ...mapProps }) => {
  return (
    <Map ref={mapProps.mapRef} {...mapProps}>
      <TileLayer
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      />
    </Map>
  );
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM