Stub window.open
Motivation
If an application calls window.open during Cypress test it might lead to two problems:
- the new URL might point at a different domain, rendering Cypress "blind" and unable to continue the test
 - the new URL might open in the second tab, invisible to Cypress
 
Stubbing an object's method
In order to stub (replace) an object's method we need three things:
- a reference to the object
 - method's name
 - we also have to register the stub before the application calls the method we are replacing
 
🖥 I explain how the commands cy.spy and cy.stub work at the start of the presentation How
cy.interceptworks.
Luckily for us stubbing the window.open satisfies all the criteria easily
- the command cy.window gets the reference to the application's 
windowobject - the method's name is 
open - we can use 
onBeforeLoadcallback in the cy.visit to stub thewindow.openmethod. This callback runs when thewindowobject is ready, but before any application code runs 
1  | it('opens a new window', () => {  | 
When window changes
If the application navigates to a new page or even reloads, the old window object is destroyed and the new window object is created. Thus our window.open stub can "disappear": the application calls window.open, but the stub does not intercept the new calls.
1  | // 🚨 SHOWING THE PROBLEM  | 
We need to register window.open stub for every window object created during the test. We can use cy.on('window:before:load') event:
1  | // ✅ CORRECT SOLUTION  | 
The above test correctly prevents window.open from causing problems when the application reloads or navigates to another page.
cy.on vs Cypress.on
We have used cy.on('window:before:load') to register our stub. We could have used Cypress.on('window:before:load'), but then we could not use the cy.stub command inside the callback - Cypress.on runs outside a test context and thus cannot use any cy. commands. It is often used to perform general application actions. For example we could remove window.fetch method from every window object
1  | Cypress.on('window:before:load', (win) => {  | 
In our window.open case we can bypass the problem. We can return the same stub for every window, we just have to return the variable prepared by the test via closure scope:
1  | // variable that will hold cy.stub created in the test  | 
Tip: you can reset a spy or a stub by invoking its reset() method
1  | // triggers the application to call window.open  | 
See also
I have described in detail how to deal with anchor links and window.open in two sections in the blog post Cypress Tips and Tricks:
- Deal with Second Tab in Cypress
 - Deal with 
target=_blank - I strongly recommend reading Deal with 
window.open 
There is also more documentation and examples available at:
- Sinon.js
 - Cypress guide to Stubs, Spies, and Clocks
 cy.stubandcy.spyexamples
You can also read about and practice with cy.stub in the section of the Cypress Testing Workshop
See the blog post Stub window.track