Why does cy.on stop working when moved to a custom command?

57 views Asked by At

I am using the following function to detect window opening and assert that it's opened to the correct URL:

const stubWindowOpen = () => {
  const stub = cy.stub().as(`window-open`)
  cy.on(`window:before:load`, (window) => {
    cy.stub(window, `open`).callsFake(stub)
  })
}

Then later:

const assertWindowOpened = (url) => {
  cy.get(`@window-open`).should(`have.been.calledOnce`)
  cy.get(`@window-open`).should(`be.calledWith`, url, `_blank`)
}

This works great, but I need to use this functionality across multiple files and multiple projects. I converted this to a custom command and placed it in /support/commands.js:

Cypress.Commands.add(`stubWindowOpen`, () => {
  const stub = cy.stub().as(`window-open`)
  cy.on(`window:before:load`, (window) => {
    cy.stub(window, `open`).callsFake(stub)
  })
})

However this no longer works, and the assertion fails, with the message:

expected window-open to have been called exactly once, but it was never called

Why does moving this to a custom command cause it to stop working?

1

There are 1 answers

0
TesterDick On

The .callsFake(stub) part doesn't seem to be needed. The usual pattern is just

cy.stub(window, 'open').as('window-open')

There shouldn't be any difference between the function version and the custom command version, so I can't say why you observe a difference.

To check it out, ran a simple web page with script to call window.open.

<body>
  <script>
    window.open('https://example.com')
  </script>
</body>

Then tested with this

Cypress.Commands.add('stubWindowOpen', () => {
  cy.on('window:before:load', (window) => {
    cy.stub(window, 'open').as('window-open')
  })
})

it('tests with stubWindowOpen custom command', () => {
  cy.stubWindowOpen()
  cy.visit('html/stub.open.html');
  cy.get('@window-open').should('have.been.calledOnce')
})

enter image description here