Skip to main content

_javascript

TL;DR - Show Me The Code

4-work-with-multiple-windows/code/javascript/test/multiple-windows.spec.js
const assert = require("assert");
const {Builder, By} = require("selenium-webdriver");

describe("Multiple Windows", function () {
let driver;

beforeEach(async function () {
driver = await new Builder().forBrowser("firefox").build();
});

afterEach(async function () {
await driver.quit();
});

it("non-deterministic switching", async function () {
await driver.get("https://the-internet.herokuapp.com/windows");
await driver.findElement(By.css(".example a")).click();
const windowHandles = await driver.getAllWindowHandles();
await driver.switchTo().window(windowHandles[0]);
assert((await driver.getTitle()) === "The Internet");
await driver.switchTo().window(windowHandles[windowHandles.length - 1]);
// Waiting for the new window to have a title, then we consider it is loaded
await driver.wait(async function () {
return (await driver.getTitle()) !== "";
}, 2000);
assert((await driver.getTitle()) === "New Window");
});

it("browser agnostic switching", async function () {
await driver.get("https://the-internet.herokuapp.com/windows");
const windowHandlesBefore = await driver.getAllWindowHandles();
await driver.findElement(By.css(".example a")).click();
const windowHandlesAfter = await driver.getAllWindowHandles();
const newWindow = windowHandlesAfter.find(
handle => !windowHandlesBefore.includes(handle)
);
await driver.switchTo().window(windowHandlesBefore[0]);
assert((await driver.getTitle()) === "The Internet");
await driver.switchTo().window(newWindow);
// Waiting for the new window to have a title, then we consider it is loaded
await driver.wait(async function () {
return (await driver.getTitle()) !== "";
}, 2000);
assert((await driver.getTitle()) === "New Window");
});
});

Code Walkthrough

Importing Libraries, Setup and Teardown

The first two lines are pulling in our testing framework (e.g., require("assert")), driving the browser with Selenium (e.g., const {Builder, By} = require("selenium-webdriver");). Then we wire up some test setup and teardown methods.

Example 1

Line 15 shows a test that exercises new window functionality from an application. In this case, we'll be using the new window example from the-internet.

After loading the page we click the link which spawns a new window. We then grab the window handles (a.k.a. unique identifier strings which represent each open browser window) and switch between them based on their order (assuming that the first one is the originating window, and that the second one is the new window). We round this test out by performing a simple check against the title of the page to make sure Selenium is focused on the correct window.

While this may seem like a good approach it can present problems later because the order of the window handles is not consistent across all browsers. Some return it in the order opened, others alphabetically.

Here's a more resilient approach. One that will work across all browsers.

Example 2

Line 29 shows that after loading the page we store the window handles in a variable (e.g., windowHandlesBefore) and then proceed with clicking the new window link.

Now that we have two windows open we grab all the window handles again (e.g., windowHandlesAfter) and search through them to find the new window handle (e.g., the handle that's in the new window handle collection but not the initial one). We store the result in another variable (e.g., newWindow) and then switch between the windows each time checking the page title to make sure the correct window is in focus.

For more information about switching windows (and tabs) visit the official Selenium documentation page.

Executing the Test

Before executing the test, we need to make sure the required dependencies are declared on the package.json file.

Toggle to see the package.json file.
4-work-with-multiple-windows/code/javascript/package.json
{
"dependencies": {
"selenium-webdriver": "4.25.0"
},
"description": "A project to showcase working with multiple windows using official WebdriverJs",
"devDependencies": {
"mocha": "10.7.3"
},
"license": "MIT",
"name": "download-a-file",
"scripts": {
"test": "npx mocha test/**/*.spec.js --timeout 60000"
},
"version": "1.0.0"
}

Finally, we can run the test by executing npm test from the command-line.