Created
July 9, 2014 14:47
-
-
Save marekkalnik/964b6cb1d6f93308e8ca to your computer and use it in GitHub Desktop.
Using spinners in BehatContext
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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