Skip to content

Commit

Permalink
Rewrite timeout handling code to support Selenium Server 3 (#400)
Browse files Browse the repository at this point in the history
Corrected invalid timeout handling. Support Selenium Server 3 timeouts. Deprecate "page load"/"page Load" timeouts.
  • Loading branch information
aik099 authored Nov 11, 2024
1 parent db44be5 commit c5edd67
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 11 deletions.
55 changes: 45 additions & 10 deletions src/Selenium2Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -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();
}

/**
Expand All @@ -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);
}
}
Expand All @@ -401,6 +430,7 @@ public function stop()
}

$this->started = false;
$this->isW3C = false;
try {
$this->wdSession->close();
} catch (\Exception $e) {
Expand Down Expand Up @@ -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()
Expand Down
46 changes: 45 additions & 1 deletion tests/Custom/TimeoutTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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));
}

Expand Down Expand Up @@ -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'),
);
}
}

0 comments on commit c5edd67

Please sign in to comment.