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; } }