Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / vendor / behat / mink-selenium2-driver / src / Selenium2Driver.php
diff --git a/vendor/behat/mink-selenium2-driver/src/Selenium2Driver.php b/vendor/behat/mink-selenium2-driver/src/Selenium2Driver.php
deleted file mode 100755 (executable)
index b0d7ca7..0000000
+++ /dev/null
@@ -1,1097 +0,0 @@
-<?php
-
-/*
- * This file is part of the Behat\Mink.
- * (c) Konstantin Kudryashov <ever.zet@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Behat\Mink\Driver;
-
-use Behat\Mink\Exception\DriverException;
-use Behat\Mink\Selector\Xpath\Escaper;
-use WebDriver\Element;
-use WebDriver\Exception\NoSuchElement;
-use WebDriver\Exception\UnknownError;
-use WebDriver\Exception;
-use WebDriver\Key;
-use WebDriver\WebDriver;
-
-/**
- * Selenium2 driver.
- *
- * @author Pete Otaqui <pete@otaqui.com>
- */
-class Selenium2Driver extends CoreDriver
-{
-    /**
-     * Whether the browser has been started
-     * @var Boolean
-     */
-    private $started = false;
-
-    /**
-     * The WebDriver instance
-     * @var WebDriver
-     */
-    private $webDriver;
-
-    /**
-     * @var string
-     */
-    private $browserName;
-
-    /**
-     * @var array
-     */
-    private $desiredCapabilities;
-
-    /**
-     * The WebDriverSession instance
-     * @var \WebDriver\Session
-     */
-    private $wdSession;
-
-    /**
-     * The timeout configuration
-     * @var array
-     */
-    private $timeouts = array();
-
-    /**
-     * @var Escaper
-     */
-    private $xpathEscaper;
-
-    /**
-     * Instantiates the driver.
-     *
-     * @param string $browserName         Browser name
-     * @param array  $desiredCapabilities The desired capabilities
-     * @param string $wdHost              The WebDriver host
-     */
-    public function __construct($browserName = 'firefox', $desiredCapabilities = null, $wdHost = 'http://localhost:4444/wd/hub')
-    {
-        $this->setBrowserName($browserName);
-        $this->setDesiredCapabilities($desiredCapabilities);
-        $this->setWebDriver(new WebDriver($wdHost));
-        $this->xpathEscaper = new Escaper();
-    }
-
-    /**
-     * Sets the browser name
-     *
-     * @param string $browserName the name of the browser to start, default is 'firefox'
-     */
-    protected function setBrowserName($browserName = 'firefox')
-    {
-        $this->browserName = $browserName;
-    }
-
-    /**
-     * Sets the desired capabilities - called on construction.  If null is provided, will set the
-     * defaults as desired.
-     *
-     * See http://code.google.com/p/selenium/wiki/DesiredCapabilities
-     *
-     * @param array $desiredCapabilities an array of capabilities to pass on to the WebDriver server
-     */
-    public function setDesiredCapabilities($desiredCapabilities = null)
-    {
-        if (null === $desiredCapabilities) {
-            $desiredCapabilities = self::getDefaultCapabilities();
-        }
-
-        if (isset($desiredCapabilities['firefox'])) {
-            foreach ($desiredCapabilities['firefox'] as $capability => $value) {
-                switch ($capability) {
-                    case 'profile':
-                        $desiredCapabilities['firefox_'.$capability] = base64_encode(file_get_contents($value));
-                        break;
-                    default:
-                        $desiredCapabilities['firefox_'.$capability] = $value;
-                }
-            }
-
-            unset($desiredCapabilities['firefox']);
-        }
-
-        // See https://sites.google.com/a/chromium.org/chromedriver/capabilities
-        if (isset($desiredCapabilities['chrome'])) {
-
-            $chromeOptions = array();
-
-            foreach ($desiredCapabilities['chrome'] as $capability => $value) {
-                if ($capability == 'switches') {
-                    $chromeOptions['args'] = $value;
-                } else {
-                    $chromeOptions[$capability] = $value;
-                }
-                $desiredCapabilities['chrome.'.$capability] = $value;
-            }
-
-            $desiredCapabilities['chromeOptions'] = $chromeOptions;
-
-            unset($desiredCapabilities['chrome']);
-        }
-
-        $this->desiredCapabilities = $desiredCapabilities;
-    }
-
-    /**
-     * Sets the WebDriver instance
-     *
-     * @param WebDriver $webDriver An instance of the WebDriver class
-     */
-    public function setWebDriver(WebDriver $webDriver)
-    {
-        $this->webDriver = $webDriver;
-    }
-
-    /**
-     * Gets the WebDriverSession instance
-     *
-     * @return \WebDriver\Session
-     */
-    public function getWebDriverSession()
-    {
-        return $this->wdSession;
-    }
-
-    /**
-     * Returns the default capabilities
-     *
-     * @return array
-     */
-    public static function getDefaultCapabilities()
-    {
-        return array(
-            'browserName'       => 'firefox',
-            'version'           => '9',
-            'platform'          => 'ANY',
-            'browserVersion'    => '9',
-            'browser'           => 'firefox',
-            'name'              => 'Behat Test',
-            'deviceOrientation' => 'portrait',
-            'deviceType'        => 'tablet',
-            'selenium-version'  => '2.31.0'
-        );
-    }
-
-    /**
-     * Makes sure that the Syn event library has been injected into the current page,
-     * and return $this for a fluid interface,
-     *
-     *     $this->withSyn()->executeJsOnXpath($xpath, $script);
-     *
-     * @return Selenium2Driver
-     */
-    protected function withSyn()
-    {
-        $hasSyn = $this->wdSession->execute(array(
-            'script' => 'return typeof window["Syn"]!=="undefined" && typeof window["Syn"].trigger!=="undefined"',
-            'args'   => array()
-        ));
-
-        if (!$hasSyn) {
-            $synJs = file_get_contents(__DIR__.'/Resources/syn.js');
-            $this->wdSession->execute(array(
-                'script' => $synJs,
-                'args'   => array()
-            ));
-        }
-
-        return $this;
-    }
-
-    /**
-     * Creates some options for key events
-     *
-     * @param string $char     the character or code
-     * @param string $modifier one of 'shift', 'alt', 'ctrl' or 'meta'
-     *
-     * @return string a json encoded options array for Syn
-     */
-    protected static function charToOptions($char, $modifier = null)
-    {
-        $ord = ord($char);
-        if (is_numeric($char)) {
-            $ord = $char;
-        }
-
-        $options = array(
-            'keyCode'  => $ord,
-            'charCode' => $ord
-        );
-
-        if ($modifier) {
-            $options[$modifier.'Key'] = 1;
-        }
-
-        return json_encode($options);
-    }
-
-    /**
-     * Executes JS on a given element - pass in a js script string and {{ELEMENT}} will
-     * be replaced with a reference to the result of the $xpath query
-     *
-     * @example $this->executeJsOnXpath($xpath, 'return {{ELEMENT}}.childNodes.length');
-     *
-     * @param string  $xpath  the xpath to search with
-     * @param string  $script the script to execute
-     * @param Boolean $sync   whether to run the script synchronously (default is TRUE)
-     *
-     * @return mixed
-     */
-    protected function executeJsOnXpath($xpath, $script, $sync = true)
-    {
-        return $this->executeJsOnElement($this->findElement($xpath), $script, $sync);
-    }
-
-    /**
-     * Executes JS on a given element - pass in a js script string and {{ELEMENT}} will
-     * be replaced with a reference to the element
-     *
-     * @example $this->executeJsOnXpath($xpath, 'return {{ELEMENT}}.childNodes.length');
-     *
-     * @param Element $element the webdriver element
-     * @param string  $script  the script to execute
-     * @param Boolean $sync    whether to run the script synchronously (default is TRUE)
-     *
-     * @return mixed
-     */
-    private function executeJsOnElement(Element $element, $script, $sync = true)
-    {
-        $script  = str_replace('{{ELEMENT}}', 'arguments[0]', $script);
-
-        $options = array(
-            'script' => $script,
-            'args'   => array(array('ELEMENT' => $element->getID())),
-        );
-
-        if ($sync) {
-            return $this->wdSession->execute($options);
-        }
-
-        return $this->wdSession->execute_async($options);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function start()
-    {
-        try {
-            $this->wdSession = $this->webDriver->session($this->browserName, $this->desiredCapabilities);
-            $this->applyTimeouts();
-        } catch (\Exception $e) {
-            throw new DriverException('Could not open connection: '.$e->getMessage(), 0, $e);
-        }
-
-        if (!$this->wdSession) {
-            throw new DriverException('Could not connect to a Selenium 2 / WebDriver server');
-        }
-        $this->started = true;
-    }
-
-    /**
-     * Sets the timeouts to apply to the webdriver session
-     *
-     * @param array $timeouts The session timeout settings: Array of {script, implicit, page} => time in milliseconds
-     *
-     * @throws DriverException
-     */
-    public function setTimeouts($timeouts)
-    {
-        $this->timeouts = $timeouts;
-
-        if ($this->isStarted()) {
-            $this->applyTimeouts();
-        }
-    }
-
-    /**
-     * Applies timeouts to the current session
-     */
-    private function applyTimeouts()
-    {
-        try {
-            foreach ($this->timeouts as $type => $param) {
-                $this->wdSession->timeouts($type, $param);
-            }
-        } catch (UnknownError $e) {
-            throw new DriverException('Error setting timeout: ' . $e->getMessage(), 0, $e);
-        }
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function isStarted()
-    {
-        return $this->started;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function stop()
-    {
-        if (!$this->wdSession) {
-            throw new DriverException('Could not connect to a Selenium 2 / WebDriver server');
-        }
-
-        $this->started = false;
-        try {
-            $this->wdSession->close();
-        } catch (\Exception $e) {
-            throw new DriverException('Could not close connection', 0, $e);
-        }
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function reset()
-    {
-        $this->wdSession->deleteAllCookies();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function visit($url)
-    {
-        $this->wdSession->open($url);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getCurrentUrl()
-    {
-        return $this->wdSession->url();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function reload()
-    {
-        $this->wdSession->refresh();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function forward()
-    {
-        $this->wdSession->forward();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function back()
-    {
-        $this->wdSession->back();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function switchToWindow($name = null)
-    {
-        $this->wdSession->focusWindow($name ? $name : '');
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function switchToIFrame($name = null)
-    {
-        $this->wdSession->frame(array('id' => $name));
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setCookie($name, $value = null)
-    {
-        if (null === $value) {
-            $this->wdSession->deleteCookie($name);
-
-            return;
-        }
-
-        $cookieArray = array(
-            'name'   => $name,
-            'value'  => urlencode($value),
-            'secure' => false, // thanks, chibimagic!
-        );
-
-        $this->wdSession->setCookie($cookieArray);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getCookie($name)
-    {
-        $cookies = $this->wdSession->getAllCookies();
-        foreach ($cookies as $cookie) {
-            if ($cookie['name'] === $name) {
-                return urldecode($cookie['value']);
-            }
-        }
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getContent()
-    {
-        return $this->wdSession->source();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getScreenshot()
-    {
-        return base64_decode($this->wdSession->screenshot());
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getWindowNames()
-    {
-        return $this->wdSession->window_handles();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getWindowName()
-    {
-        return $this->wdSession->window_handle();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function findElementXpaths($xpath)
-    {
-        $nodes = $this->wdSession->elements('xpath', $xpath);
-
-        $elements = array();
-        foreach ($nodes as $i => $node) {
-            $elements[] = sprintf('(%s)[%d]', $xpath, $i+1);
-        }
-
-        return $elements;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getTagName($xpath)
-    {
-        return $this->findElement($xpath)->name();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getText($xpath)
-    {
-        $node = $this->findElement($xpath);
-        $text = $node->text();
-        $text = (string) str_replace(array("\r", "\r\n", "\n"), ' ', $text);
-
-        return $text;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getHtml($xpath)
-    {
-        return $this->executeJsOnXpath($xpath, 'return {{ELEMENT}}.innerHTML;');
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getOuterHtml($xpath)
-    {
-        return $this->executeJsOnXpath($xpath, 'return {{ELEMENT}}.outerHTML;');
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getAttribute($xpath, $name)
-    {
-        $script = 'return {{ELEMENT}}.getAttribute(' . json_encode((string) $name) . ')';
-
-        return $this->executeJsOnXpath($xpath, $script);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getValue($xpath)
-    {
-        $element = $this->findElement($xpath);
-        $elementName = strtolower($element->name());
-        $elementType = strtolower($element->attribute('type'));
-
-        // Getting the value of a checkbox returns its value if selected.
-        if ('input' === $elementName && 'checkbox' === $elementType) {
-            return $element->selected() ? $element->attribute('value') : null;
-        }
-
-        if ('input' === $elementName && 'radio' === $elementType) {
-            $script = <<<JS
-var node = {{ELEMENT}},
-    value = null;
-
-var name = node.getAttribute('name');
-if (name) {
-    var fields = window.document.getElementsByName(name),
-        i, l = fields.length;
-    for (i = 0; i < l; i++) {
-        var field = fields.item(i);
-        if (field.form === node.form && field.checked) {
-            value = field.value;
-            break;
-        }
-    }
-}
-
-return value;
-JS;
-
-            return $this->executeJsOnElement($element, $script);
-        }
-
-        // Using $element->attribute('value') on a select only returns the first selected option
-        // even when it is a multiple select, so a custom retrieval is needed.
-        if ('select' === $elementName && $element->attribute('multiple')) {
-            $script = <<<JS
-var node = {{ELEMENT}},
-    value = [];
-
-for (var i = 0; i < node.options.length; i++) {
-    if (node.options[i].selected) {
-        value.push(node.options[i].value);
-    }
-}
-
-return value;
-JS;
-
-            return $this->executeJsOnElement($element, $script);
-        }
-
-        return $element->attribute('value');
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setValue($xpath, $value)
-    {
-        $element = $this->findElement($xpath);
-        $elementName = strtolower($element->name());
-
-        if ('select' === $elementName) {
-            if (is_array($value)) {
-                $this->deselectAllOptions($element);
-
-                foreach ($value as $option) {
-                    $this->selectOptionOnElement($element, $option, true);
-                }
-
-                return;
-            }
-
-            $this->selectOptionOnElement($element, $value);
-
-            return;
-        }
-
-        if ('input' === $elementName) {
-            $elementType = strtolower($element->attribute('type'));
-
-            if (in_array($elementType, array('submit', 'image', 'button', 'reset'))) {
-                throw new DriverException(sprintf('Impossible to set value an element with XPath "%s" as it is not a select, textarea or textbox', $xpath));
-            }
-
-            if ('checkbox' === $elementType) {
-                if ($element->selected() xor (bool) $value) {
-                    $this->clickOnElement($element);
-                }
-
-                return;
-            }
-
-            if ('radio' === $elementType) {
-                $this->selectRadioValue($element, $value);
-
-                return;
-            }
-
-            if ('file' === $elementType) {
-                $element->postValue(array('value' => array(strval($value))));
-
-                return;
-            }
-        }
-
-        $value = strval($value);
-
-        if (in_array($elementName, array('input', 'textarea'))) {
-            $existingValueLength = strlen($element->attribute('value'));
-            // Add the TAB key to ensure we unfocus the field as browsers are triggering the change event only
-            // after leaving the field.
-            $value = str_repeat(Key::BACKSPACE . Key::DELETE, $existingValueLength) . $value . Key::TAB;
-        }
-
-        $element->postValue(array('value' => array($value)));
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function check($xpath)
-    {
-        $element = $this->findElement($xpath);
-        $this->ensureInputType($element, $xpath, 'checkbox', 'check');
-
-        if ($element->selected()) {
-            return;
-        }
-
-        $this->clickOnElement($element);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function uncheck($xpath)
-    {
-        $element = $this->findElement($xpath);
-        $this->ensureInputType($element, $xpath, 'checkbox', 'uncheck');
-
-        if (!$element->selected()) {
-            return;
-        }
-
-        $this->clickOnElement($element);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function isChecked($xpath)
-    {
-        return $this->findElement($xpath)->selected();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function selectOption($xpath, $value, $multiple = false)
-    {
-        $element = $this->findElement($xpath);
-        $tagName = strtolower($element->name());
-
-        if ('input' === $tagName && 'radio' === strtolower($element->attribute('type'))) {
-            $this->selectRadioValue($element, $value);
-
-            return;
-        }
-
-        if ('select' === $tagName) {
-            $this->selectOptionOnElement($element, $value, $multiple);
-
-            return;
-        }
-
-        throw new DriverException(sprintf('Impossible to select an option on the element with XPath "%s" as it is not a select or radio input', $xpath));
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function isSelected($xpath)
-    {
-        return $this->findElement($xpath)->selected();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function click($xpath)
-    {
-        $this->clickOnElement($this->findElement($xpath));
-    }
-
-    private function clickOnElement(Element $element)
-    {
-        $this->wdSession->moveto(array('element' => $element->getID()));
-        $element->click();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function doubleClick($xpath)
-    {
-        $this->mouseOver($xpath);
-        $this->wdSession->doubleclick();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function rightClick($xpath)
-    {
-        $this->mouseOver($xpath);
-        $this->wdSession->click(array('button' => 2));
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function attachFile($xpath, $path)
-    {
-        $element = $this->findElement($xpath);
-        $this->ensureInputType($element, $xpath, 'file', 'attach a file on');
-
-        $element->postValue(array('value' => array($path)));
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function isVisible($xpath)
-    {
-        return $this->findElement($xpath)->displayed();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function mouseOver($xpath)
-    {
-        $this->wdSession->moveto(array(
-            'element' => $this->findElement($xpath)->getID()
-        ));
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function focus($xpath)
-    {
-        $script = 'Syn.trigger("focus", {}, {{ELEMENT}})';
-        $this->withSyn()->executeJsOnXpath($xpath, $script);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function blur($xpath)
-    {
-        $script = 'Syn.trigger("blur", {}, {{ELEMENT}})';
-        $this->withSyn()->executeJsOnXpath($xpath, $script);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function keyPress($xpath, $char, $modifier = null)
-    {
-        $options = self::charToOptions($char, $modifier);
-        $script = "Syn.trigger('keypress', $options, {{ELEMENT}})";
-        $this->withSyn()->executeJsOnXpath($xpath, $script);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function keyDown($xpath, $char, $modifier = null)
-    {
-        $options = self::charToOptions($char, $modifier);
-        $script = "Syn.trigger('keydown', $options, {{ELEMENT}})";
-        $this->withSyn()->executeJsOnXpath($xpath, $script);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function keyUp($xpath, $char, $modifier = null)
-    {
-        $options = self::charToOptions($char, $modifier);
-        $script = "Syn.trigger('keyup', $options, {{ELEMENT}})";
-        $this->withSyn()->executeJsOnXpath($xpath, $script);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function dragTo($sourceXpath, $destinationXpath)
-    {
-        $source      = $this->findElement($sourceXpath);
-        $destination = $this->findElement($destinationXpath);
-
-        $this->wdSession->moveto(array(
-            'element' => $source->getID()
-        ));
-
-        $script = <<<JS
-(function (element) {
-    var event = document.createEvent("HTMLEvents");
-
-    event.initEvent("dragstart", true, true);
-    event.dataTransfer = {};
-
-    element.dispatchEvent(event);
-}({{ELEMENT}}));
-JS;
-        $this->withSyn()->executeJsOnElement($source, $script);
-
-        $this->wdSession->buttondown();
-        $this->wdSession->moveto(array(
-            'element' => $destination->getID()
-        ));
-        $this->wdSession->buttonup();
-
-        $script = <<<JS
-(function (element) {
-    var event = document.createEvent("HTMLEvents");
-
-    event.initEvent("drop", true, true);
-    event.dataTransfer = {};
-
-    element.dispatchEvent(event);
-}({{ELEMENT}}));
-JS;
-        $this->withSyn()->executeJsOnElement($destination, $script);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function executeScript($script)
-    {
-        if (preg_match('/^function[\s\(]/', $script)) {
-            $script = preg_replace('/;$/', '', $script);
-            $script = '(' . $script . ')';
-        }
-
-        $this->wdSession->execute(array('script' => $script, 'args' => array()));
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function evaluateScript($script)
-    {
-        if (0 !== strpos(trim($script), 'return ')) {
-            $script = 'return ' . $script;
-        }
-
-        return $this->wdSession->execute(array('script' => $script, 'args' => array()));
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function wait($timeout, $condition)
-    {
-        $script = "return $condition;";
-        $start = microtime(true);
-        $end = $start + $timeout / 1000.0;
-
-        do {
-            $result = $this->wdSession->execute(array('script' => $script, 'args' => array()));
-            usleep(100000);
-        } while (microtime(true) < $end && !$result);
-
-        return (bool) $result;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function resizeWindow($width, $height, $name = null)
-    {
-        $this->wdSession->window($name ? $name : 'current')->postSize(
-            array('width' => $width, 'height' => $height)
-        );
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function submitForm($xpath)
-    {
-        $this->findElement($xpath)->submit();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function maximizeWindow($name = null)
-    {
-        $this->wdSession->window($name ? $name : 'current')->maximize();
-    }
-
-    /**
-     * Returns Session ID of WebDriver or `null`, when session not started yet.
-     *
-     * @return string|null
-     */
-    public function getWebDriverSessionId()
-    {
-        return $this->isStarted() ? basename($this->wdSession->getUrl()) : null;
-    }
-
-    /**
-     * @param string $xpath
-     *
-     * @return Element
-     */
-    private function findElement($xpath)
-    {
-        return $this->wdSession->element('xpath', $xpath);
-    }
-
-    /**
-     * Selects a value in a radio button group
-     *
-     * @param Element $element An element referencing one of the radio buttons of the group
-     * @param string  $value   The value to select
-     *
-     * @throws DriverException when the value cannot be found
-     */
-    private function selectRadioValue(Element $element, $value)
-    {
-        // short-circuit when we already have the right button of the group to avoid XPath queries
-        if ($element->attribute('value') === $value) {
-            $element->click();
-
-            return;
-        }
-
-        $name = $element->attribute('name');
-
-        if (!$name) {
-            throw new DriverException(sprintf('The radio button does not have the value "%s"', $value));
-        }
-
-        $formId = $element->attribute('form');
-
-        try {
-            if (null !== $formId) {
-                $xpath = <<<'XPATH'
-//form[@id=%1$s]//input[@type="radio" and not(@form) and @name=%2$s and @value = %3$s]
-|
-//input[@type="radio" and @form=%1$s and @name=%2$s and @value = %3$s]
-XPATH;
-
-                $xpath = sprintf(
-                    $xpath,
-                    $this->xpathEscaper->escapeLiteral($formId),
-                    $this->xpathEscaper->escapeLiteral($name),
-                    $this->xpathEscaper->escapeLiteral($value)
-                );
-                $input = $this->wdSession->element('xpath', $xpath);
-            } else {
-                $xpath = sprintf(
-                    './ancestor::form//input[@type="radio" and not(@form) and @name=%s and @value = %s]',
-                    $this->xpathEscaper->escapeLiteral($name),
-                    $this->xpathEscaper->escapeLiteral($value)
-                );
-                $input = $element->element('xpath', $xpath);
-            }
-        } catch (NoSuchElement $e) {
-            $message = sprintf('The radio group "%s" does not have an option "%s"', $name, $value);
-
-            throw new DriverException($message, 0, $e);
-        }
-
-        $input->click();
-    }
-
-    /**
-     * @param Element $element
-     * @param string  $value
-     * @param bool    $multiple
-     */
-    private function selectOptionOnElement(Element $element, $value, $multiple = false)
-    {
-        $escapedValue = $this->xpathEscaper->escapeLiteral($value);
-        // The value of an option is the normalized version of its text when it has no value attribute
-        $optionQuery = sprintf('.//option[@value = %s or (not(@value) and normalize-space(.) = %s)]', $escapedValue, $escapedValue);
-        $option = $element->element('xpath', $optionQuery);
-
-        if ($multiple || !$element->attribute('multiple')) {
-            if (!$option->selected()) {
-                $option->click();
-            }
-
-            return;
-        }
-
-        // Deselect all options before selecting the new one
-        $this->deselectAllOptions($element);
-        $option->click();
-    }
-
-    /**
-     * Deselects all options of a multiple select
-     *
-     * Note: this implementation does not trigger a change event after deselecting the elements.
-     *
-     * @param Element $element
-     */
-    private function deselectAllOptions(Element $element)
-    {
-        $script = <<<JS
-var node = {{ELEMENT}};
-var i, l = node.options.length;
-for (i = 0; i < l; i++) {
-    node.options[i].selected = false;
-}
-JS;
-
-        $this->executeJsOnElement($element, $script);
-    }
-
-    /**
-     * Ensures the element is a checkbox
-     *
-     * @param Element $element
-     * @param string  $xpath
-     * @param string  $type
-     * @param string  $action
-     *
-     * @throws DriverException
-     */
-    private function ensureInputType(Element $element, $xpath, $type, $action)
-    {
-        if ('input' !== strtolower($element->name()) || $type !== strtolower($element->attribute('type'))) {
-            $message = 'Impossible to %s the element with XPath "%s" as it is not a %s input';
-
-            throw new DriverException(sprintf($message, $action, $xpath, $type));
-        }
-    }
-}