Dealing with new tabs in Cypress
Cypress is an amazing tool with some of the best features for developers and testers alike. But by its own admission. Cypress can never handle controlling multiple tabs, or one browser at a time.
This may put you off investing the time into learning and using this unique and modern tool. Selenium can drive multiple browsers and tabs without much effort. Why not just pick that over Cypress?
And although it’s a valid point, it’s important to note that these disadvantages are due to the unique architecture of Cypress which, in the developer’s own words:
In a sense they prevent you from writing bad, slow, or flaky tests.
Are you sure you want to do that?
Let’s look at this from a practical point of view. Is there ever going to be a test you will need to automate that calls for the independence of two browser windows or tabs?
My guess is most likely not.
Of course, there will probably be some scenarios where this functionality is desirable. But if you want your automation suite to be fast, agile, and not a drain on memory and processor usage. I am going to make the case that sticking to one tab per test is the best setup that you should strive for.
Not only is this good practise to truly ensure that you are isolating your test cases. But also helps protect you from any browser quirks or behaviour that could add unwanted flakiness to your test code.
So instead of a test dependent on your ability to control two independent browser windows or tabs. I would say that you should instead take the approach of two separate tests.
Given the case of a new browser tab opening when a button is pushed, for example. I would advocate that one test be dedicated to testing everything before the new tab is launched, including the new tab being called. And then a separate test dedicated to testing everything post the new tab being called.
So what is the solution that Cypress provides?
One of the most versatile features that Cypress comes with is the ability to stub a network request. Providing you with a way to not only tell when a call has been made to a function. But to also take control of its behaviour and really provide testers with the ability to take control of how the application performs instead of the other way around.
When you include a stub inside your code. The object that is returned is an actual value object that can be asserted on instead of a promise like object.
So in the example’s case defined above. We first need to stub the browser opening action so that Cypress can monitor when the action is called and assert on the stubbed object instead of executing the default action.
To do so include the following code:
onBeforeLoad(win) {
cy.stub(win, “open”).as(“windowOpen”);
}
To provide a little more context to this code. We are saying to execute the code within the function before the browser window loads. We are also passing in the window object so we can apply our stub.
Next, we are saying that when the open call is made to the window object. Alias it with the windowOpen name.
Finally, we have to code in an assertion that ensures the alias is called and crucial for our test. This will not open a new browser window, and our test code will continue without interruption.
cy.get(“@windowOpen”).should(“be.called”);
Putting this all together. Your test code should look something like this:
cy.visit(“www.samplepage.com”, {
onBeforeLoad(win) {
cy.stub(win, “open”).as(“windowOpen”);
},
});
cy.get(“button”).contains(“New Window”).click();
cy.get(“@windowOpen”).should(“be.called”);
Wrapping it all up
This is just a simple example of how you can use the versatility of Cypress to get around the problem of dealing with multiple browser windows.
Yes, Selenium can do so, and it does it pretty well. But as I talked about earlier. There is no such thing as a free lunch and while it may seem that you are gaining extra functionality. You might make unwanted trade-offs and unknowingly introducing unreliability to your test automation.
Cypress isn’t a perfect solution. No tool can claim to be perfect. But in the hands of someone who has knowledge of its strengths and limitations. The tool can be just as useful and powerful as any other on the market today.
I hope this blog post was useful to you.
Reach out to me on LinkedIn or Twitter if you have questions. Or contact me using my contact form.
PS: I also send out a weekly newsletter which contains links to articles I’m reading, the books I’m enjoying. And other interesting content. Sign-up here if you’re interested. It’s free!