reactjs - 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:
'© <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?
解决方案
这似乎是一个已知问题,也可以复制,例如在 Jest 中。发生异常是因为在渲染地图时(在测试中)无法正确确定地图容器的大小。
解决方案是显式设置地图容器大小,如果react-leaflet
库地图容器大小可以这样设置:
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 });
这是一个关于如何测试地图边界的完整示例:
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] }}
/>
);
});
MapWrapper
自定义组件在哪里:
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='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
/>
</Map>
);
};
推荐阅读
- django - 使用数据向 NextJS 发送 Django 请求
- python - FileNotFoundError:[Errno 2] 没有这样的文件或目录:'demofile.txt'
- parameters - 未声明的查询参数@DS_START_DATE bigquery
- kubernetes - rbac.authorization.k8s.io/v1beta1 已弃用警告
- python - TypeError:需要一个类似字节的对象,而不是'_io.TextIOWrapper'
- c - 为什么连续的 fget 接受输入但在循环打印时将其存储为不同的或空白数据?
- android - 如何在 Android 上的 RecyclerView 中使用 GridLayoutManager
- wordpress - 来自 API 的 Ninja Form 动态接收者 - Wordpress
- javascript - Google Script:如何使用文档模板显示图像而不是超链接
- python - 在异步函数(通道消费者)Django中从数据库中获取模型