Cypress - Tabs
Cypress - Handling New Browser Tabs
Section titled “Cypress - Handling New Browser Tabs”A common web pattern is for links or buttons to open new browser tabs or windows, often achieved using the target="_blank" attribute on an <a> tag. Cypress, by design, operates within a single browser tab. It does not provide native support for switching to or interacting with new tabs or windows directly.
This design choice contributes to Cypress’s speed and reliability, as managing multiple tabs can introduce flakiness. However, Cypress offers a straightforward workaround for testing scenarios involving links that would normally open in new tabs.
The Workaround: Removing the target Attribute
Section titled “The Workaround: Removing the target Attribute”The most common strategy is to programmatically remove the target attribute from the link element before clicking it. This causes the link to open in the same tab, allowing Cypress to continue interacting with the newly loaded page.
Cypress uses the jQuery method removeAttr() for this, invoked via the cy.invoke() command. By removing target="_blank", the browser’s default behavior is to open the link in the current tab.
After interacting with the content on the new page (now in the same tab), you can navigate back to the previous page using cy.go('back') if needed.
Example HTML Structure
Section titled “Example HTML Structure”Consider the following HTML snippet where a link is designed to open in a new tab:
<a id="new-tab-link" href="/new-page.html" target="_blank">Open New Page</a>Implementation in Cypress
Section titled “Implementation in Cypress”Here’s how you can test this scenario in Cypress:
describe('New Tab Handling', () => { it('Should open link in the same tab by removing target attribute', () => { // Visit the page containing the link cy.visit('https://the-internet.herokuapp.com/windows'); // A great site for practice
// Find the link that opens a new window/tab // The selector '.example > a' targets the link on this specific page cy.get('.example > a') .invoke('removeAttr', 'target') // Remove the target attribute .click(); // Click the link
// Verify that the new URL is loaded in the same tab cy.url().should('include', '/windows/new'); cy.contains('h3', 'New Window').should('be.visible');
// Optionally, navigate back to the original page cy.go('back');
// Verify we are back on the original page cy.url().should('not.include', '/windows/new'); cy.url().should('include', '/windows'); });});In this script:
cy.get('.example > a')selects the link element..invoke('removeAttr', 'target')removes thetargetattribute. This command is chained before.click()..click()then clicks the modified link, causing it to load in the current tab.cy.url().should('include', '/windows/new')verifies that navigation occurred as expected.cy.go('back')navigates back to the previous page in the browser’s history.
Handling window.open()
Section titled “Handling window.open()”Sometimes, new windows are opened via JavaScript using window.open(). While the removeAttr technique works for target attributes, window.open() requires a different approach. You can often test the intent to open a new window by stubbing window.open():
it('Should verify a new window is requested via window.open', () => { cy.visit('/page-with-js-popup.html'); // A page that uses window.open()
cy.window().then((win) => { cy.stub(win, 'open').as('windowOpen'); // Stub window.open and alias it });
cy.get('#button-that-opens-window').click();
cy.get('@windowOpen').should('be.calledOnce'); // Optionally, check the URL it was called with: // cy.get('@windowOpen').should('be.calledWith', '/expected-popup-url.html');});This method doesn’t interact with the content of the new window but verifies that the application attempted to open it, which is often sufficient for testing purposes.
Conclusion
Section titled “Conclusion”While Cypress restricts tests to a single tab, the invoke('removeAttr', 'target') method provides an effective and widely adopted solution for testing links that would otherwise open new tabs. This approach aligns with Cypress’s philosophy of promoting fast, reliable, and non-flaky tests.