Introduction
When you find yourself in the process of developing a more complex web page, you’ll surely come across a situation where the users click on buttons/links that will take them to a new tab or window. While it is straightforward to code such a button/link, testing this behavior can be quite a bit more difficult. Cypress, for instance, doesn’t have native support for accessing a new window or browser tab.
The lack of support for testing across domains is intentional, as explained by the Cypress team in the “Trade-offs” portion of their guidelines:
Because Cypress runs in the browser, it will never have multi-tabs support. We do have access to the browser automation APIs to actually switch tabs, but there is no reason for us to ever expose them.
Imagine a simple anchor tag like the following:
|
|
Testing that the anchor tags navigates to the /foo
URL, and testing any subsequent functionality after that, is not
possible in Cypress without workarounds. In this article we’ll cover a few workarounds that will allow you to test
multi-tab and multi-window workflows using Cypress.
The demo app
To try out these workarounds, we’ll be creating tests against a simple React app. The app consists of two buttons and one input field. Our simple app is set up so that when you click a button, either a new window or a new tab will be opened, and the user will be redirected to Google’s search page. The URL will be created dynamically, depending on the value entered in the input field.
The GIF below demonstrates what happens when the string “test query” is entered into the input box and the second button
is clicked. You’ll notice that we’re directed to the Google results in a new tab. Each button is using a different
mechanism for opening a new tab. The first button is using an anchor tag with a target
attribute populated to open a
new tab, and the second button is using Javascript to call the window.open
method once the button is clicked.
The whole source code used in this blog post can be found here.
In order to get the demo React app running, cd into the “cypress-new-window” directory and run npm install
. The
demo project contains three Cypress spec files which can be found in the cypress/e2e
directory. The basic.cy.js
generally checks if all elements are being rendered correctly. More interesting for this post are the window.cy.js
and
atag_blank.cy.js
spec files. The files contain tests that test multi-tab/multi-window workflows.
Accessing a new window with the window interface
Here is the code that’s executed when the second button in our React app is clicked:
|
|
As you can see, the URL is dynamically created depending on the value of inputValue
, which comes from the input field.
The _blank
value that’s passed in the second argument is the _target
of the window.open
method, and causes the URL
to be loaded in a separate tab, rather than in the current window.
In order to validate that the button links to the correct page, we can replace the window.open
method with
Cypress’ stubs before the app is loaded. Additionally, we’re using
aliases for referencing our stub (winOpen
), the button
(winOpenButton
) and the input field (input
).
|
|
Now that our stub is in place, we can define a test to verify our desired behavior. The simplest assertion we can make
is that the window.open
method is called after the button is clicked:
|
|
While this is easy to implement, it does not let us validate that we’re navigating to the correct page.
Fortunately, there is a way to check if the window.open
method is being called with an expected URL. Instead of using
.should("be.called")
we instead use .should("be.calledWith")
and specify the URL we expect to be called:
|
|
The next step here is to populate a search query in the input box and verify that the URL that’s dynamically generated by the React app is correct:
|
|
Testing additional actions after the button click
Since Cypress prevents testing across domains by default, the easiest approach to testing functionality after the button click would be to create a separate test that starts from the URL generated by our React app:
|
|
This approach is best suited to situations where no pre-existing state is necessary before accessing this URL, and where the URL can be reliably generated at the outset of the test. More complex workflows, like Single-Sign On workflows, cannot be tested with this approach.
Accessing a new window with a target attribute
Tests for the other button can be found at cypress/e2e/atag_blank.cy.js
. Let’s cover two separate approaches for
testing anchor tags that link to a separate domain.
Verifying the link attributes
We will first take a look at the first option, since this is the big methodological difference between accessing a new
tab with the href attribute and calling the window.open
method.
This option is similar to the approach we covered above with the window.open
method. Like the example above, instead
of following the actual user flow and navigating to the Google search page, we’ll instead simply verify that the URL we
would be navigating to is correct.
Accomplishing this is pretty straightforward: we can just grab the href
attribute of the anchor tag and verify it
matches what we expect:
|
|
The same can also be achieved with a dynamic URL. Just enter a search query in the input field and add the search query to the expected URL:
|
|
Similar to our window.open example, to test subsequent functionality you can write a separate test that starts by visiting the new dynamic URL.
Forcing clicks to occur on the current window
The last approach we’ll cover has the fewest amount of limitations. Since clicking the button without any adjustment
would lead to a new window being opened, the test would fail. Luckily, Cypress allows us to access and manipulate the
DOM. With that in mind, we can think of a solution which allows us to visit the target URL without the need of
accessing a new window. For that, we can simply remove the target
attribute:
|
|
If you run the test just like this, the following error will be thrown:
Due to the browser’s Same Origin Policy, Cypress doesn’t support tests that span multiple domains e.g. from
http://localhost:3000
to https://www.google.com
. If you stay in the localhost context, then you don’t need to worry
about this error. But since we are redirecting to Google’s search in this example, we need to fix this problem.
In order to fix this problem, jump into the cypress.config.js
on the root level of the project and add
chromeWebSecurity: false
to the config as follows:
|
|
After that adjustment, your tests should be working again.
Naturally we can use the same approach to run the test with a dynamically created URL. Analogous to the examples before, you’ll need to add the search query to the input field and also to the URL itself.
|
|
Conclusion
This blog post covered how you can test a new window in Cypress tests, even though Cypress doesn’t officially support
it. We have distinguished between scenarios where a new window is opened via an anchor tag with a _target
attribute
defined, versus scenarios where links are opened via a Javascript function that calls the window.open
method.
Reflect: A testing tool with built-in support for multiple tabs and windows
Reflect is a no-code testing tool that can test virtually any action you can take on a browser. In addition to testing workflows that contain multiple tabs and windows, you can also test more complex actions like drag-and-drops, hovers, and file uploads. Creating a test in Reflect is easy: the tool records your actions as you use your site and automatically translates those actions into a repeatable test that you can run any time.
Get automated test coverage for your web app today — try it for free.