You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 00:46:04