如何在Playwright E2E测试中模拟Mapbox地图旋转(Bearing)?
解决方案:测试Mapbox地图旋转时URL参数同步更新
针对你遇到的mapRef未全局暴露导致无法直接调用setBearing的问题,提供几个可行的解决思路:
1. 模拟用户真实旋转操作(无需修改组件代码)
Mapbox GL JS默认支持按住右键拖拽地图实现旋转,直接用Playwright模拟这个用户行为,完全贴合真实场景:
// 找到地图容器元素(假设选择器是[data-testid="map-container"]) const mapContainer = page.locator('[data-testid="map-container"]'); // 模拟右键按下并拖拽,触发地图旋转 await mapContainer.click({ button: 'right' }); await page.mouse.move(100, 0); // 向右拖拽100px,调整数值控制旋转角度 await page.mouse.up(); // 等待URL更新后检查bearing参数 const currentUrl = new URL(await page.url()); expect(currentUrl.searchParams.get('bearing')).not.toBeNull(); // 或者验证具体数值(根据拖拽幅度调整预期值) expect(parseFloat(currentUrl.searchParams.get('bearing'))).toBeCloseTo(45, 1);
2. 测试环境下临时暴露地图实例(最小侵入性修改)
在你的Mapbox React组件中,仅在测试环境将地图实例挂载到全局window对象,避免影响生产环境:
// 你的Mapbox组件代码 import { useEffect, useRef } from 'react'; import mapboxgl from 'mapbox-gl'; const MapComponent = () => { const mapContainerRef = useRef(null); const mapRef = useRef(null); useEffect(() => { if (!mapContainerRef.current) return; mapRef.current = new mapboxgl.Map({ container: mapContainerRef.current, // 其他配置项... }); // 仅在测试环境暴露实例 if (process.env.NODE_ENV === 'test') { window.__testMapInstance = mapRef.current; } return () => { mapRef.current?.remove(); // 测试环境清理全局变量 if (process.env.NODE_ENV === 'test') { delete window.__testMapInstance; } }; }, []); return <div ref={mapContainerRef} data-testid="map-container" />; }; export default MapComponent;
然后在Playwright测试中直接调用:
// 等待地图初始化完成 await page.waitForSelector('[data-testid="map-container"]'); // 通过全局对象调用setBearing await page.evaluate(() => { window.__testMapInstance.setBearing(45); }); // 验证URL参数 const currentUrl = new URL(await page.url()); expect(currentUrl.searchParams.get('bearing')).toBe('45');
3. 通过组件内部状态触发旋转(适合受控组件)
如果你的地图组件是受控的,支持通过props控制bearing值,可以直接在测试中触发组件状态更新:
// 假设组件通过React状态管理bearing,且暴露了更新方法 await page.locator('[data-testid="map-component"]').evaluate(el => { el.setBearing(45); }); // 验证URL参数 const currentUrl = new URL(await page.url()); expect(currentUrl.searchParams.get('bearing')).toBe('45');
注:如果组件使用useImperativeHandle暴露了旋转方法,上述代码可直接生效;若未暴露,可在组件内部添加测试专用的方法暴露逻辑。
内容的提问来源于stack exchange,提问作者Ala Eddine Menai
相关产品推荐
相关产品推荐

