diff --git a/src/Selenium2Driver.php b/src/Selenium2Driver.php index 917a4a47..242096a9 100755 --- a/src/Selenium2Driver.php +++ b/src/Selenium2Driver.php @@ -16,7 +16,9 @@ use WebDriver\Element; use WebDriver\Exception\InvalidArgument; use WebDriver\Exception\NoSuchElement; +use WebDriver\Exception\ScriptTimeout; use WebDriver\Exception\StaleElementReference; +use WebDriver\Exception\Timeout; use WebDriver\Exception\UnknownCommand; use WebDriver\Exception\UnknownError; use WebDriver\Key; @@ -61,6 +63,11 @@ class Selenium2Driver extends CoreDriver */ private $wdSession; + /** + * @var bool + */ + private $isW3C = false; + /** * The timeout configuration * @var array{script?: int, implicit?: int, page?: int} @@ -343,14 +350,17 @@ public function start() { try { $this->wdSession = $this->webDriver->session($this->browserName, $this->desiredCapabilities); + + $status = $this->webDriver->status(); + $this->isW3C = version_compare($status['build']['version'], '3.0.0', '>='); + + $this->applyTimeouts(); + $this->initialWindowHandle = $this->getWebDriverSession()->window_handle(); } catch (\Exception $e) { throw new DriverException('Could not open connection: '.$e->getMessage(), 0, $e); } $this->started = true; - - $this->applyTimeouts(); - $this->initialWindowHandle = $this->getWebDriverSession()->window_handle(); } /** @@ -376,9 +386,25 @@ public function setTimeouts(array $timeouts) */ private function applyTimeouts(): void { + $validTimeoutTypes = array('script', 'implicit', 'page load', 'pageLoad'); + try { foreach ($this->timeouts as $type => $param) { - $this->getWebDriverSession()->timeouts($type, $param); + if (!in_array($type, $validTimeoutTypes)) { + throw new DriverException('Invalid timeout type: ' . $type); + } + + if ($type === 'page load' && $this->isW3C) { + $type = 'pageLoad'; + } elseif ($type === 'pageLoad' && !$this->isW3C) { + $type = 'page load'; + } + + if ($this->isW3C) { + $this->getWebDriverSession()->timeouts(array($type => $param)); + } else { + $this->getWebDriverSession()->timeouts($type, $param); + } } } catch (UnknownError $e) { // Selenium 2.x. @@ -401,6 +427,7 @@ public function stop() } $this->started = false; + $this->isW3C = false; try { $this->wdSession->close(); } catch (\Exception $e) { @@ -428,7 +455,15 @@ public function reset() public function visit(string $url) { - $this->getWebDriverSession()->open($url); + try { + $this->getWebDriverSession()->open($url); + } catch (Timeout $e) { + // The W3C compatible Selenium Server. + throw new DriverException('Page failed to load: ' . $e->getMessage(), 0, $e); + } catch (ScriptTimeout $e) { + // The Non-W3C compatible Selenium Server. + throw new DriverException('Page failed to load: ' . $e->getMessage(), 0, $e); + } } public function getCurrentUrl() diff --git a/tests/Custom/TimeoutTest.php b/tests/Custom/TimeoutTest.php index e17e5f0d..083e79f5 100644 --- a/tests/Custom/TimeoutTest.php +++ b/tests/Custom/TimeoutTest.php @@ -37,6 +37,7 @@ public function testInvalidTimeoutSettingThrowsException() \assert($driver instanceof Selenium2Driver); $this->expectException('\Behat\Mink\Exception\DriverException'); + $this->expectExceptionMessage('Invalid timeout type: invalid'); $driver->setTimeouts(array('invalid' => 0)); } @@ -70,4 +71,28 @@ public function testLongTimeoutWaitsForElementToAppear() $this->assertNotNull($element); } + + /** + * @dataProvider shortPageLoadTimeoutThrowsExceptionDataProvider + */ + public function testShortPageLoadTimeoutThrowsException(string $timeoutType) + { + $session = $this->getSession(); + $driver = $session->getDriver(); + \assert($driver instanceof Selenium2Driver); + + $driver->setTimeouts(array($timeoutType => 1)); // Use 1ms timeout to avoid any successful page load. + + $this->expectException('\Behat\Mink\Exception\DriverException'); + $this->expectExceptionMessage('Page failed to load: '); + $session->visit('https://www.webpagetest.org/'); // Use external URL, because it loads slower, then local. + } + + public static function shortPageLoadTimeoutThrowsExceptionDataProvider(): array + { + return array( + 'w3c style' => array('pageLoad'), + 'non-w3c style' => array('page load'), + ); + } }