2

How to handle the windows in Cypress?

The problem I'm facing is that when I click a button, a new browser window gets opened in a new tab with the actual page to test.

I have tried everything -> window.open and window.location.replace without success (the target _blank is not possible because there is not that tag in the button)

How can I handle that functionality?

Thanks in advance.

Esteban
  • 21
  • 1
  • 2

2 Answers2

2

I found many different approaches to stubbing the window.open call, but none of them worked out of the box.

In my use case there's a button that launches a click event. The click event then opens a new tab with a dynamic url that I wanted to grab.

The answer is a mix of a great post: https://glebbahmutov.com/blog/stub-window-open/ and Cypress: Stub open window.

This example should work with Cypress 10.x

// Listen to window:before:load events, modify the window object before the app code runs between page transitions
// Create a stub with the alias windowOpen, choose whatever you like
// Grab the url parameter that the page was trying to open and visit the page
cy.on('window:before:load', (win) => {
  cy.stub(win, 'open').as('windowOpen').callsFake(url => {
    cy.visit(url);
  })
})

// Start by visiting the page you'll run your tests in. I'm using the baseUrl here.
cy.visit("/");

// Do whatever tests need to be done before the action the opens a new tab

// Now the element that fires a click event which then uses window.open to open a new tab 
cy.contains("Ok").click();

// The stub should now have picked the url and called cy.visit(url)
// The page that would normally open in a new tab, should be visible in the same page

// Now the next commands are intended to run in the new page and should be able to complete
cy.get(".whateverselectoryouwant")
    .should('have.text', 'whateveryourtextisonthenewpage')
ttqa
  • 326
  • 2
  • 12
1

The problem is window.open can't be stubbed in the usual (simple) way, a security feature to prevent browser hijack.

This article Stub window.open has an alternative

TLDR - modify the window before it hits the browser

// ✅ CORRECT SOLUTION
it('opens a new window', () => {
  // create a single stub we will use
  const stub = cy.stub().as('open')
  cy.on('window:before:load', (win) => {
    cy.stub(win, 'open').callsFake(stub)
  })

  cy.visit('/')
  // triggers the application to call window.open
  cy.get('button').click('Open new window')
  cy.get('@open').should('have.been.calledOnce')
Fody
  • 23,754
  • 3
  • 20
  • 37