I am in the process of upgrading from the Behat 2.x series to the Behat 3.x series. In the prior version I could load the Selenium 1 driver, which attached to PhantomJS to execute tests. When I did this I was able to hook into a function called waitForPageToLoad().
This function was provided by php-selenium (from Alexandre Salomé). It hooked into selenium and called a driver action by the same name. This worked perfectly for ensuring that Selenium waited for a page to load. At least until a timeout was reached. It made tests to go much faster.
The problem is that the Selenium 1 driver is not compatible with Behat 3.x. It looks like it has been all but abandoned and I don't see that functionality in the Selenium 2 driver for Mink.
Does anyone know of a way to make this work with Behat 3.x and Selenium 2?
Using Selenium (or any other driver for that matter), I've never had to worry about whether the page has loaded or not, with one exception: if the page finishes loading, then loads more content via AJAX.
To handle this, you can use a spin function as documented in the Behat Manual.
http://docs.behat.org/en/v2.5/cookbook/using_spin_functions.html
The benefits of this are:
I wouldn't use theirs though, the back trace is broken and who want's to wait a second between checks anyway. :)
Try this:
Assuming you are using the Mink Context (thanks Mick), you can simply check the page every second or so until the desired text has either appeared or dissapeared, or a given timeout has expired in which case we'd assume a fail.
/**
* @When I wait for :text to appear
* @Then I should see :text appear
* @param $text
* @throws \Exception
*/
public function iWaitForTextToAppear($text)
{
$this->spin(function(FeatureContext $context) use ($text) {
try {
$context->assertPageContainsText($text);
return true;
}
catch(ResponseTextException $e) {
// NOOP
}
return false;
});
}
/**
* @When I wait for :text to disappear
* @Then I should see :text disappear
* @param $text
* @throws \Exception
*/
public function iWaitForTextToDisappear($text)
{
$this->spin(function(FeatureContext $context) use ($text) {
try {
$context->assertPageContainsText($text);
}
catch(ResponseTextException $e) {
return true;
}
return false;
});
}
/**
* Based on Behat's own example
* @see http://docs.behat.org/en/v2.5/cookbook/using_spin_functions.html#adding-a-timeout
* @param $lambda
* @param int $wait
* @throws \Exception
*/
public function spin($lambda, $wait = 60)
{
$time = time();
$stopTime = $time + $wait;
while (time() < $stopTime)
{
try {
if ($lambda($this)) {
return;
}
} catch (\Exception $e) {
// do nothing
}
usleep(250000);
}
throw new \Exception("Spin function timed out after {$wait} seconds");
}