How To Set Pageload Timeout For Selenium With Behat
During testing work, I’ve noticed that sometimes Behat hangs itself by infinite waiting for answer from Selenium. I’ve figured out that I need to configure Selenium timeouts. But how…
Mink has a very weird documentation about settings timeouts. That’s because Mink itself is a just an abstraction layer and a factory of browser drivers.
So, we need to make Mink call some Selenium API function to get this work. Another problem is that Behat\Mink\Driver\DriverInterface
itself has no setTimeouts()
function.
Let’s take a closer look into Behat\Mink\Driver\Selenium2Driver
which implements this interface:
<?php
class Selenium2Driver extends CoreDriver
{
/**
* Sets the timeouts to apply to the webdriver session
* @param array $timeouts The session timeout settings: Array of {script, implicit, page} => time in microsecconds
* @throws DriverException
*/
public function setTimeouts($timeouts)
{
$this->timeouts = $timeouts;
if ($this->isStarted()) {
$this->applyTimeouts();
}
}
}
Okay, looks like we’ve got that we need, but… that doesn’t work at all!
<?php
$session = $this->mink->getSession($this->lastSession);
if ($driver instanceof Selenium2Driver) {
$driver->setTimeouts(['page' => 10000]);
}
return $session;
My Session manager initializes the session this way. Nothing changes, some pages still hang the process.
Going deeper!
Selenium2Driver::applyTimeouts()
function calls \WebDriver\Session::timeouts() internally. This function is here:
<?php
/**
* timeouts methods: /session/:sessionId/timeouts (POST)
* - $session->timeouts($json) - set timeout for an operation
* - $session->timeouts()->method() - chaining
*
* @return \WebDriver\Session|\WebDriver\Timeouts
*/
public function timeouts()
{
// set timeouts
if (func_num_args() === 1) {
$arg = func_get_arg(0); // json
$this->curl('POST', '/timeouts', $arg);
return $this;
}
if (func_num_args() === 2) {
$arg = array(
'type' => func_get_arg(0), // 'script' or 'implicit'
'ms' => func_get_arg(1), // timeout in milliseconds
);
$this->curl('POST', '/timeouts', $arg);
return $this;
}
// chaining
return new Timeouts($this->url . '/timeouts');
}
Okay, it knows nothing about ‘page’ type as described in comments…
Solution
After some investigation with Google and Selenium API I found out that timeout type I’m interested in is called ‘page load’
So,
<?php $driver->setTimeouts(['page load' => 10000]);
makes the trick! There is no mention of this nor in Mink docs nor in the code. Maybe, I’ll save a few hours for somebody by publishing this:)