Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite timeout handling code to support Selenium Server 3 #400

Merged
merged 5 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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'),
);
}
}
Loading