diff --git a/src/Selenium2Driver.php b/src/Selenium2Driver.php index e74fcb3a..d24f680e 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,15 +386,34 @@ public function setTimeouts(array $timeouts) */ private function applyTimeouts(): void { + $validTimeoutTypes = array('script', 'implicit', 'page', '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' || $type === 'pageLoad') { + @trigger_error( + 'Using "' . $type . '" timeout type is deprecated, please use "page" instead', + E_USER_DEPRECATED + ); + $type = 'page'; + } + + if ($type === 'page') { + $type = $this->isW3C ? 'pageLoad' : 'page load'; + } + + if ($this->isW3C) { + $this->getWebDriverSession()->timeouts(array($type => $param)); + } else { + $this->getWebDriverSession()->timeouts($type, $param); + } } - } catch (UnknownError $e) { - // Selenium 2.x. - throw new DriverException('Error setting timeout: ' . $e->getMessage(), 0, $e); - } catch (InvalidArgument $e) { - // Selenium 3.x. + } catch (UnknownError|InvalidArgument $e) { + // UnknownError (Selenium 2.x). InvalidArgument (Selenium 3.x). throw new DriverException('Error setting timeout: ' . $e->getMessage(), 0, $e); } } @@ -401,6 +430,7 @@ public function stop() } $this->started = false; + $this->isW3C = false; try { $this->wdSession->close(); } catch (\Exception $e) { @@ -428,7 +458,12 @@ public function reset() public function visit(string $url) { - $this->getWebDriverSession()->open($url); + try { + $this->getWebDriverSession()->open($url); + } catch (ScriptTimeout|Timeout $e) { + // ScriptTimeout (Selenium 2.x). Timeout (Selenium 3.x). + 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..c8a8ed58 100644 --- a/tests/Custom/TimeoutTest.php +++ b/tests/Custom/TimeoutTest.php @@ -3,10 +3,14 @@ namespace Behat\Mink\Tests\Driver\Custom; use Behat\Mink\Driver\Selenium2Driver; +use Behat\Mink\Exception\DriverException; use Behat\Mink\Tests\Driver\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; class TimeoutTest extends TestCase { + use ExpectDeprecationTrait; + /** * @after */ @@ -36,7 +40,8 @@ public function testInvalidTimeoutSettingThrowsException() $driver = $session->getDriver(); \assert($driver instanceof Selenium2Driver); - $this->expectException('\Behat\Mink\Exception\DriverException'); + $this->expectException(DriverException::class); + $this->expectExceptionMessage('Invalid timeout type: invalid'); $driver->setTimeouts(array('invalid' => 0)); } @@ -70,4 +75,43 @@ public function testLongTimeoutWaitsForElementToAppear() $this->assertNotNull($element); } + + public function testShortPageLoadTimeoutThrowsException() + { + $session = $this->getSession(); + $driver = $session->getDriver(); + \assert($driver instanceof Selenium2Driver); + + $driver->setTimeouts(array('page' => 500)); + + $this->expectException(DriverException::class); + $this->expectExceptionMessage('Page failed to load: '); + $session->visit($this->pathTo('/page_load.php?sleep=2')); + } + + /** + * @group legacy + * @dataProvider deprecatedPageLoadDataProvider + */ + public function testDeprecatedShortPageLoadTimeoutThrowsException(string $type) + { + $session = $this->getSession(); + $driver = $session->getDriver(); + \assert($driver instanceof Selenium2Driver); + + $this->expectDeprecation('Using "' . $type . '" timeout type is deprecated, please use "page" instead'); + $driver->setTimeouts(array($type => 500)); + + $this->expectException(DriverException::class); + $this->expectExceptionMessage('Page failed to load: '); + $session->visit($this->pathTo('/page_load.php?sleep=2')); + } + + public static function deprecatedPageLoadDataProvider(): array + { + return array( + 'w3c style' => array('pageLoad'), + 'non-w3c style' => array('page load'), + ); + } }