4 * This file is part of the Behat.
5 * (c) Konstantin Kudryashov <ever.zet@gmail.com>
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
11 namespace Behat\Behat\Output\Node\EventListener\Flow;
13 use Behat\Behat\EventDispatcher\Event\BackgroundTested;
14 use Behat\Behat\EventDispatcher\Event\ExampleTested;
15 use Behat\Behat\EventDispatcher\Event\FeatureTested;
16 use Behat\Behat\EventDispatcher\Event\OutlineTested;
17 use Behat\Behat\EventDispatcher\Event\ScenarioTested;
18 use Behat\Testwork\Output\Formatter;
19 use Behat\Testwork\Output\Node\EventListener\EventListener;
20 use Symfony\Component\EventDispatcher\Event;
23 * Behat first background fires first listener.
25 * This listener catches first scenario and background events in the feature and makes sure
26 * that background event are always fired before scenario events, thus following Gherkin format.
28 * @author Konstantin Kudryashov <ever.zet@gmail.com>
30 class FirstBackgroundFiresFirstListener implements EventListener
33 * @var \Behat\Testwork\Output\Node\EventListener\EventListener
39 private $firstBackgroundEnded = false;
43 private $delayedUntilBackgroundEnd = array();
46 * Initializes listener.
48 * @param EventListener $descendant
50 public function __construct(EventListener $descendant)
52 $this->descendant = $descendant;
58 public function listenEvent(Formatter $formatter, Event $event, $eventName)
60 $this->flushStatesIfBeginningOfTheFeature($eventName);
61 $this->markFirstBackgroundPrintedAfterBackground($eventName);
63 if ($this->isEventDelayedUntilFirstBackgroundPrinted($event)) {
64 $this->delayedUntilBackgroundEnd[] = array($event, $eventName);
69 $this->descendant->listenEvent($formatter, $event, $eventName);
70 $this->fireDelayedEventsOnAfterBackground($formatter, $eventName);
74 * Flushes state if the event is the BEFORE feature.
76 * @param string $eventName
78 private function flushStatesIfBeginningOfTheFeature($eventName)
80 if (FeatureTested::BEFORE !== $eventName) {
84 $this->firstBackgroundEnded = false;
88 * Marks first background printed.
90 * @param string $eventName
92 private function markFirstBackgroundPrintedAfterBackground($eventName)
94 if (BackgroundTested::AFTER !== $eventName) {
98 $this->firstBackgroundEnded = true;
102 * Checks if provided event should be postponed until background is printed.
104 * @param Event $event
108 private function isEventDelayedUntilFirstBackgroundPrinted(Event $event)
110 if (!$event instanceof ScenarioTested && !$event instanceof OutlineTested && !$event instanceof ExampleTested) {
114 return !$this->firstBackgroundEnded && $event->getFeature()->hasBackground();
118 * Fires delayed events on AFTER background event.
120 * @param Formatter $formatter
121 * @param string $eventName
123 private function fireDelayedEventsOnAfterBackground(Formatter $formatter, $eventName)
125 if (BackgroundTested::AFTER !== $eventName) {
129 foreach ($this->delayedUntilBackgroundEnd as $eventInfo) {
130 list($event, $eventName) = $eventInfo;
132 $this->descendant->listenEvent($formatter, $event, $eventName);
135 $this->delayedUntilBackgroundEnd = array();