Remote WebDriver

Selenium lets you automate browsers on remote computers if there is a Selenium Grid running on them. The computer that executes the code is referred to as the client computer, and the computer with the browser and driver is referred to as the remote computer or sometimes as an end-node. To direct Selenium tests to the remote computer, you need to use a Remote WebDriver class and pass the URL including the port of the grid on that machine. Please see the grid documentation for all the various ways the grid can be configured.

Basic Example

The driver needs to know where to send commands to and which browser to start on the Remote computer. So an address and an options instance are both required.

37
40
Show full example
package dev.selenium.drivers;

import dev.selenium.BaseTest;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.HasDownloads;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.chromium.HasCasting;
import org.openqa.selenium.remote.Augmenter;
import org.openqa.selenium.remote.LocalFileDetector;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.http.ClientConfig;
import org.openqa.selenium.support.ui.WebDriverWait;

public class RemoteWebDriverTest extends BaseTest {
  URL gridUrl;

  @BeforeEach
  public void startGrid() {
    gridUrl = startStandaloneGrid();
  }

  @Test
  public void runRemote() {
    ChromeOptions options = getDefaultChromeOptions();
    driver = new RemoteWebDriver(gridUrl, options);
  }

  @Test
  public void uploads() {
    ChromeOptions options = getDefaultChromeOptions();
    driver = new RemoteWebDriver(gridUrl, options);
    driver.get("https://the-internet.herokuapp.com/upload");
    File uploadFile = new File("src/test/resources/selenium-snapshot.png");

    ((RemoteWebDriver) driver).setFileDetector(new LocalFileDetector());
    WebElement fileInput = driver.findElement(By.cssSelector("input[type=file]"));
    fileInput.sendKeys(uploadFile.getAbsolutePath());
    driver.findElement(By.id("file-submit")).click();

    WebElement fileName = driver.findElement(By.id("uploaded-files"));
    Assertions.assertEquals("selenium-snapshot.png", fileName.getText());
  }

  @Test
  public void downloads() throws IOException {
    ChromeOptions options = getDefaultChromeOptions();
    options.setEnableDownloads(true);
    driver = new RemoteWebDriver(gridUrl, options);

    List<String> fileNames = new ArrayList<>();
    fileNames.add("file_1.txt");
    fileNames.add("file_2.jpg");
    driver.get("https://www.selenium.dev/selenium/web/downloads/download.html");
    driver.findElement(By.id("file-1")).click();
    driver.findElement(By.id("file-2")).click();
    new WebDriverWait(driver, Duration.ofSeconds(5))
        .until(d -> ((HasDownloads) d).getDownloadableFiles().contains("file_2.jpg"));

    List<String> files = ((HasDownloads) driver).getDownloadableFiles();

    // Sorting them to avoid differences when comparing the files
    fileNames.sort(Comparator.naturalOrder());
    files.sort(Comparator.naturalOrder());
    
    Assertions.assertEquals(fileNames, files);
    String downloadableFile = files.get(0);
    Path targetDirectory = Files.createTempDirectory("download");

    ((HasDownloads) driver).downloadFile(downloadableFile, targetDirectory);

    String fileContent = String.join("", Files.readAllLines(targetDirectory.resolve(downloadableFile)));
    Assertions.assertEquals("Hello, World!", fileContent);

    ((HasDownloads) driver).deleteDownloadableFiles();

    Assertions.assertTrue(((HasDownloads) driver).getDownloadableFiles().isEmpty());
  }

  @Test
  public void augment() {
    ChromeOptions options = getDefaultChromeOptions();
    driver = new RemoteWebDriver(gridUrl, options);

    driver = new Augmenter().augment(driver);

    Assertions.assertTrue(driver instanceof HasCasting);
  }

  @Test
  public void remoteWebDriverBuilder() {
    driver =
        RemoteWebDriver.builder()
            .address(gridUrl)
            .oneOf(getDefaultChromeOptions())
            .setCapability("ext:options", Map.of("key", "value"))
            .config(ClientConfig.defaultConfig())
            .build();

    Assertions.assertTrue(driver instanceof HasCasting);
  }
}
12
15
<details class="mt-3">
  <summary>Show full example</summary>
  <div class="pt-2">
    <div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-py" data-lang="py"><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">import</span> <span style="color:#000">os</span>

