Spy called with an object
Imagine you are spying on a call using cy.spy command. How do you check if the caller passed the right arguments? If you already read the examples from my Spies, Stubs & Clocks page, then keep reading.
📺 watch this recipe explained in the video Check If A Spy Was Called With The Right Object.
Primitive types
If the method is called with primitive arguments like strings, then it is simple to check.
<script>
setTimeout(() => {
console.log('Hello', 'world')
}, 100)
</script>
cy.window()
.its('console')
.then((console) => {
cy.spy(console, 'log').as('log')
})
cy.get('@log').should('be.calledWith', 'Hello', 'world')
Exact object
If the method is called with an object, you can do two things: either yield it to the next assertion deep.equal
or use the Sinon's built-in matching assertion.
<script>
setTimeout(() => {
console.log('User %o', { id: 123, name: 'Joe' })
}, 100)
</script>
cy.window()
.its('console')
.then((console) => {
cy.spy(console, 'log').as('log')
})
We have set up the spy to be ready when the application calls console.log
. We now need to confirm the log method was called with 2 arguments. The first argument is a primitive string User %o
. That is easy to do:
cy.get('@log').should('be.calledWith', 'User %o')
How do we confirm the second argument? Sinon-Chai library calledWith
uses deep.equal
comparison by default, thus we can simply pass the object.
// use Sinon-Chai built-in object by value match
cy.get('@log').should('be.calledWith', 'User %o', {
id: 123,
name: 'Joe',
})
We can also confirm the call using placeholder Cypress.sinon.match.object
and yield the argument to run more "assertions" using chained commands.
// yield the object to the next assertion
cy.get('@log')
.should('be.calledWith', 'User %o', Cypress.sinon.match.object)
.its('firstCall.args.1')
.should('deep.equal', { id: 123, name: 'Joe' })
Partial object
If we know some properties of the object, we can use deep.include
assertion on the yielded object.
<script>
setTimeout(() => {
console.log('User %o', { id: 123, name: 'Joe' })
}, 100)
</script>
cy.window()
.its('console')
.then((console) => {
cy.spy(console, 'log').as('log')
})
cy.get('@log')
.should('be.calledWith', 'User %o', Cypress.sinon.match.object)
.its('firstCall.args.1')
// imagine we do not know all object fields
.should('deep.include', { name: 'Joe' })
Alternatively, if we know all the expected field names, we can use Sinon matchers as placeholders:
cy.get('@log').should('be.calledWith', 'User %o', {
id: Cypress.sinon.match.number,
name: 'Joe',
})
Tip: try using cy-spok plugin for such assertions.