Vue项目中如何在Cypress测试多次模拟Geolocation的watchPosition响应?
问题:如何在Cypress中多次模拟Geolocation的watchPosition更新位置?
我有一个Vue.js应用,点击按钮后会调用Geolocation API的watchPosition函数获取用户位置,并基于该位置进行相关计算。现在用Cypress测试这一行为,已经写了StubwatchPosition的命令,但目前只能模拟一次位置,想在同一个测试中多次传入不同经纬度,验证应用对新位置的响应。
原有的Cypress命令代码:
Cypress.Commands.add('mockGeolocation', (latitude, longitude) => { cy.window().then((win) => { const mockGeolocation = { watchPosition: (successCallback, errorCallback, options) => { // Call the successCallback with mock position data const mockPosition = { coords: { latitude: latitude, longitude: longitude } } successCallback(mockPosition); // Optionally, you can call the errorCallback or handle options as needed }, clearWatch: () => { console.log("hello there") } }; // Replace the real geolocation object with the stub cy.stub(win.navigator, 'geolocation').value(mockGeolocation); }); });
原测试代码:
it('My awesome test', () => { cy.visit('/') cy.mockGeolocation(1, 2) cy.get('[data-testid="start-button-game"]').click() })
解决方案
核心思路是保存watchPosition的成功回调函数,后续调用模拟命令时直接用新坐标触发该回调,实现位置更新。
1. 修改Cypress命令
更新mockGeolocation命令,首次初始化时保存回调,后续调用直接触发更新:
Cypress.Commands.add('mockGeolocation', (latitude, longitude) => { cy.window().then((win) => { // 如果已保存过回调,直接用新坐标触发位置更新 if (win.__geolocationSuccessCallback) { const mockPosition = { coords: { latitude, longitude } }; win.__geolocationSuccessCallback(mockPosition); return; } // 首次创建stub,保存回调并触发初始位置 const mockGeolocation = { watchPosition: (successCallback, errorCallback, options) => { // 将回调存到window全局变量(__前缀避免命名冲突) win.__geolocationSuccessCallback = successCallback; // 触发初始位置 const mockPosition = { coords: { latitude, longitude } }; successCallback(mockPosition); return 1; // 返回一个watchId,对应clearWatch的参数 }, clearWatch: (watchId) => { // 应用调用clearWatch时,清理保存的回调 if (watchId === 1) { delete win.__geolocationSuccessCallback; } } }; cy.stub(win.navigator, 'geolocation').value(mockGeolocation); }); });
2. 编写多位置测试
在同一个测试中多次调用mockGeolocation,验证应用的响应:
it('验证多次位置更新的应用响应', () => { cy.visit('/'); // 首次模拟位置(1,2),启动监听 cy.mockGeolocation(1, 2); cy.get('[data-testid="start-button-game"]').click(); // 验证初始位置的响应(示例:检查页面显示的纬度经度) cy.get('[data-testid="current-latitude"]').should('contain', '1'); cy.get('[data-testid="current-longitude"]').should('contain', '2'); // 模拟位置更新到(3,4) cy.mockGeolocation(3, 4); // 验证位置更新后的响应 cy.get('[data-testid="current-latitude"]').should('contain', '3'); cy.get('[data-testid="current-longitude"]').should('contain', '4'); // 继续模拟更多位置 cy.mockGeolocation(5, 6); cy.get('[data-testid="current-latitude"]').should('contain', '5'); });
注意事项
- 全局变量
win.__geolocationSuccessCallback仅在当前测试上下文有效,Cypress会在测试结束后自动清理window环境,不会影响其他测试。 - 如果应用会调用
clearWatch,确保stub中的clearWatch逻辑正确清理回调,避免后续调用出错。 - 确认应用中的
watchPosition是持续监听状态,不会在获取一次位置后停止监听,否则后续触发回调可能无效果。
内容的提问来源于stack exchange,提问作者Korr
相关产品推荐
相关产品推荐

