1*04fd306cSNickeau<?php 2*04fd306cSNickeau 3*04fd306cSNickeaunamespace Facebook\WebDriver\Remote; 4*04fd306cSNickeau 5*04fd306cSNickeauuse Facebook\WebDriver\Interactions\WebDriverActions; 6*04fd306cSNickeauuse Facebook\WebDriver\JavaScriptExecutor; 7*04fd306cSNickeauuse Facebook\WebDriver\WebDriver; 8*04fd306cSNickeauuse Facebook\WebDriver\WebDriverBy; 9*04fd306cSNickeauuse Facebook\WebDriver\WebDriverCapabilities; 10*04fd306cSNickeauuse Facebook\WebDriver\WebDriverCommandExecutor; 11*04fd306cSNickeauuse Facebook\WebDriver\WebDriverElement; 12*04fd306cSNickeauuse Facebook\WebDriver\WebDriverHasInputDevices; 13*04fd306cSNickeauuse Facebook\WebDriver\WebDriverNavigation; 14*04fd306cSNickeauuse Facebook\WebDriver\WebDriverOptions; 15*04fd306cSNickeauuse Facebook\WebDriver\WebDriverWait; 16*04fd306cSNickeau 17*04fd306cSNickeauclass RemoteWebDriver implements WebDriver, JavaScriptExecutor, WebDriverHasInputDevices 18*04fd306cSNickeau{ 19*04fd306cSNickeau /** 20*04fd306cSNickeau * @var HttpCommandExecutor|null 21*04fd306cSNickeau */ 22*04fd306cSNickeau protected $executor; 23*04fd306cSNickeau /** 24*04fd306cSNickeau * @var WebDriverCapabilities 25*04fd306cSNickeau */ 26*04fd306cSNickeau protected $capabilities; 27*04fd306cSNickeau 28*04fd306cSNickeau /** 29*04fd306cSNickeau * @var string 30*04fd306cSNickeau */ 31*04fd306cSNickeau protected $sessionID; 32*04fd306cSNickeau /** 33*04fd306cSNickeau * @var RemoteMouse 34*04fd306cSNickeau */ 35*04fd306cSNickeau protected $mouse; 36*04fd306cSNickeau /** 37*04fd306cSNickeau * @var RemoteKeyboard 38*04fd306cSNickeau */ 39*04fd306cSNickeau protected $keyboard; 40*04fd306cSNickeau /** 41*04fd306cSNickeau * @var RemoteTouchScreen 42*04fd306cSNickeau */ 43*04fd306cSNickeau protected $touch; 44*04fd306cSNickeau /** 45*04fd306cSNickeau * @var RemoteExecuteMethod 46*04fd306cSNickeau */ 47*04fd306cSNickeau protected $executeMethod; 48*04fd306cSNickeau /** 49*04fd306cSNickeau * @var bool 50*04fd306cSNickeau */ 51*04fd306cSNickeau protected $isW3cCompliant; 52*04fd306cSNickeau 53*04fd306cSNickeau /** 54*04fd306cSNickeau * @param HttpCommandExecutor $commandExecutor 55*04fd306cSNickeau * @param string $sessionId 56*04fd306cSNickeau * @param WebDriverCapabilities|null $capabilities 57*04fd306cSNickeau * @param bool $isW3cCompliant false to use the legacy JsonWire protocol, true for the W3C WebDriver spec 58*04fd306cSNickeau */ 59*04fd306cSNickeau protected function __construct( 60*04fd306cSNickeau HttpCommandExecutor $commandExecutor, 61*04fd306cSNickeau $sessionId, 62*04fd306cSNickeau WebDriverCapabilities $capabilities = null, 63*04fd306cSNickeau $isW3cCompliant = false 64*04fd306cSNickeau ) { 65*04fd306cSNickeau $this->executor = $commandExecutor; 66*04fd306cSNickeau $this->sessionID = $sessionId; 67*04fd306cSNickeau $this->isW3cCompliant = $isW3cCompliant; 68*04fd306cSNickeau 69*04fd306cSNickeau if ($capabilities !== null) { 70*04fd306cSNickeau $this->capabilities = $capabilities; 71*04fd306cSNickeau } 72*04fd306cSNickeau } 73*04fd306cSNickeau 74*04fd306cSNickeau /** 75*04fd306cSNickeau * Construct the RemoteWebDriver by a desired capabilities. 76*04fd306cSNickeau * 77*04fd306cSNickeau * @param string $selenium_server_url The url of the remote Selenium WebDriver server 78*04fd306cSNickeau * @param DesiredCapabilities|array $desired_capabilities The desired capabilities 79*04fd306cSNickeau * @param int|null $connection_timeout_in_ms Set timeout for the connect phase to remote Selenium WebDriver server 80*04fd306cSNickeau * @param int|null $request_timeout_in_ms Set the maximum time of a request to remote Selenium WebDriver server 81*04fd306cSNickeau * @param string|null $http_proxy The proxy to tunnel requests to the remote Selenium WebDriver through 82*04fd306cSNickeau * @param int|null $http_proxy_port The proxy port to tunnel requests to the remote Selenium WebDriver through 83*04fd306cSNickeau * @param DesiredCapabilities $required_capabilities The required capabilities 84*04fd306cSNickeau * 85*04fd306cSNickeau * @return static 86*04fd306cSNickeau */ 87*04fd306cSNickeau public static function create( 88*04fd306cSNickeau $selenium_server_url = 'http://localhost:4444/wd/hub', 89*04fd306cSNickeau $desired_capabilities = null, 90*04fd306cSNickeau $connection_timeout_in_ms = null, 91*04fd306cSNickeau $request_timeout_in_ms = null, 92*04fd306cSNickeau $http_proxy = null, 93*04fd306cSNickeau $http_proxy_port = null, 94*04fd306cSNickeau DesiredCapabilities $required_capabilities = null 95*04fd306cSNickeau ) { 96*04fd306cSNickeau $selenium_server_url = preg_replace('#/+$#', '', $selenium_server_url); 97*04fd306cSNickeau 98*04fd306cSNickeau $desired_capabilities = self::castToDesiredCapabilitiesObject($desired_capabilities); 99*04fd306cSNickeau 100*04fd306cSNickeau $executor = new HttpCommandExecutor($selenium_server_url, $http_proxy, $http_proxy_port); 101*04fd306cSNickeau if ($connection_timeout_in_ms !== null) { 102*04fd306cSNickeau $executor->setConnectionTimeout($connection_timeout_in_ms); 103*04fd306cSNickeau } 104*04fd306cSNickeau if ($request_timeout_in_ms !== null) { 105*04fd306cSNickeau $executor->setRequestTimeout($request_timeout_in_ms); 106*04fd306cSNickeau } 107*04fd306cSNickeau 108*04fd306cSNickeau // W3C 109*04fd306cSNickeau $parameters = [ 110*04fd306cSNickeau 'capabilities' => [ 111*04fd306cSNickeau 'firstMatch' => [(object) $desired_capabilities->toW3cCompatibleArray()], 112*04fd306cSNickeau ], 113*04fd306cSNickeau ]; 114*04fd306cSNickeau 115*04fd306cSNickeau if ($required_capabilities !== null && !empty($required_capabilities->toArray())) { 116*04fd306cSNickeau $parameters['capabilities']['alwaysMatch'] = (object) $required_capabilities->toW3cCompatibleArray(); 117*04fd306cSNickeau } 118*04fd306cSNickeau 119*04fd306cSNickeau // Legacy protocol 120*04fd306cSNickeau if ($required_capabilities !== null) { 121*04fd306cSNickeau // TODO: Selenium (as of v3.0.1) does accept requiredCapabilities only as a property of desiredCapabilities. 122*04fd306cSNickeau // This has changed with the W3C WebDriver spec, but is the only way how to pass these 123*04fd306cSNickeau // values with the legacy protocol. 124*04fd306cSNickeau $desired_capabilities->setCapability('requiredCapabilities', (object) $required_capabilities->toArray()); 125*04fd306cSNickeau } 126*04fd306cSNickeau 127*04fd306cSNickeau $parameters['desiredCapabilities'] = (object) $desired_capabilities->toArray(); 128*04fd306cSNickeau 129*04fd306cSNickeau $command = WebDriverCommand::newSession($parameters); 130*04fd306cSNickeau 131*04fd306cSNickeau $response = $executor->execute($command); 132*04fd306cSNickeau 133*04fd306cSNickeau return static::createFromResponse($response, $executor); 134*04fd306cSNickeau } 135*04fd306cSNickeau 136*04fd306cSNickeau /** 137*04fd306cSNickeau * [Experimental] Construct the RemoteWebDriver by an existing session. 138*04fd306cSNickeau * 139*04fd306cSNickeau * This constructor can boost the performance a lot by reusing the same browser for the whole test suite. 140*04fd306cSNickeau * You cannot pass the desired capabilities because the session was created before. 141*04fd306cSNickeau * 142*04fd306cSNickeau * @param string $selenium_server_url The url of the remote Selenium WebDriver server 143*04fd306cSNickeau * @param string $session_id The existing session id 144*04fd306cSNickeau * @param int|null $connection_timeout_in_ms Set timeout for the connect phase to remote Selenium WebDriver server 145*04fd306cSNickeau * @param int|null $request_timeout_in_ms Set the maximum time of a request to remote Selenium WebDriver server 146*04fd306cSNickeau * @param bool $isW3cCompliant True to use W3C WebDriver (default), false to use the legacy JsonWire protocol 147*04fd306cSNickeau * @return static 148*04fd306cSNickeau */ 149*04fd306cSNickeau public static function createBySessionID( 150*04fd306cSNickeau $session_id, 151*04fd306cSNickeau $selenium_server_url = 'http://localhost:4444/wd/hub', 152*04fd306cSNickeau $connection_timeout_in_ms = null, 153*04fd306cSNickeau $request_timeout_in_ms = null 154*04fd306cSNickeau ) { 155*04fd306cSNickeau // BC layer to not break the method signature 156*04fd306cSNickeau $isW3cCompliant = func_num_args() > 4 ? func_get_arg(4) : true; 157*04fd306cSNickeau 158*04fd306cSNickeau $executor = new HttpCommandExecutor($selenium_server_url, null, null); 159*04fd306cSNickeau if ($connection_timeout_in_ms !== null) { 160*04fd306cSNickeau $executor->setConnectionTimeout($connection_timeout_in_ms); 161*04fd306cSNickeau } 162*04fd306cSNickeau if ($request_timeout_in_ms !== null) { 163*04fd306cSNickeau $executor->setRequestTimeout($request_timeout_in_ms); 164*04fd306cSNickeau } 165*04fd306cSNickeau 166*04fd306cSNickeau if (!$isW3cCompliant) { 167*04fd306cSNickeau $executor->disableW3cCompliance(); 168*04fd306cSNickeau } 169*04fd306cSNickeau 170*04fd306cSNickeau return new static($executor, $session_id, null, $isW3cCompliant); 171*04fd306cSNickeau } 172*04fd306cSNickeau 173*04fd306cSNickeau /** 174*04fd306cSNickeau * Close the current window. 175*04fd306cSNickeau * 176*04fd306cSNickeau * @return RemoteWebDriver The current instance. 177*04fd306cSNickeau */ 178*04fd306cSNickeau public function close() 179*04fd306cSNickeau { 180*04fd306cSNickeau $this->execute(DriverCommand::CLOSE, []); 181*04fd306cSNickeau 182*04fd306cSNickeau return $this; 183*04fd306cSNickeau } 184*04fd306cSNickeau 185*04fd306cSNickeau /** 186*04fd306cSNickeau * Create a new top-level browsing context. 187*04fd306cSNickeau * 188*04fd306cSNickeau * @codeCoverageIgnore 189*04fd306cSNickeau * @deprecated Use $driver->switchTo()->newWindow() 190*04fd306cSNickeau * @return WebDriver The current instance. 191*04fd306cSNickeau */ 192*04fd306cSNickeau public function newWindow() 193*04fd306cSNickeau { 194*04fd306cSNickeau return $this->switchTo()->newWindow(); 195*04fd306cSNickeau } 196*04fd306cSNickeau 197*04fd306cSNickeau /** 198*04fd306cSNickeau * Find the first WebDriverElement using the given mechanism. 199*04fd306cSNickeau * 200*04fd306cSNickeau * @param WebDriverBy $by 201*04fd306cSNickeau * @return RemoteWebElement NoSuchElementException is thrown in HttpCommandExecutor if no element is found. 202*04fd306cSNickeau * @see WebDriverBy 203*04fd306cSNickeau */ 204*04fd306cSNickeau public function findElement(WebDriverBy $by) 205*04fd306cSNickeau { 206*04fd306cSNickeau $raw_element = $this->execute( 207*04fd306cSNickeau DriverCommand::FIND_ELEMENT, 208*04fd306cSNickeau JsonWireCompat::getUsing($by, $this->isW3cCompliant) 209*04fd306cSNickeau ); 210*04fd306cSNickeau 211*04fd306cSNickeau return $this->newElement(JsonWireCompat::getElement($raw_element)); 212*04fd306cSNickeau } 213*04fd306cSNickeau 214*04fd306cSNickeau /** 215*04fd306cSNickeau * Find all WebDriverElements within the current page using the given mechanism. 216*04fd306cSNickeau * 217*04fd306cSNickeau * @param WebDriverBy $by 218*04fd306cSNickeau * @return RemoteWebElement[] A list of all WebDriverElements, or an empty array if nothing matches 219*04fd306cSNickeau * @see WebDriverBy 220*04fd306cSNickeau */ 221*04fd306cSNickeau public function findElements(WebDriverBy $by) 222*04fd306cSNickeau { 223*04fd306cSNickeau $raw_elements = $this->execute( 224*04fd306cSNickeau DriverCommand::FIND_ELEMENTS, 225*04fd306cSNickeau JsonWireCompat::getUsing($by, $this->isW3cCompliant) 226*04fd306cSNickeau ); 227*04fd306cSNickeau 228*04fd306cSNickeau $elements = []; 229*04fd306cSNickeau foreach ($raw_elements as $raw_element) { 230*04fd306cSNickeau $elements[] = $this->newElement(JsonWireCompat::getElement($raw_element)); 231*04fd306cSNickeau } 232*04fd306cSNickeau 233*04fd306cSNickeau return $elements; 234*04fd306cSNickeau } 235*04fd306cSNickeau 236*04fd306cSNickeau /** 237*04fd306cSNickeau * Load a new web page in the current browser window. 238*04fd306cSNickeau * 239*04fd306cSNickeau * @param string $url 240*04fd306cSNickeau * 241*04fd306cSNickeau * @return RemoteWebDriver The current instance. 242*04fd306cSNickeau */ 243*04fd306cSNickeau public function get($url) 244*04fd306cSNickeau { 245*04fd306cSNickeau $params = ['url' => (string) $url]; 246*04fd306cSNickeau $this->execute(DriverCommand::GET, $params); 247*04fd306cSNickeau 248*04fd306cSNickeau return $this; 249*04fd306cSNickeau } 250*04fd306cSNickeau 251*04fd306cSNickeau /** 252*04fd306cSNickeau * Get a string representing the current URL that the browser is looking at. 253*04fd306cSNickeau * 254*04fd306cSNickeau * @return string The current URL. 255*04fd306cSNickeau */ 256*04fd306cSNickeau public function getCurrentURL() 257*04fd306cSNickeau { 258*04fd306cSNickeau return $this->execute(DriverCommand::GET_CURRENT_URL); 259*04fd306cSNickeau } 260*04fd306cSNickeau 261*04fd306cSNickeau /** 262*04fd306cSNickeau * Get the source of the last loaded page. 263*04fd306cSNickeau * 264*04fd306cSNickeau * @return string The current page source. 265*04fd306cSNickeau */ 266*04fd306cSNickeau public function getPageSource() 267*04fd306cSNickeau { 268*04fd306cSNickeau return $this->execute(DriverCommand::GET_PAGE_SOURCE); 269*04fd306cSNickeau } 270*04fd306cSNickeau 271*04fd306cSNickeau /** 272*04fd306cSNickeau * Get the title of the current page. 273*04fd306cSNickeau * 274*04fd306cSNickeau * @return string The title of the current page. 275*04fd306cSNickeau */ 276*04fd306cSNickeau public function getTitle() 277*04fd306cSNickeau { 278*04fd306cSNickeau return $this->execute(DriverCommand::GET_TITLE); 279*04fd306cSNickeau } 280*04fd306cSNickeau 281*04fd306cSNickeau /** 282*04fd306cSNickeau * Return an opaque handle to this window that uniquely identifies it within this driver instance. 283*04fd306cSNickeau * 284*04fd306cSNickeau * @return string The current window handle. 285*04fd306cSNickeau */ 286*04fd306cSNickeau public function getWindowHandle() 287*04fd306cSNickeau { 288*04fd306cSNickeau return $this->execute( 289*04fd306cSNickeau DriverCommand::GET_CURRENT_WINDOW_HANDLE, 290*04fd306cSNickeau [] 291*04fd306cSNickeau ); 292*04fd306cSNickeau } 293*04fd306cSNickeau 294*04fd306cSNickeau /** 295*04fd306cSNickeau * Get all window handles available to the current session. 296*04fd306cSNickeau * 297*04fd306cSNickeau * Note: Do not use `end($driver->getWindowHandles())` to find the last open window, for proper solution see: 298*04fd306cSNickeau * https://github.com/php-webdriver/php-webdriver/wiki/Alert,-tabs,-frames,-iframes#switch-to-the-new-window 299*04fd306cSNickeau * 300*04fd306cSNickeau * @return array An array of string containing all available window handles. 301*04fd306cSNickeau */ 302*04fd306cSNickeau public function getWindowHandles() 303*04fd306cSNickeau { 304*04fd306cSNickeau return $this->execute(DriverCommand::GET_WINDOW_HANDLES, []); 305*04fd306cSNickeau } 306*04fd306cSNickeau 307*04fd306cSNickeau /** 308*04fd306cSNickeau * Quits this driver, closing every associated window. 309*04fd306cSNickeau */ 310*04fd306cSNickeau public function quit() 311*04fd306cSNickeau { 312*04fd306cSNickeau $this->execute(DriverCommand::QUIT); 313*04fd306cSNickeau $this->executor = null; 314*04fd306cSNickeau } 315*04fd306cSNickeau 316*04fd306cSNickeau /** 317*04fd306cSNickeau * Inject a snippet of JavaScript into the page for execution in the context of the currently selected frame. 318*04fd306cSNickeau * The executed script is assumed to be synchronous and the result of evaluating the script will be returned. 319*04fd306cSNickeau * 320*04fd306cSNickeau * @param string $script The script to inject. 321*04fd306cSNickeau * @param array $arguments The arguments of the script. 322*04fd306cSNickeau * @return mixed The return value of the script. 323*04fd306cSNickeau */ 324*04fd306cSNickeau public function executeScript($script, array $arguments = []) 325*04fd306cSNickeau { 326*04fd306cSNickeau $params = [ 327*04fd306cSNickeau 'script' => $script, 328*04fd306cSNickeau 'args' => $this->prepareScriptArguments($arguments), 329*04fd306cSNickeau ]; 330*04fd306cSNickeau 331*04fd306cSNickeau return $this->execute(DriverCommand::EXECUTE_SCRIPT, $params); 332*04fd306cSNickeau } 333*04fd306cSNickeau 334*04fd306cSNickeau /** 335*04fd306cSNickeau * Inject a snippet of JavaScript into the page for asynchronous execution in the context of the currently selected 336*04fd306cSNickeau * frame. 337*04fd306cSNickeau * 338*04fd306cSNickeau * The driver will pass a callback as the last argument to the snippet, and block until the callback is invoked. 339*04fd306cSNickeau * 340*04fd306cSNickeau * You may need to define script timeout using `setScriptTimeout()` method of `WebDriverTimeouts` first. 341*04fd306cSNickeau * 342*04fd306cSNickeau * @param string $script The script to inject. 343*04fd306cSNickeau * @param array $arguments The arguments of the script. 344*04fd306cSNickeau * @return mixed The value passed by the script to the callback. 345*04fd306cSNickeau */ 346*04fd306cSNickeau public function executeAsyncScript($script, array $arguments = []) 347*04fd306cSNickeau { 348*04fd306cSNickeau $params = [ 349*04fd306cSNickeau 'script' => $script, 350*04fd306cSNickeau 'args' => $this->prepareScriptArguments($arguments), 351*04fd306cSNickeau ]; 352*04fd306cSNickeau 353*04fd306cSNickeau return $this->execute( 354*04fd306cSNickeau DriverCommand::EXECUTE_ASYNC_SCRIPT, 355*04fd306cSNickeau $params 356*04fd306cSNickeau ); 357*04fd306cSNickeau } 358*04fd306cSNickeau 359*04fd306cSNickeau /** 360*04fd306cSNickeau * Take a screenshot of the current page. 361*04fd306cSNickeau * 362*04fd306cSNickeau * @param string $save_as The path of the screenshot to be saved. 363*04fd306cSNickeau * @return string The screenshot in PNG format. 364*04fd306cSNickeau */ 365*04fd306cSNickeau public function takeScreenshot($save_as = null) 366*04fd306cSNickeau { 367*04fd306cSNickeau $screenshot = base64_decode($this->execute(DriverCommand::SCREENSHOT), true); 368*04fd306cSNickeau 369*04fd306cSNickeau if ($save_as !== null) { 370*04fd306cSNickeau $directoryPath = dirname($save_as); 371*04fd306cSNickeau 372*04fd306cSNickeau if (!file_exists($directoryPath)) { 373*04fd306cSNickeau mkdir($directoryPath, 0777, true); 374*04fd306cSNickeau } 375*04fd306cSNickeau 376*04fd306cSNickeau file_put_contents($save_as, $screenshot); 377*04fd306cSNickeau } 378*04fd306cSNickeau 379*04fd306cSNickeau return $screenshot; 380*04fd306cSNickeau } 381*04fd306cSNickeau 382*04fd306cSNickeau /** 383*04fd306cSNickeau * Status returns information about whether a remote end is in a state in which it can create new sessions. 384*04fd306cSNickeau */ 385*04fd306cSNickeau public function getStatus() 386*04fd306cSNickeau { 387*04fd306cSNickeau $response = $this->execute(DriverCommand::STATUS); 388*04fd306cSNickeau 389*04fd306cSNickeau return RemoteStatus::createFromResponse($response); 390*04fd306cSNickeau } 391*04fd306cSNickeau 392*04fd306cSNickeau /** 393*04fd306cSNickeau * Construct a new WebDriverWait by the current WebDriver instance. 394*04fd306cSNickeau * Sample usage: 395*04fd306cSNickeau * 396*04fd306cSNickeau * ``` 397*04fd306cSNickeau * $driver->wait(20, 1000)->until( 398*04fd306cSNickeau * WebDriverExpectedCondition::titleIs('WebDriver Page') 399*04fd306cSNickeau * ); 400*04fd306cSNickeau * ``` 401*04fd306cSNickeau * @param int $timeout_in_second 402*04fd306cSNickeau * @param int $interval_in_millisecond 403*04fd306cSNickeau * 404*04fd306cSNickeau * @return WebDriverWait 405*04fd306cSNickeau */ 406*04fd306cSNickeau public function wait($timeout_in_second = 30, $interval_in_millisecond = 250) 407*04fd306cSNickeau { 408*04fd306cSNickeau return new WebDriverWait( 409*04fd306cSNickeau $this, 410*04fd306cSNickeau $timeout_in_second, 411*04fd306cSNickeau $interval_in_millisecond 412*04fd306cSNickeau ); 413*04fd306cSNickeau } 414*04fd306cSNickeau 415*04fd306cSNickeau /** 416*04fd306cSNickeau * An abstraction for managing stuff you would do in a browser menu. For example, adding and deleting cookies. 417*04fd306cSNickeau * 418*04fd306cSNickeau * @return WebDriverOptions 419*04fd306cSNickeau */ 420*04fd306cSNickeau public function manage() 421*04fd306cSNickeau { 422*04fd306cSNickeau return new WebDriverOptions($this->getExecuteMethod(), $this->isW3cCompliant); 423*04fd306cSNickeau } 424*04fd306cSNickeau 425*04fd306cSNickeau /** 426*04fd306cSNickeau * An abstraction allowing the driver to access the browser's history and to navigate to a given URL. 427*04fd306cSNickeau * 428*04fd306cSNickeau * @return WebDriverNavigation 429*04fd306cSNickeau * @see WebDriverNavigation 430*04fd306cSNickeau */ 431*04fd306cSNickeau public function navigate() 432*04fd306cSNickeau { 433*04fd306cSNickeau return new WebDriverNavigation($this->getExecuteMethod()); 434*04fd306cSNickeau } 435*04fd306cSNickeau 436*04fd306cSNickeau /** 437*04fd306cSNickeau * Switch to a different window or frame. 438*04fd306cSNickeau * 439*04fd306cSNickeau * @return RemoteTargetLocator 440*04fd306cSNickeau * @see RemoteTargetLocator 441*04fd306cSNickeau */ 442*04fd306cSNickeau public function switchTo() 443*04fd306cSNickeau { 444*04fd306cSNickeau return new RemoteTargetLocator($this->getExecuteMethod(), $this, $this->isW3cCompliant); 445*04fd306cSNickeau } 446*04fd306cSNickeau 447*04fd306cSNickeau /** 448*04fd306cSNickeau * @return RemoteMouse 449*04fd306cSNickeau */ 450*04fd306cSNickeau public function getMouse() 451*04fd306cSNickeau { 452*04fd306cSNickeau if (!$this->mouse) { 453*04fd306cSNickeau $this->mouse = new RemoteMouse($this->getExecuteMethod(), $this->isW3cCompliant); 454*04fd306cSNickeau } 455*04fd306cSNickeau 456*04fd306cSNickeau return $this->mouse; 457*04fd306cSNickeau } 458*04fd306cSNickeau 459*04fd306cSNickeau /** 460*04fd306cSNickeau * @return RemoteKeyboard 461*04fd306cSNickeau */ 462*04fd306cSNickeau public function getKeyboard() 463*04fd306cSNickeau { 464*04fd306cSNickeau if (!$this->keyboard) { 465*04fd306cSNickeau $this->keyboard = new RemoteKeyboard($this->getExecuteMethod(), $this, $this->isW3cCompliant); 466*04fd306cSNickeau } 467*04fd306cSNickeau 468*04fd306cSNickeau return $this->keyboard; 469*04fd306cSNickeau } 470*04fd306cSNickeau 471*04fd306cSNickeau /** 472*04fd306cSNickeau * @return RemoteTouchScreen 473*04fd306cSNickeau */ 474*04fd306cSNickeau public function getTouch() 475*04fd306cSNickeau { 476*04fd306cSNickeau if (!$this->touch) { 477*04fd306cSNickeau $this->touch = new RemoteTouchScreen($this->getExecuteMethod()); 478*04fd306cSNickeau } 479*04fd306cSNickeau 480*04fd306cSNickeau return $this->touch; 481*04fd306cSNickeau } 482*04fd306cSNickeau 483*04fd306cSNickeau /** 484*04fd306cSNickeau * Construct a new action builder. 485*04fd306cSNickeau * 486*04fd306cSNickeau * @return WebDriverActions 487*04fd306cSNickeau */ 488*04fd306cSNickeau public function action() 489*04fd306cSNickeau { 490*04fd306cSNickeau return new WebDriverActions($this); 491*04fd306cSNickeau } 492*04fd306cSNickeau 493*04fd306cSNickeau /** 494*04fd306cSNickeau * Set the command executor of this RemoteWebdriver 495*04fd306cSNickeau * 496*04fd306cSNickeau * @deprecated To be removed in the future. Executor should be passed in the constructor. 497*04fd306cSNickeau * @internal 498*04fd306cSNickeau * @codeCoverageIgnore 499*04fd306cSNickeau * @param WebDriverCommandExecutor $executor Despite the typehint, it have be an instance of HttpCommandExecutor. 500*04fd306cSNickeau * @return RemoteWebDriver 501*04fd306cSNickeau */ 502*04fd306cSNickeau public function setCommandExecutor(WebDriverCommandExecutor $executor) 503*04fd306cSNickeau { 504*04fd306cSNickeau $this->executor = $executor; 505*04fd306cSNickeau 506*04fd306cSNickeau return $this; 507*04fd306cSNickeau } 508*04fd306cSNickeau 509*04fd306cSNickeau /** 510*04fd306cSNickeau * Get the command executor of this RemoteWebdriver 511*04fd306cSNickeau * 512*04fd306cSNickeau * @return HttpCommandExecutor 513*04fd306cSNickeau */ 514*04fd306cSNickeau public function getCommandExecutor() 515*04fd306cSNickeau { 516*04fd306cSNickeau return $this->executor; 517*04fd306cSNickeau } 518*04fd306cSNickeau 519*04fd306cSNickeau /** 520*04fd306cSNickeau * Set the session id of the RemoteWebDriver. 521*04fd306cSNickeau * 522*04fd306cSNickeau * @deprecated To be removed in the future. Session ID should be passed in the constructor. 523*04fd306cSNickeau * @internal 524*04fd306cSNickeau * @codeCoverageIgnore 525*04fd306cSNickeau * @param string $session_id 526*04fd306cSNickeau * @return RemoteWebDriver 527*04fd306cSNickeau */ 528*04fd306cSNickeau public function setSessionID($session_id) 529*04fd306cSNickeau { 530*04fd306cSNickeau $this->sessionID = $session_id; 531*04fd306cSNickeau 532*04fd306cSNickeau return $this; 533*04fd306cSNickeau } 534*04fd306cSNickeau 535*04fd306cSNickeau /** 536*04fd306cSNickeau * Get current selenium sessionID 537*04fd306cSNickeau * 538*04fd306cSNickeau * @return string 539*04fd306cSNickeau */ 540*04fd306cSNickeau public function getSessionID() 541*04fd306cSNickeau { 542*04fd306cSNickeau return $this->sessionID; 543*04fd306cSNickeau } 544*04fd306cSNickeau 545*04fd306cSNickeau /** 546*04fd306cSNickeau * Get capabilities of the RemoteWebDriver. 547*04fd306cSNickeau * 548*04fd306cSNickeau * @return WebDriverCapabilities 549*04fd306cSNickeau */ 550*04fd306cSNickeau public function getCapabilities() 551*04fd306cSNickeau { 552*04fd306cSNickeau return $this->capabilities; 553*04fd306cSNickeau } 554*04fd306cSNickeau 555*04fd306cSNickeau /** 556*04fd306cSNickeau * Returns a list of the currently active sessions. 557*04fd306cSNickeau * 558*04fd306cSNickeau * @param string $selenium_server_url The url of the remote Selenium WebDriver server 559*04fd306cSNickeau * @param int $timeout_in_ms 560*04fd306cSNickeau * @return array 561*04fd306cSNickeau */ 562*04fd306cSNickeau public static function getAllSessions($selenium_server_url = 'http://localhost:4444/wd/hub', $timeout_in_ms = 30000) 563*04fd306cSNickeau { 564*04fd306cSNickeau $executor = new HttpCommandExecutor($selenium_server_url, null, null); 565*04fd306cSNickeau $executor->setConnectionTimeout($timeout_in_ms); 566*04fd306cSNickeau 567*04fd306cSNickeau $command = new WebDriverCommand( 568*04fd306cSNickeau null, 569*04fd306cSNickeau DriverCommand::GET_ALL_SESSIONS, 570*04fd306cSNickeau [] 571*04fd306cSNickeau ); 572*04fd306cSNickeau 573*04fd306cSNickeau return $executor->execute($command)->getValue(); 574*04fd306cSNickeau } 575*04fd306cSNickeau 576*04fd306cSNickeau public function execute($command_name, $params = []) 577*04fd306cSNickeau { 578*04fd306cSNickeau $command = new WebDriverCommand( 579*04fd306cSNickeau $this->sessionID, 580*04fd306cSNickeau $command_name, 581*04fd306cSNickeau $params 582*04fd306cSNickeau ); 583*04fd306cSNickeau 584*04fd306cSNickeau if ($this->executor) { 585*04fd306cSNickeau $response = $this->executor->execute($command); 586*04fd306cSNickeau 587*04fd306cSNickeau return $response->getValue(); 588*04fd306cSNickeau } 589*04fd306cSNickeau 590*04fd306cSNickeau return null; 591*04fd306cSNickeau } 592*04fd306cSNickeau 593*04fd306cSNickeau /** 594*04fd306cSNickeau * Execute custom commands on remote end. 595*04fd306cSNickeau * For example vendor-specific commands or other commands not implemented by php-webdriver. 596*04fd306cSNickeau * 597*04fd306cSNickeau * @see https://github.com/php-webdriver/php-webdriver/wiki/Custom-commands 598*04fd306cSNickeau * @param string $endpointUrl 599*04fd306cSNickeau * @param string $method 600*04fd306cSNickeau * @param array $params 601*04fd306cSNickeau * @return mixed|null 602*04fd306cSNickeau */ 603*04fd306cSNickeau public function executeCustomCommand($endpointUrl, $method = 'GET', $params = []) 604*04fd306cSNickeau { 605*04fd306cSNickeau $command = new CustomWebDriverCommand( 606*04fd306cSNickeau $this->sessionID, 607*04fd306cSNickeau $endpointUrl, 608*04fd306cSNickeau $method, 609*04fd306cSNickeau $params 610*04fd306cSNickeau ); 611*04fd306cSNickeau 612*04fd306cSNickeau if ($this->executor) { 613*04fd306cSNickeau $response = $this->executor->execute($command); 614*04fd306cSNickeau 615*04fd306cSNickeau return $response->getValue(); 616*04fd306cSNickeau } 617*04fd306cSNickeau 618*04fd306cSNickeau return null; 619*04fd306cSNickeau } 620*04fd306cSNickeau 621*04fd306cSNickeau /** 622*04fd306cSNickeau * @internal 623*04fd306cSNickeau * @return bool 624*04fd306cSNickeau */ 625*04fd306cSNickeau public function isW3cCompliant() 626*04fd306cSNickeau { 627*04fd306cSNickeau return $this->isW3cCompliant; 628*04fd306cSNickeau } 629*04fd306cSNickeau 630*04fd306cSNickeau /** 631*04fd306cSNickeau * Create instance based on response to NEW_SESSION command. 632*04fd306cSNickeau * Also detect W3C/OSS dialect and setup the driver/executor accordingly. 633*04fd306cSNickeau * 634*04fd306cSNickeau * @internal 635*04fd306cSNickeau * @return static 636*04fd306cSNickeau */ 637*04fd306cSNickeau protected static function createFromResponse(WebDriverResponse $response, HttpCommandExecutor $commandExecutor) 638*04fd306cSNickeau { 639*04fd306cSNickeau $responseValue = $response->getValue(); 640*04fd306cSNickeau 641*04fd306cSNickeau if (!$isW3cCompliant = isset($responseValue['capabilities'])) { 642*04fd306cSNickeau $commandExecutor->disableW3cCompliance(); 643*04fd306cSNickeau } 644*04fd306cSNickeau 645*04fd306cSNickeau if ($isW3cCompliant) { 646*04fd306cSNickeau $returnedCapabilities = DesiredCapabilities::createFromW3cCapabilities($responseValue['capabilities']); 647*04fd306cSNickeau } else { 648*04fd306cSNickeau $returnedCapabilities = new DesiredCapabilities($responseValue); 649*04fd306cSNickeau } 650*04fd306cSNickeau 651*04fd306cSNickeau return new static($commandExecutor, $response->getSessionID(), $returnedCapabilities, $isW3cCompliant); 652*04fd306cSNickeau } 653*04fd306cSNickeau 654*04fd306cSNickeau /** 655*04fd306cSNickeau * Prepare arguments for JavaScript injection 656*04fd306cSNickeau * 657*04fd306cSNickeau * @param array $arguments 658*04fd306cSNickeau * @return array 659*04fd306cSNickeau */ 660*04fd306cSNickeau protected function prepareScriptArguments(array $arguments) 661*04fd306cSNickeau { 662*04fd306cSNickeau $args = []; 663*04fd306cSNickeau foreach ($arguments as $key => $value) { 664*04fd306cSNickeau if ($value instanceof WebDriverElement) { 665*04fd306cSNickeau $args[$key] = [ 666*04fd306cSNickeau $this->isW3cCompliant ? 667*04fd306cSNickeau JsonWireCompat::WEB_DRIVER_ELEMENT_IDENTIFIER 668*04fd306cSNickeau : 'ELEMENT' => $value->getID(), 669*04fd306cSNickeau ]; 670*04fd306cSNickeau } else { 671*04fd306cSNickeau if (is_array($value)) { 672*04fd306cSNickeau $value = $this->prepareScriptArguments($value); 673*04fd306cSNickeau } 674*04fd306cSNickeau $args[$key] = $value; 675*04fd306cSNickeau } 676*04fd306cSNickeau } 677*04fd306cSNickeau 678*04fd306cSNickeau return $args; 679*04fd306cSNickeau } 680*04fd306cSNickeau 681*04fd306cSNickeau /** 682*04fd306cSNickeau * @return RemoteExecuteMethod 683*04fd306cSNickeau */ 684*04fd306cSNickeau protected function getExecuteMethod() 685*04fd306cSNickeau { 686*04fd306cSNickeau if (!$this->executeMethod) { 687*04fd306cSNickeau $this->executeMethod = new RemoteExecuteMethod($this); 688*04fd306cSNickeau } 689*04fd306cSNickeau 690*04fd306cSNickeau return $this->executeMethod; 691*04fd306cSNickeau } 692*04fd306cSNickeau 693*04fd306cSNickeau /** 694*04fd306cSNickeau * Return the WebDriverElement with the given id. 695*04fd306cSNickeau * 696*04fd306cSNickeau * @param string $id The id of the element to be created. 697*04fd306cSNickeau * @return RemoteWebElement 698*04fd306cSNickeau */ 699*04fd306cSNickeau protected function newElement($id) 700*04fd306cSNickeau { 701*04fd306cSNickeau return new RemoteWebElement($this->getExecuteMethod(), $id, $this->isW3cCompliant); 702*04fd306cSNickeau } 703*04fd306cSNickeau 704*04fd306cSNickeau /** 705*04fd306cSNickeau * Cast legacy types (array or null) to DesiredCapabilities object. To be removed in future when instance of 706*04fd306cSNickeau * DesiredCapabilities will be required. 707*04fd306cSNickeau * 708*04fd306cSNickeau * @param array|DesiredCapabilities|null $desired_capabilities 709*04fd306cSNickeau * @return DesiredCapabilities 710*04fd306cSNickeau */ 711*04fd306cSNickeau protected static function castToDesiredCapabilitiesObject($desired_capabilities = null) 712*04fd306cSNickeau { 713*04fd306cSNickeau if ($desired_capabilities === null) { 714*04fd306cSNickeau return new DesiredCapabilities(); 715*04fd306cSNickeau } 716*04fd306cSNickeau 717*04fd306cSNickeau if (is_array($desired_capabilities)) { 718*04fd306cSNickeau return new DesiredCapabilities($desired_capabilities); 719*04fd306cSNickeau } 720*04fd306cSNickeau 721*04fd306cSNickeau return $desired_capabilities; 722*04fd306cSNickeau } 723*04fd306cSNickeau} 724