Dhamo
Dhamo

Reputation: 1251

Cypress mouse event not working on map based applications (canvas)

I have a map-based application and hovering the mouse anywhere on the map, will show me the latitude and longitude value along with coordinates as in the picture.

enter image description here

I am trying to automate that and for some strange reason, the mouse events are not recognized if I use cypress.

Below is my code on a much similar application.

context('map', () => {
    beforeEach(() => {
        cy.visit('https://www.google.com/maps/')
    })

it('mouse hover /click on map', () => {
    cy.contains('I agree').click(); 
    //cy.contains('Jeg accepterer').click();
    cy.contains('COVID-19', { timeout: 30000 }).should('be.visible')
    //Hovering mouse or manual click gives the right values, 
    //  so added click also in above code
    cy.get('.widget-scene-canvas').click(80, 90)
    //.realClick();
 });

//Tried the following combinations and no luck: 
    // cy.get('.grid-container').eq(0).contains('Lat')
    // .invoke('trigger', 'mouseout')
    // .invoke('trigger', 'mouseenter')
    // .invoke('trigger', 'mouseleave')
    // .invoke('trigger', 'mouseover')
    // .trigger('mouseenter')
    // .trigger('onmouseover')
    // .trigger('mousedown', { force: true, which: 1 })
    // .trigger('mousemove', { force: true, clientX: 400, clientY: 500 })
    // .trigger('mouseup', { force: true })
    // .realHover()

Upvotes: 2

Views: 1093

Answers (1)

Michael Hines
Michael Hines

Reputation: 1098

Looking at https://www.google.com/maps/ I don't see the lat-long .grid-container you mention, but you can get lat-long from the map with a right-click.

The basic problem is that google maps loads some additional code after initial display. You can see it in the Cypress log as (xhr) and clicking these logs shows the code in dev console.

The simplest way to get lat-long from https://www.google.com/maps is to arbitrarily wait, but it's flaky depending on network speed.

cy.visit('https://www.google.com/maps/place/copenhagen')
cy.get('body').click()   // remove any covering layers, e.g covid messages

cy.wait(7000)  // wait for whatever code is required to display lat-long

cy.get('canvas').rightclick('center')  // open context menu

cy.contains("Directions from here")  // this text is visible
  .parents('ul')                     // parent menu
  .children().eq(0)                  // first item is lat-long
  .invoke('text')
  .should('contain', '55.67119, 12.45374')   // passes

To get rid of the arbitrary wait there are a couple of strategies

  • use an intercept and wait until all (xhr) stop after say 2 seconds (still a bit arbitrary)

  • identify which (xhr) contains the code needed to perform the click (for your map) or right-click (for google maps), then wait on an intercept for that (xhr)


The problem might be that the lat-lon displayed is a child of the canvas.

In google maps, it's a child of DOM so it can easily be queried by Cypress.

But when you inspect the <canvas> element in dev tools, it has no children to query, although clearly there are children displayed on the screen.

Upvotes: 1

Related Questions