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\AfterStepSetup;
14 use Behat\Behat\EventDispatcher\Event\AfterStepTested;
15 use Behat\Behat\EventDispatcher\Event\BackgroundTested;
16 use Behat\Behat\EventDispatcher\Event\FeatureTested;
17 use Behat\Testwork\Output\Formatter;
18 use Behat\Testwork\Output\Node\EventListener\EventListener;
19 use Symfony\Component\EventDispatcher\Event;
22 * Behat only first background fires listener.
24 * This listener catches all in-background events and then proxies them further
25 * only if they meet one of two conditions:
27 * 1. It is a first background
28 * 2. It is a failing step
30 * @author Konstantin Kudryashov <ever.zet@gmail.com>
32 class OnlyFirstBackgroundFiresListener implements EventListener
41 private $firstBackgroundEnded = false;
45 private $inBackground = false;
49 private $stepSetupHadOutput = false;
52 * Initializes listener.
54 * @param EventListener $descendant
56 public function __construct(EventListener $descendant)
58 $this->descendant = $descendant;
64 public function listenEvent(Formatter $formatter, Event $event, $eventName)
66 $this->flushStatesIfBeginningOfTheFeature($eventName);
67 $this->markBeginningOrEndOfTheBackground($eventName);
69 if ($this->isSkippableEvent($event)) {
73 $this->markFirstBackgroundPrintedAfterBackground($eventName);
75 $this->descendant->listenEvent($formatter, $event, $eventName);
79 * Flushes state if the event is the BEFORE feature.
81 * @param string $eventName
83 private function flushStatesIfBeginningOfTheFeature($eventName)
85 if (FeatureTested::BEFORE !== $eventName) {
89 $this->firstBackgroundEnded = false;
90 $this->inBackground = false;
94 * Marks beginning or end of the background.
96 * @param string $eventName
98 private function markBeginningOrEndOfTheBackground($eventName)
100 if (BackgroundTested::BEFORE === $eventName) {
101 $this->inBackground = true;
104 if (BackgroundTested::AFTER === $eventName) {
105 $this->inBackground = false;
110 * Marks first background printed.
112 * @param string $eventName
114 private function markFirstBackgroundPrintedAfterBackground($eventName)
116 if (BackgroundTested::AFTER !== $eventName) {
120 $this->firstBackgroundEnded = true;
124 * Checks if provided event is skippable.
126 * @param Event $event
130 private function isSkippableEvent(Event $event)
132 if (!$this->firstBackgroundEnded) {
136 return $event instanceof BackgroundTested || $this->isNonFailingConsequentBackgroundStep($event);
140 * Checks if provided event is a non-failing step in consequent background.
142 * @param Event $event
146 private function isNonFailingConsequentBackgroundStep(Event $event)
148 if (!$this->inBackground) {
152 return !$this->isStepEventWithOutput($event);
156 * Checks if provided event is a step event which setup or teardown produced any output.
158 * @param Event $event
162 private function isStepEventWithOutput(Event $event)
164 return $this->isBeforeStepEventWithOutput($event) || $this->isAfterStepWithOutput($event);
168 * Checks if provided event is a BEFORE step with setup that produced output.
170 * @param Event $event
174 private function isBeforeStepEventWithOutput(Event $event)
176 if ($event instanceof AfterStepSetup && $event->hasOutput()) {
177 $this->stepSetupHadOutput = true;
186 * Checks if provided event is an AFTER step with teardown that produced output.
188 * @param Event $event
192 private function isAfterStepWithOutput(Event $event)
194 if ($event instanceof AfterStepTested && ($this->stepSetupHadOutput || $event->hasOutput())) {
195 $this->stepSetupHadOutput = false;