问题
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