Skip to content

Instantly share code, notes, and snippets.

@marekkalnik
Created July 9, 2014 14:47
Show Gist options
  • Save marekkalnik/964b6cb1d6f93308e8ca to your computer and use it in GitHub Desktop.
Save marekkalnik/964b6cb1d6f93308e8ca to your computer and use it in GitHub Desktop.
Using spinners in BehatContext
<?php
use Behat\MinkExtension\Context\MinkContext;
class BaseFeatureContext extends MinkContext
{
/**
* This function prevents Behat form failing a tests if the HTML is not loaded yet.
* Behat with Selenium often executes tests faster thant Selenium is able to retreive
* the HTML causing false negatives.
*
* Use this for all test cases that depend on a presence of some elements on the
* website.
*
* Pass an anonymous function containing your normal test as an argument.
* The function needs to return a boolean.
*
* @see http://docs.behat.org/cookbook/using_spin_functions.html
*
* @param \Closure $closure
* @param int $tries
*
* @return bool
*
* @throws \Exception|UnsupportedTestException
* @throws \Exception
*/
public function spin($closure, $tries = 30)
{
for ($i = 0; $i < $tries; $i++) {
try {
if ($result = $closure($this)) {
if (!is_bool($result)) {
throw new UnsupportedTestException(
'The spinned callback needs to return true on success or throw an Exception'
);
}
return true;
}
} catch (UnsupportedTestException $e) {
// If the test is unsupported, we quit
throw $e;
} catch (\Exception $e) {
// do nothing to continue the loop
}
usleep(300000);
}
$backtrace = debug_backtrace();
throw new \Exception(
"Timeout thrown by " . $backtrace[1]['class'] . "::" . $backtrace[1]['function'] . "()\n" .
"With the following arguments: " . print_r($backtrace[1]['args'], true)
);
}
/**
* @Given /^I wait to see "(?P<text>(?:[^"]|\\")*)"$/
*
* @param string $text
*
* @return bool
*/
public function iWaitToSee($text)
{
return $this->assertPageContainsText($text);
}
/**
* Overrides MinkContext method by adding a spin
*
* {@inheritdoc}
*/
public function assertPageContainsText($text)
{
$this->waitUntilPageLoaded();
return $this->spin(
function ($context) use ($text) {
$context->assertSession()->pageTextContains($context->fixStepArgument($text));
return true;
}
);
}
/**
* This methods makes Selenium2 wait until the body element is present.
* This supposes that the html is loaded (even if it's not 100% reliable).
*
* @return bool
*/
protected function waitUntilPageLoaded()
{
$this->spin(
function ($context) {
$context->assertSession()->elementExists('xpath', '//body');
return true;
}
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment