diff --git a/.travis.yml b/.travis.yml
index 84d53110a686..fb0e3a767c75 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,6 +14,8 @@ env:
global:
- TEST_DAV=$(tests/travis/changed_app.sh dav)
- TC=litmus-v2
+ - SRV_HOST_NAME=owncloud
+ - SRV_HOST_PORT=8888
matrix:
- DB=sqlite
@@ -21,20 +23,30 @@ branches:
only:
- master
- /^stable\d+(\.\d+)?$/
+ - /^.*selenium.*$/
addons:
apt:
packages:
- realpath
+ hosts:
+ - owncloud
+ sauce_connect:
+ username: "individual-it"
+ jwt:
+ secure: "WaPqAVjcC6B4T5NWA1nffrywsnR9UZ5u3c2DrNLDR12cXJti0SbxGcE2Er8EGS1iCMxqMnpZfchbCelYmew5FOyeErqMTtni3lZ1gAu4KM35V5gUaRau8uEvTZk7AVHfDRSYlB/TJJV8sl8I33i3UvzUgsz4Il41X8qribycQOWoUCsiABIy/Fm05MhWugKjzBJ3Au/ZnNkYEjLW5z1cPymiuvNsUGvm9ushu2WwEc31hsS9lvpOcNVgdPJy2OaxNIZip8yH0c9gteo6rE7oElc81773K4QFf/0H0pD7Q4lUhqdHTn/aNyqWu8QaiS2BtygFKR15vxqbkloPQovM7S/Xr+PV7wQxItLE/E0QD8FkvIjoIVC4L448Mw+zBntpdGtmV4/UJJLl+VRFlLf5l2Do5fum1SeLI0kYaaN9rTXsFp/rmC7vT6dk3CiAm9owD69uWTVUecTqx2gRgNRdEXvL7t/6AZ8kspmWYdL9ekBSQ83rXlo7p8ZZm/Iu4k10JPCKxGfxVHFLVlPB6Z43+yBAtNjLkPdDP3+2FxU4LvvDKKXn2eESwkG2Mq5dEm4HAethygPJ48QmTYGPgg4b6PlcxWHoiC7qGZYWYj0Pmxt3kE6iZ4wxHG4cCU5p0/2MyGXzynjLz1qC6CZtXZbuyXDfrjvwcPXvvuANg0IX3hw="
before_install:
- make
- - sh -c "if [ '$TEST_DAV' = '1' ]; then bash tests/travis/before_install.sh $DB; fi"
+ - if [ ! -z "$SAUCE_USERNAME" ] && [ ! -z "$SAUCE_ACCESS_KEY" ]; then export TEST_SELENIUM=1 ; else export TEST_SELENIUM=0 ; fi
+ - sh -c "if [ '$TEST_DAV' = '1' ] || [ '$TEST_SELENIUM' = '1' ]; then bash tests/travis/before_install.sh $DB; fi"
install:
- - sh -c "if [ '$TEST_DAV' = '1' ]; then bash tests/travis/install.sh $DB; fi"
+ - sh -c "if [ '$TEST_DAV' = '1' ] || [ '$TEST_SELENIUM' = '1' ]; then bash tests/travis/install.sh $DB; fi"
- sh -c "if [ '$TEST_DAV' = '1' ]; then bash apps/dav/tests/travis/$TC/install.sh; fi"
+before_script:
+ - sh -c "if [ '$TEST_SELENIUM' = '1' ]; then bash tests/travis/start_php_dev_server.sh; fi"
script:
- sh -c "if [ '$TC' = 'syntax' ]; then make test-php-lint ; fi"
@@ -42,6 +54,7 @@ script:
- sh -c "if [ '$TEST_DAV' = '1' ]; then echo \"Testing DAV\"; fi"
- sh -c "if [ '$TEST_DAV' = '1' ]; then bash apps/dav/tests/travis/$TC/script.sh; fi"
+ - sh -c "if [ '$TEST_SELENIUM' = '1' ]; then phpunit -c tests/phpunit-selenium-autotest.xml; fi"
matrix:
include:
diff --git a/tests/Core/Frontend/LoginTest.php b/tests/Core/Frontend/LoginTest.php
new file mode 100644
index 000000000000..d0f68cd31ec4
--- /dev/null
+++ b/tests/Core/Frontend/LoginTest.php
@@ -0,0 +1,44 @@
+.
+*
+*/
+
+use Test\SeleniumTestCase;
+
+class LoginTest extends SeleniumTestCase {
+
+ public function testNormalLogin() {
+
+ $this->webDriver->get($this->rootURL);
+ $login = $this->webDriver->findElement ( WebDriverBy::id("user"));
+ $login->click();
+ $login->sendKeys("admin");
+
+ $login = $this->webDriver->findElement ( WebDriverBy::id("password"));
+ $login->click();
+ $login->sendKeys("admin");
+
+ $login = $this->webDriver->findElement ( WebDriverBy::id("submit"));
+ $login->click();
+ sleep(5);
+ $fileElement = $this->webDriver->findElement(WebDriverBy::xpath("//span[@class='innernametext']"));
+ $this->assertEquals($fileElement->getText(), "welcome");
+ }
+}
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 2746405a387e..d6c750db9dad 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -7,6 +7,7 @@
}
require_once __DIR__ . '/../lib/base.php';
+require_once __DIR__ . '/vendor/facebook/webdriver/lib/__init__.php';
// especially with code coverage it will require some more time
set_time_limit(0);
diff --git a/tests/lib/SeleniumTestCase.php b/tests/lib/SeleniumTestCase.php
new file mode 100644
index 000000000000..8d1faa728af5
--- /dev/null
+++ b/tests/lib/SeleniumTestCase.php
@@ -0,0 +1,98 @@
+.
+*
+*/
+
+namespace Test;
+
+use Test\TestCase;
+
+abstract class SeleniumTestCase extends TestCase {
+ protected $webDriver;
+ protected $rootURL;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $sauceUserName = getenv("SAUCE_USERNAME");
+ $sauceAccessKey = getenv("SAUCE_ACCESS_KEY");
+ $capabilities = array (
+ \WebDriverCapabilityType::BROWSER_NAME => 'chrome',
+ 'tunnel-identifier' => getenv('TRAVIS_JOB_NUMBER')
+ );
+ $this->rootURL="http://". getenv('SRV_HOST_NAME') .":" . getenv('SRV_HOST_PORT'). "/" . getenv('SRV_HOST_URL');
+
+ if ($sauceAccessKey != "") {
+ $this->webDriver = \RemoteWebDriver::create ( 'http://'.$sauceUserName.':'.$sauceAccessKey.'@localhost:4445/wd/hub', $capabilities );
+ } else {
+ $this->webDriver = \RemoteWebDriver::create ( 'http://localhost:4444/wd/hub', $capabilities );
+ }
+
+ }
+
+ public static function setUpBeforeClass() {
+ $dataDir = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data-autotest');
+ if (!file_exists($dataDir . "/admin")) {
+ mkdir($dataDir . "/admin");
+ mkdir($dataDir . "/admin/files");
+ copy(\OC::$SERVERROOT . '/core/skeleton/welcome.txt', $dataDir. "/admin/files/welcome.txt");
+ }
+ }
+
+ protected function tearDown() {
+ parent::tearDown();
+ $this->webDriver->quit ();
+ }
+
+ /**
+ * waits till an element is displayed on page
+ * @param WebDriverElement $element to wait for
+ * @param INT $timeout max. time to wait
+ */
+ protected function waitTillElementIsDisplayed($element, $timeout = 30) {
+ for($counter = 0; $counter <= $timeout; $counter ++) {
+ try {
+ if ($element->isDisplayed () === false) {
+ break;
+ }
+ } catch ( Exception $e ) {
+ break;
+ }
+
+ sleep (1);
+ }
+ }
+
+ /**
+ * waits till an element is stale
+ * @param WebDriverElement $element to wait for
+ * @param INT $timeout max. time to wait
+ */
+ protected function waitTillElementIsStale($element, $timeout = 30) {
+ for ($i=0; $i<=$timeout; $i++) {
+ try {
+ $element->findElements(\WebDriverBy::id("does-not-matter"));
+ } catch (StaleElementReferenceException $e) {
+ return true;
+ }
+ sleep(1);
+ }
+ }
+}
diff --git a/tests/phpunit-selenium-autotest.xml b/tests/phpunit-selenium-autotest.xml
new file mode 100644
index 000000000000..a25f5a5513ff
--- /dev/null
+++ b/tests/phpunit-selenium-autotest.xml
@@ -0,0 +1,21 @@
+
+
+
+ Core/Frontend
+
+
+
+
+
+ ..
+
+
+
+
+
+
diff --git a/tests/travis/install.sh b/tests/travis/install.sh
index fe7907f798ca..b91f77147001 100755
--- a/tests/travis/install.sh
+++ b/tests/travis/install.sh
@@ -45,6 +45,11 @@ cat > ./tests/autoconfig-sqlite.php < false,
+ 'trusted_domains' =>
+ array (
+ 0 => 'localhost',
+ 1 => '$SRV_HOST_NAME',
+ ),
'dbtype' => 'sqlite',
'dbtableprefix' => 'oc_',
'adminlogin' => '$ADMINLOGIN',
@@ -57,6 +62,11 @@ cat > ./tests/autoconfig-mysql.php < false,
+ 'trusted_domains' =>
+ array (
+ 0 => 'localhost',
+ 1 => '$SRV_HOST_NAME',
+ ),
'dbtype' => 'mysql',
'dbtableprefix' => 'oc_',
'adminlogin' => '$ADMINLOGIN',
@@ -73,6 +83,11 @@ cat > ./tests/autoconfig-pgsql.php < false,
+ 'trusted_domains' =>
+ array (
+ 0 => 'localhost',
+ 1 => '$SRV_HOST_NAME',
+ ),
'dbtype' => 'pgsql',
'dbtableprefix' => 'oc_',
'adminlogin' => '$ADMINLOGIN',
@@ -89,6 +104,11 @@ cat > ./tests/autoconfig-oracle.php < false,
+ 'trusted_domains' =>
+ array (
+ 0 => 'localhost',
+ 1 => '$SRV_HOST_NAME',
+ ),
'dbtype' => 'oci',
'dbtableprefix' => 'oc_',
'adminlogin' => '$ADMINLOGIN',
diff --git a/tests/travis/start_php_dev_server.sh b/tests/travis/start_php_dev_server.sh
new file mode 100644
index 000000000000..c7e644c0f7c0
--- /dev/null
+++ b/tests/travis/start_php_dev_server.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+# ownCloud
+#
+# @author Artur Neumann
+# @copyright 2017 Artur Neumann info@individual-it.net
+#
+
+
+set -e
+
+php -S $SRV_HOST_NAME:$SRV_HOST_PORT > /dev/null 2>&1 &
diff --git a/tests/vendor/facebook/webdriver/README.md b/tests/vendor/facebook/webdriver/README.md
new file mode 100644
index 000000000000..d5272c4f4a49
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/README.md
@@ -0,0 +1,105 @@
+php-webdriver -- WebDriver bindings for PHP
+===========================================
+
+## DESCRIPTION
+
+This WebDriver client aims to be as close as possible to bindings in other languages. The concepts are very similar to the Java, .NET, Python and Ruby bindings for WebDriver.
+
+Looking for documentation about php-webdriver? See http://facebook.github.io/php-webdriver/
+
+The PHP client was rewritten from scratch. Using the old version? Check out Adam Goucher's fork of it at https://github.com/Element-34/php-webdriver
+
+Any complaint, question, idea? You can post it on the user group https://www.facebook.com/groups/phpwebdriver/.
+
+## GETTING THE CODE
+
+### Github
+ git clone git@github.com:facebook/php-webdriver.git
+
+### Packagist
+Add the dependency. https://packagist.org/packages/facebook/webdriver
+
+ {
+ "require": {
+ "facebook/webdriver": "dev-master"
+ }
+ }
+
+Download the composer.phar
+
+ curl -sS https://getcomposer.org/installer | php
+
+Install the library.
+
+ php composer.phar install
+
+
+
+## GETTING STARTED
+
+* All you need as the server for this client is the selenium-server-standalone-#.jar file provided here: http://selenium-release.storage.googleapis.com/index.html
+
+* Download and run that file, replacing # with the current server version.
+
+ java -jar selenium-server-standalone-#.jar
+
+* Then when you create a session, be sure to pass the url to where your server is running.
+
+ // This would be the url of the host running the server-standalone.jar
+ $host = 'http://localhost:4444/wd/hub'; // this is the default
+
+* Launch Firefox
+
+ $driver = RemoteWebDriver::create($host, DesiredCapabilities::firefox());
+
+* Launch Chrome
+
+ $driver = RemoteWebDriver::create($host, DesiredCapabilities::chrome());
+
+* You can also customize the desired capabilities.
+
+ $desired_capabilities = DesiredCapabilities::firefox();
+ $desired_capabilities->setJavascriptEnabled(false);
+ RemoteWebDriver::create($host, $desired_capabilities);
+
+* See https://code.google.com/p/selenium/wiki/DesiredCapabilities for more details.
+
+## RUN UNIT TESTS
+
+To run unit tests simply run:
+
+ ./vendor/bin/phpunit -c ./tests
+
+Note: For the functional test suite, a running selenium server is required.
+
+## MORE INFORMATION
+
+Check out the Selenium docs and wiki at http://docs.seleniumhq.org/docs/ and https://code.google.com/p/selenium/wiki
+
+Learn how to integrate it with PHPUnit [Blogpost](http://codeception.com/11-12-2013/working-with-phpunit-and-selenium-webdriver.html) | [Demo Project](https://github.com/DavertMik/php-webdriver-demo)
+
+## SUPPORT
+
+We have a great community willing to try and help you!
+
+Currently we offer support in two manners:
+
+### Via our Facebook Group
+
+If you have questions or are an active contributor consider joining our facebook group and contributing to the communal discussion and support
+
+https://www.facebook.com/groups/phpwebdriver/
+
+### Via Github
+
+If you're reading this you've already found our Github repository. If you have a question, feel free to submit it as an issue and our staff will do their best to help you as soon as possible.
+
+## CONTRIBUTING
+
+We love to have your help to make php-webdriver better. Feel free to
+
+* open an [issue](https://github.com/facebook/php-webdriver/issues) if you run into any problem.
+* fork the project and submit [pull request](https://github.com/facebook/php-webdriver/pulls). Before the pull requests can be accepted, a [Contributors Licensing Agreement](http://developers.facebook.com/opensource/cla) must be signed.
+
+When you are going to contribute, please keep in mind that this webdriver client aims to be as close as possible to other languages Java/Ruby/Python/C#.
+FYI, here is the overview of [the official Java API](http://selenium.googlecode.com/svn/trunk/docs/api/java/index.html?overview-summary.html)
diff --git a/tests/vendor/facebook/webdriver/composer.json b/tests/vendor/facebook/webdriver/composer.json
new file mode 100644
index 000000000000..00faaa7bf5e6
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/composer.json
@@ -0,0 +1,23 @@
+{
+ "name": "facebook/webdriver",
+ "description": "A php client for WebDriver",
+ "keywords": ["webdriver", "selenium", "php", "facebook"],
+ "homepage": "https://github.com/facebook/php-webdriver",
+ "type": "library",
+ "license": "Apache-2.0",
+ "support": {
+ "issues": "https://github.com/facebook/php-webdriver/issues",
+ "forum": "https://www.facebook.com/groups/phpwebdriver/",
+ "source": "https://github.com/facebook/php-webdriver"
+ },
+ "require": {
+ "php": ">=5.3.19"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "3.7.*",
+ "phpdocumentor/phpdocumentor": "2.*"
+ },
+ "autoload": {
+ "classmap": ["lib/"]
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/example.php b/tests/vendor/facebook/webdriver/example.php
new file mode 100644
index 000000000000..a1e133b912e9
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/example.php
@@ -0,0 +1,49 @@
+get('http://docs.seleniumhq.org/');
+
+// adding cookie
+$driver->manage()->deleteAllCookies();
+$driver->manage()->addCookie(array(
+ 'name' => 'cookie_name',
+ 'value' => 'cookie_value',
+));
+$cookies = $driver->manage()->getCookies();
+print_r($cookies);
+
+// click the link 'About'
+$link = $driver->findElement(
+ WebDriverBy::id('menu_about')
+);
+$link->click();
+
+// print the title of the current page
+echo "The title is " . $driver->getTitle() . "'\n";
+
+// print the title of the current page
+echo "The current URI is " . $driver->getCurrentURL() . "'\n";
+
+// Search 'php' in the search box
+$input = $driver->findElement(
+ WebDriverBy::id('q')
+);
+$input->sendKeys('php')->submit();
+
+// wait at most 10 seconds until at least one result is shown
+$driver->wait(10)->until(
+ WebDriverExpectedCondition::presenceOfAllElementsLocatedBy(
+ WebDriverBy::className('gsc-result')
+ )
+);
+
+// close the Firefox
+$driver->quit();
diff --git a/tests/vendor/facebook/webdriver/lib/JavaScriptExecutor.php b/tests/vendor/facebook/webdriver/lib/JavaScriptExecutor.php
new file mode 100644
index 000000000000..131a7fef19d5
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/JavaScriptExecutor.php
@@ -0,0 +1,47 @@
+wait(20, 1000)->until(
+ * WebDriverExpectedCondition::titleIs('WebDriver Page')
+ * );
+ *
+ * @param int $timeout_in_second
+ * @param int $interval_in_millisecond
+ * @return WebDriverWait
+ */
+ public function wait(
+ $timeout_in_second = 30,
+ $interval_in_millisecond = 250);
+
+ /**
+ * An abstraction for managing stuff you would do in a browser menu. For
+ * example, adding and deleting cookies.
+ *
+ * @return WebDriverOptions
+ */
+ public function manage();
+
+ /**
+ * An abstraction allowing the driver to access the browser's history and to
+ * navigate to a given URL.
+ *
+ * @return WebDriverNavigation
+ * @see WebDriverNavigation
+ */
+ public function navigate();
+
+ /**
+ * Switch to a different window or frame.
+ *
+ * @return WebDriverTargetLocator
+ * @see WebDriverTargetLocator
+ */
+ public function switchTo();
+
+ /**
+ * @param string $name
+ * @param array $params
+ * @return mixed
+ */
+ public function execute($name, $params);
+}
diff --git a/tests/vendor/facebook/webdriver/lib/WebDriverAction.php b/tests/vendor/facebook/webdriver/lib/WebDriverAction.php
new file mode 100644
index 000000000000..80a310a641a4
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/WebDriverAction.php
@@ -0,0 +1,25 @@
+executor = $executor;
+ }
+
+ /**
+ * Accept alert
+ *
+ * @return WebDriverAlert The instance.
+ */
+ public function accept() {
+ $this->executor->execute(DriverCommand::ACCEPT_ALERT);
+ return $this;
+ }
+
+ /**
+ * Dismiss alert
+ *
+ * @return WebDriverAlert The instance.
+ */
+ public function dismiss() {
+ $this->executor->execute(DriverCommand::DISMISS_ALERT);
+ return $this;
+ }
+
+ /**
+ * Get alert text
+ *
+ * @return string
+ */
+ public function getText() {
+ return $this->executor->execute(DriverCommand::GET_ALERT_TEXT);
+ }
+
+ /**
+ * Send keystrokes to javascript prompt() dialog
+ *
+ * @param string $value
+ * @return WebDriverAlert
+ */
+ public function sendKeys($value) {
+ $this->executor->execute(
+ DriverCommand::SET_ALERT_VALUE,
+ array('text' => $value)
+ );
+ return $this;
+ }
+
+}
diff --git a/tests/vendor/facebook/webdriver/lib/WebDriverBy.php b/tests/vendor/facebook/webdriver/lib/WebDriverBy.php
new file mode 100644
index 000000000000..3409afd2588c
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/WebDriverBy.php
@@ -0,0 +1,128 @@
+mechanism = $mechanism;
+ $this->value = $value;
+ }
+
+ /**
+ * @return string
+ */
+ public function getMechanism() {
+ return $this->mechanism;
+ }
+
+ /**
+ * @return string
+ */
+ public function getValue() {
+ return $this->value;
+ }
+
+ /**
+ * Locates elements whose class name contains the search value; compound class
+ * names are not permitted.
+ *
+ * @param string $class_name
+ * @return WebDriverBy
+ */
+ public static function className($class_name) {
+ return new WebDriverBy('class name', $class_name);
+ }
+
+ /**
+ * Locates elements matching a CSS selector.
+ *
+ * @param string $css_selector
+ * @return WebDriverBy
+ */
+ public static function cssSelector($css_selector) {
+ return new WebDriverBy('css selector', $css_selector);
+ }
+
+ /**
+ * Locates elements whose ID attribute matches the search value.
+ *
+ * @param string $id
+ * @return WebDriverBy
+ */
+ public static function id($id) {
+ return new WebDriverBy('id', $id);
+ }
+
+ /**
+ * Locates elements whose NAME attribute matches the search value.
+ *
+ * @param string $name
+ * @return WebDriverBy
+ */
+ public static function name($name) {
+ return new WebDriverBy('name', $name);
+ }
+
+ /**
+ * Locates anchor elements whose visible text matches the search value.
+ *
+ * @param string $link_text
+ * @return WebDriverBy
+ */
+ public static function linkText($link_text) {
+ return new WebDriverBy('link text', $link_text);
+ }
+
+ /**
+ * Locates anchor elements whose visible text partially matches the search
+ * value.
+ *
+ * @param string $partial_link_text
+ * @return WebDriverBy
+ */
+ public static function partialLinkText($partial_link_text) {
+ return new WebDriverBy('partial link text', $partial_link_text);
+ }
+
+ /**
+ * Locates elements whose tag name matches the search value.
+ *
+ * @param string $tag_name
+ * @return WebDriverBy
+ */
+ public static function tagName($tag_name) {
+ return new WebDriverBy('tag name', $tag_name);
+ }
+
+ /**
+ * Locates elements matching an XPath expression.
+ *
+ * @param string $xpath
+ * @return WebDriverBy
+ */
+ public static function xpath($xpath) {
+ return new WebDriverBy('xpath', $xpath);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/WebDriverCapabilities.php b/tests/vendor/facebook/webdriver/lib/WebDriverCapabilities.php
new file mode 100644
index 000000000000..1e70efb2cf25
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/WebDriverCapabilities.php
@@ -0,0 +1,49 @@
+width = $width;
+ $this->height = $height;
+ }
+
+ /**
+ * Get the height.
+ *
+ * @return int The height.
+ */
+ public function getHeight() {
+ return $this->height;
+ }
+
+ /**
+ * Get the width.
+ *
+ * @return int The width.
+ */
+ public function getWidth() {
+ return $this->width;
+ }
+
+ /**
+ * Check whether the given dimension is the same as the instance.
+ *
+ * @param WebDriverDimension $dimension The dimension to be compared with.
+ * @return bool Whether the height and the width are the same as the
+ * instance.
+ */
+ public function equals(WebDriverDimension $dimension) {
+ return $this->height === $dimension->getHeight() &&
+ $this->width === $dimension->getWidth();
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/WebDriverDispatcher.php b/tests/vendor/facebook/webdriver/lib/WebDriverDispatcher.php
new file mode 100644
index 000000000000..c5c4f191fbae
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/WebDriverDispatcher.php
@@ -0,0 +1,80 @@
+driver = $driver;
+ return $this;
+ }
+
+ /**
+ * @return null|EventFiringWebDriver
+ */
+ public function getDefaultDriver() {
+ return $this->driver;
+ }
+
+ /**
+ * @param WebDriverEventListener $listener
+ * @return $this
+ */
+ public function register(WebDriverEventListener $listener) {
+ $this->listeners[] = $listener;
+ return $this;
+ }
+
+ /**
+ * @param WebDriverEventListener $listener
+ * @return $this
+ */
+ public function unregister(WebDriverEventListener $listener) {
+ $key = array_search($listener, $this->listeners, true);
+ if ($key !== false) {
+ unset($this->listeners[$key]);
+ }
+ return $this;
+ }
+
+ /**
+ * @param mixed $method
+ * @param mixed $arguments
+ * @return $this
+ */
+ public function dispatch($method, $arguments) {
+ foreach ($this->listeners as $listener) {
+ call_user_func_array(array($listener, $method), $arguments);
+ }
+ return $this;
+ }
+
+}
diff --git a/tests/vendor/facebook/webdriver/lib/WebDriverElement.php b/tests/vendor/facebook/webdriver/lib/WebDriverElement.php
new file mode 100644
index 000000000000..62a0a1543916
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/WebDriverElement.php
@@ -0,0 +1,134 @@
+results = $results;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getResults() {
+ return $this->results;
+ }
+
+ /**
+ * Throw WebDriverExceptions.
+ * For $status_code >= 0, they are errors defined in the json wired protocol.
+ * For $status_code < 0, they are errors defined in php-webdriver.
+ *
+ * @param int $status_code
+ * @param string $message
+ * @param mixed $results
+ */
+ public static function throwException($status_code, $message, $results) {
+ switch ($status_code) {
+ case -1:
+ throw new WebDriverCurlException($message);
+ case 0:
+ // Success
+ break;
+ case 1:
+ throw new IndexOutOfBoundsException($message, $results);
+ case 2:
+ throw new NoCollectionException($message, $results);
+ case 3:
+ throw new NoStringException($message, $results);
+ case 4:
+ throw new NoStringLengthException($message, $results);
+ case 5:
+ throw new NoStringWrapperException($message, $results);
+ case 6:
+ throw new NoSuchDriverException($message, $results);
+ case 7:
+ throw new NoSuchElementException($message, $results);
+ case 8:
+ throw new NoSuchFrameException($message, $results);
+ case 9:
+ throw new UnknownCommandException($message, $results);
+ case 10:
+ throw new StaleElementReferenceException($message, $results);
+ case 11:
+ throw new ElementNotVisibleException($message, $results);
+ case 12:
+ throw new InvalidElementStateException($message, $results);
+ case 13:
+ throw new UnknownServerException($message, $results);
+ case 14:
+ throw new ExpectedException($message, $results);
+ case 15:
+ throw new ElementNotSelectableException($message, $results);
+ case 16:
+ throw new NoSuchDocumentException($message, $results);
+ case 17:
+ throw new UnexpectedJavascriptException($message, $results);
+ case 18:
+ throw new NoScriptResultException($message, $results);
+ case 19:
+ throw new XPathLookupException($message, $results);
+ case 20:
+ throw new NoSuchCollectionException($message, $results);
+ case 21:
+ throw new TimeOutException($message, $results);
+ case 22:
+ throw new NullPointerException($message, $results);
+ case 23:
+ throw new NoSuchWindowException($message, $results);
+ case 24:
+ throw new InvalidCookieDomainException($message, $results);
+ case 25:
+ throw new UnableToSetCookieException($message, $results);
+ case 26:
+ throw new UnexpectedAlertOpenException($message, $results);
+ case 27:
+ throw new NoAlertOpenException($message, $results);
+ case 28:
+ throw new ScriptTimeoutException($message, $results);
+ case 29:
+ throw new InvalidCoordinatesException($message, $results);
+ case 30:
+ throw new IMENotAvailableException($message, $results);
+ case 31:
+ throw new IMEEngineActivationFailedException($message, $results);
+ case 32:
+ throw new InvalidSelectorException($message, $results);
+ case 33:
+ throw new SessionNotCreatedException($message, $results);
+ case 34:
+ throw new MoveTargetOutOfBoundsException($message, $results);
+ default:
+ throw new UnrecognizedExceptionException($message, $results);
+ }
+ }
+}
+
+class IndexOutOfBoundsException extends WebDriverException {} // 1
+class NoCollectionException extends WebDriverException {} // 2
+class NoStringException extends WebDriverException {} // 3
+class NoStringLengthException extends WebDriverException {} // 4
+class NoStringWrapperException extends WebDriverException {} // 5
+class NoSuchDriverException extends WebDriverException {} // 6
+class NoSuchElementException extends WebDriverException {} // 7
+class NoSuchFrameException extends WebDriverException {} // 8
+class UnknownCommandException extends WebDriverException {} // 9
+class StaleElementReferenceException extends WebDriverException {} // 10
+class ElementNotVisibleException extends WebDriverException {} // 11
+class InvalidElementStateException extends WebDriverException {} // 12
+class UnknownServerException extends WebDriverException {} // 13
+class ExpectedException extends WebDriverException {} // 14
+class ElementNotSelectableException extends WebDriverException {} // 15
+class NoSuchDocumentException extends WebDriverException {} // 16
+class UnexpectedJavascriptException extends WebDriverException {} // 17
+class NoScriptResultException extends WebDriverException {} // 18
+class XPathLookupException extends WebDriverException {} // 19
+class NoSuchCollectionException extends WebDriverException {} // 20
+class TimeOutException extends WebDriverException {} // 21
+class NullPointerException extends WebDriverException {} // 22
+class NoSuchWindowException extends WebDriverException {} // 23
+class InvalidCookieDomainException extends WebDriverException {} // 24
+class UnableToSetCookieException extends WebDriverException {} // 25
+class UnexpectedAlertOpenException extends WebDriverException {} // 26
+class NoAlertOpenException extends WebDriverException {} // 27
+class ScriptTimeoutException extends WebDriverException {} // 28
+class InvalidCoordinatesException extends WebDriverException {}// 29
+class IMENotAvailableException extends WebDriverException {} // 30
+class IMEEngineActivationFailedException extends WebDriverException {}// 31
+class InvalidSelectorException extends WebDriverException {} // 32
+class SessionNotCreatedException extends WebDriverException {} // 33
+class MoveTargetOutOfBoundsException extends WebDriverException {} // 34
+
+// Fallback
+class UnrecognizedExceptionException extends WebDriverException {}
+
+class UnexpectedTagNameException extends WebDriverException {
+
+ /**
+ * @param string $expected_tag_name
+ * @param string $actual_tag_name
+ */
+ public function __construct(
+ $expected_tag_name,
+ $actual_tag_name) {
+ parent::__construct(
+ sprintf(
+ "Element should have been \"%s\" but was \"%s\"",
+ $expected_tag_name, $actual_tag_name
+ )
+ );
+ }
+}
+
+class UnsupportedOperationException extends WebDriverException {}
diff --git a/tests/vendor/facebook/webdriver/lib/WebDriverExpectedCondition.php b/tests/vendor/facebook/webdriver/lib/WebDriverExpectedCondition.php
new file mode 100644
index 000000000000..ca9f4df7cd60
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/WebDriverExpectedCondition.php
@@ -0,0 +1,409 @@
+apply;
+ }
+
+ protected function __construct($apply) {
+ $this->apply = $apply;
+ }
+
+ /**
+ * An expectation for checking the title of a page.
+ *
+ * @param string $title The expected title, which must be an exact match.
+ * @return bool WebDriverExpectedCondition True when the title matches,
+ * false otherwise.
+ */
+ public static function titleIs($title) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($title) {
+ return $title === $driver->getTitle();
+ }
+ );
+ }
+
+ /**
+ * An expectation for checking substring of a page Title.
+ *
+ * @param string $title The expected substring of Title.
+ * @return bool WebDriverExpectedCondition True when in title,
+ * false otherwise.
+ */
+ public static function titleContains($title) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($title) {
+ return strpos($driver->getTitle(), $title) !== false;
+ }
+ );
+ }
+
+ /**
+ * An expectation for checking that an element is present on the DOM of a
+ * page. This does not necessarily mean that the element is visible.
+ *
+ * @param WebDriverBy $by The locator used to find the element.
+ * @return WebDriverExpectedCondition The element which
+ * is located.
+ */
+ public static function presenceOfElementLocated(WebDriverBy $by) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($by) {
+ return $driver->findElement($by);
+ }
+ );
+ }
+
+ /**
+ * An expectation for checking that an element is present on the DOM of a page
+ * and visible. Visibility means that the element is not only displayed but
+ * also has a height and width that is greater than 0.
+ *
+ * @param WebDriverBy $by The locator used to find the element.
+ * @return WebDriverExpectedCondition The element which is
+ * located and visible.
+ */
+ public static function visibilityOfElementLocated(WebDriverBy $by) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($by) {
+ try {
+ $element = $driver->findElement($by);
+ return $element->isDisplayed() ? $element : null;
+ } catch (StaleElementReferenceException $e) {
+ return null;
+ }
+ }
+ );
+ }
+
+ /**
+ * An expectation for checking that an element, known to be present on the DOM
+ * of a page, is visible. Visibility means that the element is not only
+ * displayed but also has a height and width that is greater than 0.
+ *
+ * @param WebDriverElement $element The element to be checked.
+ * @return WebDriverExpectedCondition The same
+ * WebDriverElement once it is visible.
+ */
+ public static function visibilityOf(WebDriverElement $element) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($element) {
+ return $element->isDisplayed() ? $element : null;
+ }
+ );
+ }
+
+ /**
+ * An expectation for checking that there is at least one element present on a
+ * web page.
+ *
+ * @param WebDriverBy $by The locator used to find the element.
+ * @return WebDriverExpectedCondition An array of WebDriverElements
+ * once they are located.
+ */
+ public static function presenceOfAllElementsLocatedBy(WebDriverBy $by) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($by) {
+ $elements = $driver->findElements($by);
+ return count($elements) > 0 ? $elements : null;
+ }
+ );
+ }
+
+ /**
+ * An expectation for checking if the given text is present in the specified
+ * element.
+ *
+ * @param WebDriverBy $by The locator used to find the element.
+ * @param string $text The text to be presented in the element.
+ * @return bool WebDriverExpectedCondition Whether the text is presented.
+ */
+ public static function textToBePresentInElement(
+ WebDriverBy $by, $text) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($by, $text) {
+ try {
+ $element_text = $driver->findElement($by)->getText();
+ return strpos($element_text, $text) !== false;
+ } catch (StaleElementReferenceException $e) {
+ return null;
+ }
+ }
+ );
+ }
+
+ /**
+ * An expectation for checking if the given text is present in the specified
+ * elements value attribute.
+ *
+ * @param WebDriverBy $by The locator used to find the element.
+ * @param string $text The text to be presented in the element value.
+ * @return bool WebDriverExpectedCondition Whether the text is presented.
+ */
+ public static function textToBePresentInElementValue(
+ WebDriverBy $by, $text) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($by, $text) {
+ try {
+ $element_text = $driver->findElement($by)->getAttribute('value');
+ return strpos($element_text, $text) !== false;
+ } catch (StaleElementReferenceException $e) {
+ return null;
+ }
+ }
+ );
+ }
+
+ /**
+ * Expectation for checking if iFrame exists.
+ * If iFrame exists switches driver's focus to the iFrame
+ *
+ * @param string $frame_locator The locator used to find the iFrame
+ * expected to be either the id or name value of the i/frame
+ * @return WebDriverExpectedCondition object focused on new frame
+ * when frame is found bool false otherwise
+ */
+ public static function frameToBeAvailableAndSwitchToIt($frame_locator) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($frame_locator) {
+ try {
+ return $driver->switchTo()->frame($frame_locator);
+ } catch (NoSuchFrameException $e) {
+ return false;
+ }
+ }
+ );
+ }
+
+ /**
+ * An expectation for checking that an element is either invisible or not
+ * present on the DOM.
+ *
+ * @param WebDriverBy $by The locator used to find the element.
+ * @return bool WebDriverExpectedCondition Whether there is no element
+ * located.
+ */
+ public static function invisibilityOfElementLocated(WebDriverBy $by) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($by) {
+ try {
+ return !($driver->findElement($by)->isDisplayed());
+ } catch (NoSuchElementException $e) {
+ return true;
+ } catch (StaleElementReferenceException $e) {
+ return true;
+ }
+ }
+ );
+ }
+
+ /**
+ * An expectation for checking that an element with text is either invisible
+ * or not present on the DOM.
+ *
+ * @param WebdriverBy $by The locator used to find the element.
+ * @param string $text The text of the element.
+ * @return bool WebDriverExpectedCondition Whether the text is found in the
+ * element located.
+ */
+ public static function invisibilityOfElementWithText(
+ WebDriverBy $by, $text) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($by, $text) {
+ try {
+ return !($driver->findElement($by)->getText() === $text);
+ } catch (NoSuchElementException $e) {
+ return true;
+ } catch (StaleElementReferenceException $e) {
+ return true;
+ }
+ }
+ );
+ }
+
+ /**
+ * An expectation for checking an element is visible and enabled such that you
+ * can click it.
+ *
+ * @param WebDriverBy $by The locator used to find the element
+ * @return WebDriverExpectedCondition The WebDriverElement
+ * once it is located, visible and clickable
+ */
+ public static function elementToBeClickable(WebDriverBy $by) {
+ $visibility_of_element_located =
+ WebDriverExpectedCondition::visibilityOfElementLocated($by);
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($visibility_of_element_located) {
+ $element = call_user_func(
+ $visibility_of_element_located->getApply(),
+ $driver
+ );
+ try {
+ if ($element !== null && $element->isEnabled()) {
+ return $element;
+ } else {
+ return null;
+ }
+ } catch (StaleElementReferenceException $e) {
+ return null;
+ }
+ }
+ );
+ }
+
+ /**
+ * Wait until an element is no longer attached to the DOM.
+ *
+ * @param WebDriverElement $element The element to wait for.
+ * @return bool WebDriverExpectedCondition false if the element is still
+ * attached to the DOM, true otherwise.
+ */
+ public static function stalenessOf(WebDriverElement $element) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($element) {
+ try {
+ $element->isEnabled();
+ return false;
+ } catch (StaleElementReferenceException $e) {
+ return true;
+ }
+ }
+ );
+ }
+
+ /**
+ * Wrapper for a condition, which allows for elements to update by redrawing.
+ *
+ * This works around the problem of conditions which have two parts: find an
+ * element and then check for some condition on it. For these conditions it is
+ * possible that an element is located and then subsequently it is redrawn on
+ * the client. When this happens a StaleElementReferenceException is thrown
+ * when the second part of the condition is checked.
+ *
+ * @param WebDriverExpectedCondition $condition The condition wrapped.
+ * @return WebDriverExpectedCondition The return value of the
+ * getApply() of the given condition.
+ */
+ public static function refreshed(WebDriverExpectedCondition $condition) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($condition) {
+ try {
+ return call_user_func($condition->getApply(), $driver);
+ } catch (StaleElementReferenceException $e) {
+ return null;
+ }
+ }
+ );
+ }
+
+ /**
+ * An expectation for checking if the given element is selected.
+ *
+ * @param mixed $element_or_by Either the element or the locator.
+ * @return bool WebDriverExpectedCondition whether the element is selected.
+ */
+ public static function elementToBeSelected($element_or_by) {
+ return WebDriverExpectedCondition::elementSelectionStateToBe(
+ $element_or_by,
+ true
+ );
+ }
+
+ /**
+ * An expectation for checking if the given element is selected.
+ *
+ * @param mixed $element_or_by Either the element or the locator.
+ * @param bool $selected The required state.
+ * @return bool WebDriverExpectedCondition Whether the element is selected.
+ */
+ public static function elementSelectionStateToBe(
+ $element_or_by,
+ $selected
+ ) {
+ if ($element_or_by instanceof WebDriverElement) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($element_or_by, $selected) {
+ return $element_or_by->isSelected() === $selected;
+ }
+ );
+ } else if ($element_or_by instanceof WebDriverBy) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($element_or_by, $selected) {
+ try {
+ $element = $driver->findElement($element_or_by);
+ return $element->isSelected() === $selected;
+ } catch (StaleElementReferenceException $e) {
+ return null;
+ }
+ }
+ );
+ }
+ }
+
+ /**
+ * An expectation for whether an alert() box is present.
+ *
+ * @return WebDriverExpectedCondition if alert() is present,
+ * null otherwise.
+ */
+ public static function alertIsPresent() {
+ return new WebDriverExpectedCondition(
+ function ($driver) {
+ try {
+ // Unlike the Java code, we get a WebDriverAlert object regardless
+ // of whether there is an alert. Calling getText() will throw
+ // an exception if it is not really there.
+ $alert = $driver->switchTo()->alert();
+ $alert->getText();
+ return $alert;
+ } catch (NoAlertOpenException $e) {
+ return null;
+ }
+ }
+ );
+ }
+
+ /**
+ * An expectation with the logical opposite condition of the given condition.
+ *
+ * @param WebDriverExpectedCondition $condition The condition to be negated.
+ * @return mixed The negation of the result of the given condition.
+ */
+ public static function not(WebDriverExpectedCondition $condition) {
+ return new WebDriverExpectedCondition(
+ function ($driver) use ($condition) {
+ $result = call_user_func($condition->getApply(), $driver);
+ return !$result;
+ }
+ );
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/WebDriverHasInputDevices.php b/tests/vendor/facebook/webdriver/lib/WebDriverHasInputDevices.php
new file mode 100644
index 000000000000..949c26dc8db6
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/WebDriverHasInputDevices.php
@@ -0,0 +1,30 @@
+executor = $executor;
+ }
+
+ /**
+ * Move back a single entry in the browser's history, if possible.
+ *
+ * @return WebDriverNavigation The instance.
+ */
+ public function back() {
+ $this->executor->execute(DriverCommand::GO_BACK);
+ return $this;
+ }
+
+ /**
+ * Move forward a single entry in the browser's history, if possible.
+ *
+ * @return WebDriverNavigation The instance.
+ */
+ public function forward() {
+ $this->executor->execute(DriverCommand::GO_FORWARD);
+ return $this;
+ }
+
+ /**
+ * Refresh the current page.
+ *
+ * @return WebDriverNavigation The instance.
+ */
+ public function refresh() {
+ $this->executor->execute(DriverCommand::REFRESH);
+ return $this;
+ }
+
+ /**
+ * Navigate to the given URL.
+ *
+ * @param string $url
+ * @return WebDriverNavigation The instance.
+ */
+ public function to($url) {
+ $params = array('url' => (string)$url);
+ $this->executor->execute(DriverCommand::GET, $params);
+ return $this;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/WebDriverOptions.php b/tests/vendor/facebook/webdriver/lib/WebDriverOptions.php
new file mode 100644
index 000000000000..61b5eb16f68d
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/WebDriverOptions.php
@@ -0,0 +1,167 @@
+executor = $executor;
+ }
+
+ /**
+ * Add a specific cookie.
+ *
+ * Here are the valid attributes of a cookie array.
+ * 'name' : string The name of the cookie; may not be null or an empty
+ * string.
+ * 'value' : string The cookie value; may not be null.
+ * 'path' : string The path the cookie is visible to. If left blank or set
+ * to null, will be set to "/".
+ * 'domain': string The domain the cookie is visible to. It should be null or
+ * the same as the domain of the current URL.
+ * 'secure': bool Whether this cookie requires a secure connection(https?).
+ * It should be null or equal to the security of the current
+ * URL.
+ * 'expiry': int The cookie's expiration date; may be null.
+ *
+ * @param array $cookie An array with key as the attributes mentioned above.
+ * @return WebDriverOptions The current instance.
+ */
+ public function addCookie(array $cookie) {
+ $this->validate($cookie);
+ $this->executor->execute(
+ DriverCommand::ADD_COOKIE,
+ array('cookie' => $cookie)
+ );
+ return $this;
+ }
+
+ /**
+ * Delete all the cookies that are currently visible.
+ *
+ * @return WebDriverOptions The current instance.
+ */
+ public function deleteAllCookies() {
+ $this->executor->execute(DriverCommand::DELETE_ALL_COOKIES);
+ return $this;
+ }
+
+ /**
+ * Delete the cookie with the give name.
+ *
+ * @param string $name
+ * @return WebDriverOptions The current instance.
+ */
+ public function deleteCookieNamed($name) {
+ $this->executor->execute(
+ DriverCommand::DELETE_COOKIE,
+ array(':name' => $name)
+ );
+ return $this;
+ }
+
+ /**
+ * Get the cookie with a given name.
+ *
+ * @param string $name
+ * @return array The cookie, or null if no cookie with the given name is
+ * presented.
+ */
+ public function getCookieNamed($name) {
+ $cookies = $this->getCookies();
+ foreach ($cookies as $cookie) {
+ if ($cookie['name'] === $name) {
+ return $cookie;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get all the cookies for the current domain.
+ *
+ * @return array The array of cookies presented.
+ */
+ public function getCookies() {
+ return $this->executor->execute(DriverCommand::GET_ALL_COOKIES);
+ }
+
+ private function validate(array $cookie) {
+ if (!isset($cookie['name']) ||
+ $cookie['name'] === '' ||
+ strpos($cookie['name'], ';') !== false) {
+ throw new InvalidArgumentException(
+ '"name" should be non-empty and does not contain a ";"');
+ }
+
+ if (!isset($cookie['value'])) {
+ throw new InvalidArgumentException(
+ '"value" is required when setting a cookie.');
+ }
+
+ if (isset($cookie['domain']) && strpos($cookie['domain'], ':') !== false) {
+ throw new InvalidArgumentException(
+ '"domain" should not contain a port:'.(string)$cookie['domain']);
+ }
+ }
+
+ /**
+ * Return the interface for managing driver timeouts.
+ *
+ * @return WebDriverTimeouts
+ */
+ public function timeouts() {
+ return new WebDriverTimeouts($this->executor);
+ }
+
+ /**
+ * An abstraction allowing the driver to manipulate the browser's window
+ *
+ * @return WebDriverWindow
+ * @see WebDriverWindow
+ */
+ public function window() {
+ return new WebDriverWindow($this->executor);
+ }
+
+ /**
+ * Get the log for a given log type. Log buffer is reset after each request.
+ *
+ * @param string $log_type The log type.
+ * @return array The list of log entries.
+ * @see https://code.google.com/p/selenium/wiki/JsonWireProtocol#Log_Type
+ */
+ public function getLog($log_type) {
+ return $this->executor->execute(
+ DriverCommand::GET_LOG,
+ array('type' => $log_type)
+ );
+ }
+
+ /**
+ * Get available log types.
+ *
+ * @return array The list of available log types.
+ * @see https://code.google.com/p/selenium/wiki/JsonWireProtocol#Log_Type
+ */
+ public function getAvailableLogTypes() {
+ return $this->executor->execute(DriverCommand::GET_AVAILABLE_LOG_TYPES);
+ }
+
+}
diff --git a/tests/vendor/facebook/webdriver/lib/WebDriverPlatform.php b/tests/vendor/facebook/webdriver/lib/WebDriverPlatform.php
new file mode 100644
index 000000000000..9d0e413fc7d6
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/WebDriverPlatform.php
@@ -0,0 +1,29 @@
+x = $x;
+ $this->y = $y;
+ }
+
+ /**
+ * Get the x-coordinate.
+ *
+ * @return int The x-coordinate of the point.
+ */
+ public function getX() {
+ return $this->x;
+ }
+
+ /**
+ * Get the y-coordinate.
+ *
+ * @return int The y-coordinate of the point.
+ */
+ public function getY() {
+ return $this->y;
+ }
+
+ /**
+ * Set the point to a new position.
+ *
+ * @param int $new_x
+ * @param int $new_y
+ * @return WebDriverPoint The same instance with updated coordinates.
+ */
+ public function move($new_x, $new_y) {
+ $this->x = $new_x;
+ $this->y = $new_y;
+ return $this;
+ }
+
+ /**
+ * Move the current by offsets.
+ *
+ * @param int $x_offset
+ * @param int $y_offset
+ * @return WebDriverPoint The same instance with updated coordinates.
+ */
+ public function moveBy($x_offset, $y_offset) {
+ $this->x += $x_offset;
+ $this->y += $y_offset;
+ return $this;
+ }
+
+ /**
+ * Check whether the given point is the same as the instance.
+ *
+ * @param WebDriverPoint $point The point to be compared with.
+ * @return bool Whether the x and y coordinates are the same as the instance.
+ */
+ public function equals(WebDriverPoint $point) {
+ return $this->x === $point->getX() &&
+ $this->y === $point->getY();
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/WebDriverSearchContext.php b/tests/vendor/facebook/webdriver/lib/WebDriverSearchContext.php
new file mode 100644
index 000000000000..dacea3f333ea
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/WebDriverSearchContext.php
@@ -0,0 +1,42 @@
+getTagName();
+
+ if ($tag_name !== 'select') {
+ throw new UnexpectedTagNameException('select', $tag_name);
+ }
+ $this->element = $element;
+ $value = $element->getAttribute('multiple');
+ $this->isMulti = ($value === 'true');
+ }
+
+ /**
+ * @return bool Whether this select element support selecting multiple
+ * options. This is done by checking the value of the 'multiple'
+ * attribute.
+ */
+ public function isMultiple() {
+ return $this->isMulti;
+ }
+
+ /**
+ * @return array All options belonging to this select tag.
+ */
+ public function getOptions() {
+ return $this->element->findElements(WebDriverBy::tagName('option'));
+ }
+
+ /**
+ * @return array All selected options belonging to this select tag.
+ */
+ public function getAllSelectedOptions() {
+ $selected_options = array();
+ foreach ($this->getOptions() as $option) {
+ if ($option->isSelected()) {
+ $selected_options[] = $option;
+ }
+ }
+ return $selected_options;
+ }
+
+ /**
+ * @return WebDriverElement The first selected option in this select tag (or
+ * the currently selected option in a normal select)
+ */
+ public function getFirstSelectedOption() {
+ foreach ($this->getOptions() as $option) {
+ if ($option->isSelected()) {
+ return $option;
+ }
+ }
+
+ throw new NoSuchElementException('No options are selected');
+ }
+
+ /**
+ * Deselect all options in multiple select tag.
+ *
+ * @return void
+ */
+ public function deselectAll() {
+ if (!$this->isMultiple()) {
+ throw new UnsupportedOperationException(
+ 'You may only deselect all options of a multi-select'
+ );
+ }
+
+ foreach ($this->getOptions() as $option) {
+ if ($option->isSelected()) {
+ $option->click();
+ }
+ }
+ }
+
+ /**
+ * Select the option at the given index.
+ *
+ * @param int $index The index of the option. (0-based)
+ * @return void
+ */
+ public function selectByIndex($index) {
+ $matched = false;
+ foreach ($this->getOptions() as $option) {
+ if ($option->getAttribute('index') === (string)$index) {
+ if (!$option->isSelected()) {
+ $option->click();
+ if (!$this->isMultiple()) {
+ return;
+ }
+ }
+ $matched = true;
+ }
+ }
+ if (!$matched) {
+ throw new NoSuchElementException(
+ sprintf('Cannot locate option with index: %d', $index)
+ );
+ }
+ }
+
+ /**
+ * Select all options that have value attribute matching the argument. That
+ * is, when given "foo" this would select an option like:
+ *
+ * ;
+ *
+ * @param string $value The value to match against.
+ * @return void
+ */
+ public function selectByValue($value) {
+ $matched = false;
+ $xpath = './/option[@value = '.$this->escapeQuotes($value).']';
+ $options = $this->element->findElements(WebDriverBy::xpath($xpath));
+
+ foreach ($options as $option) {
+ if (!$option->isSelected()) {
+ $option->click();
+ }
+ if (!$this->isMultiple()) {
+ return;
+ }
+ $matched = true;
+ }
+
+ if (!$matched) {
+ throw new NoSuchElementException(
+ sprintf('Cannot locate option with value: %s', $value)
+ );
+ }
+ }
+
+ /**
+ * Select all options that display text matching the argument. That is, when
+ * given "Bar" this would select an option like:
+ *
+ * ;
+ *
+ * @param string $text The visible text to match against.
+ * @return void
+ */
+ public function selectByVisibleText($text) {
+ $matched = false;
+ $xpath = './/option[normalize-space(.) = '.$this->escapeQuotes($text).']';
+ $options = $this->element->findElements(WebDriverBy::xpath($xpath));
+
+ foreach ($options as $option) {
+ if (!$option->isSelected()) {
+ $option->click();
+ }
+ if (!$this->isMultiple()) {
+ return;
+ }
+ $matched = true;
+ }
+
+ // Since the mechanism of getting the text in xpath is not the same as
+ // webdriver, use the expensive getText() to check if nothing is matched.
+ if (!$matched) {
+ foreach ($this->getOptions() as $option) {
+ if ($option->getText() === $text) {
+ if (!$option->isSelected()) {
+ $option->click();
+ }
+ if (!$this->isMultiple()) {
+ return;
+ }
+ $matched = true;
+ }
+ }
+ }
+
+ if (!$matched) {
+ throw new NoSuchElementException(
+ sprintf('Cannot locate option with text: %s', $text)
+ );
+ }
+ }
+
+ /**
+ * Deselect the option at the given index.
+ *
+ * @param int $index The index of the option. (0-based)
+ * @return void
+ */
+ public function deselectByIndex($index) {
+ foreach ($this->getOptions() as $option) {
+ if ($option->getAttribute('index') === (string)$index &&
+ $option->isSelected()) {
+ $option->click();
+ }
+ }
+ }
+
+ /**
+ * Deselect all options that have value attribute matching the argument. That
+ * is, when given "foo" this would select an option like:
+ *
+ * ;
+ *
+ * @param string $value The value to match against.
+ * @return void
+ */
+ public function deselectByValue($value) {
+ $xpath = './/option[@value = '.$this->escapeQuotes($value).']';
+ $options = $this->element->findElements(WebDriverBy::xpath($xpath));
+ foreach ($options as $option) {
+ if ($option->isSelected()) {
+ $option->click();
+ }
+ }
+ }
+
+ /**
+ * Deselect all options that display text matching the argument. That is, when
+ * given "Bar" this would select an option like:
+ *
+ * ;
+ *
+ * @param string $text The visible text to match against.
+ * @return void
+ */
+ public function deselectByVisibleText($text) {
+ $xpath = './/option[normalize-space(.) = '.$this->escapeQuotes($text).']';
+ $options = $this->element->findElements(WebDriverBy::xpath($xpath));
+ foreach ($options as $option) {
+ if ($option->isSelected()) {
+ $option->click();
+ }
+ }
+ }
+
+ /**
+ * Convert strings with both quotes and ticks into:
+ * foo'"bar -> concat("foo'", '"', "bar")
+ *
+ * @param string $to_escape The string to be converted.
+ * @return string The escaped string.
+ */
+ protected function escapeQuotes($to_escape) {
+ if (strpos($to_escape, '"') !== false && strpos($to_escape, "'") !== false) {
+ $substrings = explode('"', $to_escape);
+
+ $escaped = "concat(";
+ $first = true;
+ foreach ($substrings as $string) {
+ if (!$first) {
+ $escaped .= ", '\"',";
+ $first = false;
+ }
+ $escaped .= '"' . $string . '"';
+ }
+ return $escaped;
+ }
+
+ if (strpos($to_escape, '"') !== false) {
+ return sprintf("'%s'", $to_escape);
+ }
+
+ return sprintf('"%s"', $to_escape);
+ }
+
+}
diff --git a/tests/vendor/facebook/webdriver/lib/WebDriverTargetLocator.php b/tests/vendor/facebook/webdriver/lib/WebDriverTargetLocator.php
new file mode 100644
index 000000000000..d2c0a65f258d
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/WebDriverTargetLocator.php
@@ -0,0 +1,62 @@
+executor = $executor;
+ }
+
+ /**
+ * Specify the amount of time the driver should wait when searching for an
+ * element if it is not immediately present.
+ *
+ * @param int $seconds Wait time in second.
+ * @return WebDriverTimeouts The current instance.
+ */
+ public function implicitlyWait($seconds) {
+ $this->executor->execute(
+ DriverCommand::IMPLICITLY_WAIT,
+ array('ms' => $seconds * 1000)
+ );
+ return $this;
+ }
+
+ /**
+ * Set the amount of time to wait for an asynchronous script to finish
+ * execution before throwing an error.
+ *
+ * @param int $seconds Wait time in second.
+ * @return WebDriverTimeouts The current instance.
+ */
+ public function setScriptTimeout($seconds) {
+ $this->executor->execute(
+ DriverCommand::SET_SCRIPT_TIMEOUT,
+ array('ms' => $seconds * 1000)
+ );
+ return $this;
+ }
+
+ /**
+ * Set the amount of time to wait for a page load to complete before throwing
+ * an error.
+ *
+ * @param int $seconds Wait time in second.
+ * @return WebDriverTimeouts The current instance.
+ */
+ public function pageLoadTimeout($seconds) {
+ $this->executor->execute(DriverCommand::SET_TIMEOUT, array(
+ 'type' => 'page load',
+ 'ms' => $seconds * 1000,
+ ));
+ return $this;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/WebDriverWait.php b/tests/vendor/facebook/webdriver/lib/WebDriverWait.php
new file mode 100644
index 000000000000..55ace62af750
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/WebDriverWait.php
@@ -0,0 +1,70 @@
+driver = $driver;
+ $this->timeout = $timeout_in_second ?: 30;
+ $this->interval = $interval_in_millisecond ?: 250;
+ }
+
+ /**
+ * Calls the function provided with the driver as an argument until the return
+ * value is not falsey.
+ *
+ * @param (closure|WebDriverExpectedCondition)
+ * @param string $message
+ * @return mixed The return value of $func_or_ec
+ */
+ public function until($func_or_ec, $message = "") {
+ $end = microtime(true) + $this->timeout;
+ $last_exception = null;
+
+ while ($end > microtime(true)) {
+ try {
+ if ($func_or_ec instanceof WebDriverExpectedCondition) {
+ $ret_val = call_user_func($func_or_ec->getApply(), $this->driver);
+ } else {
+ $ret_val = call_user_func($func_or_ec, $this->driver);
+ }
+ if ($ret_val) {
+ return $ret_val;
+ }
+ } catch (NoSuchElementException $e) {
+ $last_exception = $e;
+ }
+ usleep($this->interval * 1000);
+ }
+
+ if ($last_exception) {
+ throw $last_exception;
+ }
+ throw new TimeOutException($message);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/WebDriverWindow.php b/tests/vendor/facebook/webdriver/lib/WebDriverWindow.php
new file mode 100644
index 000000000000..0bf86388b5f6
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/WebDriverWindow.php
@@ -0,0 +1,143 @@
+executor = $executor;
+ }
+
+ /**
+ * Get the position of the current window, relative to the upper left corner
+ * of the screen.
+ *
+ * @return array The current window position.
+ */
+ public function getPosition() {
+ $position = $this->executor->execute(
+ DriverCommand::GET_WINDOW_POSITION,
+ array(':windowHandle' => 'current')
+ );
+ return new WebDriverPoint(
+ $position['x'],
+ $position['y']
+ );
+ }
+
+ /**
+ * Get the size of the current window. This will return the outer window
+ * dimension, not just the view port.
+ *
+ * @return array The current window size.
+ */
+ public function getSize() {
+ $size = $this->executor->execute(
+ DriverCommand::GET_WINDOW_SIZE,
+ array(':windowHandle' => 'current')
+ );
+ return new WebDriverDimension(
+ $size['width'],
+ $size['height']
+ );
+ }
+
+ /**
+ * Maximizes the current window if it is not already maximized
+ *
+ * @return WebDriverWindow The instance.
+ */
+ public function maximize() {
+ $this->executor->execute(
+ DriverCommand::MAXIMIZE_WINDOW,
+ array(':windowHandle' => 'current')
+ );
+ return $this;
+ }
+
+ /**
+ * Set the size of the current window. This will change the outer window
+ * dimension, not just the view port.
+ *
+ * @param WebDriverDimension $size
+ * @return WebDriverWindow The instance.
+ */
+ public function setSize(WebDriverDimension $size) {
+ $params = array(
+ 'width' => $size->getWidth(),
+ 'height' => $size->getHeight(),
+ ':windowHandle' => 'current',
+ );
+ $this->executor->execute(DriverCommand::SET_WINDOW_SIZE, $params);
+ return $this;
+ }
+
+ /**
+ * Set the position of the current window. This is relative to the upper left
+ * corner of the screen.
+ *
+ * @param WebDriverPoint $position
+ * @return WebDriverWindow The instance.
+ */
+ public function setPosition(WebDriverPoint $position) {
+ $params = array(
+ 'x' => $position->getX(),
+ 'y' => $position->getY(),
+ ':windowHandle' => 'current',
+ );
+ $this->executor->execute(DriverCommand::SET_WINDOW_POSITION, $params);
+ return $this;
+ }
+
+ /**
+ * Get the current browser orientation.
+ *
+ * @return string Either LANDSCAPE|PORTRAIT
+ */
+ public function getScreenOrientation() {
+ return $this->executor->execute(DriverCommand::GET_SCREEN_ORIENTATION);
+ }
+
+
+ /**
+ * Set the browser orientation. The orientation should either
+ * LANDSCAPE|PORTRAIT
+ *
+ * @param string $orientation
+ * @return WebDriverWindow The instance.
+ * @throws IndexOutOfBoundsException
+ */
+ public function setScreenOrientation($orientation) {
+ $orientation = strtoupper($orientation);
+ if (!in_array($orientation, array('PORTRAIT', 'LANDSCAPE'))) {
+ throw new IndexOutOfBoundsException(
+ "Orientation must be either PORTRAIT, or LANDSCAPE"
+ );
+ }
+
+ $this->executor->execute(
+ DriverCommand::SET_SCREEN_ORIENTATION,
+ array('orientation' => $orientation)
+ );
+
+ return $this;
+
+ }
+
+}
diff --git a/tests/vendor/facebook/webdriver/lib/__init__.php b/tests/vendor/facebook/webdriver/lib/__init__.php
new file mode 100755
index 000000000000..55219b4918ab
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/__init__.php
@@ -0,0 +1,116 @@
+setCommandExecutor($executor)
+ ->startSession($desired_capabilities);
+ return $driver;
+ }
+
+ public function startSession($desired_capabilities) {
+ $command = new WebDriverCommand(
+ null,
+ DriverCommand::NEW_SESSION,
+ array(
+ 'desiredCapabilities' => $desired_capabilities->toArray(),
+ )
+ );
+ $response = $this->executor->execute($command);
+ $this->setSessionID($response->getSessionID());
+ }
+
+ /**
+ * @param string $url The url of the remote server
+ * @param DesiredCapabilities $desired_capabilities The desired capabilities
+ * @param int|null $connection_timeout_in_ms
+ * @param int|null $request_timeout_in_ms
+ */
+ public static function create(
+ $url = 'http://localhost:4444/wd/hub',
+ $desired_capabilities = null,
+ $timeout_in_ms = null,
+ $request_timeout_in_ms = null
+ ) {
+ throw new WebDriverException('Please use ChromeDriver::start() instead.');
+ }
+
+ public static function createBySessionID(
+ $session_id,
+ $url = 'http://localhost:4444/wd/hub'
+ ) {
+ throw new WebDriverException('Please use ChromeDriver::start() instead.');
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/chrome/ChromeDriverService.php b/tests/vendor/facebook/webdriver/lib/chrome/ChromeDriverService.php
new file mode 100644
index 000000000000..c4de774e7f62
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/chrome/ChromeDriverService.php
@@ -0,0 +1,29 @@
+binary = $path;
+ return $this;
+ }
+
+ /**
+ * @param array $arguments
+ * @return ChromeOptions
+ */
+ public function addArguments(array $arguments) {
+ $this->arguments = array_merge($this->arguments, $arguments);
+ return $this;
+ }
+
+ /**
+ * Add a Chrome extension to install on browser startup. Each path should be
+ * a packed Chrome extension.
+ *
+ * @param array $paths
+ * @return ChromeOptions
+ */
+ public function addExtensions(array $paths) {
+ foreach ($paths as $path) {
+ $this->addExtension($path);
+ }
+ return $this;
+ }
+
+ /**
+ * @param array $encoded_extensions An array of base64 encoded of the
+ * extensions.
+ * @return ChromeOptions
+ */
+ public function addEncodedExtensions(array $encoded_extensions) {
+ foreach ($encoded_extensions as $encoded_extension) {
+ $this->addEncodedExtension($encoded_extension);
+ }
+ return $this;
+ }
+
+ /**
+ * Sets an experimental option which has not exposed officially.
+ *
+ * @param string $name
+ * @param mixed $value
+ * @return ChromeOptions
+ */
+ public function setExperimentalOption($name, $value) {
+ $this->experimentalOptions[$name] = $value;
+ return $this;
+ }
+
+ /**
+ * @return DesiredCapabilities The DesiredCapabilities for Chrome with this
+ * options.
+ */
+ public function toCapabilities() {
+ $capabilities = DesiredCapabilities::chrome();
+ $capabilities->setCapability(self::CAPABILITY, $this);
+ return $capabilities;
+ }
+
+ /**
+ * @return array
+ */
+ public function toArray() {
+ $options = $this->experimentalOptions;
+
+ // The selenium server expects a 'dictionary' instead of a 'list' when
+ // reading the chrome option. However, an empty array in PHP will be
+ // converted to a 'list' instead of a 'dictionary'. To fix it, we always
+ // set the 'binary' to avoid returning an empty array.
+ $options['binary'] = $this->binary;
+
+ if ($this->arguments) {
+ $options['args'] = $this->arguments;
+ }
+
+ if ($this->extensions) {
+ $options['extensions'] = $this->extensions;
+ }
+
+ return $options;
+ }
+
+ /**
+ * Add a Chrome extension to install on browser startup. Each path should be a
+ * packed Chrome extension.
+ *
+ * @param string $path
+ * @return ChromeOptions
+ */
+ private function addExtension($path) {
+ $this->addEncodedExtension(base64_encode(file_get_contents($path)));
+ return $this;
+ }
+
+ /**
+ * @param string $encoded_extension Base64 encoded of the extension.
+ * @return ChromeOptions
+ */
+ private function addEncodedExtension($encoded_extension) {
+ $this->extensions[] = $encoded_extension;
+ return $this;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/firefox/FirefoxDriver.php b/tests/vendor/facebook/webdriver/lib/firefox/FirefoxDriver.php
new file mode 100644
index 000000000000..b1580baa66c1
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/firefox/FirefoxDriver.php
@@ -0,0 +1,19 @@
+extensions[] = $extension;
+ return $this;
+ }
+
+ /**
+ * @param string $key
+ * @param string|bool|int $value
+ * @return FirefoxProfile
+ */
+ public function setPreference($key, $value) {
+ if (is_string($value)) {
+ $value = sprintf('"%s"', $value);
+ } else if (is_int($value)) {
+ $value = sprintf('%d', $value);
+ } else if (is_bool($value)) {
+ $value = $value ? 'true' : 'false';
+ } else {
+ throw new WebDriverException(
+ 'The value of the preference should be either a string, int or bool.');
+ }
+ $this->preferences[$key] = $value;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function encode() {
+ $temp_dir = $this->createTempDirectory('WebDriverFirefoxProfile');
+
+ foreach ($this->extensions as $extension) {
+ $this->installExtension($extension, $temp_dir);
+ }
+
+ $content = "";
+ foreach ($this->preferences as $key => $value) {
+ $content .= sprintf("user_pref(\"%s\", %s);\n", $key, $value);
+ }
+ file_put_contents($temp_dir.'/user.js', $content);
+
+ $zip = new ZipArchive();
+ $temp_zip = tempnam('', 'WebDriverFirefoxProfileZip');
+ $zip->open($temp_zip, ZipArchive::CREATE);
+
+ $dir = new RecursiveDirectoryIterator($temp_dir);
+ $files = new RecursiveIteratorIterator($dir);
+ foreach ($files as $name => $object) {
+ if (is_dir($name)) {
+ continue;
+ }
+ $dir_prefix = preg_replace(
+ '#\\\\#',
+ '\\\\\\\\',
+ $temp_dir.DIRECTORY_SEPARATOR
+ );
+ $path = preg_replace("#^{$dir_prefix}#", "", $name);
+ $zip->addFile($name, $path);
+ }
+ $zip->close();
+
+ $profile = base64_encode(file_get_contents($temp_zip));
+ return $profile;
+ }
+
+ /**
+ * @param string $extension The path to the extension.
+ * @param string $profile_dir The path to the profile directory.
+ * @return string The path to the directory of this extension.
+ */
+ private function installExtension($extension, $profile_dir) {
+ $temp_dir = $this->createTempDirectory();
+
+ $this->extractTo($extension, $temp_dir);
+
+ $install_rdf_path = $temp_dir.'/install.rdf';
+ // This is a hacky way to parse the id since there is no offical
+ // RDF parser library.
+ $matches = array();
+ $xml = file_get_contents($install_rdf_path);
+ preg_match('#([^<]+)#', $xml, $matches);
+ $ext_dir = $profile_dir.'/extensions/'.$matches[1];
+
+ mkdir($ext_dir, 0777, true);
+
+ $this->extractTo($extension, $ext_dir);
+ return $ext_dir;
+ }
+
+ /**
+ * @param string $prefix Prefix of the temp directory.
+ * @return string The path to the temp directory created.
+ */
+ private function createTempDirectory($prefix = '') {
+ $temp_dir = tempnam('', $prefix);
+ if (file_exists($temp_dir)) {
+ unlink($temp_dir);
+ mkdir($temp_dir);
+ if (!is_dir($temp_dir)) {
+ throw new WebDriverException('Cannot create firefox profile.');
+ }
+ }
+ return $temp_dir;
+ }
+
+ /**
+ * @param string $xpi The path to the .xpi extension.
+ * @param string $target_dir The path to the unzip directory.
+ * @return FirefoxProfile
+ */
+ private function extractTo($xpi, $target_dir) {
+ $zip = new ZipArchive();
+ if ($zip->open($xpi)) {
+ $zip->extractTo($target_dir);
+ $zip->close();
+ } else {
+ throw new Exception("Failed to open the firefox extension. '$xpi'");
+ }
+ return $this;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/WebDriverActions.php b/tests/vendor/facebook/webdriver/lib/interactions/WebDriverActions.php
new file mode 100644
index 000000000000..e560db92b76e
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/WebDriverActions.php
@@ -0,0 +1,236 @@
+driver = $driver;
+ $this->keyboard = $driver->getKeyboard();
+ $this->mouse = $driver->getMouse();
+ $this->action = new WebDriverCompositeAction();
+ }
+
+ /**
+ * A convenience method for performing the actions without calling build().
+ * @return void
+ */
+ public function perform() {
+ $this->action->perform();
+ }
+
+ /**
+ * Mouse click.
+ * If $element is provided, move to the middle of the element first.
+ *
+ * @param WebDriverElement $element
+ * @return WebDriverActions
+ */
+ public function click(WebDriverElement $element = null) {
+ $this->action->addAction(
+ new WebDriverClickAction($this->mouse, $element)
+ );
+ return $this;
+ }
+
+ /**
+ * Mouse click and hold.
+ * If $element is provided, move to the middle of the element first.
+ *
+ * @param WebDriverElement $element
+ * @return WebDriverActions
+ */
+ public function clickAndHold(WebDriverElement $element = null) {
+ $this->action->addAction(
+ new WebDriverClickAndHoldAction($this->mouse, $element)
+ );
+ return $this;
+ }
+
+ /**
+ * Context-click (right click).
+ * If $element is provided, move to the middle of the element first.
+ *
+ * @param WebDriverElement $element
+ * @return WebDriverActions
+ */
+ public function contextClick(WebDriverElement $element = null) {
+ $this->action->addAction(
+ new WebDriverContextClickAction($this->mouse, $element)
+ );
+ return $this;
+ }
+
+ /**
+ * Double click.
+ * If $element is provided, move to the middle of the element first.
+ *
+ * @param WebDriverElement $element
+ * @return WebDriverActions
+ */
+ public function doubleClick(WebDriverElement $element = null) {
+ $this->action->addAction(
+ new WebDriverDoubleClickAction($this->mouse, $element)
+ );
+ return $this;
+ }
+
+ /**
+ * Drag and drop from $source to $target.
+ *
+ * @param WebDriverElement $source
+ * @param WebDriverElement $target
+ * @return WebDriverActions
+ */
+ public function dragAndDrop(WebDriverElement $source,
+ WebDriverElement $target) {
+ $this->action->addAction(
+ new WebDriverClickAndHoldAction($this->mouse, $source)
+ );
+ $this->action->addAction(
+ new WebDriverMouseMoveAction($this->mouse, $target)
+ );
+ $this->action->addAction(
+ new WebDriverButtonReleaseAction($this->mouse, $target)
+ );
+ return $this;
+ }
+
+ /**
+ * Drag $source and drop by offset ($x_offset, $y_offset).
+ *
+ * @param WebDriverElement $source
+ * @param int $x_offset
+ * @param int $y_offset
+ * @return WebDriverActions
+ */
+ public function dragAndDropBy(WebDriverElement $source,
+ $x_offset,
+ $y_offset) {
+ $this->action->addAction(
+ new WebDriverClickAndHoldAction($this->mouse, $source)
+ );
+ $this->action->addAction(
+ new WebDriverMoveToOffsetAction($this->mouse, null, $x_offset, $y_offset)
+ );
+ $this->action->addAction(
+ new WebDriverButtonReleaseAction($this->mouse, null)
+ );
+ return $this;
+ }
+
+ /**
+ * Mouse move by offset.
+ *
+ * @param int $x_offset
+ * @param int $y_offset
+ * @return WebDriverActions
+ */
+ public function moveByOffset($x_offset, $y_offset) {
+ $this->action->addAction(
+ new WebDriverMoveToOffsetAction($this->mouse, null, $x_offset, $y_offset)
+ );
+ return $this;
+ }
+
+ /**
+ * Move to the middle of the given WebDriverElement. If offset are provided,
+ * move the an offset from the top-left cornerof that element.
+ *
+ * @param WebDriverElement $element
+ * @param int $x_offset
+ * @param int $y_offset
+ * @return WebDriverActions
+ */
+ public function moveToElement(WebDriverElement $element,
+ $x_offset = null,
+ $y_offset = null) {
+ $this->action->addAction(new WebDriverMoveToOffsetAction(
+ $this->mouse, $element, $x_offset, $y_offset
+ ));
+ return $this;
+ }
+
+ /**
+ * Release the mouse button.
+ * If $element is provided, move to the middle of the element first.
+ *
+ * @param WebDriverElement $element
+ * @return WebDriverActions
+ */
+ public function release(WebDriverElement $element = null) {
+ $this->action->addAction(
+ new WebDriverButtonReleaseAction($this->mouse, $element)
+ );
+ return $this;
+ }
+
+ /**
+ * Press a key on keyboard.
+ * If $element is provided, focus on that element first.
+ *
+ * @see WebDriverKeys for special keys like CONTROL, ALT, etc.
+ * @param WebDriverElement $element
+ * @param string $key
+ * @return WebDriverActions
+ */
+ public function keyDown(WebDriverElement $element = null, $key = null) {
+ $this->action->addAction(
+ new WebDriverKeyDownAction($this->keyboard, $this->mouse, $element, $key)
+ );
+ return $this;
+ }
+
+ /**
+ * Release a key on keyboard.
+ * If $element is provided, focus on that element first.
+ *
+ * @see WebDriverKeys for special keys like CONTROL, ALT, etc.
+ * @param WebDriverElement $element
+ * @param string $key
+ * @return WebDriverActions
+ */
+ public function keyUp(WebDriverElement $element = null, $key = null) {
+ $this->action->addAction(
+ new WebDriverKeyUpAction($this->keyboard, $this->mouse, $element, $key)
+ );
+ return $this;
+ }
+
+ /**
+ * Send keys by keyboard.
+ * If $element is provided, focus on that element first.
+ *
+ * @see WebDriverKeys for special keys like CONTROL, ALT, etc.
+ * @param WebDriverElement $element
+ * @param string $keys
+ * @return WebDriverActions
+ */
+ public function sendKeys(WebDriverElement $element = null, $keys = null) {
+ $this->action->addAction(
+ new WebDriverSendKeysAction(
+ $this->keyboard, $this->mouse, $element, $keys
+ )
+ );
+ return $this;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/WebDriverCompositeAction.php b/tests/vendor/facebook/webdriver/lib/interactions/WebDriverCompositeAction.php
new file mode 100644
index 000000000000..8cb204b727b8
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/WebDriverCompositeAction.php
@@ -0,0 +1,51 @@
+actions[] = $action;
+ return $this;
+ }
+
+ /**
+ * Get the number of actions in the sequence.
+ *
+ * @return int The number of actions.
+ */
+ public function getNumberOfActions() {
+ return count($this->actions);
+ }
+
+ /**
+ * Perform the seqeunce of actions.
+ */
+ public function perform() {
+ foreach ($this->actions as $action) {
+ $action->perform();
+ }
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/WebDriverTouchActions.php b/tests/vendor/facebook/webdriver/lib/interactions/WebDriverTouchActions.php
new file mode 100644
index 000000000000..5be31d427a1b
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/WebDriverTouchActions.php
@@ -0,0 +1,153 @@
+touchScreen = $driver->getTouch();
+ }
+
+ /**
+ * @param WebDriverElement $element
+ * @return WebDriverTouchActions
+ */
+ public function tap(WebDriverElement $element) {
+ $this->action->addAction(
+ new WebDriverTapAction($this->touchScreen, $element)
+ );
+ return $this;
+ }
+
+ /**
+ * @param int $x
+ * @param int $y
+ * @return WebDriverTouchActions
+ */
+ public function down($x, $y) {
+ $this->action->addAction(
+ new WebDriverDownAction($this->touchScreen, $x, $y)
+ );
+ return $this;
+ }
+
+ /**
+ * @param int $x
+ * @param int $y
+ * @return WebDriverTouchActions
+ */
+ public function up($x, $y) {
+ $this->action->addAction(
+ new WebDriverUpAction($this->touchScreen, $x, $y)
+ );
+ return $this;
+ }
+
+ /**
+ * @param int $x
+ * @param int $y
+ * @return WebDriverTouchActions
+ */
+ public function move($x, $y) {
+ $this->action->addAction(
+ new WebDriverMoveAction($this->touchScreen, $x, $y)
+ );
+ return $this;
+ }
+
+ /**
+ * @param int $x
+ * @param int $y
+ * @return WebDriverTouchActions
+ */
+ public function scroll($x, $y) {
+ $this->action->addAction(
+ new WebDriverScrollAction($this->touchScreen, $x, $y)
+ );
+ return $this;
+ }
+
+ /**
+ * @param WebDriverElement $element
+ * @param int $x
+ * @param int $y
+ * @return WebDriverTouchActions
+ */
+ public function scrollFromElement(WebDriverElement $element, $x, $y) {
+ $this->action->addAction(
+ new WebDriverScrollFromElementAction($this->touchScreen, $element, $x, $y)
+ );
+ return $this;
+ }
+
+ /**
+ * @param WebDriverElement $element
+ * @return WebDriverTouchActions
+ */
+ public function doubleTap(WebDriverElement $element) {
+ $this->action->addAction(
+ new WebDriverDoubleTapAction($this->touchScreen, $element)
+ );
+ return $this;
+ }
+
+ /**
+ * @param WebDriverElement $element
+ * @return WebDriverTouchActions
+ */
+ public function longPress(WebDriverElement $element) {
+ $this->action->addAction(
+ new WebDriverLongPressAction($this->touchScreen, $element)
+ );
+ return $this;
+ }
+
+ /**
+ * @param int $x
+ * @param int $y
+ * @return WebDriverTouchActions
+ */
+ public function flick($x, $y) {
+ $this->action->addAction(
+ new WebDriverFlickAction($this->touchScreen, $x, $y)
+ );
+ return $this;
+ }
+
+ /**
+ * @param WebDriverElement $element
+ * @param int $x
+ * @param int $y
+ * @param int $speed
+ * @return WebDriverTouchActions
+ */
+ public function flickFromElement(WebDriverElement $element, $x, $y, $speed) {
+ $this->action->addAction(
+ new WebDriverFlickFromElementAction(
+ $this->touchScreen, $element, $x, $y, $speed
+ )
+ );
+ return $this;
+ }
+
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/WebDriverTouchScreen.php b/tests/vendor/facebook/webdriver/lib/interactions/WebDriverTouchScreen.php
new file mode 100644
index 000000000000..d38a8bccf2d4
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/WebDriverTouchScreen.php
@@ -0,0 +1,118 @@
+mouse->mouseUp($this->getActionLocation());
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverClickAction.php b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverClickAction.php
new file mode 100644
index 000000000000..0aba9dc16587
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverClickAction.php
@@ -0,0 +1,23 @@
+mouse->click($this->getActionLocation());
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverClickAndHoldAction.php b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverClickAndHoldAction.php
new file mode 100644
index 000000000000..80622ed11ae2
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverClickAndHoldAction.php
@@ -0,0 +1,26 @@
+mouse->mouseDown($this->getActionLocation());
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverContextClickAction.php b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverContextClickAction.php
new file mode 100644
index 000000000000..4802fdc3a9ee
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverContextClickAction.php
@@ -0,0 +1,26 @@
+mouse->contextClick($this->getActionLocation());
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverCoordinates.php b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverCoordinates.php
new file mode 100644
index 000000000000..18cc42020d0b
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverCoordinates.php
@@ -0,0 +1,68 @@
+onScreen = $on_screen;
+ $this->inViewPort = $in_view_port;
+ $this->onPage = $on_page;
+ $this->auxiliary = $auxiliary;
+ }
+
+ /**
+ * @return WebDriverPoint
+ */
+ public function onScreen() {
+ throw new UnsupportedOperationException(
+ 'onScreen is planned but not yet supported by Selenium'
+ );
+ }
+
+ /**
+ * @return WebDriverPoint
+ */
+ public function inViewPort() {
+ return call_user_func($this->inViewPort);
+ }
+
+ /**
+ * @return WebDriverPoint
+ */
+ public function onPage() {
+ return call_user_func($this->onPage);
+ }
+
+ /**
+ * @return Object The attached object.
+ */
+ public function getAuxiliary() {
+ return $this->auxiliary;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverDoubleClickAction.php b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverDoubleClickAction.php
new file mode 100644
index 000000000000..41fd4171662f
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverDoubleClickAction.php
@@ -0,0 +1,23 @@
+mouse->doubleClick($this->getActionLocation());
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverKeyDownAction.php b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverKeyDownAction.php
new file mode 100644
index 000000000000..1de8ae0ed7cb
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverKeyDownAction.php
@@ -0,0 +1,24 @@
+focusOnElement();
+ $this->keyboard->pressKey($this->key);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverKeyUpAction.php b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverKeyUpAction.php
new file mode 100644
index 000000000000..06e652700397
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverKeyUpAction.php
@@ -0,0 +1,24 @@
+focusOnElement();
+ $this->keyboard->releaseKey($this->key);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverKeysRelatedAction.php b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverKeysRelatedAction.php
new file mode 100644
index 000000000000..c97069d87fd7
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverKeysRelatedAction.php
@@ -0,0 +1,47 @@
+keyboard = $keyboard;
+ $this->mouse = $mouse;
+ $this->locationProvider = $location_provider;
+ }
+
+ /**
+ * @return void
+ */
+ protected function focusOnElement() {
+ if ($this->locationProvider) {
+ $this->mouse->click($this->locationProvider->getCoordinates());
+ }
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverMouseAction.php b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverMouseAction.php
new file mode 100644
index 000000000000..4c16a7b3938d
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverMouseAction.php
@@ -0,0 +1,48 @@
+mouse = $mouse;
+ $this->locationProvider = $location_provider;
+ }
+
+ /**
+ * @return null|WebDriverCoordinates
+ */
+ protected function getActionLocation() {
+ if ($this->locationProvider !== null) {
+ return $this->locationProvider->getCoordinates();
+ }
+
+ return null;
+ }
+
+ /**
+ * @return void
+ */
+ protected function moveToLocation() {
+ $this->mouse->mouseMove($this->locationProvider);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverMouseMoveAction.php b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverMouseMoveAction.php
new file mode 100644
index 000000000000..ca21d3511b6e
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverMouseMoveAction.php
@@ -0,0 +1,23 @@
+mouse->mouseMove($this->getActionLocation());
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverMoveToOffsetAction.php b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverMoveToOffsetAction.php
new file mode 100644
index 000000000000..d82558b55ac7
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverMoveToOffsetAction.php
@@ -0,0 +1,38 @@
+xOffset = $x_offset;
+ $this->yOffset = $y_offset;
+ }
+
+ public function perform() {
+ $this->mouse->mouseMove(
+ $this->getActionLocation(),
+ $this->xOffset,
+ $this->yOffset
+ );
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverSendKeysAction.php b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverSendKeysAction.php
new file mode 100644
index 000000000000..8dcc69183f84
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverSendKeysAction.php
@@ -0,0 +1,41 @@
+keys = $keys;
+ }
+
+ public function perform() {
+ $this->focusOnElement();
+ $this->keyboard->sendKeys($this->keys);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverSingleKeyAction.php b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverSingleKeyAction.php
new file mode 100644
index 000000000000..7d06cd330de3
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/internal/WebDriverSingleKeyAction.php
@@ -0,0 +1,30 @@
+key = $key;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverDoubleTapAction.php b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverDoubleTapAction.php
new file mode 100644
index 000000000000..00b2c28a4ef3
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverDoubleTapAction.php
@@ -0,0 +1,23 @@
+touchScreen->doubleTap($this->locationProvider);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverDownAction.php b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverDownAction.php
new file mode 100644
index 000000000000..43c4ed08d708
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverDownAction.php
@@ -0,0 +1,37 @@
+x = $x;
+ $this->y = $y;
+ parent::__construct($touch_screen);
+ }
+
+ public function perform() {
+ $this->touchScreen->down($this->x, $this->y);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverFlickAction.php b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverFlickAction.php
new file mode 100644
index 000000000000..76337c468d5c
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverFlickAction.php
@@ -0,0 +1,34 @@
+x = $x;
+ $this->y = $y;
+ parent::__construct($touch_screen);
+ }
+
+ public function perform() {
+ $this->touchScreen->flick($this->x, $this->y);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverFlickFromElementAction.php b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverFlickFromElementAction.php
new file mode 100644
index 000000000000..f361f1c29d93
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverFlickFromElementAction.php
@@ -0,0 +1,49 @@
+x = $x;
+ $this->y = $y;
+ $this->speed = $speed;
+ parent::__construct($touch_screen, $element);
+ }
+
+ public function perform() {
+ $this->touchScreen->flickFromElement(
+ $this->locationProvider,
+ $this->x,
+ $this->y,
+ $this->speed
+ );
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverLongPressAction.php b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverLongPressAction.php
new file mode 100644
index 000000000000..556c1d47fb9a
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverLongPressAction.php
@@ -0,0 +1,23 @@
+touchScreen->longPress($this->locationProvider);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverMoveAction.php b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverMoveAction.php
new file mode 100644
index 000000000000..2c089a343cd3
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverMoveAction.php
@@ -0,0 +1,37 @@
+x = $x;
+ $this->y = $y;
+ parent::__construct($touch_screen);
+ }
+
+ public function perform() {
+ $this->touchScreen->move($this->x, $this->y);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverScrollAction.php b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverScrollAction.php
new file mode 100644
index 000000000000..082b1acaf693
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverScrollAction.php
@@ -0,0 +1,37 @@
+x = $x;
+ $this->y = $y;
+ parent::__construct($touch_screen);
+ }
+
+ public function perform() {
+ $this->touchScreen->scroll($this->x, $this->y);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverScrollFromElementAction.php b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverScrollFromElementAction.php
new file mode 100644
index 000000000000..3c985b6bdf75
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverScrollFromElementAction.php
@@ -0,0 +1,44 @@
+x = $x;
+ $this->y = $y;
+ parent::__construct($touch_screen, $element);
+ }
+
+ public function perform() {
+ $this->touchScreen->scrollFromElement(
+ $this->locationProvider,
+ $this->x,
+ $this->y
+ );
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverTapAction.php b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverTapAction.php
new file mode 100644
index 000000000000..fb1a710047ae
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverTapAction.php
@@ -0,0 +1,23 @@
+touchScreen->tap($this->locationProvider);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverTouchAction.php b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverTouchAction.php
new file mode 100644
index 000000000000..99abced9c3d9
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverTouchAction.php
@@ -0,0 +1,51 @@
+touchScreen = $touch_screen;
+ $this->locationProvider = $location_provider;
+ }
+
+ /**
+ * @return null|WebDriverCoordinates
+ */
+ protected function getActionLocation() {
+ return $this->locationProvider !== null
+ ? $this->locationProvider->getCoordinates() : null;
+ }
+
+}
diff --git a/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverUpAction.php b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverUpAction.php
new file mode 100644
index 000000000000..298302769e1f
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/interactions/touch/WebDriverUpAction.php
@@ -0,0 +1,37 @@
+x = $x;
+ $this->y = $y;
+ parent::__construct($touch_screen);
+ }
+
+ public function perform() {
+ $this->touchScreen->up($this->x, $this->y);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/internal/WebDriverLocatable.php b/tests/vendor/facebook/webdriver/lib/internal/WebDriverLocatable.php
new file mode 100644
index 000000000000..5250d13478de
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/internal/WebDriverLocatable.php
@@ -0,0 +1,25 @@
+ microtime(true)) {
+ if ($this->getHTTPResponseCode($timeout_in_ms, $url) === 200) {
+ return $this;
+ }
+ usleep(self::POLL_INTERVAL_MS);
+ }
+
+ throw new TimeOutException(sprintf(
+ "Timed out waiting for %s to become available after %d ms.",
+ $url,
+ $timeout_in_ms
+ ));
+ }
+
+ public function waitUntilUnavailable($timeout_in_ms, $url) {
+ $end = microtime(true) + $timeout_in_ms / 1000;
+
+ while ($end > microtime(true)) {
+ if ($this->getHTTPResponseCode($timeout_in_ms, $url) !== 200) {
+ return $this;
+ }
+ usleep(self::POLL_INTERVAL_MS);
+ }
+
+ throw new TimeOutException(sprintf(
+ "Timed out waiting for %s to become unavailable after %d ms.",
+ $url,
+ $timeout_in_ms
+ ));
+ }
+
+ private function getHTTPResponseCode($timeout_in_ms, $url) {
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, self::CONNECT_TIMEOUT_MS);
+ // There is a PHP bug in some versions which didn't define the constant.
+ curl_setopt(
+ $ch,
+ 156, // CURLOPT_CONNECTTIMEOUT_MS
+ self::CONNECT_TIMEOUT_MS
+ );
+ $code = null;
+ try {
+ curl_exec($ch);
+ $info = curl_getinfo($ch);
+ $code = $info['http_code'];
+ } catch (Exception $e) {
+ }
+ curl_close($ch);
+ return $code;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/remote/DesiredCapabilities.php b/tests/vendor/facebook/webdriver/lib/remote/DesiredCapabilities.php
new file mode 100644
index 000000000000..19183737193b
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/remote/DesiredCapabilities.php
@@ -0,0 +1,275 @@
+capabilities = $capabilities;
+ }
+
+ /**
+ * @return string The name of the browser.
+ */
+ public function getBrowserName() {
+ return $this->get(WebDriverCapabilityType::BROWSER_NAME, '');
+ }
+
+ /**
+ * @param string $browser_name
+ * @return DesiredCapabilities
+ */
+ public function setBrowserName($browser_name) {
+ $this->set(WebDriverCapabilityType::BROWSER_NAME, $browser_name);
+ return $this;
+ }
+
+ /**
+ * @return string The version of the browser.
+ */
+ public function getVersion() {
+ return $this->get(WebDriverCapabilityType::VERSION, '');
+ }
+
+ /**
+ * @param string $version
+ * @return DesiredCapabilities
+ */
+ public function setVersion($version) {
+ $this->set(WebDriverCapabilityType::VERSION, $version);
+ return $this;
+ }
+
+ /**
+ * @param string $name
+ * @return mixed The value of a capability.
+ */
+ public function getCapability($name) {
+ return $this->get($name);
+ }
+
+ /**
+ * @param string $name
+ * @param mixed $value
+ * @return DesiredCapabilities
+ */
+ public function setCapability($name, $value) {
+ $this->set($name, $value);
+ return $this;
+ }
+
+ /**
+ * @return string The name of the platform.
+ */
+ public function getPlatform() {
+ return $this->get(WebDriverCapabilityType::PLATFORM, '');
+ }
+
+ /**
+ * @param string $platform
+ * @return DesiredCapabilities
+ */
+ public function setPlatform($platform) {
+ $this->set(WebDriverCapabilityType::PLATFORM, $platform);
+ return $this;
+ }
+
+ /**
+ * @param string $capability_name
+ * @return bool Whether the value is not null and not false.
+ */
+ public function is($capability_name) {
+ return (bool) $this->get($capability_name);
+ }
+
+ /**
+ * @return bool Whether javascript is enabled.
+ */
+ public function isJavascriptEnabled() {
+ return $this->get(WebDriverCapabilityType::JAVASCRIPT_ENABLED, false);
+ }
+
+ /**
+ * This is a htmlUnit-only option.
+ *
+ * @param bool $enabled
+ * @return DesiredCapabilities
+ * @see https://code.google.com/p/selenium/wiki/DesiredCapabilities#Read-write_capabilities
+ */
+ public function setJavascriptEnabled($enabled) {
+ $browser = $this->getBrowserName();
+ if ($browser && $browser !== WebDriverBrowserType::HTMLUNIT) {
+ throw new Exception(
+ 'isJavascriptEnable() is a htmlunit-only option. '.
+ 'See https://code.google.com/p/selenium/wiki/DesiredCapabilities#Read-write_capabilities.'
+ );
+ }
+
+ $this->set(WebDriverCapabilityType::JAVASCRIPT_ENABLED, $enabled);
+ return $this;
+ }
+
+ /**
+ * @return array
+ */
+ public function toArray() {
+ if (isset($this->capabilities[ChromeOptions::CAPABILITY]) &&
+ $this->capabilities[ChromeOptions::CAPABILITY] instanceof ChromeOptions) {
+ $this->capabilities[ChromeOptions::CAPABILITY] =
+ $this->capabilities[ChromeOptions::CAPABILITY]->toArray();
+ }
+
+ if (isset($this->capabilities[FirefoxDriver::PROFILE]) &&
+ $this->capabilities[FirefoxDriver::PROFILE] instanceof FirefoxProfile) {
+ $this->capabilities[FirefoxDriver::PROFILE] =
+ $this->capabilities[FirefoxDriver::PROFILE]->encode();
+ }
+
+ return $this->capabilities;
+ }
+
+ /**
+ * @param string $key
+ * @param mixed $value
+ * @return DesiredCapabilities
+ */
+ private function set($key, $value) {
+ $this->capabilities[$key] = $value;
+ return $this;
+ }
+
+ /**
+ * @param string $key
+ * @param mixed $default
+ * @return mixed
+ */
+ private function get($key, $default = null) {
+ return isset($this->capabilities[$key])
+ ? $this->capabilities[$key]
+ : $default;
+ }
+
+ /**
+ * @return DesiredCapabilities
+ */
+ public static function android() {
+ return new DesiredCapabilities(array(
+ WebDriverCapabilityType::BROWSER_NAME => WebDriverBrowserType::ANDROID,
+ WebDriverCapabilityType::PLATFORM => WebDriverPlatform::ANDROID,
+ ));
+ }
+
+ /**
+ * @return DesiredCapabilities
+ */
+ public static function chrome() {
+ return new DesiredCapabilities(array(
+ WebDriverCapabilityType::BROWSER_NAME => WebDriverBrowserType::CHROME,
+ WebDriverCapabilityType::PLATFORM => WebDriverPlatform::ANY,
+ ));
+ }
+
+ /**
+ * @return DesiredCapabilities
+ */
+ public static function firefox() {
+ return new DesiredCapabilities(array(
+ WebDriverCapabilityType::BROWSER_NAME => WebDriverBrowserType::FIREFOX,
+ WebDriverCapabilityType::PLATFORM => WebDriverPlatform::ANY,
+ ));
+ }
+
+ /**
+ * @return DesiredCapabilities
+ */
+ public static function htmlUnit() {
+ return new DesiredCapabilities(array(
+ WebDriverCapabilityType::BROWSER_NAME => WebDriverBrowserType::HTMLUNIT,
+ WebDriverCapabilityType::PLATFORM => WebDriverPlatform::ANY,
+ ));
+ }
+
+ /**
+ * @return DesiredCapabilities
+ */
+ public static function htmlUnitWithJS() {
+ $caps = new DesiredCapabilities(array(
+ WebDriverCapabilityType::BROWSER_NAME => WebDriverBrowserType::HTMLUNIT,
+ WebDriverCapabilityType::PLATFORM => WebDriverPlatform::ANY,
+ ));
+ return $caps->setJavascriptEnabled(true);
+ }
+
+ /**
+ * @return DesiredCapabilities
+ */
+ public static function internetExplorer() {
+ return new DesiredCapabilities(array(
+ WebDriverCapabilityType::BROWSER_NAME => WebDriverBrowserType::IE,
+ WebDriverCapabilityType::PLATFORM => WebDriverPlatform::WINDOWS,
+ ));
+ }
+
+ /**
+ * @return DesiredCapabilities
+ */
+ public static function iphone() {
+ return new DesiredCapabilities(array(
+ WebDriverCapabilityType::BROWSER_NAME => WebDriverBrowserType::IPHONE,
+ WebDriverCapabilityType::PLATFORM => WebDriverPlatform::MAC,
+ ));
+ }
+
+ /**
+ * @return DesiredCapabilities
+ */
+ public static function ipad() {
+ return new DesiredCapabilities(array(
+ WebDriverCapabilityType::BROWSER_NAME => WebDriverBrowserType::IPAD,
+ WebDriverCapabilityType::PLATFORM => WebDriverPlatform::MAC,
+ ));
+ }
+
+ /**
+ * @return DesiredCapabilities
+ */
+ public static function opera() {
+ return new DesiredCapabilities(array(
+ WebDriverCapabilityType::BROWSER_NAME => WebDriverBrowserType::OPERA,
+ WebDriverCapabilityType::PLATFORM => WebDriverPlatform::ANY,
+ ));
+ }
+
+ /**
+ * @return DesiredCapabilities
+ */
+ public static function safari() {
+ return new DesiredCapabilities(array(
+ WebDriverCapabilityType::BROWSER_NAME => WebDriverBrowserType::SAFARI,
+ WebDriverCapabilityType::PLATFORM => WebDriverPlatform::ANY,
+ ));
+ }
+
+ /**
+ * @return DesiredCapabilities
+ */
+ public static function phantomjs() {
+ return new DesiredCapabilities(array(
+ WebDriverCapabilityType::BROWSER_NAME => WebDriverBrowserType::PHANTOMJS,
+ WebDriverCapabilityType::PLATFORM => WebDriverPlatform::ANY,
+ ));
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/remote/DriverCommand.php b/tests/vendor/facebook/webdriver/lib/remote/DriverCommand.php
new file mode 100644
index 000000000000..837e5e9de791
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/remote/DriverCommand.php
@@ -0,0 +1,169 @@
+ array('method' => 'POST', 'url' => '/session/:sessionId/accept_alert'),
+ DriverCommand::ADD_COOKIE => array('method' => 'POST', 'url' => '/session/:sessionId/cookie'),
+ DriverCommand::CLEAR_ELEMENT => array('method' => 'POST', 'url' => '/session/:sessionId/element/:id/clear'),
+ DriverCommand::CLICK_ELEMENT => array('method' => 'POST', 'url' => '/session/:sessionId/element/:id/click'),
+ DriverCommand::CLOSE => array('method' => 'DELETE', 'url' => '/session/:sessionId/window'),
+ DriverCommand::DELETE_ALL_COOKIES => array('method' => 'DELETE', 'url' => '/session/:sessionId/cookie'),
+ DriverCommand::DELETE_COOKIE => array('method' => 'DELETE', 'url' => '/session/:sessionId/cookie/:name'),
+ DriverCommand::DISMISS_ALERT => array('method' => 'POST', 'url' => '/session/:sessionId/dismiss_alert'),
+ DriverCommand::ELEMENT_EQUALS => array('method' => 'GET', 'url' => '/session/:sessionId/element/:id/equals/:other'),
+ DriverCommand::FIND_CHILD_ELEMENT => array('method' => 'POST', 'url' => '/session/:sessionId/element/:id/element'),
+ DriverCommand::FIND_CHILD_ELEMENTS => array('method' => 'POST', 'url' => '/session/:sessionId/element/:id/elements'),
+ DriverCommand::EXECUTE_SCRIPT => array('method' => 'POST', 'url' => '/session/:sessionId/execute'),
+ DriverCommand::EXECUTE_ASYNC_SCRIPT => array('method' => 'POST', 'url' => '/session/:sessionId/execute_async'),
+ DriverCommand::FIND_ELEMENT => array('method' => 'POST', 'url' => '/session/:sessionId/element'),
+ DriverCommand::FIND_ELEMENTS => array('method' => 'POST', 'url' => '/session/:sessionId/elements'),
+ DriverCommand::SWITCH_TO_FRAME => array('method' => 'POST', 'url' => '/session/:sessionId/frame'),
+ DriverCommand::SWITCH_TO_WINDOW => array('method' => 'POST', 'url' => '/session/:sessionId/window'),
+ DriverCommand::GET => array('method' => 'POST', 'url' => '/session/:sessionId/url'),
+ DriverCommand::GET_ACTIVE_ELEMENT => array('method' => 'POST', 'url' => '/session/:sessionId/element/active'),
+ DriverCommand::GET_ALERT_TEXT => array('method' => 'GET', 'url' => '/session/:sessionId/alert_text'),
+ DriverCommand::GET_ALL_COOKIES => array('method' => 'GET', 'url' => '/session/:sessionId/cookie'),
+ DriverCommand::GET_ALL_SESSIONS => array('method' => 'GET', 'url' => '/sessions'),
+ DriverCommand::GET_AVAILABLE_LOG_TYPES => array('method' => 'GET', 'url' => '/session/:sessionId/log/types'),
+ DriverCommand::GET_CURRENT_URL => array('method' => 'GET', 'url' => '/session/:sessionId/url'),
+ DriverCommand::GET_CURRENT_WINDOW_HANDLE => array('method' => 'GET', 'url' => '/session/:sessionId/window_handle'),
+ DriverCommand::GET_ELEMENT_ATTRIBUTE => array('method' => 'GET', 'url' => '/session/:sessionId/element/:id/attribute/:name'),
+ DriverCommand::GET_ELEMENT_VALUE_OF_CSS_PROPERTY => array('method' => 'GET', 'url' => '/session/:sessionId/element/:id/css/:propertyName'),
+ DriverCommand::GET_ELEMENT_LOCATION => array('method' => 'GET', 'url' => '/session/:sessionId/element/:id/location'),
+ DriverCommand::GET_ELEMENT_LOCATION_ONCE_SCROLLED_INTO_VIEW => array('method' => 'GET', 'url' => '/session/:sessionId/element/:id/location_in_view'),
+ DriverCommand::GET_ELEMENT_SIZE => array('method' => 'GET', 'url' => '/session/:sessionId/element/:id/size'),
+ DriverCommand::GET_ELEMENT_TAG_NAME => array('method' => 'GET', 'url' => '/session/:sessionId/element/:id/name'),
+ DriverCommand::GET_ELEMENT_TEXT => array('method' => 'GET', 'url' => '/session/:sessionId/element/:id/text'),
+ DriverCommand::GET_LOG => array('method' => 'POST', 'url' => '/session/:sessionId/log'),
+ DriverCommand::GET_PAGE_SOURCE => array('method' => 'GET', 'url' => '/session/:sessionId/source'),
+ DriverCommand::GET_SCREEN_ORIENTATION => array('method' => 'GET', 'url' => '/session/:sessionId/orientation'),
+ DriverCommand::GET_CAPABILITIES => array('method' => 'GET', 'url' => '/session/:sessionId'),
+ DriverCommand::GET_TITLE => array('method' => 'GET', 'url' => '/session/:sessionId/title'),
+ DriverCommand::GET_WINDOW_HANDLES => array('method' => 'GET', 'url' => '/session/:sessionId/window_handles'),
+ DriverCommand::GET_WINDOW_POSITION => array('method' => 'GET', 'url' => '/session/:sessionId/window/:windowHandle/position'),
+ DriverCommand::GET_WINDOW_SIZE => array('method' => 'GET', 'url' => '/session/:sessionId/window/:windowHandle/size'),
+ DriverCommand::GO_BACK => array('method' => 'POST', 'url' => '/session/:sessionId/back'),
+ DriverCommand::GO_FORWARD => array('method' => 'POST', 'url' => '/session/:sessionId/forward'),
+ DriverCommand::IS_ELEMENT_DISPLAYED=> array('method' => 'GET', 'url' => '/session/:sessionId/element/:id/displayed'),
+ DriverCommand::IS_ELEMENT_ENABLED=> array('method' => 'GET', 'url' => '/session/:sessionId/element/:id/enabled'),
+ DriverCommand::IS_ELEMENT_SELECTED=> array('method' => 'GET', 'url' => '/session/:sessionId/element/:id/selected'),
+ DriverCommand::MAXIMIZE_WINDOW => array('method' => 'POST', 'url' => '/session/:sessionId/window/:windowHandle/maximize'),
+ DriverCommand::MOUSE_DOWN => array('method' => 'POST', 'url' => '/session/:sessionId/buttondown'),
+ DriverCommand::MOUSE_UP => array('method' => 'POST', 'url' => '/session/:sessionId/buttonup'),
+ DriverCommand::CLICK => array('method' => 'POST', 'url' => '/session/:sessionId/click'),
+ DriverCommand::DOUBLE_CLICK => array('method' => 'POST', 'url' => '/session/:sessionId/doubleclick'),
+ DriverCommand::MOVE_TO => array('method' => 'POST', 'url' => '/session/:sessionId/moveto'),
+ DriverCommand::NEW_SESSION => array('method' => 'POST', 'url' => '/session'),
+ DriverCommand::QUIT => array('method' => 'DELETE', 'url' => '/session/:sessionId'),
+ DriverCommand::REFRESH => array('method' => 'POST', 'url' => '/session/:sessionId/refresh'),
+ DriverCommand::UPLOAD_FILE => array('method' => 'POST', 'url' => '/session/:sessionId/file'), // undocumented
+ DriverCommand::SEND_KEYS_TO_ACTIVE_ELEMENT => array('method' => 'POST', 'url' => '/session/:sessionId/keys'),
+ DriverCommand::SET_ALERT_VALUE => array('method' => 'POST', 'url' => '/session/:sessionId/alert_text'),
+ DriverCommand::SEND_KEYS_TO_ELEMENT => array('method' => 'POST', 'url' => '/session/:sessionId/element/:id/value'),
+ DriverCommand::IMPLICITLY_WAIT => array('method' => 'POST', 'url' => '/session/:sessionId/timeouts/implicit_wait'),
+ DriverCommand::SET_SCREEN_ORIENTATION => array('method' => 'POST', 'url' => '/session/:sessionId/orientation'),
+ DriverCommand::SET_TIMEOUT => array('method' => 'POST', 'url' => '/session/:sessionId/timeouts'),
+ DriverCommand::SET_SCRIPT_TIMEOUT => array('method' => 'POST', 'url' => '/session/:sessionId/timeouts/async_script'),
+ DriverCommand::SET_WINDOW_POSITION => array('method' => 'POST', 'url' => '/session/:sessionId/window/:windowHandle/position'),
+ DriverCommand::SET_WINDOW_SIZE => array('method' => 'POST', 'url' => '/session/:sessionId/window/:windowHandle/size'),
+ DriverCommand::SUBMIT_ELEMENT => array('method' => 'POST', 'url' => '/session/:sessionId/element/:id/submit'),
+ DriverCommand::SCREENSHOT => array('method' => 'GET', 'url' => '/session/:sessionId/screenshot'),
+ DriverCommand::TOUCH_SINGLE_TAP => array('method' => 'POST', 'url' => '/session/:sessionId/touch/click'),
+ DriverCommand::TOUCH_DOWN => array('method' => 'POST', 'url' => '/session/:sessionId/touch/down'),
+ DriverCommand::TOUCH_DOUBLE_TAP => array('method' => 'POST', 'url' => '/session/:sessionId/touch/doubleclick'),
+ DriverCommand::TOUCH_FLICK => array('method' => 'POST', 'url' => '/session/:sessionId/touch/flick'),
+ DriverCommand::TOUCH_LONG_PRESS => array('method' => 'POST', 'url' => '/session/:sessionId/touch/longclick'),
+ DriverCommand::TOUCH_MOVE => array('method' => 'POST', 'url' => '/session/:sessionId/touch/move'),
+ DriverCommand::TOUCH_SCROLL => array('method' => 'POST', 'url' => '/session/:sessionId/touch/scroll'),
+ DriverCommand::TOUCH_UP => array('method' => 'POST', 'url' => '/session/:sessionId/touch/up'),
+ );
+
+ /**
+ * @var string
+ */
+ protected $url;
+ /**
+ * @var resource
+ */
+ protected $curl;
+
+ /**
+ * @param string $url
+ */
+ public function __construct($url) {
+ $this->url = $url;
+ $this->curl = curl_init();
+
+ // Get credentials from $url (if any)
+ $matches = null;
+ if (preg_match("/^(https?:\/\/)(.*):(.*)@(.*?)/U", $url, $matches)) {
+ $this->url = $matches[1].$matches[4];
+ $auth_creds = $matches[2].":".$matches[3];
+ curl_setopt($this->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+ curl_setopt($this->curl, CURLOPT_USERPWD, $auth_creds);
+ }
+
+ curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt(
+ $this->curl,
+ CURLOPT_HTTPHEADER,
+ array(
+ 'Content-Type: application/json;charset=UTF-8',
+ 'Accept: application/json',
+ )
+ );
+ $this->setRequestTimeout(30000);
+ $this->setConnectionTimeout(30000);
+ }
+
+ /**
+ * Set timeout for the connect phase
+ *
+ * @param int $timeout_in_ms Timeout in milliseconds
+ * @return HttpCommandExecutor
+ */
+ public function setConnectionTimeout($timeout_in_ms) {
+ // There is a PHP bug in some versions which didn't define the constant.
+ curl_setopt(
+ $this->curl,
+ /* CURLOPT_CONNECTTIMEOUT_MS */ 156,
+ $timeout_in_ms
+ );
+ return $this;
+ }
+
+ /**
+ * Set the maximum time of a request
+ *
+ * @param int $timeout_in_ms Timeout in milliseconds
+ * @return HttpCommandExecutor
+ */
+ public function setRequestTimeout($timeout_in_ms) {
+ // There is a PHP bug in some versions (at least for PHP 5.3.3) which
+ // didn't define the constant.
+ curl_setopt(
+ $this->curl,
+ /* CURLOPT_TIMEOUT_MS */ 155,
+ $timeout_in_ms
+ );
+ return $this;
+ }
+
+ /**
+ * @param WebDriverCommand $command
+ * @return mixed
+ */
+ public function execute(WebDriverCommand $command) {
+ if (!isset(self::$commands[$command->getName()])) {
+ throw new InvalidArgumentException(
+ $command->getName()." is not a valid command."
+ );
+ }
+ $raw = self::$commands[$command->getName()];
+ $http_method = $raw['method'];
+ $url = $raw['url'];
+ $url = str_replace(':sessionId', $command->getSessionID(), $url);
+ $params = $command->getParameters();
+ foreach ($params as $name => $value) {
+ if ($name[0] === ':') {
+ $url = str_replace($name, $value, $url);
+ if ($http_method != 'POST') {
+ unset($params[$name]);
+ }
+ }
+ }
+
+ if ($params && is_array($params) && $http_method !== 'POST') {
+ throw new BadMethodCallException(sprintf(
+ 'The http method called for %s is %s but it has to be POST' .
+ ' if you want to pass the JSON params %s',
+ $url,
+ $http_method,
+ json_encode($params)
+ ));
+ }
+
+ curl_setopt($this->curl, CURLOPT_URL, $this->url . $url);
+
+ // https://github.com/facebook/php-webdriver/issues/173
+ if ($command->getName() === DriverCommand::NEW_SESSION) {
+ curl_setopt($this->curl, CURLOPT_POST, 1);
+ } else {
+ curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $http_method);
+ }
+
+ $encoded_params = null;
+
+ if ($http_method === 'POST' && $params && is_array($params)) {
+ $encoded_params = json_encode($params);
+ }
+
+ curl_setopt($this->curl, CURLOPT_POSTFIELDS, $encoded_params);
+
+ $raw_results = trim(curl_exec($this->curl));
+
+ if ($error = curl_error($this->curl)) {
+ $msg = sprintf(
+ 'Curl error thrown for http %s to %s',
+ $http_method,
+ $url);
+ if ($params && is_array($params)) {
+ $msg .= sprintf(' with params: %s', json_encode($params));
+ }
+ WebDriverException::throwException(-1, $msg . "\n\n" . $error, array());
+ }
+
+ $results = json_decode($raw_results, true);
+
+ if ($results === null && json_last_error() !== JSON_ERROR_NONE) {
+ throw new WebDriverException(
+ sprintf(
+ "JSON decoding of remote response failed.\n".
+ "Error code: %d\n".
+ "The response: '%s'\n",
+ json_last_error(),
+ $raw_results
+ )
+ );
+ }
+
+ $value = null;
+ if (is_array($results) && array_key_exists('value', $results)) {
+ $value = $results['value'];
+ }
+
+ $message = null;
+ if (is_array($value) && array_key_exists('message', $value)) {
+ $message = $value['message'];
+ }
+
+ $sessionId = null;
+ if (is_array($results) && array_key_exists('sessionId', $results)) {
+ $sessionId = $results['sessionId'];
+ }
+
+ $status = isset($results['status']) ? $results['status'] : 0;
+ WebDriverException::throwException($status, $message, $results);
+
+ $response = new WebDriverResponse($sessionId);
+ return $response
+ ->setStatus($status)
+ ->setValue($value);
+ }
+
+ /**
+ * @return string
+ */
+ public function getAddressOfRemoteServer() {
+ return $this->url;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/remote/LocalFileDetector.php b/tests/vendor/facebook/webdriver/lib/remote/LocalFileDetector.php
new file mode 100644
index 000000000000..f0107b0bac8a
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/remote/LocalFileDetector.php
@@ -0,0 +1,28 @@
+driver = $driver;
+ }
+
+ /**
+ * @param string $command_name
+ * @param array $parameters
+ * @return mixed
+ */
+ public function execute(
+ $command_name,
+ array $parameters = array()
+ ) {
+ return $this->driver->execute($command_name, $parameters);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/remote/RemoteKeyboard.php b/tests/vendor/facebook/webdriver/lib/remote/RemoteKeyboard.php
new file mode 100644
index 000000000000..2a3cc54777ec
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/remote/RemoteKeyboard.php
@@ -0,0 +1,72 @@
+executor = $executor;
+ }
+
+ /**
+ * Send keys to active element
+ * @param string|array $keys
+ * @return $this
+ */
+ public function sendKeys($keys) {
+ $this->executor->execute(DriverCommand::SEND_KEYS_TO_ACTIVE_ELEMENT, array(
+ 'value' => WebDriverKeys::encode($keys),
+ ));
+ return $this;
+ }
+
+ /**
+ * Press a modifier key
+ *
+ * @see WebDriverKeys
+ * @param string $key
+ * @return $this
+ */
+ public function pressKey($key) {
+ $this->executor->execute(DriverCommand::SEND_KEYS_TO_ACTIVE_ELEMENT, array(
+ 'value' => array((string)$key),
+ ));
+ return $this;
+ }
+
+ /**
+ * Release a modifier key
+ *
+ * @see WebDriverKeys
+ * @param string $key
+ * @return $this
+ */
+ public function releaseKey($key) {
+ $this->executor->execute(DriverCommand::SEND_KEYS_TO_ACTIVE_ELEMENT, array(
+ 'value' => array((string)$key),
+ ));
+ return $this;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/remote/RemoteMouse.php b/tests/vendor/facebook/webdriver/lib/remote/RemoteMouse.php
new file mode 100644
index 000000000000..66d010252dda
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/remote/RemoteMouse.php
@@ -0,0 +1,125 @@
+executor = $executor;
+ }
+
+ /**
+ * @param null|WebDriverCoordinates $where
+ *
+ * @return RemoteMouse
+ */
+ public function click(WebDriverCoordinates $where = null) {
+ $this->moveIfNeeded($where);
+ $this->executor->execute(DriverCommand::CLICK, array(
+ 'button' => 0,
+ ));
+ return $this;
+ }
+
+ /**
+ * @param WebDriverCoordinates $where
+ *
+ * @return RemoteMouse
+ */
+ public function contextClick(WebDriverCoordinates $where = null) {
+ $this->moveIfNeeded($where);
+ $this->executor->execute(DriverCommand::CLICK, array(
+ 'button' => 2,
+ ));
+ return $this;
+ }
+
+ /**
+ * @param WebDriverCoordinates $where
+ *
+ * @return RemoteMouse
+ */
+ public function doubleClick(WebDriverCoordinates $where = null) {
+ $this->moveIfNeeded($where);
+ $this->executor->execute(DriverCommand::DOUBLE_CLICK);
+ return $this;
+ }
+
+ /**
+ * @param WebDriverCoordinates $where
+ *
+ * @return RemoteMouse
+ */
+ public function mouseDown(WebDriverCoordinates $where = null) {
+ $this->moveIfNeeded($where);
+ $this->executor->execute(DriverCommand::MOUSE_DOWN);
+ return $this;
+ }
+
+ /**
+ * @param WebDriverCoordinates $where
+ * @param int|null $x_offset
+ * @param int|null $y_offset
+ *
+ * @return RemoteMouse
+ */
+ public function mouseMove(WebDriverCoordinates $where = null,
+ $x_offset = null,
+ $y_offset = null) {
+ $params = array();
+ if ($where !== null) {
+ $params['element'] = $where->getAuxiliary();
+ }
+ if ($x_offset !== null) {
+ $params['xoffset'] = $x_offset;
+ }
+ if ($y_offset !== null) {
+ $params['yoffset'] = $y_offset;
+ }
+ $this->executor->execute(DriverCommand::MOVE_TO, $params);
+ return $this;
+ }
+
+ /**
+ * @param WebDriverCoordinates $where
+ *
+ * @return RemoteMouse
+ */
+ public function mouseUp(WebDriverCoordinates $where = null) {
+ $this->moveIfNeeded($where);
+ $this->executor->execute(DriverCommand::MOUSE_UP);
+ return $this;
+ }
+
+ /**
+ * @param WebDriverCoordinates $where
+ * @return void
+ */
+ protected function moveIfNeeded(WebDriverCoordinates $where = null) {
+ if ($where) {
+ $this->mouseMove($where);
+ }
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/remote/RemoteTargetLocator.php b/tests/vendor/facebook/webdriver/lib/remote/RemoteTargetLocator.php
new file mode 100644
index 000000000000..949836675d9e
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/remote/RemoteTargetLocator.php
@@ -0,0 +1,97 @@
+executor = $executor;
+ $this->driver = $driver;
+ }
+
+ /**
+ * Switch to the main document if the page contains iframes. Otherwise, switch
+ * to the first frame on the page.
+ *
+ * @return WebDriver The driver focused on the top window or the first frame.
+ */
+ public function defaultContent() {
+ $params = array('id' => null);
+ $this->executor->execute(DriverCommand::SWITCH_TO_FRAME, $params);
+
+ return $this->driver;
+ }
+
+ /**
+ * Switch to the iframe by its id or name.
+ *
+ * @param WebDriverElement|string $frame The WebDriverElement,
+ the id or the name of the frame.
+ * @return WebDriver The driver focused on the given frame.
+ */
+ public function frame($frame) {
+ if ($frame instanceof WebDriverElement) {
+ $id = array('ELEMENT' => $frame->getID());
+ } else {
+ $id = (string)$frame;
+ }
+
+ $params = array('id' => $id);
+ $this->executor->execute(DriverCommand::SWITCH_TO_FRAME, $params);
+
+ return $this->driver;
+ }
+
+ /**
+ * Switch the focus to another window by its handle.
+ *
+ * @param string $handle The handle of the window to be focused on.
+ * @return WebDriver Tge driver focused on the given window.
+ * @see WebDriver::getWindowHandles
+ */
+ public function window($handle) {
+ $params = array('name' => (string)$handle);
+ $this->executor->execute(DriverCommand::SWITCH_TO_WINDOW, $params);
+
+ return $this->driver;
+ }
+
+ /**
+ * Switch to the currently active modal dialog for this particular driver
+ * instance.
+ *
+ * @return WebDriverAlert
+ */
+ public function alert() {
+ return new WebDriverAlert($this->executor);
+ }
+
+ /**
+ * Switches to the element that currently has focus within the document
+ * currently "switched to", or the body element if this cannot be detected.
+ *
+ * @return RemoteWebElement
+ */
+ public function activeElement() {
+ $response = $this->driver->execute(DriverCommand::GET_ACTIVE_ELEMENT);
+ $method = new RemoteExecuteMethod($this->driver);
+ return new RemoteWebElement($method, $response['ELEMENT']);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/remote/RemoteTouchScreen.php b/tests/vendor/facebook/webdriver/lib/remote/RemoteTouchScreen.php
new file mode 100644
index 000000000000..652020dea3c7
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/remote/RemoteTouchScreen.php
@@ -0,0 +1,192 @@
+executor = $executor;
+ }
+
+ /**
+ * @param WebDriverElement $element
+ *
+ * @return RemoteTouchScreen The instance.
+ */
+ public function tap(WebDriverElement $element) {
+ $this->executor->execute(
+ DriverCommand::TOUCH_SINGLE_TAP,
+ array('element' => $element->getID())
+ );
+
+ return $this;
+ }
+
+ /**
+ * @param WebDriverElement $element
+ *
+ * @return RemoteTouchScreen The instance.
+ */
+ public function doubleTap(WebDriverElement $element) {
+ $this->executor->execute(
+ DriverCommand::TOUCH_DOUBLE_TAP,
+ array('element' => $element->getID())
+ );
+
+ return $this;
+ }
+
+ /**
+ * @param int $x
+ * @param int $y
+ *
+ * @return RemoteTouchScreen The instance.
+ */
+ public function down($x, $y) {
+ $this->executor->execute(DriverCommand::TOUCH_DOWN, array(
+ 'x' => $x,
+ 'y' => $y,
+ ));
+
+ return $this;
+ }
+
+
+ /**
+ * @param int $xspeed
+ * @param int $yspeed
+ *
+ * @return RemoteTouchScreen The instance.
+ */
+ public function flick($xspeed, $yspeed) {
+ $this->executor->execute(DriverCommand::TOUCH_FLICK, array(
+ 'xspeed' => $xspeed,
+ 'yspeed' => $yspeed,
+ ));
+
+ return $this;
+ }
+
+ /**
+ * @param WebDriverElement $element
+ * @param int $xoffset
+ * @param int $yoffset
+ * @param int $speed
+ *
+ * @return RemoteTouchScreen The instance.
+ */
+ public function flickFromElement(
+ WebDriverElement $element, $xoffset, $yoffset, $speed
+ ) {
+ $this->executor->execute(DriverCommand::TOUCH_FLICK, array(
+ 'xoffset' => $xoffset,
+ 'yoffset' => $yoffset,
+ 'element' => $element->getID(),
+ 'speed' => $speed,
+ ));
+
+ return $this;
+ }
+
+ /**
+ * @param WebDriverElement $element
+ *
+ * @return RemoteTouchScreen The instance.
+ */
+ public function longPress(WebDriverElement $element) {
+ $this->executor->execute(
+ DriverCommand::TOUCH_LONG_PRESS,
+ array('element' => $element->getID())
+ );
+
+ return $this;
+ }
+
+ /**
+ * @param int $x
+ * @param int $y
+ *
+ * @return RemoteTouchScreen The instance.
+ */
+ public function move($x, $y) {
+ $this->executor->execute(DriverCommand::TOUCH_MOVE, array(
+ 'x' => $x,
+ 'y' => $y,
+ ));
+
+ return $this;
+ }
+
+ /**
+ * @param int $xoffset
+ * @param int $yoffset
+ *
+ * @return RemoteTouchScreen The instance.
+ */
+ public function scroll($xoffset, $yoffset) {
+ $this->executor->execute(DriverCommand::TOUCH_SCROLL, array(
+ 'xoffset' => $xoffset,
+ 'yoffset' => $yoffset,
+ ));
+
+ return $this;
+ }
+
+ /**
+ * @param WebDriverElement $element
+ * @param int $xoffset
+ * @param int $yoffset
+ *
+ * @return RemoteTouchScreen The instance.
+ */
+ public function scrollFromElement(
+ WebDriverElement $element, $xoffset, $yoffset
+ ) {
+ $this->executor->execute(DriverCommand::TOUCH_SCROLL, array(
+ 'element' => $element->getID(),
+ 'xoffset' => $xoffset,
+ 'yoffset' => $yoffset,
+ ));
+
+ return $this;
+ }
+
+
+ /**
+ * @param int $x
+ * @param int $y
+ *
+ * @return RemoteTouchScreen The instance.
+ */
+ public function up($x, $y) {
+ $this->executor->execute(DriverCommand::TOUCH_UP, array(
+ 'x' => $x,
+ 'y' => $y,
+ ));
+
+ return $this;
+ }
+
+}
diff --git a/tests/vendor/facebook/webdriver/lib/remote/RemoteWebDriver.php b/tests/vendor/facebook/webdriver/lib/remote/RemoteWebDriver.php
new file mode 100644
index 000000000000..2b0969f07a1e
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/remote/RemoteWebDriver.php
@@ -0,0 +1,494 @@
+toArray();
+ }
+
+ $executor = new HttpCommandExecutor($url);
+ if ($connection_timeout_in_ms !== null) {
+ $executor->setConnectionTimeout($connection_timeout_in_ms);
+ }
+ if ($request_timeout_in_ms !== null) {
+ $executor->setRequestTimeout($request_timeout_in_ms);
+ }
+
+ $command = new WebDriverCommand(
+ null,
+ DriverCommand::NEW_SESSION,
+ array('desiredCapabilities' => $desired_capabilities)
+ );
+
+ $response = $executor->execute($command);
+
+ $driver = new static();
+ $driver->setSessionID($response->getSessionID())
+ ->setCommandExecutor($executor);
+ return $driver;
+ }
+
+ /**
+ * [Experimental] Construct the RemoteWebDriver by an existing session.
+ *
+ * This constructor can boost the performance a lot by reusing the same
+ * browser for the whole test suite. You do not have to pass the desired
+ * capabilities because the session was created before.
+ *
+ * @param string $url The url of the remote server
+ * @param string $session_id The existing session id
+ * @return RemoteWebDriver
+ */
+ public static function createBySessionID(
+ $session_id,
+ $url = 'http://localhost:4444/wd/hub'
+ ) {
+ $driver = new static();
+ $driver->setSessionID($session_id)
+ ->setCommandExecutor(new HttpCommandExecutor($url));
+ return $driver;
+ }
+
+ /**
+ * Close the current window.
+ *
+ * @return RemoteWebDriver The current instance.
+ */
+ public function close() {
+ $this->execute(DriverCommand::CLOSE, array());
+
+ return $this;
+ }
+
+ /**
+ * Find the first WebDriverElement using the given mechanism.
+ *
+ * @param WebDriverBy $by
+ * @return RemoteWebElement NoSuchElementException is thrown in
+ * HttpCommandExecutor if no element is found.
+ * @see WebDriverBy
+ */
+ public function findElement(WebDriverBy $by) {
+ $params = array('using' => $by->getMechanism(), 'value' => $by->getValue());
+ $raw_element = $this->execute(
+ DriverCommand::FIND_ELEMENT,
+ $params
+ );
+
+ return $this->newElement($raw_element['ELEMENT']);
+ }
+
+ /**
+ * Find all WebDriverElements within the current page using the given
+ * mechanism.
+ *
+ * @param WebDriverBy $by
+ * @return RemoteWebElement[] A list of all WebDriverElements, or an empty
+ * array if nothing matches
+ * @see WebDriverBy
+ */
+ public function findElements(WebDriverBy $by) {
+ $params = array('using' => $by->getMechanism(), 'value' => $by->getValue());
+ $raw_elements = $this->execute(
+ DriverCommand::FIND_ELEMENTS,
+ $params
+ );
+
+ $elements = array();
+ foreach ($raw_elements as $raw_element) {
+ $elements[] = $this->newElement($raw_element['ELEMENT']);
+ }
+ return $elements;
+ }
+
+ /**
+ * Load a new web page in the current browser window.
+ *
+ * @param string $url
+ *
+ * @return RemoteWebDriver The current instance.
+ */
+ public function get($url) {
+ $params = array('url' => (string)$url);
+ $this->execute(DriverCommand::GET, $params);
+
+ return $this;
+ }
+
+ /**
+ * Get a string representing the current URL that the browser is looking at.
+ *
+ * @return string The current URL.
+ */
+ public function getCurrentURL() {
+ return $this->execute(DriverCommand::GET_CURRENT_URL);
+ }
+
+ /**
+ * Get the source of the last loaded page.
+ *
+ * @return string The current page source.
+ */
+ public function getPageSource() {
+ return $this->execute(DriverCommand::GET_PAGE_SOURCE);
+ }
+
+ /**
+ * Get the title of the current page.
+ *
+ * @return string The title of the current page.
+ */
+ public function getTitle() {
+ return $this->execute(DriverCommand::GET_TITLE);
+ }
+
+ /**
+ * Return an opaque handle to this window that uniquely identifies it within
+ * this driver instance.
+ *
+ * @return string The current window handle.
+ */
+ public function getWindowHandle() {
+ return $this->execute(
+ DriverCommand::GET_CURRENT_WINDOW_HANDLE,
+ array()
+ );
+ }
+
+ /**
+ * Get all window handles available to the current session.
+ *
+ * @return array An array of string containing all available window handles.
+ */
+ public function getWindowHandles() {
+ return $this->execute(DriverCommand::GET_WINDOW_HANDLES, array());
+ }
+
+ /**
+ * Quits this driver, closing every associated window.
+ *
+ * @return void
+ */
+ public function quit() {
+ $this->execute(DriverCommand::QUIT);
+ $this->executor = null;
+ }
+
+ /**
+ * Prepare arguments for JavaScript injection
+ *
+ * @param array $arguments
+ * @return array
+ */
+ private function prepareScriptArguments(array $arguments) {
+ $args = array();
+ foreach ($arguments as $key => $value) {
+ if ($value instanceof WebDriverElement) {
+ $args[$key] = array('ELEMENT'=>$value->getID());
+ } else {
+ if (is_array($value)) {
+ $value = $this->prepareScriptArguments($value);
+ }
+ $args[$key] = $value;
+ }
+ }
+ return $args;
+ }
+
+ /**
+ * Inject a snippet of JavaScript into the page for execution in the context
+ * of the currently selected frame. The executed script is assumed to be
+ * synchronous and the result of evaluating the script will be returned.
+ *
+ * @param string $script The script to inject.
+ * @param array $arguments The arguments of the script.
+ * @return mixed The return value of the script.
+ */
+ public function executeScript($script, array $arguments = array()) {
+ $params = array(
+ 'script' => $script,
+ 'args' => $this->prepareScriptArguments($arguments),
+ );
+ return $this->execute(DriverCommand::EXECUTE_SCRIPT, $params);
+ }
+
+ /**
+ * Inject a snippet of JavaScript into the page for asynchronous execution in
+ * the context of the currently selected frame.
+ *
+ * The driver will pass a callback as the last argument to the snippet, and
+ * block until the callback is invoked.
+ *
+ * @see WebDriverExecuteAsyncScriptTestCase
+ *
+ * @param string $script The script to inject.
+ * @param array $arguments The arguments of the script.
+ * @return mixed The value passed by the script to the callback.
+ */
+ public function executeAsyncScript($script, array $arguments = array()) {
+ $params = array(
+ 'script' => $script,
+ 'args' => $this->prepareScriptArguments($arguments),
+ );
+ return $this->execute(
+ DriverCommand::EXECUTE_ASYNC_SCRIPT,
+ $params
+ );
+ }
+
+ /**
+ * Take a screenshot of the current page.
+ *
+ * @param string $save_as The path of the screenshot to be saved.
+ * @return string The screenshot in PNG format.
+ */
+ public function takeScreenshot($save_as = null) {
+ $screenshot = base64_decode(
+ $this->execute(DriverCommand::SCREENSHOT)
+ );
+ if ($save_as) {
+ file_put_contents($save_as, $screenshot);
+ }
+ return $screenshot;
+ }
+
+ /**
+ * Construct a new WebDriverWait by the current WebDriver instance.
+ * Sample usage:
+ *
+ * $driver->wait(20, 1000)->until(
+ * WebDriverExpectedCondition::titleIs('WebDriver Page')
+ * );
+ *
+ * @param int $timeout_in_second
+ * @param int $interval_in_millisecond
+ *
+ * @return WebDriverWait
+ */
+ public function wait(
+ $timeout_in_second = 30,
+ $interval_in_millisecond = 250) {
+ return new WebDriverWait(
+ $this, $timeout_in_second, $interval_in_millisecond
+ );
+ }
+
+ /**
+ * An abstraction for managing stuff you would do in a browser menu. For
+ * example, adding and deleting cookies.
+ *
+ * @return WebDriverOptions
+ */
+ public function manage() {
+ return new WebDriverOptions($this->getExecuteMethod());
+ }
+
+ /**
+ * An abstraction allowing the driver to access the browser's history and to
+ * navigate to a given URL.
+ *
+ * @return WebDriverNavigation
+ * @see WebDriverNavigation
+ */
+ public function navigate() {
+ return new WebDriverNavigation($this->getExecuteMethod());
+ }
+
+ /**
+ * Switch to a different window or frame.
+ *
+ * @return RemoteTargetLocator
+ * @see RemoteTargetLocator
+ */
+ public function switchTo() {
+ return new RemoteTargetLocator($this->getExecuteMethod(), $this);
+ }
+
+ /**
+ * @return RemoteMouse
+ */
+ public function getMouse() {
+ if (!$this->mouse) {
+ $this->mouse = new RemoteMouse($this->getExecuteMethod());
+ }
+ return $this->mouse;
+ }
+
+ /**
+ * @return RemoteKeyboard
+ */
+ public function getKeyboard() {
+ if (!$this->keyboard) {
+ $this->keyboard = new RemoteKeyboard($this->getExecuteMethod());
+ }
+ return $this->keyboard;
+ }
+
+ /**
+ * @return RemoteTouchScreen
+ */
+ public function getTouch() {
+ if (!$this->touch) {
+ $this->touch = new RemoteTouchScreen($this->getExecuteMethod());
+ }
+ return $this->touch;
+ }
+
+ protected function getExecuteMethod() {
+ if (!$this->executeMethod) {
+ $this->executeMethod = new RemoteExecuteMethod($this);
+ }
+ return $this->executeMethod;
+ }
+
+ /**
+ * Construct a new action builder.
+ *
+ * @return WebDriverActions
+ */
+ public function action() {
+ return new WebDriverActions($this);
+ }
+
+ /**
+ * Return the WebDriverElement with the given id.
+ *
+ * @param string $id The id of the element to be created.
+ * @return RemoteWebElement
+ */
+ private function newElement($id) {
+ return new RemoteWebElement($this->getExecuteMethod(), $id);
+ }
+
+ /**
+ * Set the command executor of this RemoteWebdriver
+ *
+ * @param WebDriverCommandExecutor $executor
+ * @return RemoteWebDriver
+ */
+ public function setCommandExecutor(WebDriverCommandExecutor $executor) {
+ $this->executor = $executor;
+ return $this;
+ }
+
+ /**
+ * Set the command executor of this RemoteWebdriver
+ *
+ * @return HttpCommandExecutor
+ */
+ public function getCommandExecutor() {
+ return $this->executor;
+ }
+
+ /**
+ * Set the session id of the RemoteWebDriver.
+ *
+ * @param string $session_id
+ * @return RemoteWebDriver
+ */
+ public function setSessionID($session_id) {
+ $this->sessionID = $session_id;
+ return $this;
+ }
+
+ /**
+ * Get current selenium sessionID
+ *
+ * @return string sessionID
+ */
+ public function getSessionID() {
+ return $this->sessionID;
+ }
+
+ /**
+ * Get all selenium sessions.
+ *
+ * @param string $url The url of the remote server
+ * @param int $timeout_in_ms
+ * @return array
+ */
+ public static function getAllSessions(
+ $url = 'http://localhost:4444/wd/hub',
+ $timeout_in_ms = 30000
+ ) {
+ $executor = new HttpCommandExecutor($url);
+ $executor->setConnectionTimeout($timeout_in_ms);
+
+ $command = new WebDriverCommand(
+ null,
+ DriverCommand::GET_ALL_SESSIONS,
+ array()
+ );
+
+ return $executor->execute($command)->getValue();
+ }
+
+ public function execute($command_name, $params = array()) {
+ $command = new WebDriverCommand(
+ $this->sessionID,
+ $command_name,
+ $params
+ );
+
+ $response = $this->executor->execute($command);
+ return $response->getValue();
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/remote/RemoteWebElement.php b/tests/vendor/facebook/webdriver/lib/remote/RemoteWebElement.php
new file mode 100644
index 000000000000..ea4d1b992936
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/remote/RemoteWebElement.php
@@ -0,0 +1,410 @@
+executor = $executor;
+ $this->id = $id;
+ $this->fileDetector = new UselessFileDetector();
+ }
+
+ /**
+ * If this element is a TEXTAREA or text INPUT element, this will clear the
+ * value.
+ *
+ * @return RemoteWebElement The current instance.
+ */
+ public function clear() {
+ $this->executor->execute(
+ DriverCommand::CLEAR_ELEMENT,
+ array(':id' => $this->id)
+ );
+ return $this;
+ }
+
+ /**
+ * Click this element.
+ *
+ * @return RemoteWebElement The current instance.
+ */
+ public function click() {
+ $this->executor->execute(
+ DriverCommand::CLICK_ELEMENT,
+ array(':id' => $this->id)
+ );
+ return $this;
+ }
+
+ /**
+ * Find the first WebDriverElement within this element using the given
+ * mechanism.
+ *
+ * @param WebDriverBy $by
+ * @return RemoteWebElement NoSuchElementException is thrown in
+ * HttpCommandExecutor if no element is found.
+ * @see WebDriverBy
+ */
+ public function findElement(WebDriverBy $by) {
+ $params = array(
+ 'using' => $by->getMechanism(),
+ 'value' => $by->getValue(),
+ ':id' => $this->id,
+ );
+ $raw_element = $this->executor->execute(
+ DriverCommand::FIND_CHILD_ELEMENT,
+ $params
+ );
+
+ return $this->newElement($raw_element['ELEMENT']);
+ }
+
+ /**
+ * Find all WebDriverElements within this element using the given mechanism.
+ *
+ * @param WebDriverBy $by
+ * @return RemoteWebElement[] A list of all WebDriverElements, or an empty
+ * array if nothing matches
+ * @see WebDriverBy
+ */
+ public function findElements(WebDriverBy $by) {
+ $params = array(
+ 'using' => $by->getMechanism(),
+ 'value' => $by->getValue(),
+ ':id' => $this->id,
+ );
+ $raw_elements = $this->executor->execute(
+ DriverCommand::FIND_CHILD_ELEMENTS,
+ $params
+ );
+
+ $elements = array();
+ foreach ($raw_elements as $raw_element) {
+ $elements[] = $this->newElement($raw_element['ELEMENT']);
+ }
+ return $elements;
+ }
+
+ /**
+ * Get the value of a the given attribute of the element.
+ *
+ * @param string $attribute_name The name of the attribute.
+ * @return string|null The value of the attribute.
+ */
+ public function getAttribute($attribute_name) {
+ $params = array(
+ ':name' => $attribute_name,
+ ':id' => $this->id,
+ );
+ return $this->executor->execute(
+ DriverCommand::GET_ELEMENT_ATTRIBUTE,
+ $params
+ );
+ }
+
+ /**
+ * Get the value of a given CSS property.
+ *
+ * @param string $css_property_name The name of the CSS property.
+ * @return string The value of the CSS property.
+ */
+ public function getCSSValue($css_property_name) {
+ $params = array(
+ ':propertyName' => $css_property_name,
+ ':id' => $this->id,
+ );
+ return $this->executor->execute(
+ DriverCommand::GET_ELEMENT_VALUE_OF_CSS_PROPERTY,
+ $params
+ );
+ }
+
+ /**
+ * Get the location of element relative to the top-left corner of the page.
+ *
+ * @return WebDriverPoint The location of the element.
+ */
+ public function getLocation() {
+ $location = $this->executor->execute(
+ DriverCommand::GET_ELEMENT_LOCATION,
+ array(':id' => $this->id)
+ );
+ return new WebDriverPoint($location['x'], $location['y']);
+ }
+
+ /**
+ * Try scrolling the element into the view port and return the location of
+ * element relative to the top-left corner of the page afterwards.
+ *
+ * @return WebDriverPoint The location of the element.
+ */
+ public function getLocationOnScreenOnceScrolledIntoView() {
+ $location = $this->executor->execute(
+ DriverCommand::GET_ELEMENT_LOCATION_ONCE_SCROLLED_INTO_VIEW,
+ array(':id' => $this->id)
+ );
+ return new WebDriverPoint($location['x'], $location['y']);
+ }
+
+ /**
+ * @return WebDriverCoordinates
+ */
+ public function getCoordinates() {
+ $element = $this;
+
+ $on_screen = null; // planned but not yet implemented
+ $in_view_port = function () use ($element) {
+ return $element->getLocationOnScreenOnceScrolledIntoView();
+ };
+ $on_page = function () use ($element) {
+ return $element->getLocation();
+ };
+ $auxiliary = $this->getID();
+
+ return new WebDriverCoordinates(
+ $on_screen,
+ $in_view_port,
+ $on_page,
+ $auxiliary
+ );
+ }
+
+ /**
+ * Get the size of element.
+ *
+ * @return WebDriverDimension The dimension of the element.
+ */
+ public function getSize() {
+ $size = $this->executor->execute(
+ DriverCommand::GET_ELEMENT_SIZE,
+ array(':id' => $this->id)
+ );
+ return new WebDriverDimension($size['width'], $size['height']);
+ }
+
+ /**
+ * Get the tag name of this element.
+ *
+ * @return string The tag name.
+ */
+ public function getTagName() {
+ // Force tag name to be lowercase as expected by protocol for Opera driver
+ // until this issue is not resolved :
+ // https://github.com/operasoftware/operadriver/issues/102
+ // Remove it when fixed to be consistent with the protocol.
+ return strtolower($this->executor->execute(
+ DriverCommand::GET_ELEMENT_TAG_NAME,
+ array(':id' => $this->id)
+ ));
+ }
+
+ /**
+ * Get the visible (i.e. not hidden by CSS) innerText of this element,
+ * including sub-elements, without any leading or trailing whitespace.
+ *
+ * @return string The visible innerText of this element.
+ */
+ public function getText() {
+ return $this->executor->execute(
+ DriverCommand::GET_ELEMENT_TEXT,
+ array(':id' => $this->id)
+ );
+ }
+
+ /**
+ * Is this element displayed or not? This method avoids the problem of having
+ * to parse an element's "style" attribute.
+ *
+ * @return bool
+ */
+ public function isDisplayed() {
+ return $this->executor->execute(
+ DriverCommand::IS_ELEMENT_DISPLAYED,
+ array(':id' => $this->id)
+ );
+ }
+
+ /**
+ * Is the element currently enabled or not? This will generally return true
+ * for everything but disabled input elements.
+ *
+ * @return bool
+ */
+ public function isEnabled() {
+ return $this->executor->execute(
+ DriverCommand::IS_ELEMENT_ENABLED,
+ array(':id' => $this->id)
+ );
+ }
+
+ /**
+ * Determine whether or not this element is selected or not.
+ *
+ * @return bool
+ */
+ public function isSelected() {
+ return $this->executor->execute(
+ DriverCommand::IS_ELEMENT_SELECTED,
+ array(':id' => $this->id)
+ );
+ }
+
+ /**
+ * Simulate typing into an element, which may set its value.
+ *
+ * @param mixed $value The data to be typed.
+ * @return RemoteWebElement The current instance.
+ */
+ public function sendKeys($value) {
+ $local_file = $this->fileDetector->getLocalFile($value);
+ if ($local_file === null) {
+ $params = array(
+ 'value' => WebDriverKeys::encode($value),
+ ':id' => $this->id,
+ );
+ $this->executor->execute(DriverCommand::SEND_KEYS_TO_ELEMENT, $params);
+ } else {
+ $remote_path = $this->upload($local_file);
+ $params = array(
+ 'value' => WebDriverKeys::encode($remote_path),
+ ':id' => $this->id,
+ );
+ $this->executor->execute(DriverCommand::SEND_KEYS_TO_ELEMENT, $params);
+ }
+ return $this;
+ }
+
+ /**
+ * Upload a local file to the server
+ *
+ * @param string $local_file
+ *
+ * @throws WebDriverException
+ * @return string The remote path of the file.
+ */
+ private function upload($local_file) {
+ if (!is_file($local_file)) {
+ throw new WebDriverException("You may only upload files: " . $local_file);
+ }
+
+ // Create a temporary file in the system temp directory.
+ $temp_zip = tempnam('', 'WebDriverZip');
+ $zip = new ZipArchive();
+ if ($zip->open($temp_zip, ZipArchive::CREATE) !== true) {
+ return false;
+ }
+ $info = pathinfo($local_file);
+ $file_name = $info['basename'];
+ $zip->addFile($local_file, $file_name);
+ $zip->close();
+ $params = array(
+ 'file' => base64_encode(file_get_contents($temp_zip)),
+ );
+ $remote_path = $this->executor->execute(
+ DriverCommand::UPLOAD_FILE,
+ $params
+ );
+ unlink($temp_zip);
+ return $remote_path;
+ }
+
+ /**
+ * Set the fileDetector in order to let the RemoteWebElement to know that
+ * you are going to upload a file.
+ *
+ * Basically, if you want WebDriver trying to send a file, set the fileDetector
+ * to be LocalFileDetector. Otherwise, keep it UselessFileDetector.
+ *
+ * eg. $element->setFileDetector(new LocalFileDetector);
+ *
+ * @param FileDetector $detector
+ * @return RemoteWebElement
+ * @see FileDetector
+ * @see LocalFileDetector
+ * @see UselessFileDetector
+ */
+ public function setFileDetector(FileDetector $detector) {
+ $this->fileDetector = $detector;
+ return $this;
+ }
+
+ /**
+ * If this current element is a form, or an element within a form, then this
+ * will be submitted to the remote server.
+ *
+ * @return RemoteWebElement The current instance.
+ */
+ public function submit() {
+ $this->executor->execute(
+ DriverCommand::SUBMIT_ELEMENT,
+ array(':id' => $this->id)
+ );
+
+ return $this;
+ }
+
+ /**
+ * Get the opaque ID of the element.
+ *
+ * @return string The opaque ID.
+ */
+ public function getID() {
+ return $this->id;
+ }
+
+ /**
+ * Test if two element IDs refer to the same DOM element.
+ *
+ * @param WebDriverElement $other
+ * @return bool
+ */
+ public function equals(WebDriverElement $other) {
+ return $this->executor->execute(DriverCommand::ELEMENT_EQUALS, array(
+ ':id' => $this->id,
+ ':other' => $other->getID(),
+ ));
+ }
+
+ /**
+ * Return the WebDriverElement with $id
+ *
+ * @param string $id
+ *
+ * @return RemoteWebElement
+ */
+ private function newElement($id) {
+ return new RemoteWebElement($this->executor, $id);
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/remote/UselessFileDetector.php b/tests/vendor/facebook/webdriver/lib/remote/UselessFileDetector.php
new file mode 100644
index 000000000000..db4c3f2cdd55
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/remote/UselessFileDetector.php
@@ -0,0 +1,25 @@
+sessionID = $session_id;
+ $this->name = $name;
+ $this->parameters = $parameters;
+ }
+
+ public function getName() {
+ return $this->name;
+ }
+
+ public function getSessionID() {
+ return $this->sessionID;
+ }
+
+ public function getParameters() {
+ return $this->parameters;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/remote/WebDriverResponse.php b/tests/vendor/facebook/webdriver/lib/remote/WebDriverResponse.php
new file mode 100644
index 000000000000..a42e3067cac2
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/remote/WebDriverResponse.php
@@ -0,0 +1,87 @@
+sessionID = $session_id;
+ }
+
+ /**
+ * @return null|int
+ */
+ public function getStatus() {
+ return $this->status;
+ }
+
+ /**
+ * @param int $status
+ * @return WebDriverResponse
+ */
+ public function setStatus($status) {
+ $this->status = $status;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getValue() {
+ return $this->value;
+ }
+
+ /**
+ * @param mixed $value
+ * @return WebDriverResponse
+ */
+ public function setValue($value) {
+ $this->value = $value;
+ return $this;
+ }
+
+ /**
+ * @return null|string
+ */
+ public function getSessionID() {
+ return $this->sessionID;
+ }
+
+ /**
+ * @param mixed $session_id
+ * @return WebDriverResponse
+ */
+ public function setSessionID($session_id) {
+ $this->sessionID = $session_id;
+ return $this;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/remote/service/DriverCommandExecutor.php b/tests/vendor/facebook/webdriver/lib/remote/service/DriverCommandExecutor.php
new file mode 100644
index 000000000000..51cdda466d11
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/remote/service/DriverCommandExecutor.php
@@ -0,0 +1,57 @@
+getURL());
+ $this->service = $service;
+ }
+
+ /**
+ * @param WebDriverCommand $command
+ * @param array $curl_opts
+ *
+ * @return mixed
+ */
+ public function execute(WebDriverCommand $command, $curl_opts = array()) {
+ if ($command->getName() === DriverCommand::NEW_SESSION) {
+ $this->service->start();
+ }
+
+ try {
+ $value = parent::execute($command, $curl_opts);
+ if ($command->getName() === DriverCommand::QUIT) {
+ $this->service->stop();
+ }
+ return $value;
+ } catch (Exception $e) {
+ if (!$this->service->isRunning()) {
+ throw new WebDriverException('The driver server has died.');
+ }
+ throw $e;
+ }
+ }
+
+}
diff --git a/tests/vendor/facebook/webdriver/lib/remote/service/DriverService.php b/tests/vendor/facebook/webdriver/lib/remote/service/DriverService.php
new file mode 100644
index 000000000000..607bf8fb8ef0
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/remote/service/DriverService.php
@@ -0,0 +1,142 @@
+executable = self::checkExecutable($executable);
+ $this->url = sprintf('http://localhost:%d', $port);
+ $this->args = $args;
+ $this->environment = $environment ?: $_ENV;
+ }
+
+ /**
+ * @return string
+ */
+ public function getURL() {
+ return $this->url;
+ }
+
+ /**
+ * @return DriverService
+ */
+ public function start() {
+ if ($this->process !== null) {
+ return $this;
+ }
+
+ $pipes = array();
+ $this->process = proc_open(
+ sprintf("%s %s", $this->executable, implode(' ', $this->args)),
+ $descriptorspec = array(
+ 0 => array('pipe', 'r'), // stdin
+ 1 => array('pipe', 'w'), // stdout
+ 2 => array('pipe', 'a'), // stderr
+ ),
+ $pipes,
+ null,
+ $this->environment
+ );
+
+ $checker = new URLChecker();
+ $checker->waitUntilAvailable(20 * 1000, $this->url.'/status');
+
+ return $this;
+ }
+
+ /**
+ * @return DriverService
+ */
+ public function stop() {
+ if ($this->process === null) {
+ return $this;
+ }
+
+ proc_terminate($this->process);
+ $this->process = null;
+
+ $checker = new URLChecker();
+ $checker->waitUntilUnAvailable(3 * 1000, $this->url.'/shutdown');
+
+ return $this;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isRunning() {
+ if ($this->process === null) {
+ return false;
+ }
+
+ $status = proc_get_status($this->process);
+ return $status['running'];
+ }
+
+ /**
+ * Check if the executable is executable.
+ *
+ * @param string $executable
+ * @return string
+ * @throws Exception
+ */
+ protected static function checkExecutable($executable) {
+ if (!is_file($executable)) {
+ throw new Exception("'$executable' is not a file.");
+ }
+
+ if (!is_executable($executable)) {
+ throw new Exception("'$executable' is not executable.");
+ }
+
+ return $executable;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/support/events/EventFiringWebDriver.php b/tests/vendor/facebook/webdriver/lib/support/events/EventFiringWebDriver.php
new file mode 100644
index 000000000000..5f09493eb99c
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/support/events/EventFiringWebDriver.php
@@ -0,0 +1,351 @@
+dispatcher = $dispatcher ?: new WebDriverDispatcher();
+ if (!$this->dispatcher->getDefaultDriver()) {
+ $this->dispatcher->setDefaultDriver($this);
+ }
+ $this->driver = $driver;
+ return $this;
+ }
+
+ /**
+ * @return WebDriverDispatcher
+ */
+ public function getDispatcher() {
+ return $this->dispatcher;
+ }
+
+ /**
+ * @param mixed $method
+ * @return void
+ */
+ protected function dispatch($method) {
+ if (!$this->dispatcher) {
+ return;
+ }
+
+ $arguments = func_get_args();
+ unset($arguments[0]);
+ $this->dispatcher->dispatch($method, $arguments);
+ }
+
+ /**
+ * @return WebDriver
+ */
+ public function getWebDriver() {
+ return $this->driver;
+ }
+
+ /**
+ * @param WebDriverElement $element
+ * @return EventFiringWebElement
+ */
+ private function newElement(WebDriverElement $element) {
+ return new EventFiringWebElement($element, $this->getDispatcher());
+ }
+
+ /**
+ * @param mixed $url
+ * @return $this
+ * @throws WebDriverException
+ */
+ public function get($url) {
+ $this->dispatch('beforeNavigateTo', $url, $this);
+ try {
+ $this->driver->get($url);
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ $this->dispatch('afterNavigateTo', $url, $this);
+ return $this;
+ }
+
+ /**
+ * @param WebDriverBy $by
+ * @return array
+ * @throws WebDriverException
+ */
+ public function findElements(WebDriverBy $by) {
+ $this->dispatch('beforeFindBy', $by, null, $this);
+ try {
+ $elements = array();
+ foreach ($this->driver->findElements($by) as $element) {
+ $elements[] = $this->newElement($element);
+ }
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ $this->dispatch('afterFindBy', $by, null, $this);
+ return $elements;
+
+ }
+
+ /**
+ * @param WebDriverBy $by
+ * @return EventFiringWebElement
+ * @throws WebDriverException
+ */
+ public function findElement(WebDriverBy $by) {
+ $this->dispatch('beforeFindBy', $by, null, $this);
+ try {
+ $element = $this->newElement($this->driver->findElement($by));
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ $this->dispatch('afterFindBy', $by, null, $this);
+ return $element;
+ }
+
+ /**
+ * @param $script
+ * @param array $arguments
+ * @return mixed
+ * @throws WebDriverException
+ */
+ public function executeScript($script, array $arguments = array()) {
+ if (!$this->driver instanceof JavaScriptExecutor) {
+ throw new UnsupportedOperationException(
+ 'driver does not implement JavaScriptExecutor'
+ );
+ }
+
+ $this->dispatch('beforeScript', $script, $this);
+ try {
+ $result = $this->driver->executeScript($script, $arguments);
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ $this->dispatch('afterScript', $script, $this);
+ return $result;
+ }
+
+ /**
+ * @param $script
+ * @param array $arguments
+ * @return mixed
+ * @throws WebDriverException
+ */
+ public function executeAsyncScript($script, array $arguments = array()) {
+ if (!$this->driver instanceof JavaScriptExecutor) {
+ throw new UnsupportedOperationException(
+ 'driver does not implement JavaScriptExecutor'
+ );
+ }
+
+ $this->dispatch('beforeScript', $script, $this);
+ try {
+ $result = $this->driver->executeAsyncScript($script, $arguments);
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ $this->dispatch('afterScript', $script, $this);
+ return $result;
+ }
+
+ /**
+ * @return $this
+ * @throws WebDriverException
+ */
+ public function close() {
+ try {
+ $this->driver->close();
+ return $this;
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return string
+ * @throws WebDriverException
+ */
+ public function getCurrentURL() {
+ try {
+ return $this->driver->getCurrentURL();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return string
+ * @throws WebDriverException
+ */
+ public function getPageSource() {
+ try {
+ return $this->driver->getPageSource();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return string
+ * @throws WebDriverException
+ */
+ public function getTitle() {
+ try {
+ return $this->driver->getTitle();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return string
+ * @throws WebDriverException
+ */
+ public function getWindowHandle() {
+ try {
+ return $this->driver->getWindowHandle();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return array
+ * @throws WebDriverException
+ */
+ public function getWindowHandles() {
+ try {
+ return $this->driver->getWindowHandles();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @throws WebDriverException
+ */
+ public function quit() {
+ try {
+ $this->driver->quit();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @param null|string $save_as
+ * @return string
+ * @throws WebDriverException
+ */
+ public function takeScreenshot($save_as = null) {
+ try {
+ return $this->driver->takeScreenshot($save_as);
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @param int $timeout_in_second
+ * @param int $interval_in_millisecond
+ * @return WebDriverWait
+ * @throws WebDriverException
+ */
+ public function wait($timeout_in_second = 30,
+ $interval_in_millisecond = 250) {
+ try {
+ return $this->driver->wait($timeout_in_second, $interval_in_millisecond);
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return WebDriverOptions
+ * @throws WebDriverException
+ */
+ public function manage() {
+ try {
+ return $this->driver->manage();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return EventFiringWebDriverNavigation
+ * @throws WebDriverException
+ */
+ public function navigate() {
+ try {
+ return new EventFiringWebDriverNavigation(
+ $this->driver->navigate(),
+ $this->getDispatcher()
+ );
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return WebDriverTargetLocator
+ * @throws WebDriverException
+ */
+ public function switchTo() {
+ try {
+ return $this->driver->switchTo();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return WebDriverTouchScreen
+ * @throws WebDriverException
+ */
+ public function getTouch() {
+ try {
+ return $this->driver->getTouch();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ private function dispatchOnException($exception) {
+ $this->dispatch('onException', $exception, $this);
+ throw $exception;
+ }
+
+ public function execute($name, $params) {
+ try {
+ return $this->driver->execute($name, $params);
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/support/events/EventFiringWebDriverNavigation.php b/tests/vendor/facebook/webdriver/lib/support/events/EventFiringWebDriverNavigation.php
new file mode 100644
index 000000000000..5fb96f929df1
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/support/events/EventFiringWebDriverNavigation.php
@@ -0,0 +1,150 @@
+navigator = $navigator;
+ $this->dispatcher = $dispatcher;
+ return $this;
+ }
+
+ /**
+ * @return WebDriverDispatcher
+ */
+ public function getDispatcher() {
+ return $this->dispatcher;
+ }
+
+ /**
+ * @param mixed $method
+ * @return void
+ */
+ protected function dispatch($method) {
+ if (!$this->dispatcher) {
+ return;
+ }
+
+ $arguments = func_get_args();
+ unset($arguments[0]);
+ $this->dispatcher->dispatch($method, $arguments);
+ }
+
+ /**
+ * @return WebDriverNavigation
+ */
+ public function getNavigator() {
+ return $this->navigator;
+ }
+
+ /**
+ * @return $this
+ * @throws WebDriverException
+ */
+ public function back() {
+ $this->dispatch(
+ 'beforeNavigateBack',
+ $this->getDispatcher()->getDefaultDriver()
+ );
+ try {
+ $this->navigator->back();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ $this->dispatch(
+ 'afterNavigateBack',
+ $this->getDispatcher()->getDefaultDriver()
+ );
+ return $this;
+ }
+
+ /**
+ * @return $this
+ * @throws WebDriverException
+ */
+ public function forward() {
+ $this->dispatch(
+ 'beforeNavigateForward',
+ $this->getDispatcher()->getDefaultDriver()
+ );
+ try {
+ $this->navigator->forward();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ $this->dispatch(
+ 'afterNavigateForward',
+ $this->getDispatcher()->getDefaultDriver()
+ );
+ return $this;
+ }
+
+ /**
+ * @return $this
+ * @throws WebDriverException
+ */
+ public function refresh() {
+ try {
+ $this->navigator->refresh();
+ return $this;
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @param mixed $url
+ * @return $this
+ * @throws WebDriverException
+ */
+ public function to($url) {
+ $this->dispatch(
+ 'beforeNavigateTo',
+ $url,
+ $this->getDispatcher()->getDefaultDriver()
+ );
+ try {
+ $this->navigator->to($url);
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ $this->dispatch(
+ 'afterNavigateTo',
+ $url,
+ $this->getDispatcher()->getDefaultDriver()
+ );
+ return $this;
+ }
+
+ private function dispatchOnException($exception) {
+ $this->dispatch('onException', $exception);
+ throw $exception;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/lib/support/events/EventFiringWebElement.php b/tests/vendor/facebook/webdriver/lib/support/events/EventFiringWebElement.php
new file mode 100644
index 000000000000..1e0e499af175
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/lib/support/events/EventFiringWebElement.php
@@ -0,0 +1,358 @@
+element = $element;
+ $this->dispatcher = $dispatcher;
+ return $this;
+ }
+
+ /**
+ * @return WebDriverDispatcher
+ */
+ public function getDispatcher() {
+ return $this->dispatcher;
+ }
+
+ /**
+ * @param mixed $method
+ * @return void
+ */
+ protected function dispatch($method) {
+ if (!$this->dispatcher) {
+ return;
+ }
+ $arguments = func_get_args();
+ unset($arguments[0]);
+ $this->dispatcher->dispatch($method, $arguments);
+ }
+
+ /**
+ * @return WebDriverElement
+ */
+ public function getElement() {
+ return $this->element;
+ }
+
+ /**
+ * @param WebDriverElement $element
+ * @return EventFiringWebElement
+ */
+ private function newElement(WebDriverElement $element) {
+ return new EventFiringWebElement($element, $this->getDispatcher());
+ }
+
+ /**
+ * @param mixed $value
+ * @return $this
+ * @throws WebDriverException
+ */
+ public function sendKeys($value) {
+
+ $this->dispatch('beforeChangeValueOf', $this);
+ try {
+ $this->element->sendKeys($value);
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ $this->dispatch('afterChangeValueOf', $this);
+ return $this;
+
+ }
+
+ /**
+ * @return $this
+ * @throws WebDriverException
+ */
+ public function click() {
+ $this->dispatch('beforeClickOn', $this);
+ try {
+ $this->element->click();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ $this->dispatch('afterClickOn', $this);
+ return $this;
+ }
+
+ /**
+ * @param WebDriverBy $by
+ * @return EventFiringWebElement
+ * @throws WebDriverException
+ */
+ public function findElement(WebDriverBy $by) {
+ $this->dispatch(
+ 'beforeFindBy',
+ $by,
+ $this,
+ $this->dispatcher->getDefaultDriver());
+ try {
+ $element = $this->newElement($this->element->findElement($by));
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ $this->dispatch(
+ 'afterFindBy',
+ $by,
+ $this,
+ $this->dispatcher->getDefaultDriver()
+ );
+ return $element;
+ }
+
+ /**
+ * @param WebDriverBy $by
+ * @return array
+ * @throws WebDriverException
+ */
+ public function findElements(WebDriverBy $by) {
+ $this->dispatch(
+ 'beforeFindBy',
+ $by,
+ $this,
+ $this->dispatcher->getDefaultDriver()
+ );
+ try {
+ $elements = array();
+ foreach ($this->element->findElements($by) as $element) {
+ $elements[] = $this->newElement($element);
+ }
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ $this->dispatch(
+ 'afterFindBy',
+ $by,
+ $this,
+ $this->dispatcher->getDefaultDriver()
+ );
+ return $elements;
+ }
+
+ /**
+ * @return $this
+ * @throws WebDriverException
+ */
+ public function clear() {
+ try {
+ $this->element->clear();
+ return $this;
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @param string $attribute_name
+ * @return string
+ * @throws WebDriverException
+ */
+ public function getAttribute($attribute_name) {
+ try {
+ return $this->element->getAttribute($attribute_name);
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @param string $css_property_name
+ * @return string
+ * @throws WebDriverException
+ */
+ public function getCSSValue($css_property_name) {
+ try {
+ return $this->element->getCSSValue($css_property_name);
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return WebDriverPoint
+ * @throws WebDriverException
+ */
+ public function getLocation() {
+ try {
+ return $this->element->getLocation();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return WebDriverPoint
+ * @throws WebDriverException
+ */
+ public function getLocationOnScreenOnceScrolledIntoView() {
+ try {
+ return $this->element->getLocationOnScreenOnceScrolledIntoView();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return WebDriverCoordinates
+ */
+ public function getCoordinates() {
+ try {
+ return $this->element->getCoordinates();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+
+ /**
+ * @return WebDriverDimension
+ * @throws WebDriverException
+ */
+ public function getSize() {
+ try {
+ return $this->element->getSize();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return string
+ * @throws WebDriverException
+ */
+ public function getTagName() {
+ try {
+ return $this->element->getTagName();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return string
+ * @throws WebDriverException
+ */
+ public function getText() {
+ try {
+ return $this->element->getText();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return bool
+ * @throws WebDriverException
+ */
+ public function isDisplayed() {
+ try {
+ return $this->element->isDisplayed();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return bool
+ * @throws WebDriverException
+ */
+ public function isEnabled() {
+ try {
+ return $this->element->isEnabled();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return bool
+ * @throws WebDriverException
+ */
+ public function isSelected() {
+ try {
+ return $this->element->isSelected();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return $this
+ * @throws WebDriverException
+ */
+ public function submit() {
+ try {
+ $this->element->submit();
+ return $this;
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ /**
+ * @return string
+ * @throws WebDriverException
+ */
+ public function getID() {
+ try {
+ return $this->element->getID();
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+
+ /**
+ * Test if two element IDs refer to the same DOM element.
+ *
+ * @param WebDriverElement $other
+ * @return bool
+ */
+ public function equals(WebDriverElement $other) {
+ try {
+ return $this->element->equals($other);
+ } catch (WebDriverException $exception) {
+ $this->dispatchOnException($exception);
+ }
+ }
+
+ private function dispatchOnException($exception) {
+ $this->dispatch(
+ 'onException',
+ $exception,
+ $this->dispatcher->getDefaultDriver()
+ );
+ throw $exception;
+ }
+
+
+}
diff --git a/tests/vendor/facebook/webdriver/tests/bootstrap.php b/tests/vendor/facebook/webdriver/tests/bootstrap.php
new file mode 100644
index 000000000000..46df8183ea22
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/bootstrap.php
@@ -0,0 +1,4 @@
+driver->get($this->getTestPath('index.html'));
+ self::assertEquals(
+ 'php-webdriver test page',
+ $this->driver->getTitle()
+ );
+ }
+
+ public function testGetText() {
+ $this->driver->get($this->getTestPath('index.html'));
+ self::assertEquals(
+ 'Welcome to the facebook/php-webdriver testing page.',
+ $this->driver->findElement(WebDriverBy::id('welcome'))->getText()
+ );
+ }
+
+ public function testGetById() {
+ $this->driver->get($this->getTestPath('index.html'));
+ self::assertEquals(
+ 'Test by ID',
+ $this->driver->findElement(WebDriverBy::id('id_test'))->getText()
+ );
+ }
+
+ public function testGetByClassName() {
+ $this->driver->get($this->getTestPath('index.html'));
+ self::assertEquals(
+ 'Test by Class',
+ $this->driver->findElement(WebDriverBy::className('test_class'))->getText()
+ );
+ }
+
+ public function testGetByCssSelector() {
+ $this->driver->get($this->getTestPath('index.html'));
+ self::assertEquals(
+ 'Test by Class',
+ $this->driver->findElement(WebDriverBy::cssSelector('.test_class'))->getText()
+ );
+ }
+
+ public function testGetByLinkText() {
+ $this->driver->get($this->getTestPath('index.html'));
+ self::assertEquals(
+ 'Click here',
+ $this->driver->findElement(WebDriverBy::linkText('Click here'))->getText()
+ );
+ }
+
+ public function testGetByName() {
+ $this->driver->get($this->getTestPath('index.html'));
+ self::assertEquals(
+ 'Test Value',
+ $this->driver->findElement(WebDriverBy::name('test_name'))->getAttribute('value')
+ );
+ }
+
+ public function testGetByXpath() {
+ $this->driver->get($this->getTestPath('index.html'));
+ self::assertEquals(
+ 'Test Value',
+ $this->driver->findElement(WebDriverBy::xpath('//input[@name="test_name"]'))->getAttribute('value')
+ );
+ }
+
+ public function testGetByPartialLinkText() {
+ $this->driver->get($this->getTestPath('index.html'));
+ self::assertEquals(
+ 'Click here',
+ $this->driver->findElement(WebDriverBy::partialLinkText('Click'))->getText()
+ );
+ }
+
+ public function testGetByTagName() {
+ $this->driver->get($this->getTestPath('index.html'));
+ self::assertEquals(
+ 'Test Value',
+ $this->driver->findElement(WebDriverBy::tagName('input'))->getAttribute('value')
+ );
+ }
+}
\ No newline at end of file
diff --git a/tests/vendor/facebook/webdriver/tests/functional/FileUploadTest.php b/tests/vendor/facebook/webdriver/tests/functional/FileUploadTest.php
new file mode 100644
index 000000000000..84ec454e8654
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/functional/FileUploadTest.php
@@ -0,0 +1,42 @@
+driver->get($this->getTestPath('upload.html'));
+ $file_input = $this->driver->findElement(WebDriverBy::id('upload'));
+ $file_input->setFileDetector(new LocalFileDetector())
+ ->sendKeys(__DIR__ . '/files/FileUploadTestCaseFile.txt');
+ self::assertNotEquals($this->getFilePath(), $file_input->getAttribute('value'));
+ }
+
+ public function testUselessFileDetectorSendKeys() {
+ $this->driver->get($this->getTestPath('upload.html'));
+ $file_input = $this->driver->findElement(WebDriverBy::id('upload'));
+ $file_input->sendKeys($this->getFilePath());
+ self::assertEquals($this->getFilePath(), $file_input->getAttribute('value'));
+ }
+
+ private function getFilePath() {
+ return __DIR__ . '/files/FileUploadTestCaseFile.txt';
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/tests/functional/WebDriverTestCase.php b/tests/vendor/facebook/webdriver/tests/functional/WebDriverTestCase.php
new file mode 100644
index 000000000000..4a5b77f6c067
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/functional/WebDriverTestCase.php
@@ -0,0 +1,48 @@
+driver = RemoteWebDriver::create(
+ 'http://localhost:4444/wd/hub',
+ array(
+ WebDriverCapabilityType::BROWSER_NAME
+ //=> WebDriverBrowserType::FIREFOX,
+ => WebDriverBrowserType::HTMLUNIT,
+ )
+ );
+ }
+
+ protected function tearDown() {
+ $this->driver->quit();
+ }
+
+ /**
+ * Get the URL of the test html.
+ *
+ * @param $path
+ * @return string
+ */
+ protected function getTestPath($path) {
+ return 'file:///'.dirname(__FILE__).'/html/'.$path;
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/tests/functional/files/FileUploadTestCaseFile.txt b/tests/vendor/facebook/webdriver/tests/functional/files/FileUploadTestCaseFile.txt
new file mode 100644
index 000000000000..0ca232e37120
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/functional/files/FileUploadTestCaseFile.txt
@@ -0,0 +1 @@
+text file
diff --git a/tests/vendor/facebook/webdriver/tests/functional/html/index.html b/tests/vendor/facebook/webdriver/tests/functional/html/index.html
new file mode 100644
index 000000000000..6bafefdc9f69
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/functional/html/index.html
@@ -0,0 +1,12 @@
+
+
+ php-webdriver test page
+
+
+ Welcome to the facebook/php-webdriver testing page.
+ Test by ID
+ Test by Class
+ Click here
+
+
+
\ No newline at end of file
diff --git a/tests/vendor/facebook/webdriver/tests/functional/html/upload.html b/tests/vendor/facebook/webdriver/tests/functional/html/upload.html
new file mode 100644
index 000000000000..d542ad04f7c1
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/functional/html/upload.html
@@ -0,0 +1,10 @@
+
+
+ Upload a file
+
+
+
+
+
diff --git a/tests/vendor/facebook/webdriver/tests/phpunit.xml b/tests/vendor/facebook/webdriver/tests/phpunit.xml
new file mode 100644
index 000000000000..88bf4dbdefd2
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/phpunit.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+ ./unit
+
+
+ ./functional
+
+
+
+
diff --git a/tests/vendor/facebook/webdriver/tests/unit/bootstrap.php b/tests/vendor/facebook/webdriver/tests/unit/bootstrap.php
new file mode 100644
index 000000000000..562467964031
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/unit/bootstrap.php
@@ -0,0 +1,3 @@
+webDriverMouse = $this->getMock('WebDriverMouse');
+ $this->locationProvider = $this->getMock('WebDriverLocatable');
+ $this->webDriverButtonReleaseAction = new WebDriverButtonReleaseAction(
+ $this->webDriverMouse,
+ $this->locationProvider
+ );
+ }
+
+ public function testPerformSendsMouseUpCommand() {
+ $coords = $this->getMockBuilder('WebDriverCoordinates')->disableOriginalConstructor()->getMock();
+ $this->webDriverMouse->expects($this->once())->method('mouseUp')->with($coords);
+ $this->locationProvider->expects($this->once())->method('getCoordinates')->will($this->returnValue($coords));
+ $this->webDriverButtonReleaseAction->perform();
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverClickActionTest.php b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverClickActionTest.php
new file mode 100644
index 000000000000..98fd39197406
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverClickActionTest.php
@@ -0,0 +1,40 @@
+webDriverMouse = $this->getMock('WebDriverMouse');
+ $this->locationProvider = $this->getMock('WebDriverLocatable');
+ $this->webDriverClickAction = new WebDriverClickAction(
+ $this->webDriverMouse,
+ $this->locationProvider
+ );
+ }
+
+ public function testPerformSendsClickCommand() {
+ $coords = $this->getMockBuilder('WebDriverCoordinates')->disableOriginalConstructor()->getMock();
+ $this->webDriverMouse->expects($this->once())->method('click')->with($coords);
+ $this->locationProvider->expects($this->once())->method('getCoordinates')->will($this->returnValue($coords));
+ $this->webDriverClickAction->perform();
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverClickAndHoldActionTest.php b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverClickAndHoldActionTest.php
new file mode 100644
index 000000000000..fe1826ee078e
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverClickAndHoldActionTest.php
@@ -0,0 +1,40 @@
+webDriverMouse = $this->getMock('WebDriverMouse');
+ $this->locationProvider = $this->getMock('WebDriverLocatable');
+ $this->webDriverClickAndHoldAction = new WebDriverClickAndHoldAction(
+ $this->webDriverMouse,
+ $this->locationProvider
+ );
+ }
+
+ public function testPerformSendsMouseDownCommand() {
+ $coords = $this->getMockBuilder('WebDriverCoordinates')->disableOriginalConstructor()->getMock();
+ $this->webDriverMouse->expects($this->once())->method('mouseDown')->with($coords);
+ $this->locationProvider->expects($this->once())->method('getCoordinates')->will($this->returnValue($coords));
+ $this->webDriverClickAndHoldAction->perform();
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverContextClickActionTest.php b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverContextClickActionTest.php
new file mode 100644
index 000000000000..7ac3162cc95b
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverContextClickActionTest.php
@@ -0,0 +1,40 @@
+webDriverMouse = $this->getMock('WebDriverMouse');
+ $this->locationProvider = $this->getMock('WebDriverLocatable');
+ $this->webDriverContextClickAction = new WebDriverContextClickAction(
+ $this->webDriverMouse,
+ $this->locationProvider
+ );
+ }
+
+ public function testPerformSendsContextClickCommand() {
+ $coords = $this->getMockBuilder('WebDriverCoordinates')->disableOriginalConstructor()->getMock();
+ $this->webDriverMouse->expects($this->once())->method('contextClick')->with($coords);
+ $this->locationProvider->expects($this->once())->method('getCoordinates')->will($this->returnValue($coords));
+ $this->webDriverContextClickAction->perform();
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverCoordinatesTest.php b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverCoordinatesTest.php
new file mode 100644
index 000000000000..cf4cc0d12fc9
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverCoordinatesTest.php
@@ -0,0 +1,38 @@
+getAuxiliary());
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverDoubleClickActionTest.php b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverDoubleClickActionTest.php
new file mode 100644
index 000000000000..a0c85ac0d3a4
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverDoubleClickActionTest.php
@@ -0,0 +1,40 @@
+webDriverMouse = $this->getMock('WebDriverMouse');
+ $this->locationProvider = $this->getMock('WebDriverLocatable');
+ $this->webDriverDoubleClickAction = new WebDriverDoubleClickAction(
+ $this->webDriverMouse,
+ $this->locationProvider
+ );
+ }
+
+ public function testPerformSendsDoubleClickCommand() {
+ $coords = $this->getMockBuilder('WebDriverCoordinates')->disableOriginalConstructor()->getMock();
+ $this->webDriverMouse->expects($this->once())->method('doubleClick')->with($coords);
+ $this->locationProvider->expects($this->once())->method('getCoordinates')->will($this->returnValue($coords));
+ $this->webDriverDoubleClickAction->perform();
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverKeyDownActionTest.php b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverKeyDownActionTest.php
new file mode 100644
index 000000000000..f82b25cb1c36
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverKeyDownActionTest.php
@@ -0,0 +1,44 @@
+webDriverKeyboard = $this->getMock('WebDriverKeyboard');
+ $this->webDriverMouse = $this->getMock('WebDriverMouse');
+ $this->locationProvider = $this->getMock('WebDriverLocatable');
+ $this->webDriverKeyDownAction = new WebDriverKeyDownAction(
+ $this->webDriverKeyboard,
+ $this->webDriverMouse,
+ $this->locationProvider
+ );
+ }
+
+ public function testPerformFocusesOnElementAndSendPressKeyCommand() {
+ $coords = $this->getMockBuilder('WebDriverCoordinates')->disableOriginalConstructor()->getMock();
+ $this->webDriverMouse->expects($this->once())->method('click')->with($coords);
+ $this->locationProvider->expects($this->once())->method('getCoordinates')->will($this->returnValue($coords));
+ $this->webDriverKeyboard->expects($this->once())->method('pressKey');
+ $this->webDriverKeyDownAction->perform();
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverKeyUpActionTest.php b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverKeyUpActionTest.php
new file mode 100644
index 000000000000..e35277bd7583
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverKeyUpActionTest.php
@@ -0,0 +1,45 @@
+webDriverKeyboard = $this->getMock('WebDriverKeyboard');
+ $this->webDriverMouse = $this->getMock('WebDriverMouse');
+ $this->locationProvider = $this->getMock('WebDriverLocatable');
+ $this->webDriverKeyUpAction = new WebDriverKeyUpAction(
+ $this->webDriverKeyboard,
+ $this->webDriverMouse,
+ $this->locationProvider,
+ 'a'
+ );
+ }
+
+ public function testPerformFocusesOnElementAndSendPressKeyCommand() {
+ $coords = $this->getMockBuilder('WebDriverCoordinates')->disableOriginalConstructor()->getMock();
+ $this->webDriverMouse->expects($this->once())->method('click')->with($coords);
+ $this->locationProvider->expects($this->once())->method('getCoordinates')->will($this->returnValue($coords));
+ $this->webDriverKeyboard->expects($this->once())->method('releaseKey')->with('a');
+ $this->webDriverKeyUpAction->perform();
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverMouseMoveActionTest.php b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverMouseMoveActionTest.php
new file mode 100644
index 000000000000..aec3444d3883
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverMouseMoveActionTest.php
@@ -0,0 +1,40 @@
+webDriverMouse = $this->getMock('WebDriverMouse');
+ $this->locationProvider = $this->getMock('WebDriverLocatable');
+ $this->webDriverMouseMoveAction = new WebDriverMouseMoveAction(
+ $this->webDriverMouse,
+ $this->locationProvider
+ );
+ }
+
+ public function testPerformFocusesOnElementAndSendPressKeyCommand() {
+ $coords = $this->getMockBuilder('WebDriverCoordinates')->disableOriginalConstructor()->getMock();
+ $this->webDriverMouse->expects($this->once())->method('mouseMove')->with($coords);
+ $this->locationProvider->expects($this->once())->method('getCoordinates')->will($this->returnValue($coords));
+ $this->webDriverMouseMoveAction->perform();
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverMouseToOffsetActionTest.php b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverMouseToOffsetActionTest.php
new file mode 100644
index 000000000000..2cd2bc75d162
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverMouseToOffsetActionTest.php
@@ -0,0 +1,42 @@
+webDriverMouse = $this->getMock('WebDriverMouse');
+ $this->locationProvider = $this->getMock('WebDriverLocatable');
+ $this->webDriverMoveToOffsetAction = new WebDriverMoveToOffsetAction(
+ $this->webDriverMouse,
+ $this->locationProvider,
+ 150,
+ 200
+ );
+ }
+
+ public function testPerformFocusesOnElementAndSendPressKeyCommand() {
+ $coords = $this->getMockBuilder('WebDriverCoordinates')->disableOriginalConstructor()->getMock();
+ $this->webDriverMouse->expects($this->once())->method('mouseMove')->with($coords, 150, 200);
+ $this->locationProvider->expects($this->once())->method('getCoordinates')->will($this->returnValue($coords));
+ $this->webDriverMoveToOffsetAction->perform();
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverSendKeysActionTest.php b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverSendKeysActionTest.php
new file mode 100644
index 000000000000..9f9cad84b160
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/unit/interactions/internal/WebDriverSendKeysActionTest.php
@@ -0,0 +1,47 @@
+webDriverKeyboard = $this->getMock('WebDriverKeyboard');
+ $this->webDriverMouse = $this->getMock('WebDriverMouse');
+ $this->locationProvider = $this->getMock('WebDriverLocatable');
+ $this->keys = array('t', 'e', 's', 't');
+ $this->webDriverSendKeysAction = new WebDriverSendKeysAction(
+ $this->webDriverKeyboard,
+ $this->webDriverMouse,
+ $this->locationProvider,
+ $this->keys
+ );
+ }
+
+ public function testPerformFocusesOnElementAndSendPressKeyCommand() {
+ $coords = $this->getMockBuilder('WebDriverCoordinates')->disableOriginalConstructor()->getMock();
+ $this->webDriverKeyboard->expects($this->once())->method('sendKeys')->with($this->keys);
+ $this->webDriverMouse->expects($this->once())->method('click')->with($coords);
+ $this->locationProvider->expects($this->once())->method('getCoordinates')->will($this->returnValue($coords));
+ $this->webDriverSendKeysAction->perform();
+ }
+}
diff --git a/tests/vendor/facebook/webdriver/tests/unit/phpunit.xml b/tests/vendor/facebook/webdriver/tests/unit/phpunit.xml
new file mode 100644
index 000000000000..0338c9327827
--- /dev/null
+++ b/tests/vendor/facebook/webdriver/tests/unit/phpunit.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+ ../unit
+
+
+
+