Dexter  Goodwin

Dexter Goodwin


Digdug: A JavaScript Library for Launching WebDriver Service Tunnels

Dig Dug

Dig Dug is a library for downloading and managing WebDriver service tunnels, along with Selenium and individual WebDrivers.


Dig Dug can connect to an existing local WebDriver or Selenium server, manage a local Selenium server, or connect to various remote cloud testing systems.

Local server

Use NullTunnel to connect to an already-running server such as Selenium or a standalone ChromeDriver instance. NullTunnel, as its name suggests, essentially nulls out most of the default functionality in Tunnel, such as the download method (used to download a service tunnel binary). For example, calling start on any of the other tunnel classes would download the necessary tunnel binaries and spawn a child process, but calling start on a NullTunnel does nothing (with the assumption that the tunnel has already been started).

Managed Selenium server

Dig Dug can manage a local Selenium server with its SeleniumTunnel. By default the tunnel will download a recent version of Selenium and ChromeDriver. The most commonly used options for the Selenium tunnel are version and drivers. The version option simply sets the version of Selenium to use, such as '3.4.0'. The drivers option tells SeleniumTunnel which drivers to download, and optionally which versions to use. For example, to configure SeleniumTunnel to use geckodriver 0.18.0 and the default version of ChromeDriver with Selenium 3.5.2:

