Screenshots and PDFs
A test fails on the CI server and the stack trace says an element was not found. What was on the screen at the time? Without a picture, the first debugging step is to re-run the test locally and hope it fails the same way. A screenshot taken at the moment of failure turns that guess into evidence, and the same API is the basis of visual comparison and archiving.
Recommended approach
WebDriver’s screenshot command returns the current viewport as a PNG, Base64-encoded. Every binding wraps that so you can save it straight to a file. Calling the same command on an element rather than the driver crops the image to that element’s bounding box, which is the right choice when you want to compare a component rather than a whole page.
A viewport screenshot captures only what is visible without scrolling. Firefox supports a
full-page screenshot through its own driver API; with WebDriver BiDi enabled, the browsing
context module’s captureScreenshot command works across browsers and can also capture a box
or an element.
To produce a PDF rather than an image, use the print command. It takes a PrintOptions
object for orientation, page ranges, size, margins, scale and whether to print background
graphics, and returns the document Base64-encoded, ready to decode and write to a file.
Attach a screenshot to every failure in your test framework’s teardown hook: it is cheap, and the one time you need it you will be glad it is there.
Take a screenshot of the viewport:
let encodedString = await driver.takeScreenshot();/examples/javascript/test/interactions/windows.spec.js
const {Builder, By} = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const assert = require("node:assert");
let opts = new chrome.Options();
opts.addArguments('--headless');
let startIndex = 0
let endIndex = 5
let pdfMagicNumber = 'JVBER'
let imgMagicNumber = 'iVBOR'
let base64Code
describe('Interactions - Windows', function () {
let driver;
before(async function () {
driver = await new Builder().forBrowser('chrome').setChromeOptions(opts).build();
});
after(async () => await driver.quit());
it('Should be able to print page to pdf', async function () {
await driver.get('https://www.selenium.dev/selenium/web/alerts.html');
let base64 = await driver.printPage({pageRanges: ["1-2"]});
// page can be saved as a PDF as below
// await fs.writeFileSync('./test.pdf', base64, 'base64');
base64Code = base64.slice(startIndex, endIndex)
assert.strictEqual(base64Code, pdfMagicNumber)
});
it('Should be able to get text using executeScript', async function () {
await driver.get('https://www.selenium.dev/selenium/web/javascriptPage.html');
// Stores the header element
let header = await driver.findElement(By.css('h1'));
// Executing JavaScript to capture innerText of header element
let text = await driver.executeScript('return arguments[0].innerText', header);
assert.strictEqual(text, `Type Stuff`)
});
it('Should be able to take Element Screenshot', async function () {
await driver.get('https://www.selenium.dev/selenium/web/javascriptPage.html');
let header = await driver.findElement(By.css('h1'));
// Captures the element screenshot
let encodedString = await header.takeScreenshot(true);
// save screenshot as below
// await fs.writeFileSync('./image.png', encodedString, 'base64');
base64Code = encodedString.slice(startIndex, endIndex)
assert.strictEqual(base64Code, imgMagicNumber)
});
it('Should be able to takeScreenshot', async function () {
await driver.get('https://www.selenium.dev/selenium/web/javascriptPage.html');
// Captures the screenshot
let encodedString = await driver.takeScreenshot();
// save screenshot as below
// await fs.writeFileSync('./image.png', encodedString, 'base64');
base64Code = encodedString.slice(startIndex, endIndex)
assert.strictEqual(base64Code, imgMagicNumber)
});
it('Should be able to switch to newWindow and newTab and close', async function () {
await driver.get('https://www.selenium.dev/selenium/web/');
const initialWindow = await driver.getAllWindowHandles();
assert.strictEqual(initialWindow.length, 1)
// Opens a new tab and switches to new tab
await driver.switchTo().newWindow('tab');
const browserTabs = await driver.getAllWindowHandles();
assert.strictEqual(browserTabs.length, 2)
// Opens a new window and switches to new window
await driver.switchTo().newWindow('window');
const windows = await driver.getAllWindowHandles();
assert.strictEqual(windows.length, 3)
//Close the tab or window
await driver.close();
//Switch back to the old tab or window
await driver.switchTo().window(windows[1]);
const windowsAfterClose = await driver.getAllWindowHandles();
assert.strictEqual(windowsAfterClose.length, 2);
});
it('Should be able to getWindow Size', async function () {
await driver.get('https://www.selenium.dev/selenium/web/');
// Access each dimension individually
const { width, height } = await driver.manage().window().getRect();
// Or store the dimensions and query them later
const rect = await driver.manage().window().getRect();
const windowWidth = rect.width;
const windowHeight = rect.height;
assert.ok(windowWidth>0);
assert.ok(windowHeight>0);
});
it('Should be able to getWindow position', async function () {
await driver.get('https://www.selenium.dev/selenium/web/');
// Access each dimension individually
const { x, y } = await driver.manage().window().getRect();
// Or store the dimensions and query them later
const rect = await driver.manage().window().getRect();
const x1 = rect.x;
const y1 = rect.y;
assert.ok(x1>=0);
assert.ok(y1>=0);
});
});Take a screenshot of one element:
let header = await driver.findElement(By.css('h1'));
// Captures the element screenshot
let encodedString = await header.takeScreenshot(true);/examples/javascript/test/interactions/windows.spec.js
const {Builder, By} = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const assert = require("node:assert");
let opts = new chrome.Options();
opts.addArguments('--headless');
let startIndex = 0
let endIndex = 5
let pdfMagicNumber = 'JVBER'
let imgMagicNumber = 'iVBOR'
let base64Code
describe('Interactions - Windows', function () {
let driver;
before(async function () {
driver = await new Builder().forBrowser('chrome').setChromeOptions(opts).build();
});
after(async () => await driver.quit());
it('Should be able to print page to pdf', async function () {
await driver.get('https://www.selenium.dev/selenium/web/alerts.html');
let base64 = await driver.printPage({pageRanges: ["1-2"]});
// page can be saved as a PDF as below
// await fs.writeFileSync('./test.pdf', base64, 'base64');
base64Code = base64.slice(startIndex, endIndex)
assert.strictEqual(base64Code, pdfMagicNumber)
});
it('Should be able to get text using executeScript', async function () {
await driver.get('https://www.selenium.dev/selenium/web/javascriptPage.html');
// Stores the header element
let header = await driver.findElement(By.css('h1'));
// Executing JavaScript to capture innerText of header element
let text = await driver.executeScript('return arguments[0].innerText', header);
assert.strictEqual(text, `Type Stuff`)
});
it('Should be able to take Element Screenshot', async function () {
await driver.get('https://www.selenium.dev/selenium/web/javascriptPage.html');
let header = await driver.findElement(By.css('h1'));
// Captures the element screenshot
let encodedString = await header.takeScreenshot(true);
// save screenshot as below
// await fs.writeFileSync('./image.png', encodedString, 'base64');
base64Code = encodedString.slice(startIndex, endIndex)
assert.strictEqual(base64Code, imgMagicNumber)
});
it('Should be able to takeScreenshot', async function () {
await driver.get('https://www.selenium.dev/selenium/web/javascriptPage.html');
// Captures the screenshot
let encodedString = await driver.takeScreenshot();
// save screenshot as below
// await fs.writeFileSync('./image.png', encodedString, 'base64');
base64Code = encodedString.slice(startIndex, endIndex)
assert.strictEqual(base64Code, imgMagicNumber)
});
it('Should be able to switch to newWindow and newTab and close', async function () {
await driver.get('https://www.selenium.dev/selenium/web/');
const initialWindow = await driver.getAllWindowHandles();
assert.strictEqual(initialWindow.length, 1)
// Opens a new tab and switches to new tab
await driver.switchTo().newWindow('tab');
const browserTabs = await driver.getAllWindowHandles();
assert.strictEqual(browserTabs.length, 2)
// Opens a new window and switches to new window
await driver.switchTo().newWindow('window');
const windows = await driver.getAllWindowHandles();
assert.strictEqual(windows.length, 3)
//Close the tab or window
await driver.close();
//Switch back to the old tab or window
await driver.switchTo().window(windows[1]);
const windowsAfterClose = await driver.getAllWindowHandles();
assert.strictEqual(windowsAfterClose.length, 2);
});
it('Should be able to getWindow Size', async function () {
await driver.get('https://www.selenium.dev/selenium/web/');
// Access each dimension individually
const { width, height } = await driver.manage().window().getRect();
// Or store the dimensions and query them later
const rect = await driver.manage().window().getRect();
const windowWidth = rect.width;
const windowHeight = rect.height;
assert.ok(windowWidth>0);
assert.ok(windowHeight>0);
});
it('Should be able to getWindow position', async function () {
await driver.get('https://www.selenium.dev/selenium/web/');
// Access each dimension individually
const { x, y } = await driver.manage().window().getRect();
// Or store the dimensions and query them later
const rect = await driver.manage().window().getRect();
const x1 = rect.x;
const y1 = rect.y;
assert.ok(x1>=0);
assert.ok(y1>=0);
});
});Take a full-page screenshot in Firefox:
File screenshot = driver.getFullPageScreenshotAs(OutputType.FILE);/examples/java/src/test/java/dev/selenium/browsers/FirefoxTest.java
package dev.selenium.browsers;
import dev.selenium.BaseTest;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.*;
import org.openqa.selenium.remote.service.DriverFinder;
public class FirefoxTest extends BaseTest {
private FirefoxDriver driver;
@AfterEach
public void clearProperties() {
System.clearProperty(GeckoDriverService.GECKO_DRIVER_LOG_PROPERTY);
System.clearProperty(GeckoDriverService.GECKO_DRIVER_LOG_LEVEL_PROPERTY);
if (driver != null) {
driver.quit();
}
}
@Test
public void basicOptions() {
FirefoxOptions options = new FirefoxOptions();
driver = new FirefoxDriver(options);
}
@Test
public void arguments() {
FirefoxOptions options = new FirefoxOptions();
options.addArguments("-headless");
driver = new FirefoxDriver(options);
}
@Test
@DisabledOnOs(OS.WINDOWS)
public void setBrowserLocation() {
FirefoxOptions options = new FirefoxOptions();
options.setBinary(getFirefoxLocation());
driver = new FirefoxDriver(options);
}
@Test
public void logsToFile() throws IOException {
File logLocation = getTempFile("logsToFile", ".log");
FirefoxDriverService service =
new GeckoDriverService.Builder().withLogFile(logLocation).build();
driver = new FirefoxDriver(service);
String fileContent = new String(Files.readAllBytes(logLocation.toPath()));
Assertions.assertTrue(fileContent.contains("geckodriver INFO Listening on"));
}
@Test
public void logsToConsole() throws IOException {
File logLocation = getTempFile("logsToConsole", ".log");
System.setOut(new PrintStream(logLocation));
FirefoxDriverService service =
new GeckoDriverService.Builder().withLogOutput(System.out).build();
driver = new FirefoxDriver(service);
String fileContent = new String(Files.readAllBytes(logLocation.toPath()));
Assertions.assertTrue(fileContent.contains("geckodriver INFO Listening on"));
}
@Test
public void logsWithLevel() throws IOException {
File logLocation = getTempFile("logsWithLevel", ".log");
System.setProperty(GeckoDriverService.GECKO_DRIVER_LOG_PROPERTY, logLocation.getAbsolutePath());
FirefoxDriverService service =
new GeckoDriverService.Builder().withLogLevel(FirefoxDriverLogLevel.DEBUG).build();
driver = new FirefoxDriver(service);
String fileContent = new String(Files.readAllBytes(logLocation.toPath()));
Assertions.assertTrue(fileContent.contains("Marionette\tDEBUG"));
}
@Test
public void stopsTruncatingLogs() throws IOException {
File logLocation = getTempFile("geckodriver-", "log");
System.setProperty(GeckoDriverService.GECKO_DRIVER_LOG_PROPERTY, logLocation.getAbsolutePath());
System.setProperty(
GeckoDriverService.GECKO_DRIVER_LOG_LEVEL_PROPERTY, FirefoxDriverLogLevel.DEBUG.toString());
FirefoxDriverService service =
new GeckoDriverService.Builder().withTruncatedLogs(false).build();
driver = new FirefoxDriver(service);
String fileContent = new String(Files.readAllBytes(logLocation.toPath()));
Assertions.assertFalse(fileContent.contains(" ... "));
}
@Test
public void setProfileLocation() {
File profileDirectory = getTempDirectory("profile-");
FirefoxDriverService service =
new GeckoDriverService.Builder().withProfileRoot(profileDirectory).build();
driver = new FirefoxDriver(service);
String location = (String) driver.getCapabilities().getCapability("moz:profile");
Assertions.assertTrue(location.contains(profileDirectory.getAbsolutePath()));
}
@Test
public void installAddon() {
driver = startFirefoxDriver();
Path xpiPath = Paths.get("src/test/resources/extensions/selenium-example.xpi");
driver.installExtension(xpiPath);
driver.get("https://www.selenium.dev/selenium/web/blank.html");
WebElement injected = driver.findElement(By.id("webextensions-selenium-example"));
Assertions.assertEquals(
"Content injected by webextensions-selenium-example", injected.getText());
}
@Test
public void uninstallAddon() {
driver = startFirefoxDriver();
Path xpiPath = Paths.get("src/test/resources/extensions/selenium-example.xpi");
String id = driver.installExtension(xpiPath);
driver.uninstallExtension(id);
driver.get("https://www.selenium.dev/selenium/web/blank.html");
Assertions.assertEquals(driver.findElements(By.id("webextensions-selenium-example")).size(), 0);
}
@Test
public void installUnsignedAddonPath() {
driver = startFirefoxDriver();
Path path = Paths.get("src/test/resources/extensions/selenium-example");
driver.installExtension(path, true);
driver.get("https://www.selenium.dev/selenium/web/blank.html");
WebElement injected = getLocatedElement(driver, By.id("webextensions-selenium-example"));
Assertions.assertEquals(
"Content injected by webextensions-selenium-example", injected.getText());
}
private Path getFirefoxLocation() {
FirefoxOptions options = new FirefoxOptions();
options.setBrowserVersion("stable");
DriverFinder finder = new DriverFinder(GeckoDriverService.createDefaultService(), options);
return Path.of(finder.getBrowserPath());
}
@Test
public void fullPageScreenshot() throws Exception {
driver = startFirefoxDriver();
driver.get("https://www.selenium.dev");
File screenshot = driver.getFullPageScreenshotAs(OutputType.FILE);
File targetFile = new File("full_page_screenshot.png");
Files.move(screenshot.toPath(), targetFile.toPath());
// Verify the screenshot file exists
Assertions.assertTrue(targetFile.exists(), "The full page screenshot file should exist");
Files.deleteIfExists(targetFile.toPath());
}
@Test
public void setContext() {
GeckoDriverService service =
new GeckoDriverService.Builder().withAllowSystemAccess(true).build();
driver = new FirefoxDriver(service, new FirefoxOptions());
driver.setContext(FirefoxCommandContext.CHROME);
driver.executeScript("console.log('Inside Chrome context');");
// Verify the context is back to "content"
Assertions.assertEquals(
FirefoxCommandContext.CHROME, driver.getContext(),
"The context should be 'chrome'"
);
}
@Test
public void firefoxProfile() {
FirefoxProfile profile = new FirefoxProfile();
FirefoxOptions options = new FirefoxOptions();
profile.setPreference("javascript.enabled", "False");
options.setProfile(profile);
driver = new FirefoxDriver(options);
}
}
driver.save_full_page_screenshot("full_page_screenshot.png")/examples/python/tests/browsers/test_firefox.py
import os
import subprocess
import sys
import pytest
from selenium import webdriver
def test_basic_options():
options = webdriver.FirefoxOptions()
driver = webdriver.Firefox(options=options)
driver.quit()
def test_arguments():
options = webdriver.FirefoxOptions()
options.add_argument("-headless")
driver = webdriver.Firefox(options=options)
driver.quit()
def test_set_browser_location(firefox_bin):
options = webdriver.FirefoxOptions()
options.binary_location = firefox_bin
driver = webdriver.Firefox(options=options)
driver.quit()
def test_log_to_file(log_path):
service = webdriver.FirefoxService(log_output=log_path, service_args=['--log', 'debug'])
driver = webdriver.Firefox(service=service)
driver.get("https://www.selenium.dev")
with open(log_path, 'r') as fp:
assert "geckodriver INFO Listening on" in fp.readline()
driver.quit()
def test_log_to_stdout(capfd):
service = webdriver.FirefoxService(log_output=subprocess.STDOUT)
driver = webdriver.Firefox(service=service)
out, err = capfd.readouterr()
assert "geckodriver INFO Listening on" in out
driver.quit()
def test_log_level(log_path):
service = webdriver.FirefoxService(log_output=log_path, service_args=['--log', 'debug'])
driver = webdriver.Firefox(service=service)
with open(log_path, 'r') as f:
assert '\tDEBUG' in f.read()
driver.quit()
def test_log_truncation(log_path):
service = webdriver.FirefoxService(service_args=['--log-no-truncate', '--log', 'debug'], log_output=log_path)
driver = webdriver.Firefox(service=service)
with open(log_path, 'r') as f:
assert ' ... ' not in f.read()
driver.quit()
def test_profile_location(temp_dir):
service = webdriver.FirefoxService(service_args=['--profile-root', temp_dir])
driver = webdriver.Firefox(service=service)
profile_name = driver.capabilities.get('moz:profile').replace('\\', '/').split('/')[-1]
assert profile_name in os.listdir(temp_dir)
driver.quit()
def test_install_addon(firefox_driver, addon_path_xpi):
driver = firefox_driver
driver.install_addon(addon_path_xpi)
driver.get("https://www.selenium.dev/selenium/web/blank.html")
injected = driver.find_element(webdriver.common.by.By.ID, "webextensions-selenium-example")
assert injected.text == "Content injected by webextensions-selenium-example"
def test_uninstall_addon(firefox_driver, addon_path_xpi):
driver = firefox_driver
id = driver.install_addon(addon_path_xpi)
driver.uninstall_addon(id)
driver.get("https://www.selenium.dev/selenium/web/blank.html")
assert len(driver.find_elements(webdriver.common.by.By.ID, "webextensions-selenium-example")) == 0
def test_install_unsigned_addon_directory(firefox_driver, addon_path_dir):
driver = firefox_driver
driver.install_addon(addon_path_dir, temporary=True)
driver.get("https://www.selenium.dev/selenium/web/blank.html")
injected = driver.find_element(webdriver.common.by.By.ID, "webextensions-selenium-example")
assert injected.text == "Content injected by webextensions-selenium-example"
def test_install_unsigned_addon_directory_slash(firefox_driver, addon_path_dir_slash):
driver = firefox_driver
driver.install_addon(addon_path_dir_slash, temporary=True)
driver.get("https://www.selenium.dev/selenium/web/blank.html")
injected = driver.find_element(webdriver.common.by.By.ID, "webextensions-selenium-example")
assert injected.text == "Content injected by webextensions-selenium-example"
def test_full_page_screenshot(firefox_driver):
driver = firefox_driver
driver.get("https://www.selenium.dev")
driver.save_full_page_screenshot("full_page_screenshot.png")
assert os.path.exists("full_page_screenshot.png")
driver.quit()
def test_set_context():
options = webdriver.FirefoxOptions()
service = webdriver.FirefoxService(service_args=["--allow-system-access"])
driver = webdriver.Firefox(options=options, service=service)
with driver.context(driver.CONTEXT_CHROME):
driver.execute_script("console.log('Inside Chrome context');")
# Check if the context is back to content
assert driver.execute("GET_CONTEXT")["value"] == "content"
driver.quit()
def test_firefox_profile():
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
options = Options()
firefox_profile = FirefoxProfile()
firefox_profile.set_preference("javascript.enabled", False)
options.profile = firefox_profile
driver = webdriver.Firefox(options=options)
driver.quit()
screenshot = driver.save_full_page_screenshot(File.join(dir, 'screenshot.png'))/examples/ruby/spec/browsers/firefox_spec.rb
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Firefox' do
describe 'Options' do
let(:firefox_location) { driver_finder && ENV.fetch('FIREFOX_BIN', nil) }
it 'basic options' do
options = Selenium::WebDriver::Options.firefox
@driver = Selenium::WebDriver.for :firefox, options: options
end
it 'add arguments' do
options = Selenium::WebDriver::Options.firefox
options.args << '-headless'
@driver = Selenium::WebDriver.for :firefox, options: options
end
it 'sets location of binary' do
options = Selenium::WebDriver::Options.firefox
options.binary = firefox_location
@driver = Selenium::WebDriver.for :firefox, options: options
end
end
describe 'Service' do
let(:file_name) { Tempfile.new('geckodriver').path }
let(:root_directory) { Dir.mktmpdir }
after do
FileUtils.rm_f(file_name)
FileUtils.rm_rf(root_directory)
end
it 'logs to file' do
service = Selenium::WebDriver::Service.firefox
service.log = file_name
@driver = Selenium::WebDriver.for :firefox, service: service
expect(File.readlines(file_name).first).to include("geckodriver\tINFO\tListening on")
end
it 'logs to console' do
service = Selenium::WebDriver::Service.firefox
service.log = $stdout
expect {
@driver = Selenium::WebDriver.for :firefox, service: service
}.to output(/geckodriver INFO Listening on/).to_stdout_from_any_process
end
it 'sets log level' do
service = Selenium::WebDriver::Service.firefox
service.log = file_name
service.args += %w[--log debug]
@driver = Selenium::WebDriver.for :firefox, service: service
expect(File.readlines(file_name).grep(/Marionette DEBUG/).any?).to eq true
end
it 'stops truncating log lines' do
service = Selenium::WebDriver::Service.firefox(log: file_name, args: %w[--log debug])
service.args << '--log-no-truncate'
@driver = Selenium::WebDriver.for :firefox, service: service
expect(File.readlines(file_name).grep(/ \.\.\. /).any?).to eq false
end
it 'sets default profile location' do
service = Selenium::WebDriver::Service.firefox
service.args += ['--profile-root', root_directory]
@driver = Selenium::WebDriver.for :firefox, service: service
profile_location = Dir.new(@driver.capabilities['moz:profile'])
expect(profile_location.path.gsub('\\', '/')).to include(root_directory)
end
end
describe 'Features' do
let(:driver) { start_firefox }
it 'installs addon' do
extension_file_path = File.expand_path('../spec_support/extensions/webextensions-selenium-example.xpi', __dir__)
driver.install_addon(extension_file_path)
driver.get 'https://www.selenium.dev/selenium/web/blank.html'
injected = driver.find_element(id: 'webextensions-selenium-example')
expect(injected.text).to eq 'Content injected by webextensions-selenium-example'
end
it 'uninstalls addon' do
extension_file_path = File.expand_path('../spec_support/extensions/webextensions-selenium-example.xpi', __dir__)
extension_id = driver.install_addon(extension_file_path)
driver.uninstall_addon(extension_id)
driver.get 'https://www.selenium.dev/selenium/web/blank.html'
expect(driver.find_elements(id: 'webextensions-selenium-example')).to be_empty
end
it 'installs unsigned addon' do
extension_dir_path = File.expand_path('../spec_support/extensions/webextensions-selenium-example/', __dir__)
driver.install_addon(extension_dir_path, true)
driver.navigate.to 'https://www.selenium.dev/selenium/web/blank.html'
injected = driver.find_element(id: 'webextensions-selenium-example')
expect(injected.text).to eq 'Content injected by webextensions-selenium-example'
end
it 'takes full page screenshot' do
driver.navigate.to 'https://www.selenium.dev/selenium/web/blank.html'
Dir.mktmpdir('screenshot_test') do |dir|
screenshot = driver.save_full_page_screenshot(File.join(dir, 'screenshot.png'))
expect(screenshot).to be_a File
end
end
it 'sets the context' do
driver.context = 'content'
expect(driver.context).to eq 'content'
end
end
describe 'Profile' do
it 'creates a new profile' do
profile = Selenium::WebDriver::Firefox::Profile.new
profile['browser.download.dir'] = '/tmp/webdriver-downloads'
options = Selenium::WebDriver::Firefox::Options.new(profile: profile)
expect(options.profile).to eq(profile)
end
end
def driver_finder
options = Selenium::WebDriver::Options.firefox(browser_version: 'stable')
service = Selenium::WebDriver::Service.firefox
finder = Selenium::WebDriver::DriverFinder.new(options, service)
ENV['GECKODRIVER_BIN'] = finder.driver_path
ENV['FIREFOX_BIN'] = finder.browser_path
end
end
Capture a screenshot through BiDi:
String screenshot = browsingContext.captureScreenshot();/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.time.Duration;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Rectangle;
import org.openqa.selenium.UnexpectedAlertBehaviour;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.BiDiException;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContextInfo;
import org.openqa.selenium.bidi.browsingcontext.NavigationResult;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.print.PrintOptions;
import org.openqa.selenium.remote.RemoteWebElement;
import org.openqa.selenium.support.ui.WebDriverWait;
import static org.openqa.selenium.support.ui.ExpectedConditions.titleIs;
import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOfElementLocated;
class BrowsingContextTest extends BaseTest {
@BeforeEach
public void setup() {
FirefoxOptions options = new FirefoxOptions();
options.setCapability("webSocketUrl", true);
options.setUnhandledPromptBehaviour(UnexpectedAlertBehaviour.IGNORE);
driver = new FirefoxDriver(options);
wait = new WebDriverWait(driver, Duration.ofSeconds(10));
}
@Test
void testCreateABrowsingContextForGivenId() {
String id = driver.getWindowHandle();
BrowsingContext browsingContext = new BrowsingContext(driver, id);
Assertions.assertEquals(id, browsingContext.getId());
}
@Test
void testCreateAWindow() {
BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.WINDOW);
Assertions.assertNotNull(browsingContext.getId());
}
@Test
void testCreateATab() {
BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.TAB);
Assertions.assertNotNull(browsingContext.getId());
}
@Test
void testNavigateToAUrl() {
BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.TAB);
NavigationResult info = browsingContext.navigate("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html");
Assertions.assertNotNull(browsingContext.getId());
Assertions.assertNotNull(info.getNavigationId());
Assertions.assertTrue(info.getUrl().contains("/bidi/logEntryAdded.html"));
}
@Test
void testNavigateToAUrlWithReadinessState() {
BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.TAB);
NavigationResult info = browsingContext.navigate("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html",
ReadinessState.COMPLETE);
Assertions.assertNotNull(browsingContext.getId());
Assertions.assertNotNull(info.getNavigationId());
Assertions.assertTrue(info.getUrl().contains("/bidi/logEntryAdded.html"));
}
@Test
void testGetTreeWithAChild() {
String referenceContextId = driver.getWindowHandle();
BrowsingContext parentWindow = new BrowsingContext(driver, referenceContextId);
parentWindow.navigate("https://www.selenium.dev/selenium/web/iframes.html", ReadinessState.COMPLETE);
List<BrowsingContextInfo> contextInfoList = parentWindow.getTree();
Assertions.assertEquals(1, contextInfoList.size());
BrowsingContextInfo info = contextInfoList.get(0);
Assertions.assertEquals(1, info.getChildren().size());
Assertions.assertEquals(referenceContextId, info.getId());
Assertions.assertTrue(info.getChildren().get(0).getUrl().contains("formPage.html"));
}
@Test
void testGetTreeWithDepth() {
String referenceContextId = driver.getWindowHandle();
BrowsingContext parentWindow = new BrowsingContext(driver, referenceContextId);
parentWindow.navigate("https://www.selenium.dev/selenium/web/iframes.html", ReadinessState.COMPLETE);
List<BrowsingContextInfo> contextInfoList = parentWindow.getTree(0);
Assertions.assertEquals(1, contextInfoList.size());
BrowsingContextInfo info = contextInfoList.get(0);
Assertions.assertNull(info.getChildren()); // since depth is 0
Assertions.assertEquals(referenceContextId, info.getId());
}
@Test
void testGetAllTopLevelContexts() {
BrowsingContext window1 = new BrowsingContext(driver, driver.getWindowHandle());
BrowsingContext window2 = new BrowsingContext(driver, WindowType.WINDOW);
List<BrowsingContextInfo> contextInfoList = window1.getTopLevelContexts();
Assertions.assertEquals(2, contextInfoList.size());
}
@Test
void testCloseAWindow() {
BrowsingContext window1 = new BrowsingContext(driver, WindowType.WINDOW);
BrowsingContext window2 = new BrowsingContext(driver, WindowType.WINDOW);
window2.close();
Assertions.assertThrows(BiDiException.class, window2::getTree);
}
@Test
void testCloseATab() {
BrowsingContext tab1 = new BrowsingContext(driver, WindowType.TAB);
BrowsingContext tab2 = new BrowsingContext(driver, WindowType.TAB);
tab2.close();
Assertions.assertThrows(BiDiException.class, tab2::getTree);
}
@Test
void testActivateABrowsingContext() {
BrowsingContext window1 = new BrowsingContext(driver, driver.getWindowHandle());
BrowsingContext window2 = new BrowsingContext(driver, WindowType.WINDOW);
window1.activate();
boolean isFocused = (boolean) ((JavascriptExecutor) driver).executeScript("return document.hasFocus();");
Assertions.assertTrue(isFocused);
}
@Test
void testReloadABrowsingContext() {
BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.TAB);
browsingContext.navigate("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html", ReadinessState.COMPLETE);
NavigationResult reloadInfo = browsingContext.reload(ReadinessState.INTERACTIVE);
Assertions.assertNotNull(reloadInfo.getNavigationId());
Assertions.assertTrue(reloadInfo.getUrl().contains("/bidi/logEntryAdded.html"));
}
@Test
void testHandleUserPrompt() {
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
driver.get("https://www.selenium.dev/selenium/web/alerts.html");
driver.findElement(By.id("alert")).click();
browsingContext.handleUserPrompt();
Assertions.assertTrue(driver.getPageSource().contains("Testing Alerts and Stuff"));
}
@Test
void testAcceptUserPrompt() {
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
driver.get("https://www.selenium.dev/selenium/web/alerts.html");
driver.findElement(By.id("alert")).click();
browsingContext.handleUserPrompt("true");
Assertions.assertTrue(driver.getPageSource().contains("Testing Alerts and Stuff"));
}
@Test
void testDismissUserPrompt() {
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
driver.get("https://www.selenium.dev/selenium/web/alerts.html");
driver.findElement(By.id("alert")).click();
browsingContext.handleUserPrompt("true");
Assertions.assertTrue(driver.getPageSource().contains("Testing Alerts and Stuff"));
}
@Test
void testPassUserTextToUserPrompt() {
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
driver.get("https://www.selenium.dev/selenium/web/alerts.html");
driver.findElement(By.id("prompt-with-default")).click();
String userText = "Selenium automates browsers";
browsingContext.handleUserPrompt(true, userText);
Assertions.assertTrue(driver.getPageSource().contains(userText));
}
@Test
void testDismissUserPromptWithText() {
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
driver.get("https://www.selenium.dev/selenium/web/alerts.html");
driver.findElement(By.id("prompt-with-default")).click();
String userText = "Selenium automates browsers";
browsingContext.handleUserPrompt(false, userText);
Assertions.assertFalse(driver.getPageSource().contains(userText));
}
@Test
void textCaptureScreenshot() {
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
driver.get("https://www.selenium.dev/selenium/web/alerts.html");
String screenshot = browsingContext.captureScreenshot();
Assertions.assertFalse(screenshot.isEmpty());
}
@Test
void textCaptureViewportScreenshot() {
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
driver.get("https://www.selenium.dev/selenium/web/coordinates_tests/simple_page.html");
WebElement element = driver.findElement(By.id("box"));
Rectangle elementRectangle = element.getRect();
String screenshot =
browsingContext.captureBoxScreenshot(
elementRectangle.getX(), elementRectangle.getY(), 5, 5);
Assertions.assertFalse(screenshot.isEmpty());
}
@Test
void textCaptureElementScreenshot() {
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
driver.get("https://www.selenium.dev/selenium/web/formPage.html");
WebElement element = driver.findElement(By.id("checky"));
String screenshot = browsingContext.captureElementScreenshot(((RemoteWebElement) element).getId());
Assertions.assertFalse(screenshot.isEmpty());
}
@Test
void textSetViewport() {
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
driver.get("https://www.selenium.dev/selenium/web/formPage.html");
browsingContext.setViewport(250, 300);
List<Long> newViewportSize =
(List<Long>)
((JavascriptExecutor) driver)
.executeScript("return [window.innerWidth, window.innerHeight];");
Assertions.assertEquals(250, newViewportSize.get(0));
Assertions.assertEquals(300, newViewportSize.get(1));
}
@Test
void textSetViewportWithDevicePixelRatio() {
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
driver.get("https://www.selenium.dev/selenium/web/formPage.html");
browsingContext.setViewport(250, 300, 5);
Long newDevicePixelRatio =
(Long) ((JavascriptExecutor) driver).executeScript("return window.devicePixelRatio");
Assertions.assertEquals(5, newDevicePixelRatio);
}
@Test
void testPrintPage() {
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
driver.get("https://www.selenium.dev/selenium/web/formPage.html");
PrintOptions printOptions = new PrintOptions();
String printPage = browsingContext.print(printOptions);
Assertions.assertFalse(printPage.isEmpty());
}
@Test
void testNavigateBackInTheBrowserHistory() {
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
browsingContext.navigate("https://www.selenium.dev/selenium/web/formPage.html", ReadinessState.COMPLETE);
wait.until(visibilityOfElementLocated(By.id("imageButton"))).submit();
wait.until(titleIs("We Arrive Here"));
browsingContext.back();
Assertions.assertTrue(driver.getPageSource().contains("We Leave From Here"));
}
@Test
void canNavigateForwardInTheBrowserHistory() {
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
browsingContext.navigate("https://www.selenium.dev/selenium/web/formPage.html", ReadinessState.COMPLETE);
wait.until(visibilityOfElementLocated(By.id("imageButton"))).submit();
wait.until(titleIs("We Arrive Here"));
browsingContext.back();
Assertions.assertTrue(driver.getPageSource().contains("We Leave From Here"));
browsingContext.forward();
wait.until(titleIs("We Arrive Here"));
}
@Test
void canTraverseBrowserHistory() {
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
browsingContext.navigate("https://www.selenium.dev/selenium/web/formPage.html", ReadinessState.COMPLETE);
wait.until(visibilityOfElementLocated(By.id("imageButton"))).submit();
wait.until(titleIs("We Arrive Here"));
browsingContext.traverseHistory(-1);
Assertions.assertTrue(driver.getPageSource().contains("We Leave From Here"));
}
}
var screenshot = await context.CaptureScreenshotAsync();/examples/dotnet/SeleniumDocs/BiDi/BrowsingContext/BrowsingContextTest.CaptureScreenshot.cs
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.BiDi.BrowsingContext;
using System.Threading.Tasks;
namespace SeleniumDocs.BiDi.BrowsingContext;
partial class BrowsingContextTest
{
[TestMethod]
public async Task CaptureScreenshot()
{
var screenshot = await context.CaptureScreenshotAsync();
Assert.IsNotNull(screenshot);
Assert.IsNotNull(screenshot.Data);
Assert.IsNotNull(screenshot.ToByteArray());
}
[TestMethod]
public async Task CaptureViewportScreenshot()
{
var screenshot = await context.CaptureScreenshotAsync(new() { Clip = new BoxClipRectangle(5, 5, 10, 10) });
Assert.IsNotNull(screenshot);
Assert.IsNotNull(screenshot.Data);
}
[TestMethod]
public async Task CaptureElementScreenshot()
{
driver.Url = "https://www.selenium.dev/selenium/web/formPage.html";
var nodes = (await context.LocateNodesAsync(new CssLocator("#checky"))).Nodes;
Assert.IsTrue(nodes.Length > 0, "Expected to locate #checky");
var screenshot = await context.CaptureScreenshotAsync(new() { Clip = new ElementClipRectangle(nodes[0]) });
Assert.IsNotNull(screenshot);
Assert.IsNotNull(screenshot.Data);
}
}
const response = await browsingContext.captureScreenshot()/examples/javascript/test/bidirectional/browsingContext.spec.js
const {By, until, Builder} = require("selenium-webdriver");
const firefox = require('selenium-webdriver/firefox');
const BrowsingContext = require('selenium-webdriver/bidi/browsingContext');
const assert = require("assert");
describe('Browsing Context', function () {
let driver
let startIndex = 0
let endIndex = 5
let pdfMagicNumber = 'JVBER'
let pngMagicNumber = 'iVBOR'
beforeEach(async function () {
const options = new firefox.Options().enableBidi()
options.setAlertBehavior('ignore')
driver = new Builder()
.forBrowser('firefox')
.setFirefoxOptions(options)
.build()
})
afterEach(async function () {
await driver.quit()
})
it('test create a browsing context for given id', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
assert.equal(browsingContext.id, id)
})
it('test create a window', async function () {
const browsingContext = await BrowsingContext(driver, {
type: 'window',
})
assert.notEqual(browsingContext.id, null)
})
it('test create a window with a reference context', async function () {
const browsingContext = await BrowsingContext(driver, {
type: 'window',
referenceContext: await driver.getWindowHandle(),
})
assert.notEqual(browsingContext.id, null)
})
it('test create a tab', async function () {
const browsingContext = await BrowsingContext(driver, {
type: 'tab',
})
assert.notEqual(browsingContext.id, null)
})
it('test create a tab with a reference context', async function () {
const browsingContext = await BrowsingContext(driver, {
type: 'tab',
referenceContext: await driver.getWindowHandle(),
})
assert.notEqual(browsingContext.id, null)
})
it('test navigate to a url', async function () {
const browsingContext = await BrowsingContext(driver, {
type: 'tab',
})
let info = await browsingContext.navigate('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html')
assert.notEqual(browsingContext.id, null)
assert.notEqual(info.navigationId, null)
assert(info.url.includes('/bidi/logEntryAdded.html'))
})
it('test navigate to a url with readiness state', async function () {
const browsingContext = await BrowsingContext(driver, {
type: 'tab',
})
const info = await browsingContext.navigate(
'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html',
'complete'
)
assert.notEqual(browsingContext.id, null)
assert.notEqual(info.navigationId, null)
assert(info.url.includes('/bidi/logEntryAdded.html'))
})
it('test get tree with a child', async function () {
const browsingContextId = await driver.getWindowHandle()
const parentWindow = await BrowsingContext(driver, {
browsingContextId: browsingContextId,
})
await parentWindow.navigate('https://www.selenium.dev/selenium/web/iframes.html', 'complete')
const contextInfo = await parentWindow.getTree()
assert.equal(contextInfo.children.length, 1)
assert.equal(contextInfo.id, browsingContextId)
assert(contextInfo.children[0]['url'].includes('formPage.html'))
})
it('test get tree with depth', async function () {
const browsingContextId = await driver.getWindowHandle()
const parentWindow = await BrowsingContext(driver, {
browsingContextId: browsingContextId,
})
await parentWindow.navigate('https://www.selenium.dev/selenium/web/iframes.html', 'complete')
const contextInfo = await parentWindow.getTree(0)
assert.equal(contextInfo.children, null)
assert.equal(contextInfo.id, browsingContextId)
})
it('test close a window', async function () {
const window1 = await BrowsingContext(driver, {type: 'window'})
const window2 = await BrowsingContext(driver, {type: 'window'})
await window2.close()
assert.doesNotThrow(async function () {
await window1.getTree()
})
await assert.rejects(window2.getTree(), {message: 'no such frame'})
})
it('test close a tab', async function () {
const tab1 = await BrowsingContext(driver, {type: 'tab'})
const tab2 = await BrowsingContext(driver, {type: 'tab'})
await tab2.close()
assert.doesNotThrow(async function () {
await tab1.getTree()
})
await assert.rejects(tab2.getTree(), {message: 'no such frame'})
})
it('can print PDF with all valid parameters', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
await driver.get("https://www.selenium.dev/selenium/web/printPage.html")
const result = await browsingContext.printPage({
orientation: 'landscape',
scale: 1,
background: true,
width: 30,
height: 30,
top: 1,
bottom: 1,
left: 1,
right: 1,
shrinkToFit: true,
pageRanges: ['1-2'],
})
let base64Code = result.data.slice(0, 5)
assert.strictEqual(base64Code, 'JVBER')
})
it('can take box screenshot', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
const response = await browsingContext.captureBoxScreenshot(5, 5, 10, 10)
const base64code = response.slice(0, 5)
assert.equal(base64code, 'iVBOR')
})
it('can take element screenshot', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
await driver.get("https://www.selenium.dev/selenium/web/formPage.html")
const element = await driver.findElement(By.id('checky'))
const elementId = await element.getId()
const response = await browsingContext.captureElementScreenshot(elementId)
const base64code = response.slice(0, 5)
assert.equal(base64code, 'iVBOR')
})
it('can activate a browsing context', async function () {
const id = await driver.getWindowHandle()
const window1 = await BrowsingContext(driver, {
browsingContextId: id,
})
await BrowsingContext(driver, {
type: 'window',
})
const result = await driver.executeScript('return document.hasFocus();')
assert.equal(result, false)
await window1.activate()
const result2 = await driver.executeScript('return document.hasFocus();')
assert.equal(result2, true)
})
it('can handle user prompt', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
await driver.get("https://www.selenium.dev/selenium/web/alerts.html")
await driver.findElement(By.id('alert')).click()
await driver.wait(until.alertIsPresent())
await browsingContext.handleUserPrompt()
const result = await driver.getTitle()
assert.equal(result, 'Testing Alerts')
})
it('can accept user prompt', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
await driver.get("https://www.selenium.dev/selenium/web/alerts.html")
await driver.findElement(By.id('alert')).click()
await driver.wait(until.alertIsPresent())
await browsingContext.handleUserPrompt(true)
const result = await driver.getTitle()
assert.equal(result, 'Testing Alerts')
})
it('can dismiss user prompt', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
await driver.get("https://www.selenium.dev/selenium/web/alerts.html")
await driver.findElement(By.id('alert')).click()
await driver.wait(until.alertIsPresent())
await browsingContext.handleUserPrompt(false)
const result = await driver.getTitle()
assert.equal(result, 'Testing Alerts')
})
it('can pass user text to user prompt', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
await driver.get("https://www.selenium.dev/selenium/web/alerts.html")
await driver.findElement(By.id('prompt')).click()
await driver.wait(until.alertIsPresent())
const userText = 'Selenium automates browsers'
await browsingContext.handleUserPrompt(undefined, userText)
const result = await driver.getPageSource()
assert.equal(result.includes(userText), true)
})
it('can accept user prompt with user text', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
await driver.get("https://www.selenium.dev/selenium/web/alerts.html")
await driver.findElement(By.id('prompt')).click()
await driver.wait(until.alertIsPresent())
const userText = 'Selenium automates browsers'
await browsingContext.handleUserPrompt(true, userText)
const result = await driver.getPageSource()
assert.equal(result.includes(userText), true)
})
it('can dismiss user prompt with user text', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
await driver.get("https://www.selenium.dev/selenium/web/alerts.html")
await driver.findElement(By.id('alert')).click()
await driver.wait(until.alertIsPresent())
const userText = 'Selenium automates browsers'
await browsingContext.handleUserPrompt(false, userText)
const result = await driver.getPageSource()
assert.equal(result.includes(userText), false)
})
it('can set viewport', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
await driver.get("https://www.selenium.dev/selenium/web/blank.html")
await browsingContext.setViewport(250, 300)
const result = await driver.executeScript('return [window.innerWidth, window.innerHeight];')
assert.equal(result[0], 250)
assert.equal(result[1], 300)
})
it('can reload a browsing context', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
const result = await browsingContext.navigate(
'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html', 'complete')
await browsingContext.reload(undefined, 'complete')
assert.notEqual(result.navigationId, null)
assert(result.url.includes('/bidi/logEntryAdded.html'))
})
it('can take screenshot', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
const response = await browsingContext.captureScreenshot()
const base64code = response.slice(startIndex, endIndex)
assert.equal(base64code, pngMagicNumber)
})
it('can traverse browser history', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
await browsingContext.navigate('https://www.selenium.dev/selenium/web/formPage.html', 'complete')
await driver.wait(until.elementLocated(By.id('imageButton'))).submit()
await driver.wait(until.titleIs('We Arrive Here'), 2500)
await browsingContext.traverseHistory(-1)
const source = await driver.getPageSource()
assert.equal(source.includes('We Leave From Here'), true)
})
it('can navigate back in browser history', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
await browsingContext.navigate('https://www.selenium.dev/selenium/web/formPage.html', 'complete')
await driver.wait(until.elementLocated(By.id('imageButton'))).submit()
await driver.wait(until.titleIs('We Arrive Here'), 2500)
await browsingContext.back()
const source = await driver.getPageSource()
assert.equal(source.includes('We Leave From Here'), true)
})
it('can navigate forward in browser history', async function () {
const id = await driver.getWindowHandle()
const browsingContext = await BrowsingContext(driver, {
browsingContextId: id,
})
await browsingContext.navigate('https://www.selenium.dev/selenium/web/formPage.html', 'complete')
await driver.wait(until.elementLocated(By.id('imageButton'))).submit()
await driver.wait(until.titleIs('We Arrive Here'), 2500)
await browsingContext.back()
const source = await driver.getPageSource()
assert.equal(source.includes('We Leave From Here'), true)
await browsingContext.forward()
await driver.wait(until.titleIs('We Arrive Here'), 2500)
});
it('Get All Top level browsing contexts', async () => {
const id = await driver.getWindowHandle()
const window1 = await BrowsingContext(driver, {
browsingContextId: id,
})
await BrowsingContext(driver, { type: 'window' })
const res = await window1.getTopLevelContexts()
assert.equal(res.length, 2)
})
})
Print the page to PDF:
PrintsPage printer = (PrintsPage) driver;
PrintOptions printOptions = new PrintOptions();
Pdf printedPage = printer.print(printOptions);/examples/java/src/test/java/dev/selenium/interactions/PrintsPageTest.java
package dev.selenium.interactions;
import org.openqa.selenium.Pdf;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.openqa.selenium.print.PrintOptions;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.PrintsPage;
import dev.selenium.BaseTest;
public class PrintsPageTest extends BaseTest{
@BeforeEach
public void setup() {
ChromeOptions options = getDefaultChromeOptions();
options.setCapability("webSocketUrl", true);
driver = new ChromeDriver(options);
}
@Test
public void PrintWithPrintsPageTest()
{
driver.get("https://www.selenium.dev/");
PrintsPage printer = (PrintsPage) driver;
PrintOptions printOptions = new PrintOptions();
Pdf printedPage = printer.print(printOptions);
Assertions.assertNotNull(printedPage);
}
@Test
public void PrintWithBrowsingContextTest()
{
BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
driver.get("https://www.selenium.dev/selenium/web/formPage.html");
PrintOptions printOptions = new PrintOptions();
String printPage = browsingContext.print(printOptions);
Assertions.assertTrue(printPage.length() > 0);
}
}
print_options = PrintOptions()
pdf = driver.print_page(print_options)/examples/python/tests/interactions/test_prints_page.py
import pytest
from selenium import webdriver
from selenium.webdriver.common.print_page_options import PrintOptions
pytest.fixture()
def driver():
driver = webdriver.Chrome()
yield driver
driver.quit()
def test_prints_page(driver):
driver.get("https://www.selenium.dev/")
print_options = PrintOptions()
pdf = driver.print_page(print_options)
assert len(pdf) > 0 PrintOptions printOptions = new PrintOptions();
PrintDocument printedPage = driver.Print(printOptions);/examples/dotnet/SeleniumDocs/Interactions/PrintOptionsTest.cs
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace SeleniumDocumentation.SeleniumInteractions
{
[TestClass]
public class PrintOptionsTest
{
[TestMethod]
public void TestOrientation()
{
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://selenium.dev");
PrintOptions printOptions = new PrintOptions();
printOptions.Orientation = PrintOrientation.Landscape;
PrintOrientation currentOrientation = printOptions.Orientation;
driver.Quit();
}
[TestMethod]
public void TestRange()
{
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://selenium.dev");
PrintOptions printOptions = new PrintOptions();
printOptions.AddPageRangeToPrint("1-3"); // add range of pages
printOptions.AddPageToPrint(5); // add individual page
driver.Quit();
}
[TestMethod]
public void TestSize()
{
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.selenium.dev/");
PrintOptions printOptions = new PrintOptions();
PrintOptions.PageSize currentDimensions = printOptions.PageDimensions;
driver.Quit();
}
[TestMethod]
public void TestBackgrounds()
{
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.selenium.dev/");
PrintOptions printOptions = new PrintOptions();
printOptions.OutputBackgroundImages = true;
bool currentBackgrounds = printOptions.OutputBackgroundImages;
driver.Quit();
}
[TestMethod]
public void TestMargins()
{
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.selenium.dev/");
PrintOptions printOptions = new PrintOptions();
PrintOptions.Margins currentMargins = printOptions.PageMargins;
driver.Quit();
}
[TestMethod]
public void TestScale()
{
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.selenium.dev/");
PrintOptions printOptions = new PrintOptions();
printOptions.ScaleFactor = 0.5;
double currentScale = printOptions.ScaleFactor;
driver.Quit();
}
[TestMethod]
public void TestShrinkToFit()
{
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.selenium.dev/");
PrintOptions printOptions = new PrintOptions();
printOptions.ShrinkToFit = true;
bool currentShrinkToFit = printOptions.ShrinkToFit;
driver.Quit();
}
[TestMethod]
public void PrintWithPrintsPageTest()
{
WebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.selenium.dev/");
PrintOptions printOptions = new PrintOptions();
PrintDocument printedPage = driver.Print(printOptions);
Assert.IsTrue(printedPage.AsBase64EncodedString.StartsWith("JVBER"));
driver.Quit();
}
}
}
let base64 = await driver.printPage({pageRanges: ["1-2"]});/examples/javascript/test/interactions/windows.spec.js
const {Builder, By} = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const assert = require("node:assert");
let opts = new chrome.Options();
opts.addArguments('--headless');
let startIndex = 0
let endIndex = 5
let pdfMagicNumber = 'JVBER'
let imgMagicNumber = 'iVBOR'
let base64Code
describe('Interactions - Windows', function () {
let driver;
before(async function () {
driver = await new Builder().forBrowser('chrome').setChromeOptions(opts).build();
});
after(async () => await driver.quit());
it('Should be able to print page to pdf', async function () {
await driver.get('https://www.selenium.dev/selenium/web/alerts.html');
let base64 = await driver.printPage({pageRanges: ["1-2"]});
// page can be saved as a PDF as below
// await fs.writeFileSync('./test.pdf', base64, 'base64');
base64Code = base64.slice(startIndex, endIndex)
assert.strictEqual(base64Code, pdfMagicNumber)
});
it('Should be able to get text using executeScript', async function () {
await driver.get('https://www.selenium.dev/selenium/web/javascriptPage.html');
// Stores the header element
let header = await driver.findElement(By.css('h1'));
// Executing JavaScript to capture innerText of header element
let text = await driver.executeScript('return arguments[0].innerText', header);
assert.strictEqual(text, `Type Stuff`)
});
it('Should be able to take Element Screenshot', async function () {
await driver.get('https://www.selenium.dev/selenium/web/javascriptPage.html');
let header = await driver.findElement(By.css('h1'));
// Captures the element screenshot
let encodedString = await header.takeScreenshot(true);
// save screenshot as below
// await fs.writeFileSync('./image.png', encodedString, 'base64');
base64Code = encodedString.slice(startIndex, endIndex)
assert.strictEqual(base64Code, imgMagicNumber)
});
it('Should be able to takeScreenshot', async function () {
await driver.get('https://www.selenium.dev/selenium/web/javascriptPage.html');
// Captures the screenshot
let encodedString = await driver.takeScreenshot();
// save screenshot as below
// await fs.writeFileSync('./image.png', encodedString, 'base64');
base64Code = encodedString.slice(startIndex, endIndex)
assert.strictEqual(base64Code, imgMagicNumber)
});
it('Should be able to switch to newWindow and newTab and close', async function () {
await driver.get('https://www.selenium.dev/selenium/web/');
const initialWindow = await driver.getAllWindowHandles();
assert.strictEqual(initialWindow.length, 1)
// Opens a new tab and switches to new tab
await driver.switchTo().newWindow('tab');
const browserTabs = await driver.getAllWindowHandles();
assert.strictEqual(browserTabs.length, 2)
// Opens a new window and switches to new window
await driver.switchTo().newWindow('window');
const windows = await driver.getAllWindowHandles();
assert.strictEqual(windows.length, 3)
//Close the tab or window
await driver.close();
//Switch back to the old tab or window
await driver.switchTo().window(windows[1]);
const windowsAfterClose = await driver.getAllWindowHandles();
assert.strictEqual(windowsAfterClose.length, 2);
});
it('Should be able to getWindow Size', async function () {
await driver.get('https://www.selenium.dev/selenium/web/');
// Access each dimension individually
const { width, height } = await driver.manage().window().getRect();
// Or store the dimensions and query them later
const rect = await driver.manage().window().getRect();
const windowWidth = rect.width;
const windowHeight = rect.height;
assert.ok(windowWidth>0);
assert.ok(windowHeight>0);
});
it('Should be able to getWindow position', async function () {
await driver.get('https://www.selenium.dev/selenium/web/');
// Access each dimension individually
const { x, y } = await driver.manage().window().getRect();
// Or store the dimensions and query them later
const rect = await driver.manage().window().getRect();
const x1 = rect.x;
const y1 = rect.y;
assert.ok(x1>=0);
assert.ok(y1>=0);
});
});Common errors
- ScreenshotException: the browser could not capture the screen, usually because the window is minimised or the element is not rendered. Maximise the window or scroll the element into view.
- StaleElementReferenceException: the element being captured was re-rendered between locating it and taking the screenshot.
Reference
- Browser window screenshots and element screenshots
- Firefox full-page screenshots
- BiDi browsing context: screenshot and print commands
- Print page: every print option



