How do I assert against objects with spies in Cypress?

久未见 提交于 2019-12-11 09:38:23

问题


I am using Cypress spies to test client-side analytics.

My intent in this test is to confirm that identify has been called like so:

identify('myemail@email.com', { groupId: 1002, groupName: "myGroup", someProp: 1, anotherProp: 2 })

I hook the spies into emitter events on a global analytics object in window:before:load (note the while loop is to deal with delays in the library loading):

Cypress.on("window:before:load", async (win: Window) => {

  const sleep = (n = 1) => new Promise(r => setTimeout(r, n));
  let set = false;
  while (set === false) {
    if (win["analytics"]) {
      set = true;
      const a = win["analytics"];
      const pageSpy = cy.spy().as("page");
      const idSpy = cy.spy().as("identify");
      a.on("page", pageSpy);
      a.on("identify", idSpy);

    } else {
       // default sleep of 1ms. this is b/c there's a super tight
       // window from analytics init and the calls I'm looking to
       // track (~25ms)
      await sleep();
      continue;
    }
  }
});

The intent here is that every time a page or identify method is called, the spy is called with the args from the page / identify call.

Then, in my test:

 it("calls identify on page load", () => {
    const idProps = {
      groupId: 1002,
      groupName: "myGroup",
      someProp: 1,
      anotherProp: 2
    };

    cy.visit("https://mypage.com");

    cy.get("@identify").should(
      "be.calledWith",
      "myemail@email.com"
    ).and("be.calledWith",idProps);
  });

The first assertion passes ("be.calledWith", "myemail@email.com").

The second assertion, however, fails:

Command:  get
cypress_runner.js:141344 Alias:    @identify
cypress_runner.js:141344 Yielded:  ƒ identify
cypress_runner.js:141344 Error:    CypressError: Timed out retrying: expected identify to have been called with arguments Object{4}

    The following calls were made:

    identify("myemail@email.com", Object{4}, undefined) at o.proxy (https://exmaple.com/__cypress/runner/cypress_runner.js:45839:22)

I have tried using sinon.match, but that isn't supported in Cypress' version of sinon.

I also tried extracting the raw calls / args (ie spy.getCalls()), but this doesn't seem to be supported when accessing the spy via an alias (i.e. cy.get('@identify')).

So: is there any way to deep match the args passed to a cypress spy?


回答1:


I've solved the problem in the OP title. Wrapping the analytics method in a spy was another problem, but I've updated the snippet in OP to reflect how I fixed that (i.e., changing sleep interval to 1ms).

You can assert on the object in a spy call's args using the callback signature of cy.should:

 const idProps = {
      groupId: 1002,
      groupName: "myGroup",
      someProp: 1,
      anotherProp: 2
    };

cy.get("@identify").should(a => {
      expect(a).to.be.calledWith("myemail@email.com");
      // pardon the property index-ref style, using typescript and i'm lazy
      const spy = a["getCalls"](); 
      const { args } = spy[0];
      expect(args[1]).to.deep.equal(idProps);
    });


来源:https://stackoverflow.com/questions/52266967/how-do-i-assert-against-objects-with-spies-in-cypress

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!