import sys import pytest from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.remote.file_detector import LocalFileDetector from selenium.webdriver.support.wait import WebDriverWait @pytest.mark.skipif(sys.platform == "win32", reason="Gets stuck on Windows, passes locally") def test_start_remote(server): options = get_default_chrome_options() driver = webdriver.Remote(command_executor=server, options=options) assert "localhost" in driver.command_executor._client_config.remote_server_addr driver.quit() @pytest.mark.skipif(sys.platform == "win32", reason="Gets stuck on Windows, passes locally") def test_uploads(server): options = get_default_chrome_options() driver = webdriver.Remote(command_executor=server, options=options) driver.get("https://the-internet.herokuapp.com/upload") upload_file = os.path.abspath( os.path.join(os.path.dirname(file), "..", "selenium-snapshot.png")) driver.file_detector = LocalFileDetector() file_input = driver.find_element(By.CSS_SELECTOR, "input[type='file']") file_input.send_keys(upload_file) driver.find_element(By.ID, "file-submit").click() file_name_element = driver.find_element(By.ID, "uploaded-files") file_name = file_name_element.text assert file_name == "selenium-snapshot.png" @pytest.mark.skipif(sys.platform == "win32", reason="Gets stuck on Windows, passes locally") def test_downloads(server, temp_dir): options = get_default_chrome_options() options.enable_downloads = True driver = webdriver.Remote(command_executor=server, options=options) file_names = ["file_1.txt", "file_2.jpg"] driver.get('https://www.selenium.dev/selenium/web/downloads/download.html') driver.find_element(By.ID, "file-1").click() driver.find_element(By.ID, "file-2").click() WebDriverWait(driver, 3).until(lambda d: "file_2.jpg" in d.get_downloadable_files()) files = driver.get_downloadable_files() assert sorted(files) == sorted(file_names) downloadable_file = file_names[0] target_directory = temp_dir driver.download_file(downloadable_file, target_directory) target_file = os.path.join(target_directory, downloadable_file) with open(target_file, "r") as file: assert "Hello, World!" in file.read() driver.delete_downloadable_files() assert not driver.get_downloadable_files() def get_default_chrome_options(): options = webdriver.ChromeOptions() options.add_argument("–no-sandbox") return options

<div class="text-end pb-2 mt-2">
  <a href="https://github.com/SeleniumHQ/seleniumhq.github.io/blob/display_full/examples/python/tests/drivers/test_remote_webdriver.py#L13-L14" target="_blank">
    <i class="fas fa-external-link-alt pl-2"></i>
    <strong>View full example on GitHub</strong>
  </a>
</div>
27
30
Show full example
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Tokens;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Support.UI;

namespace SeleniumDocs.Drivers
{
    [TestClass]
    public class RemoteWebDriverTest : BaseTest
    {
        [TestInitialize]
        public async Task Setup()
        {
            await StartServer();
        }

        [TestMethod]
        public void RunRemote()
        {
            var options = new ChromeOptions();
            driver = new RemoteWebDriver(GridUrl, options);

            Assert.IsInstanceOfType(driver, typeof(IHasDownloads));
        }

        [TestMethod]
        public void Uploads()
        {
            var options = new ChromeOptions();
            driver = new RemoteWebDriver(GridUrl, options);

            driver.Url = "https://the-internet.herokuapp.com/upload";

            string baseDirectory = AppContext.BaseDirectory;
            string relativePath = "../../../TestSupport/selenium-snapshot.png";

            string uploadFile = Path.GetFullPath(Path.Combine(baseDirectory, relativePath));

            ((RemoteWebDriver)driver).FileDetector = new LocalFileDetector();
            IWebElement fileInput = driver.FindElement(By.CssSelector("input[type=file]"));
            fileInput.SendKeys(uploadFile);
            driver.FindElement(By.Id("file-submit")).Click();

            IWebElement fileName = driver.FindElement(By.Id("uploaded-files"));
            Assert.AreEqual("selenium-snapshot.png", fileName.Text);
        }

        [TestMethod]
        public void Downloads()
        {
            ChromeOptions options = new ChromeOptions
            {
                EnableDownloads = true
            };

            driver = new RemoteWebDriver(GridUrl, options);

            driver.Url = "https://selenium.dev/selenium/web/downloads/download.html";
            driver.FindElement(By.Id("file-1")).Click();
            driver.FindElement(By.Id("file-2")).Click();
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
            wait.Until(d => ((RemoteWebDriver)d).GetDownloadableFiles().Contains("file_2.jpg"));

            IReadOnlyList<string> names = ((RemoteWebDriver)driver).GetDownloadableFiles();

            Assert.IsTrue(names.Contains("file_1.txt"));
            Assert.IsTrue(names.Contains("file_2.jpg"));
            string downloadableFile = names.First(f => f == "file_1.txt");
            string targetDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());

