Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing onclick events on SVG with Cypress

I am testing a d3 application with Cypress. As of the tests, I'd like to make sure a specific function is called when a circle within an SVG element is clicked. The function is called when I'm clicking manually but the test that I wrote fails, so I assume I made a mistake somewhere in the test. Here's the test code I have right now:

import * as app from "../../app";

describe("Scatter plot", () => {
  before(() => {
    cy.visit("http://localhost:1234");
  });
  it("Triggers the displayMovieInfo on click", () => {
    const displayMovieInfo = cy.spy(app, "displayMovieInfo");
    cy.get("#scatterPlot")
      .get("circle")
      .eq(0)
      .click({ force: true });

    expect(displayMovieInfo).to.be.called;
  });
});

The output I get from Cypress:

expected displayMovieInfo to have been called at least once, but it was never called

Any help will be appreciated!

Update: I believe the click might have not worked before because the circle didn't exist when cypress attempted to click it. By adding "await cy.wait(1000);" before the click action, the function is called (I can see the results and a message logged from inside it). Sadly, the test is still failing.

Update 2: I changed the test to use the window object (see below), but the assertion still fails (the test itself succeeds, which is also not a good thing).

 cy.window()
      .then(window => {
        displayMovieInfoSpy = cy.spy(window, "displayMovieInfo");
        cy.get("#scatterPlot")
          .get("circle")
          .eq(2)
          .click({ force: true })
          .as("clicking");
        expect(displayMovieInfoSpy).to.be.called;
      });

Update 3: It seems that the combination of d3 and parcel.js causes the test to fail. When using d3 alone or parcel.js alone, the test works just fine. Also, the expect statement should be in the then block after the click action.

like image 584
wicccked Avatar asked Sep 16 '18 01:09

wicccked


1 Answers

Seems you're importing app variable on the test directly. This object is a different one than the one on your browser. You should make a global variable (or method) for getting your app variable directly from your browser

cy.window().its('app').then((app) => { 
   // your test with app var
})

Also you might want to use then() condition to ensure it checks it after. But this may not be necessary.

.click({ force: true }).then(() => {
   expect(displayMovieInfo).to.be.called;
});
like image 122
Pau Penín Avatar answered Oct 03 '22 14:10

Pau Penín