Cypress Multiple window

Introduction: 

As of now cypress doesn’t support handling multiple windows out of the box but there is a solution for this problem. Cypress provides a very powerful command “cy.task()“. Using this command we can execute any code on Node like database operations, linking other automation tools such as selenium, playwright, etc. 

So, in this blog, we will understand and resolve this problem. We will integrate selenium in our existing cypress framework and handle multiple windows and tasks related to it using Cypress command cy.task()

Pre-requisites: 

Before proceeding further, make sure that the below dependencies are installed on your system. 

  • Cypress 
  • Chai 
  • Selenium Webdriver 
  • Chromedriver 

Folder Structure: 

To create a folder, right-click on a folder and then choose the “New Folder” option, enter the folder name, and hit enter. 

Make sure that the cypress framework folder structure is as same as the image mentioned below:

Folder creation for cypress multiple windows

Configuration: 

The webpage URL is mentioned in the envConfig.json file, as mentioned below: 

envConfig.json

We need to define the task name in the cypress.config.js file under defineConfig, as mentioned below:

const { defineConfig } = require("cypress");
const  {performSomeActionsSecondWindow} = require ('./cypress/plugins/PerformSomeActionsSecondWindow.js');
module.exports = defineConfig({
  defaultCommandTimeout: 60000,
  pageLoadTimeout: 90000,
  chromeWebSecurity: false,
  waitForAnimations: true,
  requestTimeout: 60000,
  responseTimeout: 90000,
  numTestsKeptInMemory: 10,
  viewportWidth: 1920,
  viewportHeight: 1080,
  e2e: {
    setupNodeEvents(on, config) {
      on('task', {performSomeActionsSecondWindow});
    },
  },
});
cypress.config.js

Scenario for Testcase:  

Handling multiple windows in a Cypress Automation Framework:

  •  Perform some actions using cypress 
    1. Visit the website: https://automationteststore.com/
    2. Verify page title 
  • Handle multiple windows using selenium 
    1. Visit the website: https://automationteststore.com/ This is the first window (parent window). 
    2. Look for the Facebook icon at the top right corner of the website. 
    3. Perform SHIFT + Click (click the left button of the mouse) on the Facebook icon, this will open the Facebook website into a new window which will be our second window 
    4. Extract the title of the second window 
    5. Enter username and password 
  • Perform some actions using cypress 
    1. Verify the title extracted from the second window
    2. Click on the Login or register button 
    3. Verify the title of ‘Account Login’ page 

Understanding the Testcase and used methods: 

Testcase code is as mentioned below:

const envConfig = require('../fixtures/envConfig.json');
const expectedFirstWindowHomePageTitle = 'A place to practice your automation skills!'
const expectedSecondWindowFacebookPageTitle = 'Facebook – log in or sign up';
const expectedFirstWindowLoginPageTitle = 'Account Login';
describe('Handle multiple windows in Cypress', () => {
  it('Handling multiple windows in Cypress using Selenium', () => {
    // Step: 1 - Perform some action using cypress 
    cy.visit(envConfig.baseUrl);
    cy.title().should('contain', expectedFirstWindowHomePageTitle);
    
    // Step: 2 - Handle multiple windows using selenium 
    cy.task('performSomeActionsSecondWindow').then($res=>{
      expect($res).to.equal(expectedSecondWindowFacebookPageTitle);
    });
    // Step: 3 - Perform some action using cypress 
    cy.get('ul li').contains('Login or register').should('be.visible').click();
    cy.title().should('contain', expectedFirstWindowLoginPageTitle);  
  })
});

MultipleWindowsTests.cy.js 

MultipleWindowsTests.cy.js

Step 1: Perform some actions using cypress 

  1. Navigate to a website
    • cy.visit() is used to navigate to a website 
  2. Verify page title 
    • cy.title() is used to get web page titles and chai assertions 

Step 2: Handle multiple windows using selenium

As we are using JavaScript for our Cypress framework, so we will use the same for Selenium.

The code for this step is mentioned below:

require("chromedriver");
const { By, Key, Builder, until, Actions } = require('selenium-webdriver');
const {expect} = require('chai');
const envConfig = require('../fixtures/envConfig.json');
const performSomeActionsSecondWindow = async () => {
  // To wait for browser to build and launch properly
  let driver = await new Builder().forBrowser("chrome").build();
  // await driver.manage().window().maximize();
  // To fetch website from the browser
  await driver.get(envConfig.baseUrl);
  
  // Store the ID of the parent window
  const parentWindow = await driver.getWindowHandle();
  expect(await driver.getAllWindowHandles()).to.have.length(1);
  
  // Click on element and open link in new window
  const element = await driver.findElement(By.css('[title="Facebook"]'));
  await driver.actions().keyDown(Key.SHIFT).click(element).perform();
  // Wait for the new window
  await driver.wait(
    async () => (await driver.getAllWindowHandles()).length === 2,
    10000
  );
  // Switch to new window (second window)
  const windows = await driver.getAllWindowHandles();
  await driver.switchTo().window(windows[1]);
  
  // Extract the second window page title
  let secondWindowTitle = await driver.getTitle();
  // Perform some actions
  await driver.findElement(By.css('input[id="email"]')).sendKeys('cypressmultiwindowshanlder@fakemail.coom')
  await driver.findElement(By.css('input[id="pass"]')).sendKeys('&^w4h$6$^4g')
  // Close all open windows
  await driver.close();
  await driver.switchTo().window(parentWindow)
  await driver.close();
  return secondWindowTitle;
};
module.exports = {performSomeActionsSecondWindow};

PerformSomeActionsSecondWindow.js 

Cypress multiple windows

Pre-Steps: Configure and launch a browser using Selenium [Chrome browser]. 

let driver = await new Builder().forBrowser(“chrome”).build(); 

  1. Visit the website 
    • driver.get(): Navigate to a web page 
  2. Look for the Facebook icon at the top right corner of the website.  
    • driver.getWindowHandle(): Returns parent window id 
    • driver.findElement(By.css()): Locate an element using CSS locator 
  3. Open a link in new window 
    • click(): used to perform click operation 
    • driver.actions().keyDown(Key.SHIFT).click(element).perform(); : This will perform keyboard action (SHIFT + Click) on a particular element, in our case, it will open a link in a new window. 
  4. Extract the title of the second window 
    • driver.getAllWindowHandles(): Returns all window handles ids in an array of string 
    • driver.switchTo().window(windowId): Used to switch focus of to another window[In our case, driver focus switch to second window] 
    • driver.getTitle(): Returns page title 
  5. Perform some operations: Enter username and password 
    • sendKeys(): Type into the textbox 

driver.close() is used to close the current open window 

Step 3: Perform some action using cypress 

  1. Verify title extracted from the second window
    • Use chai assertions for verifying the title 
  2. Click on ‘Login or register’ button 
    • cy.get(): Locate an element 
    • click(): Perform click operation  
  3. Verify title of ‘Account Login’ page 
    • Use chai assertions for verification of the title 

Execution:

Watch the test case execution video:  

Note: Please make sure that the package.json file is as mentioned below: 

{
  "name": "handle_multiple_windows",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "presets": [
    "@babel/preset-env"
  ],
  "dependencies": {
    "chromedriver": "^105.0.0",
    "selenium-webdriver": "^4.4.0"
  },
  "devDependencies": {
    "chai": "^4.3.6",
    "cypress": "^10.7.0"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
Handle multiple windows in cypress

Conclusion:

So, in this way, we have successfully handled multiple windows in cypress using cy.task(). By using cy.task(), we can easily integrate automation tools like Selenium into our existing framework which supports handling multiple browser windows.