const tunnel = new SeleniumTunnel({
  version: '3.5.2',
  drivers: [
      name: 'firefox',
      version: '0.18.0'

To determine what are the most recent versions of Selenium and the various webdrivers, Dig Dug will first attempt to download a version manifest from If this fails, Dig Dug will fall back to the manifest contained in the package. The actual location used to download the manifest can be controlled via the webDriverConfigUrl property on SeleniumTunnel. Set the property to false to prevent SeleniumTunnel from trying to download the manifest.

Cloud testing services

Dig Dug supports the following cloud testing services:

In many cases, the only configuration you’ll need to do to create a tunnel is provide authentication data. This can be provided via options to a Tunnel constructor or via environment variables. The service tunnels use the following environment variables:

Tunnel classEnvironment variables
CrossBrowserTestingTunnelCBT_USERNAME, CBT_APIKEY

Other properties, such as the local port the tunnel should serve on or the URL of a proxy server the tunnel should go through, can be passed to a tunnel constructor or set on a tunnel instance. See the API docs for Tunnel and its subclasses for available properties:


To create a new tunnel, import the desired tunnel class, create a new instance, and call its start method. start returns a Promise that resolves when the tunnel has successfully started. For example, to create a new Sauce Labs tunnel:

import SauceLabsTunnel from '@theintern/digdug/SauceLabsTunnel';
const tunnel = new SauceLabsTunnel();
tunnel.start().then(() => {
  // interact with the WebDriver server at tunnel.clientUrl

Once a tunnel has been started, a test runner can interact with it as described in the service’s documentation. For example, the Sauce Labs and TestingBot executables start a WebDriver server on localhost that the test client communicates with, while a test client will connect to after the tunnel has started to use BrowserStack.

The tunnel classes also provide a sendJobState convenience method to let the remote service know whether a test session passed or failed. This method accepts a session ID and an object containing service-specific data, and it returns a Promise that resolves if the job state was successfully updated.

tunnel.sendJobState(sessionId, { success: true });

When testing is finished, call the tunnel’s stop method to cleanly shut it down. This method returns a Promise that is resolved when the service tunnel executable has exited.

tunnel.stop().then(() => {
  // the tunnel has been shut down


Dig Dug includes a utility script, digdugEnvironmnents, that will display all the environments provided by a remote testing service.

$ ./node_modules/.bin/digdugEnvironments SauceLabsTunnel
{"platform":"OS X 10.9","browserName":"firefox","version":"4"}
{"platform":"OS X 10.9","browserName":"firefox","version":"5"}
{"platform":"OS X 10.9","browserName":"firefox","version":"6"}
{"platform":"OS X 10.9","browserName":"firefox","version":"7"}
{"platform":"OS X 10.9","browserName":"firefox","version":"8"}
{"platform":"OS X 10.9","browserName":"firefox","version":"9"}
{"platform":"OS X 10.9","browserName":"firefox","version":"10"}

Note that BrowserStackTunnel requires that the BROWSERSTACK_ACCESS_KEY and BROWSERSTACK_USERNAME environment variables exist and are set to a user’s account access key and username. The other tunnels do not (currently) require authentication to request an environment list.

More information

Download Details: 

Author: Theintern
Source Code: 
License: View license

#javascript #typescript #webdriver 

Digdug: A JavaScript Library for Launching WebDriver Service Tunnels
Dexter  Goodwin

Dexter Goodwin


A JavaScript Client Library That Brings Cross-platform Consistency


A JavaScript client library that brings cross-platform consistency to the Selenium WebDriver API

Unlike existing WebDriver client libraries that assume the remote server will just do the Right Thing, Leadfoot detects and works around inconsistencies in WebDriver server implementations, using native WebDriver/Selenium commands when possible, so you can just worry about making your tests work—not bugs in WebDriver servers.

Enhanced capabilities are also exposed to end-users about which features and APIs a remote environment supports, so you don’t have to browser sniff to decide whether (for example) you’re testing a touch-device or a mouse-device. Optional convenience methods are also available for use, and support for chai-as-promised is built in.

Leadfoot has been tested with the following remote drivers:

  • InternetExplorerDriver
  • Microsoft WebDriver
  • FirefoxDriver
  • geckodriver
  • ChromeDriver
  • SafariDriver
  • safaridriver (native)
  • Selendroid
  • ios-driver

Using Leadfoot

Leadfoot can be installed and used as a stand-alone library. It is also an integral part of the Intern testing framework, which provides you with all of the tools you need to write robust unit and functional tests. Follow the instructions on writing functional tests with Intern to learn how to use Leadfoot with Intern.

Firefox, Safari, and Edge

Firefox 49+, Safari 10+, and Microsoft Edge are all on the bleeding edge of WebDriver-based browser automation. They all use relatively new drivers that implement the still-under-development W3C WebDriver standard, so feature support is spotty at times. For best results, use the most recent versions of Selenium and the browser’s native driver (geckodriver, Microsoft WebDriver, or safaridriver), and the most recent browser version in Firefox’s case.


Main components

A program will generally interact with three main components of Leadfoot:

  1. A Server, which manages communication with a remote WebDriver server
  2. A Session, which manages communication with a single remote browser instance
  3. A Command, which provides an API for interacting with a remote browser


Much of Leadfoot’s API is provided by the Command class. Commands are Promise-like, and the Command API is fluid and asynchronous. A sequence of commands to load a remote page, find a button, and click it typically looks like:


Methods in a Command chain execute asynchronously and sequentially. Each method will wait for the previous one in the chain to complete. If multiple Command chains are started, they will run in parallel (as much as JavaScript supports running code in parallel).

Session vs Element

Commands support both session interactions, which operate against the entire browser session, and element interactions, which operate against specific elements taken from the currently loaded page. Things like navigating the browser with get, moving the mouse cursor, and executing scripts are session interactions, while getting text displayed on the page, typing into form fields, and getting element attributes are element interactions.

Some method names, like click, are identical for both Session and Element APIs; in this case, the element APIs are suffixed with the word Element in order to identify them uniquely.

Element context

Session interactions can be performed at any time, from any Command. On the other hand, to perform element interactions, you first need to retrieve one or more elements to interact with. This can be done using any of the find or findAll methods, by the getActiveElement method, or by returning elements from execute or executeAsync calls. The retrieved elements are stored internally as the element context of the Command chain. When element methods, such as getVisibleText, are called on a Command, they operate on the current context.

    // finds one element -> single element context
    .then(text => {
        // `text` is the text from the element context

When an element method is called and the current context is a multi-element, the result will be returned as an array:

    // finds multiple elements -> multiple element context
    .then(texts => {
        // `texts` is an array of text from each of the `p` elements

The find and findAll methods also operate on the current context. If a command has been filtered by element, the find and findAll commands will only find elements within the current context. Otherwise, they will find elements throughout the page.


“Helpers” are functions that can be inserted into a Command chain to provide higher-level functionality. For example, Leadfoot includes a pollUntil helper. This function can be used to pause a Command chain until a condition is met. For example, the following snippet will retrieve a page and then wait for a ready global variable to be defined on the page:

import pollUntil from '@theintern/leadfoot/helpers/pollUntil';

	.then(pollUntil('return window.ready', 5000))
	// ...

How To — Quick answers to common questions

Use Leadfoot as a standalone library

Install leadfoot in your project

npm install @theintern/leadfoot

Create a Server — this manages communication between your app and a remote WebDriver server

import Server from '@theintern/leadfoot/Server'
const server = new Server('http://my-webdriver-server.local');

Create a new session — this is a connection to a remote browser

const session = server.createSession({ "browserName": "chrome" });

Create a Command — this is what your app will use to call WebDriver commands

import Command from '@theintern/leadfoot/Command'
const command = new Command(session);

Start talking to the browser

    // ...

Use Leadfoot with async/await

Leadfoot is Promise-based, so it works very well with async/await.

const page = await command.get('http://page.local');
const form = await page.findById('login-form');
await form.findByCssSelector('[name="username"]').type('bob');
await form.findByCssSelector('[name="password"]').type('12345');
await form.findByCssSelector('.submit').click()

How to iterate through elements

Using Array.reduce:

    .then(headings => {
        return headings.reduce((textsPromise, heading) => {
            return textsPromise.then(texts => {
                return heading.getText().then(text => {
                    return texts.concat(text);
        }, Promise.resolve([]));

Using async/await:

    .then(async headings => {
        const texts = [];
        for (const heading of headings) {
            texts.push(await heading.getVisibleText());
        return texts;

Since Leadfoot element methods will work on arrays as well as individual found elements, in this case one could also simply do:


More information

Download Details: 

Author: theintern
Source Code: 
License: View license

#javascript #webdriver #crossplatform 

A JavaScript Client Library That Brings Cross-platform Consistency

Build a UI Testing with Pytest and Selenium WebDriver

Build a UI Testing with Pytest and Selenium WebDriver

Introduction to Selenium WebDriver with Python. Learn how to build a UI testing solution from the ground up using pytest and Selenium WebDriver. 

There's been a lot of discussion around Python. According to several surveys, it is one of the most in demand languages today. It's also particularly good for test automation. Whether you are a manual tester who is just learning to program for the first time, or you're a seasoned developer, Python is a great language to use.

Join Applitools Developer Advocate, Andrew Knight as he demonstrates how you can build a UI testing solution from the ground up using pytest and Selenium WebDriver. At the end, you'll understand how to create your own fully working solution to extend with any tests that you want.

#python #pytest #selenium #webdriver #testing 

Build a UI Testing with Pytest and Selenium WebDriver

Query Selector Shadow Dom


querySelector that can pierce Shadow DOM roots without knowing the path through nested shadow roots. Useful for automated testing of Web Components e.g. with Selenium, Puppeteer.


// available as an ES6 module for importing in Browser environments

import { querySelectorAllDeep, querySelectorDeep } from 'query-selector-shadow-dom';

What is a nested shadow root?

Image of Shadow DOM elements in dev tools You can see that .dropdown-item:not([hidden]) (Open downloads folder) is several layers deep in shadow roots, most tools will make you do something like

document.querySelector("body > downloads-manager").shadowRoot.querySelector("#toolbar").shadowRoot.querySelector(".dropdown-item:not([hidden])")


with query-selector-shadow-dom:

import { querySelectorAllDeep, querySelectorDeep } from 'query-selector-shadow-dom';


  • querySelectorAllDeep - mirrors querySelectorAll from the browser, will return an Array of elements matching the query
  • querySelectorDeep - mirrors querySelector from the browser, will return the first matching element of the query.
  • collectAllElementsDeep - collects all elements on the page, including shadow dom

Both of the methods above accept a 2nd parameter, see section Provide alternative node. This will change the starting element to search from i.e. it will find ancestors of that node that match the query.

Known limitations

  • Source ordering of results may not be preserved. Due to the nature of how this library works, by breaking down selectors into parts, when using multiple selectors (e.g. split by commas) the results will be based on the order of the query, not the order the result appear in the dom. This is different from the native querySelectorAll functionality. You can read more about this here:



This plugin implements a custom selector strategy:

// make sure you have selenium standalone running
const { remote } = require('webdriverio');
const { locatorStrategy } = require('query-selector-shadow-dom/plugins/webdriverio');

(async () => {
    const browser = await remote({
        logLevel: 'error',
        path: '/wd/hub',
        capabilities: {
            browserName: 'chrome'

    // The magic - registry custom strategy
    browser.addLocatorStrategy('shadow', locatorStrategy);

    // now you have a `shadow` custom locator.

    // All elements on the page
    await browser.waitUntil(() => browser.custom$("shadow", ".btn-in-shadow-dom"));
    const elements = await browser.$$("*");

    const elementsShadow = await browser.custom$$("shadow", "*");

    console.log("All Elements on Page Excluding Shadow Dom", elements.length);
    console.log("All Elements on Page Including Shadow Dom", elementsShadow.length);

    await browser.url('')
    // find input element in shadow dom
    const input = await browser.custom$('shadow', '#type-to-input');
    // type to input ! Does not work in firefox, see above.
    await input.setValue('Typed text to input');
    // Firefox workaround
    // await browser.execute((input, val) => input.value = val, input, 'Typed text to input')

    await browser.deleteSession()
})().catch((e) => console.error(e))

How is this different to shadow$

shadow$ only goes one level deep in a shadow root.

Take this example. Image of Shadow DOM elements in dev tools You can see that .dropdown-item:not([hidden]) (Open downloads folder) is several layers deep in shadow roots, but this library will find it, shadow$ would not. You would have to construct a path via css or javascript all the way through to find the right element.

const { remote } = require('webdriverio')
const { locatorStrategy } = require('query-selector-shadow-dom/plugins/webdriverio');

(async () => {
    const browser = await remote({capabilities: {browserName: 'chrome'}})

    browser.addLocatorStrategy('shadow', locatorStrategy);

    await browser.url('chrome://downloads')
    const moreActions = await browser.custom$('shadow', '#moreActions');
    const span = await browser.custom$('shadow', '.dropdown-item:not([hidden])');
    const text = await span.getText()
    // prints `Open downloads folder`

    await browser.deleteSession()
})().catch((e) => console.error(e))

Known issues

From the above, firefox setValue does NOT currently work. . A workaround for now is to use a custom command (or method on your component object) that sets the input field's value via browser.execute(function).

Safari pretty much doesn't work, not really a surprise.

There are some webdriver examples available in the examples folder of this repository. WebdriverIO examples


Update: As of 5.4.0 Puppeteer now has a built in shadow Dom selector, this module might not be required for Puppeteer anymore. They don't have any documentation:

There are some puppeteer examples available in the examples folder of this repository.

Puppeteer examples


Update: as of Playwright v0.14.0 their CSS and text selectors work with shadow Dom out of the box, you don't need this library anymore for Playwright.

Playwright works really nicely with this package.

This module exposes a playwright selectorEngine:

const { selectorEngine } = require("query-selector-shadow-dom/plugins/playwright");
const playwright = require('playwright');

 await selectors.register('shadow', createTagNameEngine);
  await page.goto('chrome://downloads');
  // shadow= allows a css query selector that automatically pierces shadow roots.
  await page.waitForSelector('shadow=#no-downloads span', {timeout: 3000})

For a full example see:


This project provides a Protractor plugin, which can be enabled in your protractor.conf.js file:

exports.config = {
    plugins: [{
        package: 'query-selector-shadow-dom/plugins/protractor'
    // ... other Protractor-specific config

The plugin registers a new locator - by.shadowDomCss(selector /* string */), which can be used in regular Protractor tests:


The locator also works with Serenity/JS tests that use Protractor under the hood:

import 'query-selector-shadow-dom/plugins/protractor';
import { Target } from '@serenity-js/protractor'
import { by } from 'protractor';

const ElementOfInterest = Target.the('element of interest')

See the end-to-end tests for more examples.


Provide alternative node

    // query from another node
    querySelectorShadowDom.querySelectorAllDeep('child', document.querySelector('#startNode'));
    // query an iframe
    querySelectorShadowDom.querySelectorAllDeep('child', iframe.contentDocument);

This library does not allow you to query across iframe boundaries, you will need to get a reference to the iframe you want to interact with. 
If your iframe is inside of a shadow root you could cuse querySelectorDeep to find the iframe, then pass the contentDocument into the 2nd argument of querySelectorDeep or querySelectorAllDeep.

Chrome downloads page

In the below examples the components being searched for are nested within web components shadowRoots.

// Download and Paste the lib code in dist into chrome://downloads console to try it out :)

console.log(querySelectorShadowDom.querySelectorAllDeep('downloads-item:nth-child(4) #remove'));
console.log(querySelectorShadowDom.querySelectorAllDeep('#downloads-list .is-active a[href^="https://"]'));
console.log(querySelectorShadowDom.querySelectorDeep('#downloads-list div#title-area + a'));

Shady DOM

If using the polyfills and shady DOM, this library will still work.


  • Shipped as an ES6 module to be included using a bundler of your choice (or not).
  • ES5 version bundled ontop the window as window.querySelectorShadowDom available for easy include into a test framework

Running the code locally

npm install

Running the tests

npm test

Running the tests in watch mode

npm run watch

Running the build

npm run build

Author: Georgegriff
Source Code: 
License: MIT license

#node #javascript #webdriver #webcomponents 

Query Selector Shadow Dom
Anthony  Dach

Anthony Dach


Page Object: Gem to Implement PageObject Pattern in Watir Webdriver


A simple gem that assists in creating flexible page objects for testing browser based applications. The goal is to facilitate creating abstraction layers in your tests to decouple the tests from the item they are testing and to provide a simple interface to the elements on a page. It works with both watir and selenium-webdriver.


The project wiki is the first place to go to learn about how to use page-object.

The rdocs for this project can be found at

To see the changes from release to release please look at the ChangeLog

To read about the motivation for this gem please read this blog entry

There is a book that describes in detail how to use this gem and others to create a complete view of testing web and other types of applications. The book is named Cucumber & Cheese


If you need help using the page-object gem please ask your questions on Stack Overflow. Please be sure to use the page-object-gem tag. If you wish to report an issue or request a new feature use the github issue tracking page.

Basic Usage

Defining your page object

You define a new page object by including the PageObject module:

class LoginPage
  include PageObject

When you include this module numerous methods are added to your class that allow you to easily define your page. For the login page you might add the following:

class LoginPage
  include PageObject
  text_field(:username, :id => 'username')
  text_field(:password, :id => 'password')
  button(:login, :id => 'login')

Calling the text_field and button methods adds several methods to our page object that allow us to interact with the items on the page. To login using this page we could simply write the following code:

login_page.username = 'cheezy'
login_page.password = 'secret'

Another approach might be to create higher level methods on our page object that hide the implementation details even further. Our page object might look like this:

class LoginPage
  include PageObject
  text_field(:username, :id => 'username')
  text_field(:password, :id => 'password')
  button(:login, :id => 'login')
  def login_with(username, password)
    self.username = username
    self.password = password

and your usage of the page would become:

login_page.login_with 'cheezy', 'secret'

Creating your page object

page-object supports both watir and selenium-webdriver. The one used will be determined by which driver you pass into the constructor of your page object. The page object can be created like this:

browser = :firefox
my_page_object =


browser = Selenium::WebDriver.for :firefox
my_page_object =

Known Issues



  • Fork the project.
  • Test drive your feature addition or bug fix. Adding specs is important and I will not accept a pull request that does not have tests.
  • Make sure you describe your new feature with a cucumber scenario.
  • Make sure you provide RDoc comments for any new public method you add. Remember, others will be using this gem.
  • Commit, do not mess with Rakefile, version, or ChangeLog. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
  • Send me a pull request. Bonus points for topic branches.

Download Details:
Author: cheezy
Source Code:
License: MIT License

#selenium #ruby #webdriver #testing 

Page Object: Gem to Implement PageObject Pattern in Watir Webdriver

Whatsapp Chatbot: Developed using Selinium Webdriver in Python

WhatsApp Chatbot

A simple Whatsapp chatbot that chats with a group or person using the web version of Whatsapp


You will require a recent version of Google Chrome and the drivers. The drivers are included in the drivers directory of this project.
To run the following python script you will need the Selenium Webdriver for Python

pip3 install selenium

How to use the program

  • Run the
  • Wait for both tabs to load and navigate to the WhatsApp Tab
  • If you are running for the first time scan the QRCode using your phone
  • Select the Group or Person you want the Chat bot to work with
  • Press ENTER in the python terminal

Now ask your friend to send a message. All messages to the chat bot should start with the $ sign.

Example : $Hello there.



Whatsapp Policy

Please note that Whatsapp does not encourage bots on their messaging service. Any mass advertising or spamming will lead to your account being banned. This is only for fun and experimental purposes. Use it at your own risk

Download Details:
Author: DollarAkshay
Source Code:

#chatbot  #python #Selinium #webdriver 

Whatsapp Chatbot: Developed using Selinium Webdriver in Python
Anthony  Dach

Anthony Dach


Test Automation Project Based on Selenium-Webdriver with Python

Important notice

I would like to inform everyone who is interested in this project that I decided to go back to working on it. I am planning to implement some major changes like separating framework from tests, adding sample tests for another website than and removing tests implemented before. Thank you guys for forking and giving stars for this project. I appreciate it a lot!

Test Automation Project

This is my first test automation project based on Selenium-Webdriver with Python. It's still developing package of automated tests of demo website. The collection of tests contains:

  • user login tests (correct / incorrect login and password)
  • hotels search tests
  • flights search tests
  • tours search tests
  • transfers search tests

Project Structure

Here you can find a short description of main directories and it's content

  • locators - there are locators of web elements in grouped in classes
  • pages - there are sets of method for each test step (notice: some repeated methods were moved to
  • tests - there are sets of tests for main functionalities of website
  • reports - if you run tests with Allure, tests reports will be saved in this directory
  • utils - this directory contains files responsible for configuration, e.g. for webdriver management or for reading input data from xlsx files included in project

Project Features

  • framework follows page object pattern
  • data-driven tests - in most tests the option of loading data from an xlsx file has been implemented
  • logger has been implemented in each step of test cases, e.g.
@allure.step("Setting destination to '{1}'")
    def set_destination(self, destination):"Setting destination: {destination}")
Logs screenshot
  • the ability to easily generate legible and attractive test reports using Allure (for more look Generate Test Report section below)
  • tests can be run on popular browsers - Chrome and Firefox are preconfigured in DriverFactory class and both can be select in, e.g.
def setup(request):
    driver = DriverFactory.get_driver("chrome")

Getting Started

To enjoy the automated tests, develop the framework or adapt it to your own purposes, just download the project or clone repository. You need to install packages using pip according to requirements.txt file. Run the command below in terminal:

$ pip install -r requirements.txt

Run Automated Tests

To run selected test without Allure report you need to set pytest as default test runner in Pycharm first

File > Settings > Tools > Python Integrated Tools > Testing

After that you just need to choose one of the tests from "tests" directory and click "Run test" green arrow. There are 2 versions of test in each test file. In general test cases you can easily modify test inputs. Data-driven tests base on xlsx files from utils directory.

Generate Test Report

To generate all tests report using Allure you need to run tests by command first:

$ pytest --alluredir=<reports directory path>

After that you need to use command:

$ allure serve <reports directory path>

Allure report screenshot

Report is generated in Chrome browser.

Download Details:
Author: startrug
Source Code:
License: MIT License

#selenium  #python #google-chrome #webdriver 

Test Automation Project Based on Selenium-Webdriver with Python
Anthony  Dach

Anthony Dach


Selenium Jupiter: JUnit 5 Extension for Selenium WebDriver

Selenium-Jupiter is an open-source Java library that implements a JUnit 5 extension for developing Selenium WebDriver tests. Selenium-Jupiter uses several features of the Jupiter extension (such as parameters resolution, test templates, or conditional test execution). Thanks to this, the resulting Selenium-Jupiter tests follow a minimalist approach (i.e., the required boilerplate code for WebDriver is reduced) while providing a wide range of advanced features for end-to-end testing.


You can find the complete documentation of Selenium-Jupiter here. This site contains all the features, examples, and configuration capabilities of Selenium-Jupiter.

Local browsers

Selenium-Jupiter can be used to control local browsers programmatically using Selenium WebDriver. To do that, we need to specify the flavor of the browser to be used by declaring WebDriver parameters in tests or constructors. For instance, we declare a ChromeDriver parameter to use Chrome, FirefoxDriver for Firefox, and so on. For instance:

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import io.github.bonigarcia.seljup.SeleniumJupiter;

class ChromeTest {

    void test(ChromeDriver driver) {
        assertThat(driver.getTitle()).contains("Selenium WebDriver");


Internally, Selenium-Jupiter uses WebDriverManager to manage the WebDriver binaries (i.e., chromedriver, geckodriver, etc.) required to use local browsers.

Browsers in Docker containers

Selenium-Jupiter allows using browsers in Docker containers very easily. The only requirement is to get installed Docker Engine in the machine running the tests. The following example shows a test using this feature. Internally, it pulls the image from Docker Hub, starts the container, and instantiates the WebDriver object to use it. This example also enables the recording of the browser session and remote access using noVNC:

import static io.github.bonigarcia.seljup.BrowserType.CHROME;
import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.openqa.selenium.WebDriver;

import io.github.bonigarcia.seljup.DockerBrowser;
import io.github.bonigarcia.seljup.SeleniumJupiter;

class DockerChromeTest {

    void testChrome(@DockerBrowser(type = CHROME) WebDriver driver) {
        assertThat(driver.getTitle()).contains("Selenium WebDriver");


Conditional tests

Selenium-Jupiter provides the class-level annotation @EnabledIfBrowserAvailable to skip tests conditionally depending on the availability of local browsers. For example:

import static io.github.bonigarcia.seljup.Browser.SAFARI;
import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.openqa.selenium.safari.SafariDriver;

import io.github.bonigarcia.seljup.EnabledIfBrowserAvailable;
import io.github.bonigarcia.seljup.SeleniumJupiter;

class SafariTest {

    void test(SafariDriver driver) {
        assertThat(driver.getTitle()).contains("Selenium WebDriver");


Test templates

Test templates are a special kind of test in which the same test logic is executed several times according to some custom data. In Selenium-Jupiter, the data to feed a test template is referred to as the browser scenario (a JSON file by default).

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith;
import org.openqa.selenium.WebDriver;

import io.github.bonigarcia.seljup.SeleniumJupiter;

class TemplateTest {

    void templateTest(WebDriver driver) {
        assertThat(driver.getTitle()).contains("Selenium WebDriver");


... and the browser scenario is:

   "browsers": [
            "type": "chrome-in-docker",
            "version": "latest"
            "type": "chrome-in-docker",
            "version": "latest-1"
            "type": "chrome-in-docker",
            "version": "beta"
            "type": "chrome-in-docker",
            "version": "dev"

Download Details:
Author: bonigarcia
Source Code:
License: Apache-2.0 License

#selenium  #java #webdriver #junit #jupiter

Selenium Jupiter: JUnit 5 Extension for Selenium WebDriver
Anthony  Dach

Anthony Dach


Webdrivers: Keep Your Selenium WebDrivers Updated Automatically


Run Selenium tests more easily with automatic installation and updates for all supported webdrivers.


webdrivers downloads drivers and directs Selenium to use them. Currently supports:

Works on macOS, Linux, Windows, and Windows Subsystem for Linux (WSL) v1 and v2. And do see the browser and OS specific notes at the bottom.


In your Gemfile:

gem 'webdrivers', '~> 5.0', require: false

In your project:

require 'webdrivers'

The drivers will now be automatically downloaded or updated when you launch a browser through Selenium.

Specific Drivers

If you want webdrivers to only manage specific drivers you can specify one or more as follows:

require 'webdrivers/chromedriver'
require 'webdrivers/geckodriver'
require 'webdrivers/iedriver'
require 'webdrivers/edgedriver'

Download Location

The default download location is ~/.webdrivers directory, and this is configurable:

Webdrivers.install_dir = '/webdrivers/install/dir'

Alternatively, you can define the path via the WD_INSTALL_DIR environment variable.

Version Pinning

If you would like to use a specific (older or beta) version, you can specify it for each driver. Otherwise, the latest (stable) driver will be downloaded and passed to Selenium.

# Chrome
Webdrivers::Chromedriver.required_version = '2.46'

# Firefox
Webdrivers::Geckodriver.required_version  = '0.23.0'

# Internet Explorer
Webdrivers::IEdriver.required_version     = '3.14.0'

# Edge (Chromium)
Webdrivers::Edgedriver.required_version   = ''

You can explicitly trigger the update in your code, but this will happen automatically when the driver is initialized:


Caching Drivers

You can set Webdrivers to only look for updates if the previous check was longer ago than a specified number of seconds.

Webdrivers.cache_time = 86_400 # Default: 86,400 Seconds (24 hours)

Alternatively, you can define this value via the WD_CACHE_TIME environment variable. Only set one to avoid confusion.

Special exception for chromedriver and msedgedriver

Cache time will be respected as long as a driver binary exists and the versions of the browser and the driver match. For example, if you update Chrome or Edge to v76.0.123 and its driver is still at v76.0.100, webdrivers will ignore the cache time and update the driver to make sure you're using a compatible build version.


If there is a proxy between you and the Internet then you will need to configure the gem to use the proxy. You can do this by calling the configure method.

Webdrivers.configure do |config|
  config.proxy_addr = ''
  config.proxy_port = '8080'
  config.proxy_user = 'username'
  config.proxy_pass = 'password'

SSL_connect errors

If you are getting an error like this (especially common on Windows):

SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

Add the following to your Gemfile:

gem "net_http_ssl_fix"

Add the following to your code:

require 'net_http_ssl_fix'

Other solutions are documented on the RubyGems website.

Rake tasks

Each driver has its own set of rake tasks (with Railtie support) that you can call once before executing the tests. These are especially useful if you're running tests in parallel and want to avoid performing an update check per thread.

If you are using Rails default configuration the webdrivers gem will only be loaded in the test group so you will need to specify the test environment when using the tasks:

RAILS_ENV=test rails webdrivers:chromedriver:update

If you are not using Rails, you'll need to load them into your Rakefile like this:

require 'webdrivers'
load 'webdrivers/Rakefile'

The full list of available tasks is:

$ bundle exec rake -T
rake webdrivers:chromedriver:remove           # Force remove chromedriver
rake webdrivers:chromedriver:update[version]  # Remove and download updated chromedriver if necessary
rake webdrivers:chromedriver:version          # Print current chromedriver version
rake webdrivers:edgedriver:remove             # Force remove msedgedriver
rake webdrivers:edgedriver:update[version]    # Remove and download updated msedgedriver if necessary
rake webdrivers:edgedriver:version            # Print current msedgedriver version
rake webdrivers:geckodriver:remove            # Force remove geckodriver
rake webdrivers:geckodriver:update[version]   # Remove and download updated geckodriver if necessary
rake webdrivers:geckodriver:version           # Print current geckodriver version
rake webdrivers:iedriver:remove               # Force remove IEDriverServer
rake webdrivers:iedriver:update[version]      # Remove and download updated IEDriverServer if necessary
rake webdrivers:iedriver:version              # Print current IEDriverServer version

These tasks respect the WD_INSTALL_DIR, WD_CACHE_TIME, WD_CHROME_PATH, and WD_EDGE_CHROME_PATH environment variables, which can also be passed through the rake command:

$ bundle exec rake webdrivers:chromedriver:update[2.46] webdrivers:geckodriver:update[0.24.0] WD_CACHE_TIME=86_400 WD_INSTALL_DIR='my_dir'
2019-05-20 19:03:01 INFO Webdrivers Updated to chromedriver 2.46.628388
2019-05-20 19:03:04 INFO Webdrivers Updated to geckodriver 0.24.0

Please note that these tasks do not use any of the configurations from your project (code) and only respect the ENV variables and the version (optional) passed to the rake tasks.


The logging level can be configured for debugging purpose:

Webdrivers.logger.level = :DEBUG

Browser & OS Specific Notes


The version of chromedriver will depend on the version of Chrome you are using it with:

  • For versions >= 70, the downloaded version of chromedriver will match the installed version of Google Chrome. More information here.
  • For versions <= 69, chromedriver version 2.41 will be downloaded.
  • For beta versions, you'll have to require the beta version of chromedriver using Webdrivers::Chromedriver.required_version.

The gem looks for the Chrome/Chromium version that chromedriver will use by default. You can override this behavior by providing a path to the browser binary you want to use:

Selenium::WebDriver::Chrome.path = '/chromium/install/path/to/binary'

Alternatively, you can define the path via the WD_CHROME_PATH environment variable.

This is also required if Google Chrome is not installed in its default location.

Chrome on Heroku

Follow the specific instructions here if you're using heroku-buildpack-google-chrome.

Microsoft Edge (Chromium)

Microsoft Edge (Chromium) support was added in v4.1.0. Notes from the Chrome/Chromium section apply to this browser as well.

Please note that msedgedriver requires selenium-webdriver v4.

WSLv1 support

While WSLv1 is not designed to run headful applications like Chrome, it can run exes; as such when found to be running in WSL, webdrivers will use Chrome on the Windows filesystem.

It's recommended that you install the new PowerShell (PS7) to avoid a known issue with the console font being changed when calling the old PowerShell (PS5).

WSLv2 support

Webdrivers will detect WSLv2 as running on Linux and use Chrome on the Linux filesystem.

WSLv2 doesn't support connecting to host ports out of the box, so it isn't possible to connect to Chromedriver on Windows without extra configurations, see: The simplest way to use Chromedriver with WSLv2 is to run Chrome headless on Linux.

Chrome and Edge on Apple M1 (arm64)

If you're switching from Intel to M1, you'll have to manually delete the existing Intel (mac64) driver before the M1 (arm64) build can be downloaded. Otherwise, you'll get an error: Bad CPU type in executable - ~/.webdrivers/chromedriver (Errno::E086)


Please see the wiki for solutions to commonly reported issues.

Join us in the #webdrivers-gem channel on Slack if you have any questions.

Download Details:
Author: titusfortner
Source Code:
License: MIT License

#selenium  #ruby #webdriver 

Webdrivers: Keep Your Selenium WebDrivers Updated Automatically
Anthony  Dach

Anthony Dach


Extension to The Official Selenium Dotnet Webdriver


This driver is an extension of the Selenium C# client. It has all the functionalities of the regular driver, but add Appium specific methods on top of this.


NuGet Package:


Note: we will NOT publish a signed version of this assembly since the dependencies we access through NuGet do not have a signed version - thus breaking the chain and causing us headaches. With that said, you are more than welcome to download the code and build a signed version yourself.



  • You need to add the following namespace line: using OpenQA.Selenium.Appium;.
  • Use the AppiumDriver class/subclass to construct the driver. It works the same as the Selenium Webdriver, except that the ports are defaulted to Appium values, and the driver does not know how to start the Appium on its own.
  • To use the Appium methods on Element, you need to specify the parameter of AppiumDriver or its subclasses.

Read Wiki

See samples here

Dev Build+Test


  • Open with Xamarin
  • Rebuild all
  • Run tests in test/specs

JetBrains Rider

  • Open with Rider
  • From the menu Build -> Rebuild Solution
  • Run tests in Appium.Net.Integration.Tests

Visual studio

Nuget Deployment (for maintainers)

To Setup Nuget

  • Download Nuget exe.
  • Setup the Api Key (see here).
  • alias NuGet='mono <Nuget Path>/NuGet.exe'

To Release a New Version

  • update assemblyInfo.cs,, and appium-dotnet-driver.nuspec with new new version number and release details, then check it in
  • pull new code
  • Rebuild All with Release target.
  • NuGet pack appium-dotnet-driver.nuspec
  • NuGet push Appium.WebDriver.<version>.nupkg

Download Details:
Author: appium
Source Code:
License: Apache-2.0 License

#selenium #csharp #dotnet #webdriver 

Extension to The Official Selenium Dotnet Webdriver
Anthony  Dach

Anthony Dach


PHP Webdriver: PHP Client for Selenium/WebDriver Protocol

PHP Webdriver – Selenium WebDriver Bindings for PHP


Php-webdriver library is PHP language binding for Selenium WebDriver, which allows you to control web browsers from PHP.

This library is compatible with Selenium server version 2.x, 3.x and 4.x.

The library supports JsonWireProtocol and also implements experimental support of W3C WebDriver. The W3C WebDriver support is not yet full-featured, however it should allow to control Firefox via Geckodriver and new versions of Chrome and Chromedriver with just a slight limitations.

The concepts of this library are very similar to the "official" Java, .NET, Python and Ruby bindings from the Selenium project.


Installation is possible using Composer.

If you don't already use Composer, you can download the composer.phar binary:

curl -sS | php

Then install the library:

php composer.phar require php-webdriver/webdriver

Upgrade from version <1.8.0

Starting from version 1.8.0, the project has been renamed from facebook/php-webdriver to php-webdriver/webdriver.

In order to receive the new version and future updates, you need to rename it in your composer.json:

"require": {
-    "facebook/webdriver": "(version you use)",
+    "php-webdriver/webdriver": "(version you use)",

and run composer update.

Getting started

1. Start server (aka. remote end)

To control a browser, you need to start a remote end (server), which will listen to the commands sent from this library and will execute them in the respective browser.

This could be Selenium standalone server, but for local development, you can send them directly to so-called "browser driver" like Chromedriver or Geckodriver.

a) Chromedriver

📙 Below you will find a simple example. Make sure to read our wiki for more information on Chrome/Chromedriver.

Install the latest Chrome and Chromedriver. Make sure to have a compatible version of Chromedriver and Chrome!

Run chromedriver binary, you can pass port argument, so that it listens on port 4444:

chromedriver --port=4444

b) Geckodriver

📙 Below you will find a simple example. Make sure to read our wiki for more information on Firefox/Geckodriver.

Install the latest Firefox and Geckodriver. Make sure to have a compatible version of Geckodriver and Firefox!

Run geckodriver binary (it start to listen on port 4444 by default):


c) Selenium standalone server

Selenium server can be useful when you need to execute multiple tests at once, when you run tests in several different browsers (like on your CI server), or when you need to distribute tests amongst several machines in grid mode (where one Selenium server acts as a hub, and others connect to it as nodes).

Selenium server then act like a proxy and takes care of distributing commands to the respective nodes.

The latest version can be found on the Selenium download page.

📙 You can find further Selenium server information in our wiki.

d) Docker

Selenium server could also be started inside Docker container - see docker-selenium project.

2. Create a Browser Session

When creating a browser session, be sure to pass the url of your running server.

For example:

// Chromedriver (if started using --port=4444 as above)
$serverUrl = 'http://localhost:4444';
// Geckodriver
$serverUrl = 'http://localhost:4444';
// selenium-server-standalone-#.jar (version 2.x or 3.x)
$serverUrl = 'http://localhost:4444/wd/hub';
// selenium-server-standalone-#.jar (version 4.x)
$serverUrl = 'http://localhost:4444';

Now you can start browser of your choice:

use Facebook\WebDriver\Remote\RemoteWebDriver;

// Chrome
$driver = RemoteWebDriver::create($serverUrl, DesiredCapabilities::chrome());
// Firefox
$driver = RemoteWebDriver::create($serverUrl, DesiredCapabilities::firefox());
// Microsoft Edge
$driver = RemoteWebDriver::create($serverUrl, DesiredCapabilities::microsoftEdge());

3. Customize Desired Capabilities

Desired capabilities define properties of the browser you are about to start.

They can be customized:

use Facebook\WebDriver\Firefox\FirefoxOptions;
use Facebook\WebDriver\Remote\DesiredCapabilities;

$desiredCapabilities = DesiredCapabilities::firefox();

// Disable accepting SSL certificates
$desiredCapabilities->setCapability('acceptSslCerts', false);

// Add arguments via FirefoxOptions to start headless firefox
$firefoxOptions = new FirefoxOptions();
$desiredCapabilities->setCapability(FirefoxOptions::CAPABILITY, $firefoxOptions);

$driver = RemoteWebDriver::create($serverUrl, $desiredCapabilities);

Capabilities can also be used to 📙 configure a proxy server which the browser should use.

To configure browser-specific capabilities, you may use 📙 ChromeOptions or 📙 FirefoxOptions.

4. Control your browser

// Go to URL

// Find search element by its id, write 'PHP' inside and submit
$driver->findElement(WebDriverBy::id('searchInput')) // find search input element
    ->sendKeys('PHP') // fill the search box
    ->submit(); // submit the whole form

// Find element of 'History' item in menu by its css selector
$historyButton = $driver->findElement(
    WebDriverBy::cssSelector('#ca-history a')
// Read text of the element and print it to output
echo 'About to click to a button with text: ' . $historyButton->getText();

// Click the element to navigate to revision history page

// Make sure to always call quit() at the end to terminate the browser session

See example.php for full example scenario. Visit our GitHub wiki for 📙 php-webdriver command reference and further examples.

NOTE: Above snippets are not intended to be a working example by simply copy-pasting. See example.php for a working example.


For latest changes see file.

More information

Some basic usage example is provided in example.php file.

How-tos are provided right here in 📙 our GitHub wiki.

If you don't use IDE, you may use API documentation of php-webdriver.

You may also want to check out the Selenium project docs and wiki.

Testing framework integration

To take advantage of automatized testing you may want to integrate php-webdriver to your testing framework. There are some projects already providing this:


We have a great community willing to help you!

❓ Do you have a question, idea or some general feedback? Visit our Discussions page. (Alternatively, you can look for many answered questions also on StackOverflow).

🐛 Something isn't working, and you want to report a bug? Submit it here as a new issue.

📙 Looking for a how-to or reference documentation? See our wiki.

Contributing ❤️

We love to have your help to make php-webdriver better. See for more information about contributing and developing php-webdriver.

Php-webdriver is community project - if you want to join the effort with maintaining and developing this library, the best is to look on issues marked with "help wanted" label. Let us know in the issue comments if you want to contribute and if you want any guidance, and we will be delighted to help you to prepare your pull request.

Download Details:
Author: php-webdriver
Source Code:
License: MIT License

#selenium  #php #webdriver 

PHP Webdriver: PHP Client for Selenium/WebDriver Protocol
Anthony  Dach

Anthony Dach


Selenium-Standalone: A Node Based CLI Library for Launching Selenium

Node.js Selenium Standalone

A node based CLI library for launching Selenium with WebDriver support.

Install & Run

As Global NPM Package

npm install selenium-standalone -g
selenium-standalone install && selenium-standalone start

As a Local NPM Package

npm install selenium-standalone --save-dev
npx selenium-standalone install && npx selenium-standalone start

As a Docker Service

docker run -it -p 4444:4444 webdriverio/selenium-standalone

If you run Chrome or Firefox tests within a Docker container make sure you set capabilities so that the session is headless, e.g.:

capabilities: {
  browserName: 'chrome',
  'goog:chromeOptions': {
    args: ['--no-sandbox', '--headless']

or Firefox:

capabilities: {
  browserName: 'firefox',
  'moz:firefoxOptions': {
    args: ['-headless']

If you are looking for more sophisticated Docker container that allows you to run browser, check out the Docker Selenium project.

Supported Drivers:

Command line interface (CLI)

See CLI docs

Application Programming Interface (API)

See API docs

Available browsers

By default, Google Chrome, Firefox and Microsoft Edge are available when installed on the host system.

Starting from v6.22 chrome, edgechromium, and geckodriver support latest as version.


Examples of combining with other tools

:woman_technologist: :man_technologist: Contributing

You like this project and want to help making it better? Awesome! Have a look into our Contributor Documentation to get started with setting up the repo.

If you're looking for issues to help out with, check out the issues labelled "good first pick". You can also reach out in our Gitter Channel if you have question on where to start contributing.

Download Details:
Source Code: 

#selenium  #javascript #nodejs #node #webdriver 

Selenium-Standalone: A Node Based CLI Library for Launching Selenium
Joshua Yates

Joshua Yates


Selenium TestNG Tutorial for Beginners

Selenium TestNG Tutorial For Beginners | Selenium Tutorial For Beginners

This Edureka video on Selenium Testing will tell you the need for testing, and why Selenium is the best testing tool in the market.

The following have been covered in this video:
1. Need For Testing
2. Testing Types & Software Application Types
3. Selenium as an automation testing tool
4. Selenium Basics

00:00 Introduction
00:25 Agenda
01:07 Need of Automation
07:03 Selenium

#selenium #testing #webdriver #testng

Selenium TestNG Tutorial for Beginners

Selenium Python using SeleniumBase Framework - Full Course

In this 3 hours full course for Selenium Python using SeleniumBase Framework, we will be covering everything from setting up your project from scratch to all the way to integrating it with CI/CD.

4:30 - Setup & Installation
12:24 - Write your first test
41:15 - Find multiple elements
57:04 - Working with input fields
1:06:27 - How to upload a file?
1:25:57 - Optimize Tests
1:36:31 - Page Object Model
1:47:19 - Handling wait commands
2:07:18 - Exception Handling
2:20:34 - Generate Screenshots
2:31:21 - Generate Test Reports
2:37:44 - Cross Browser & Parallel Testing
2:43:35 - Jenkins & GitHub Integration
2:56:04 - It's a wrap!

Thanks for watching :)

#selenium  #webdriver  #python 

Selenium Python using SeleniumBase Framework - Full Course
Aurelio  Yost

Aurelio Yost


Do Mocha Tests Run in Parallel? Part V

This video explains how to run the parallel test with mocha. 
It is Part V of the JavaScript Test Automation LambdaTest Tutorial series. In this video, Ryan Howard (@ryantestsstuff), an engineer, explains parallel testing with mocha. You will also learn how you can run mocha end-to-end tests in parallel.

This video also answers 🚩 

◼ Does mocha run tests in parallel?
◼ How to run the mocha test?
◼ Does Mocha run tests in order?
◼ How to conduct parallel testing?

Vɪᴅᴇᴏ Cʜᴀᴘᴛᴇʀꜱ 🔰

➤ 00:00 Introduction -JavaScript Testing Tutorial for beginners
➤ 01:07 What is parallelization?
➤ 04:28 How to add test cases?
➤ 08:08 How to run your tests in parallel?

Learn more -:

#selenium  #mocha  #javascript  #automation  #webdriver  #testing 

Do Mocha Tests Run in Parallel? Part V