getScenarios() as $nextScenario) { if ($nextScenario->getLine() > $step->getLine()) { break; } $scenario = $nextScenario; } return $scenario; } /** * Retry until no exceptions are thrown, or until * $timeout seconds are reached. * * If timeout reached, re-throws the first exception. * * @param callable $callback * @param int $timeout * @return mixed * @throws Exception */ protected function retryThrowable($callback, $timeout = 3) { $firstEx = null; do { try { return call_user_func($callback); } catch (Exception $ex) { if (!$firstEx) { $firstEx = $ex; } } sleep(1); } while (--$timeout >= 0); throw $firstEx; } /** * Check if a step has a given tag * * @param StepScope|ScenarioScope $event * @param string $tag * @return bool */ protected function stepHasTag($event, $tag) { $checks = []; if ($event instanceof StepScope) { $checks[] = $feature = $event->getFeature(); $checks[] = $this->getStepScenario($feature, $event->getStep()); } elseif ($event instanceof ScenarioScope) { $checks[] = $event->getFeature(); $checks[] = $event->getScenario(); } else { throw new InvalidArgumentException(sprintf( '%s expected an instance of either %s or %s. Got %s instead', __METHOD__, StepScope::class, ScenarioScope::class, is_object($event) ? sprintf('an instance of %s', get_class($event)) : gettype($event) )); } foreach ($checks as $check) { if ($check instanceof TaggedNodeInterface && $check->hasTag($tag)) { return true; } } return false; } }