Cypress - simulate multiple responses for watchPosition stub

I have a small VueJs app where clicking on a button triggers the watchPosition function from the Geolocation API to retrieve the user's position and perform some calculations with it.

Now, I want to test this functionality using Cypress testing.

To do so, I've created a stub for the watchLocation function in a Cypress command:

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);
    });
  });

After setting up the mockGeolocation command, I use it in my test like this:

  it('Testing my app', () => {
   
    cy.visit('/')

    cy.mockGeolocation(1, 2)
    cy.get('[data-testid="start-button-game"]').click()
  })

Although this setup works for one iteration, I now want to be able to call cy.mockGeolocation multiple times within the same test with different coordinates to validate the app's response to varied positions. How can I accomplish this?

Answer №1

The issue lies in the fact that watchPosition functions as a watcher, typically set once to respond to navigator object events in a push pattern.

However, the mock you've established fetches data each time using a pull pattern for a different function.

I believe there should be a method to mock a watcher/listener, though it eludes me currently.

As an alternative, I suggest switching from watchPosition to getCurrentPosition, which appears more suitable for initiation via button click.

Cypress.Commands.add('mockGeolocation', (latitude, longitude) => {
  cy.window().then((win) => {
    const mockGeolocation = {
      getCurrentPosition: (successCallback, errorCallback, options) => {
        ...  // remaining code provided
  
it('tests geolocation with mock', () => {

  cy.visit('/')

  cy.mockGeolocation(1, 2)
  cy.get('[data-testid="start-button-game"]').click()
  cy.get('location')
    .should('have.text', 'Your current position is Lat: 1 Long: 2')  // passes
  
  cy.mockGeolocation(3, 4)
  cy.get('[data-testid="start-button-game"]').click()
  cy.get('location')
    .should('have.text', 'Your current position is Lat: 3 Long: 4')  // passes
})

Tested with this app

<button data-testid="start-button-game" onclick="handler()">Get geolocation</button>
<location>Unknown</location>

<script>
  function success(pos) {
    const crd = pos.coords;
    const {latitude,longitude} = crd;
    const location = document.querySelector('location')
    location.innerText = `Your current position is Lat: ${latitude} Long: ${longitude}`
  }
  function error() {
  }
  const options = {}
  function handler() {
    window.navigator.geolocation.getCurrentPosition(success, error, options)
  }
</script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue with Firefox mobile's camera functionality

I am facing an issue with my web app for mobile devices where I am trying to display the mobile camera using Firefox mobile browser. I am using nodejs with express as a server and connecting to the server via localhost with my smartphone. Although Firefox ...

Guidelines for adjusting the next/image component to a full 100% height

In my Next.js application, I am trying to display an image that fills the full height of its container while automatically adjusting its width based on its aspect ratio. I attempted the following method: <Image src="/deco.svg" alt=&qu ...

Troubleshooting: Why are my images not displaying in webpack and node.js setup?

My problem: I'm facing an issue with background images in my project. I have included two images and used file-loader to bundle them through webpack. While the images display correctly in the app during development using webpack-dev-server, they disap ...

Having trouble turning off a multi-select drop down option

Hello, I'm a newcomer to AngularJs and facing an issue with disabling my multiselect dropdown under a specific condition. Initially, I attempted to disable the dropdown using the following code: document.getElementById("multidropdown").disabled = tr ...

Guide to setting up collapsible sections within a parent collapsible

I came across this animated collapsible code that I'm using: https://www.w3schools.com/howto/howto_js_collapsible.asp Here is the HTML: <button type="button" class="collapsible">Open Collapsible</button> <div class="content"> &l ...

What is the best way to iterate through JSON objects stored in a single location?

Currently, I am dealing with a single JSON object structured as follows: Object --> text --> body --> div Array[20] --> 0 Object --> text --> body --> div Array[20] --> 1 Object --> text --> body --> div Array[20] --> . ...

Automatically injecting dependencies in Aurelia using Typescript

Recently, I started working with Typescript and Aurelia framework. Currently, I am facing an issue while trying to implement the @autoinject decorator in a VS2015 ASP.NET MVC 6 project. Below is the code snippet I am using: import {autoinject} from "aure ...

Having trouble calling REST API in node.js, whereas it works perfectly fine when called from the browser?

My goal is to invoke the WebServer [mongoose embedded webserver] that is currently running on another machine. Here is the code snippet: var express = require('express'); var http = require('http'); var router = express.Router(); /* ...

Replace the phrase "add to cart" with "plus" and "minus" in Opencart

I am trying to customize the Add to Cart functionality in OpenCart 2.0.1.1 by replacing it with plus and minus buttons. I have successfully added the plus button, however, I am facing difficulty coding for the minus button. The code snippet below shows w ...

Utilizing nested v-for in Vue.js with lodash's groupBy function

When fetching data from a database, I am using lodash groupby to group my data like so: var vm = this axios.get(this.buildURL()) .then(function(response) { Vue.set(vm.$data, 'model', response.data.model) vm.groupData = _.groupBy(vm.model ...

Trapped in the clutches of the 'Access-Control-Allow-Origin' snag in our Node.js application

Our nodeJS application is deployed on AWS Lambda, and we are encountering an authentication issue with CORS policy when trying to make a request. The error in the console states: Access to XMLHttpRequest at 'https://vklut41ib9.execute-api.ap-south-1 ...

What are some ways to keep the text within the boundaries of the input box?

How can I prevent the letters from extending beyond the bar when typing a lot of characters? Your assistance in resolving this issue is greatly appreciated. <div id="tasks-container"> <div id="tasks-header"> ...

The HTML select element fails to drop down over the THREE.js scene

I'm currently working on enhancing the Three.js editor for a project. editor link One of the tasks I'm tackling is adding a select element on top of the viewport in the editor. Unfortunately, the dropdown functionality of the select element isn ...

Struggling to remove quotation marks from a string that was originally an array before being converted?

Here is the code snippet that I am struggling with: users = [{ "userid": "45", "name": "steve" }, { "userid": "32", "name": "john" }]; getuser = users.flatMap(user => user.userid === '32' ? user.name : []); result = getuser.toSt ...

Issue with Angular Factory not being invoked

I am currently using a tutorial to create a MEAN app with Google Maps. However, I have encountered an issue where the map is not appearing on the page. Surprisingly, there are no errors in the browser console and even when debugging with node-inspector, I ...

I'm looking for a solution to reorganize my current state in order to display the image URL

My React component, which also utilizes TypeScript, is responsible for returning a photo to its parent component: import React, { useEffect, useState } from "react"; import axios from "axios"; export const Photo = () => { const [i ...

Use the JavaScript .replaceAll() method to replace the character """ with the characters """

My goal is to pass a JSON string from Javascript to a C# .exe as a command line argument using node.js child-process. The JSON I am working with looks like this: string jsonString = '{"name":"Tim"}' The challenge lies in preserving the double q ...

Tips for capturing and storing video with HTML5 WebRTC

Before reading the description, make sure to run the code snippet first. This will provide you with a better understanding of the structure. In the 2nd video element, I am trying to record, play, and save video. The issue I'm encountering is that the ...

Access Denied: Origin Issue with OAuth2

I am requesting an authorization code from the OAuth2 Server in order to authenticate a user with my Microsoft App. For more information, I consulted this document. This is my attempt to make the call: function httpGet(){ var theUrl = "https://lo ...

Having trouble grasping the purpose of app.use('/') in the Express framework

Below is the code snippet I am currently working with: // Initializing express, body-parser, mongodb, http, and cors var app = express(); app.use(cors()); app.use(express.urlencoded()); // Parse incoming JSON data from API clients app.use(express.json()); ...