            ((RemoteWebDriver)driver).DownloadFile(downloadableFile, targetDirectory);

            string fileContent = File.ReadAllText(Path.Combine(targetDirectory, downloadableFile));
            Assert.AreEqual("Hello, World!", fileContent.Trim());

            ((RemoteWebDriver)driver).DeleteDownloadableFiles();

            Assert.IsTrue(((RemoteWebDriver)driver).GetDownloadableFiles().IsNullOrEmpty());
            Directory.Delete(targetDirectory, recursive: true);
        }

        [TestMethod]
        public void CustomExecutor()
        {
            driver = new RemoteWebDriver(GridUrl, new FirefoxOptions());
            driver.Navigate().GoToUrl("https://www.selenium.dev/");

            var customCommandDriver = driver as ICustomDriverCommandExecutor;
            customCommandDriver.RegisterCustomDriverCommands(FirefoxDriver.CustomCommandDefinitions);

            var screenshotResponse = customCommandDriver
                .ExecuteCustomDriverCommand(FirefoxDriver.GetFullPageScreenshotCommand, null);

            Screenshot image = new Screenshot((string)screenshotResponse);

            string targetDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
            Directory.CreateDirectory(targetDirectory);
            string targetFile = Path.GetFullPath(Path.Combine(targetDirectory, "fullPage.png"));

            using (var memoryStream = new MemoryStream(image.AsByteArray))
            using (var fileStream = new FileStream(targetFile, FileMode.Create))
            {
                memoryStream.WriteTo(fileStream);
            }

            Assert.IsTrue(File.Exists(targetFile));
            
            Directory.Delete(targetDirectory, true);
        }
    }
}
19
22
Show full example
# frozen_string_literal: true

require 'spec_helper'
require 'selenium/server'

RSpec.describe 'Remote WebDriver' do
  let(:target_directory) { File.join(Dir.tmpdir, SecureRandom.uuid) }
  let(:wait) { Selenium::WebDriver::Wait.new(timeout: 2) }
  let(:server) do
    Selenium::Server.get(:latest,
                         background: true,
                         args: %w[--selenium-manager true --enable-managed-downloads true])
  end
  let(:grid_url) { server.webdriver_url }

  before { server.start }
  after { server.stop }

  it 'starts remotely' do
    options = Selenium::WebDriver::Options.chrome
    driver = Selenium::WebDriver.for :remote, url: grid_url, options: options

    expect { driver.session_id }.not_to raise_exception
  end

  it 'uploads' do
    options = Selenium::WebDriver::Options.chrome
    driver = Selenium::WebDriver.for :remote, url: server.webdriver_url, options: options

    driver.get('https://the-internet.herokuapp.com/upload')
    upload_file = File.expand_path('../spec_support/selenium-snapshot.png', __dir__)

    driver.file_detector = ->((filename, *)) { filename.include?('selenium') && filename }
    file_input = driver.find_element(css: 'input[type=file]')
    file_input.send_keys(upload_file)
    driver.find_element(id: 'file-submit').click

    file_name = driver.find_element(id: 'uploaded-files')
    expect(file_name.text).to eq 'selenium-snapshot.png'
  end

  it 'downloads' do
    options = Selenium::WebDriver::Options.chrome(enable_downloads: true)
    driver = Selenium::WebDriver.for :remote, url: grid_url, options: options

    file_names = %w[file_1.txt file_2.jpg]
    driver.get('https://www.selenium.dev/selenium/web/downloads/download.html')
    driver.find_element(id: 'file-1').click
    driver.find_element(id: 'file-2').click
    wait.until { driver.downloadable_files.include?('file_2.jpg') && driver.downloadable_files.include?('file_1.txt') }

    files = driver.downloadable_files

    expect(files.sort).to eq file_names.sort
    downloadable_file = 'file_1.txt'

    driver.download_file(downloadable_file, target_directory)

    file_content = File.read("#{target_directory}/#{downloadable_file}").strip
    expect(file_content).to eq('Hello, World!')

    driver.delete_downloadable_files

    expect(driver.downloadable_files).to be_empty
  end
end