123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604 |
- <?php
- // Copyright 2004-present Facebook. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- namespace Facebook\WebDriver\Remote;
- use Facebook\WebDriver\Interactions\WebDriverActions;
- use Facebook\WebDriver\JavaScriptExecutor;
- use Facebook\WebDriver\WebDriver;
- use Facebook\WebDriver\WebDriverBy;
- use Facebook\WebDriver\WebDriverCapabilities;
- use Facebook\WebDriver\WebDriverCommandExecutor;
- use Facebook\WebDriver\WebDriverElement;
- use Facebook\WebDriver\WebDriverHasInputDevices;
- use Facebook\WebDriver\WebDriverNavigation;
- use Facebook\WebDriver\WebDriverOptions;
- use Facebook\WebDriver\WebDriverWait;
- class RemoteWebDriver implements WebDriver, JavaScriptExecutor, WebDriverHasInputDevices
- {
- /**
- * @var HttpCommandExecutor|null
- */
- protected $executor;
- /**
- * @var WebDriverCapabilities
- */
- protected $capabilities;
- /**
- * @var string
- */
- protected $sessionID;
- /**
- * @var RemoteMouse
- */
- protected $mouse;
- /**
- * @var RemoteKeyboard
- */
- protected $keyboard;
- /**
- * @var RemoteTouchScreen
- */
- protected $touch;
- /**
- * @var RemoteExecuteMethod
- */
- protected $executeMethod;
- protected function __construct(
- HttpCommandExecutor $commandExecutor,
- $sessionId,
- WebDriverCapabilities $capabilities = null
- ) {
- $this->executor = $commandExecutor;
- $this->sessionID = $sessionId;
- if ($capabilities !== null) {
- $this->capabilities = $capabilities;
- }
- }
- /**
- * Construct the RemoteWebDriver by a desired capabilities.
- *
- * @param string $selenium_server_url The url of the remote Selenium WebDriver server
- * @param DesiredCapabilities|array $desired_capabilities The desired capabilities
- * @param int|null $connection_timeout_in_ms Set timeout for the connect phase to remote Selenium WebDriver server
- * @param int|null $request_timeout_in_ms Set the maximum time of a request to remote Selenium WebDriver server
- * @param string|null $http_proxy The proxy to tunnel requests to the remote Selenium WebDriver through
- * @param int|null $http_proxy_port The proxy port to tunnel requests to the remote Selenium WebDriver through
- * @param DesiredCapabilities $required_capabilities The required capabilities
- * @return RemoteWebDriver
- */
- public static function create(
- $selenium_server_url = 'http://localhost:4444/wd/hub',
- $desired_capabilities = null,
- $connection_timeout_in_ms = null,
- $request_timeout_in_ms = null,
- $http_proxy = null,
- $http_proxy_port = null,
- DesiredCapabilities $required_capabilities = null
- ) {
- $selenium_server_url = preg_replace('#/+$#', '', $selenium_server_url);
- $desired_capabilities = self::castToDesiredCapabilitiesObject($desired_capabilities);
- $executor = new HttpCommandExecutor($selenium_server_url, $http_proxy, $http_proxy_port);
- if ($connection_timeout_in_ms !== null) {
- $executor->setConnectionTimeout($connection_timeout_in_ms);
- }
- if ($request_timeout_in_ms !== null) {
- $executor->setRequestTimeout($request_timeout_in_ms);
- }
- if ($required_capabilities !== null) {
- // TODO: Selenium (as of v3.0.1) does accept requiredCapabilities only as a property of desiredCapabilities.
- // This will probably change in future with the W3C WebDriver spec, but is the only way how to pass these
- // values now.
- $desired_capabilities->setCapability('requiredCapabilities', $required_capabilities->toArray());
- }
- $command = new WebDriverCommand(
- null,
- DriverCommand::NEW_SESSION,
- ['desiredCapabilities' => $desired_capabilities->toArray()]
- );
- $response = $executor->execute($command);
- $returnedCapabilities = new DesiredCapabilities($response->getValue());
- $driver = new static($executor, $response->getSessionID(), $returnedCapabilities);
- return $driver;
- }
- /**
- * Cast legacy types (array or null) to DesiredCapabilities object. To be removed in future when instance of
- * DesiredCapabilities will be required.
- *
- * @param array|DesiredCapabilities|null $desired_capabilities
- * @return DesiredCapabilities
- */
- protected static function castToDesiredCapabilitiesObject($desired_capabilities = null)
- {
- if ($desired_capabilities === null) {
- return new DesiredCapabilities();
- }
- if (is_array($desired_capabilities)) {
- return new DesiredCapabilities($desired_capabilities);
- }
- return $desired_capabilities;
- }
- /**
- * [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 cannot the desired capabilities because the session was created before.
- *
- * @param string $selenium_server_url The url of the remote Selenium WebDriver server
- * @param string $session_id The existing session id
- * @return RemoteWebDriver
- */
- public static function createBySessionID($session_id, $selenium_server_url = 'http://localhost:4444/wd/hub')
- {
- $executor = new HttpCommandExecutor($selenium_server_url);
- return new static($executor, $session_id);
- }
- /**
- * Close the current window.
- *
- * @return RemoteWebDriver The current instance.
- */
- public function close()
- {
- $this->execute(DriverCommand::CLOSE, []);
- 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 = ['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 = ['using' => $by->getMechanism(), 'value' => $by->getValue()];
- $raw_elements = $this->execute(
- DriverCommand::FIND_ELEMENTS,
- $params
- );
- $elements = [];
- 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 = ['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,
- []
- );
- }
- /**
- * 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, []);
- }
- /**
- * Quits this driver, closing every associated window.
- */
- 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 = [];
- foreach ($arguments as $key => $value) {
- if ($value instanceof WebDriverElement) {
- $args[$key] = ['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 = [])
- {
- $params = [
- '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 = [])
- {
- $params = [
- '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;
- }
- /**
- * @return RemoteExecuteMethod
- */
- 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
- */
- protected function newElement($id)
- {
- return new RemoteWebElement($this->getExecuteMethod(), $id);
- }
- /**
- * Set the command executor of this RemoteWebdriver
- *
- * @deprecated To be removed in the future. Executor should be passed in the constructor.
- * @internal
- * @codeCoverageIgnore
- * @param WebDriverCommandExecutor $executor Despite the typehint, it have be an instance of HttpCommandExecutor.
- * @return RemoteWebDriver
- */
- public function setCommandExecutor(WebDriverCommandExecutor $executor)
- {
- $this->executor = $executor;
- return $this;
- }
- /**
- * Get the command executor of this RemoteWebdriver
- *
- * @return HttpCommandExecutor
- */
- public function getCommandExecutor()
- {
- return $this->executor;
- }
- /**
- * Set the session id of the RemoteWebDriver.
- *
- * @deprecated To be removed in the future. Session ID should be passed in the constructor.
- * @internal
- * @codeCoverageIgnore
- * @param string $session_id
- * @return RemoteWebDriver
- */
- public function setSessionID($session_id)
- {
- $this->sessionID = $session_id;
- return $this;
- }
- /**
- * Get current selenium sessionID
- *
- * @return string
- */
- public function getSessionID()
- {
- return $this->sessionID;
- }
- /**
- * Get capabilities of the RemoteWebDriver.
- *
- * @return WebDriverCapabilities
- */
- public function getCapabilities()
- {
- return $this->capabilities;
- }
- /**
- * Returns a list of the currently active sessions.
- *
- * @param string $selenium_server_url The url of the remote Selenium WebDriver server
- * @param int $timeout_in_ms
- * @return array
- */
- public static function getAllSessions($selenium_server_url = 'http://localhost:4444/wd/hub', $timeout_in_ms = 30000)
- {
- $executor = new HttpCommandExecutor($selenium_server_url);
- $executor->setConnectionTimeout($timeout_in_ms);
- $command = new WebDriverCommand(
- null,
- DriverCommand::GET_ALL_SESSIONS,
- []
- );
- return $executor->execute($command)->getValue();
- }
- public function execute($command_name, $params = [])
- {
- $command = new WebDriverCommand(
- $this->sessionID,
- $command_name,
- $params
- );
- if ($this->executor) {
- $response = $this->executor->execute($command);
- return $response->getValue();
- }
- return null;
- }
- }
|