Failed Conditions
Pull Request — master (#1)
by Yo
04:24 queued 01:19
created

resolveContextAndNodeHeader()   C

Complexity

Conditions 8
Paths 13

Size

Total Lines 43
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
dl 0
loc 43
ccs 0
cts 37
cp 0
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 35
nc 13
nop 1
crap 72
1
<?php
2
namespace Yoanm\BehatUtilsExtension\Subscriber;
3
4
use Behat\Behat\EventDispatcher\Event\BackgroundTested;
5
use Behat\Behat\EventDispatcher\Event\ExampleTested;
6
use Behat\Behat\EventDispatcher\Event\FeatureTested;
7
use Behat\Behat\EventDispatcher\Event\GherkinNodeTested;
8
use Behat\Behat\EventDispatcher\Event\OutlineTested;
9
use Behat\Behat\EventDispatcher\Event\ScenarioTested;
10
use Behat\Behat\EventDispatcher\Event\StepTested;
11
use Behat\Gherkin\Node\ExampleNode;
12
use Behat\Gherkin\Node\StepContainerInterface;
13
use Behat\Gherkin\Node\StepNode;
14
use Behat\Testwork\EventDispatcher\Event\AfterTested;
15
use Psr\Log\LoggerInterface;
16
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
17
18
/**
19
 * Class BehatStepLoggerSubscriber
20
 */
21
class BehatStepLoggerSubscriber implements EventSubscriberInterface
22
{
23
    const HEADER_ACTION_IN = 'IN';
24
    const HEADER_ACTION_OUT = 'OUT';
25
26
    const HEADER_NODE_FEATURE = 'FEATURE';
27
    const HEADER_NODE_BACKGROUND = 'BACKGROUND';
28
    const HEADER_NODE_SCENARIO = 'SCENARIO';
29
    const HEADER_NODE_OUTLINE = 'OUTLINE';
30
    const HEADER_NODE_EXAMPLE = 'EXAMPLE';
31
    const HEADER_NODE_STEP = 'STEP';
32
33
    /** @var LoggerInterface */
34
    private $logger;
35
36
    /**
37
     * @param LoggerInterface $logger
38
     */
39 1
    public function __construct(LoggerInterface $logger)
40
    {
41 1
        $this->logger = $logger;
42 1
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47 1
    public static function getSubscribedEvents()
48
    {
49
        // Use high priority to log event at beginning
50 1
        $listener = ['logEvent', ListenerPriority::HIGH_PRIORITY];
51
        return [
52 1
            FeatureTested::BEFORE => $listener,
53 1
            BackgroundTested::BEFORE => $listener,
54 1
            ScenarioTested::BEFORE => $listener,
55 1
            OutlineTested::BEFORE => $listener,
56 1
            ExampleTested::BEFORE => $listener,
57 1
            StepTested::BEFORE => $listener,
58
59 1
            FeatureTested::AFTER => $listener,
60 1
            BackgroundTested::AFTER => $listener,
61 1
            ScenarioTested::AFTER => $listener,
62 1
            OutlineTested::AFTER => $listener,
63 1
            ExampleTested::AFTER => $listener,
64 1
            StepTested::AFTER => $listener,
65 1
        ];
66
    }
67
68
    /**
69
     * @param GherkinNodeTested $event
70
     */
71
    public function logEvent(GherkinNodeTested $event)
72
    {
73
        list($header, $context) = $this->processNodeEvent($event);
74
        $this->logger->debug($header, $context);
75
    }
76
77
    /**
78
     * @param GherkinNodeTested $event
79
     *
80
     * @return array
81
     */
82
    protected function processNodeEvent(GherkinNodeTested $event)
83
    {
84
        list($context, $nodeHeader) = $this->resolveContextAndNodeHeader($event);
85
86
        return [
87
            sprintf(
88
                '[%s][%s]',
89
                $nodeHeader,
90
                $this->resolveActionType($event)
91
            ),
92
            $context
93
        ];
94
    }
95
96
    /**
97
     * @param GherkinNodeTested $event
98
     *
99
     * @return string
100
     */
101
    protected function resolveActionType(GherkinNodeTested $event)
102
    {
103
        return $event instanceof AfterTested
104
            ? self::HEADER_ACTION_OUT
105
            : self::HEADER_ACTION_IN;
106
    }
107
108
    /**
109
     * @param GherkinNodeTested $event
110
     *
111
     * @return array
112
     */
113
    protected function resolveContextAndNodeHeader(GherkinNodeTested $event)
114
    {
115
        $context = [];
116
        switch (true) {
117
            case $event instanceof StepTested:
118
                $nodeHeader = self::HEADER_NODE_STEP;
119
                $context['text'] = $event->getStep()->getText();
120
                break;
121
            case $event instanceof BackgroundTested:
122
                $nodeHeader = self::HEADER_NODE_BACKGROUND;
123
                $context['title'] = $event->getBackground()->getTitle();
124
                break;
125
            case $event instanceof ScenarioTested:
126
                $scenario = $event->getScenario();
127
                $nodeHeader = self::HEADER_NODE_SCENARIO;
128
                if ($scenario instanceof ExampleNode) {
129
                    $nodeHeader = self::HEADER_NODE_EXAMPLE;
130
                    $context['tokens'] = $scenario->getTokens();
131
                }
132
                $context['title'] = $scenario->getTitle();
133
                break;
134
            case $event instanceof OutlineTested:
135
                $nodeHeader = self::HEADER_NODE_OUTLINE;
136
                $context['title'] = $event->getOutline()->getTitle();
137
                break;
138
            case $event instanceof FeatureTested:
139
                $nodeHeader = self::HEADER_NODE_FEATURE;
140
                $context['title'] = $event->getFeature()->getTitle();
141
                $context['file'] = $event->getFeature()->getFile();
142
                break;
143
            default:
144
                throw new \InvalidArgumentException(sprintf('"%s" not handled !', get_class($event)));
145
        }
146
147
        if (!$event instanceof FeatureTested) {
148
            $context['line'] = $this->resolveNodeLine($event);
149
        }
150
151
        return [
152
            $context,
153
            $nodeHeader
154
        ];
155
    }
156
157
    /**
158
     * @param GherkinNodeTested $event
159
     *
160
     * @return int
161
     */
162
    protected function resolveNodeLine(GherkinNodeTested $event)
163
    {
164
        $node = $event->getNode();
165
        $line = $node->getLine();
166
167
        if ($node instanceof StepContainerInterface
168
            && $event instanceof AfterTested
169
            && !$event instanceof StepTested /* no need to process step event end line */
170
        ) {
171
            // in case of end event, try to find the last line of the node
172
173
            /** @var StepContainerInterface $node*/
174
            $stepList = $node->getSteps();
175
            $lastStep = array_pop($stepList);
176
177
            // Check if StepContainer was not empty
178
            if ($lastStep instanceof StepNode) {
179
                $line = $lastStep->getLine();
180
            }
181
        }
182
183
        return $line;
184
    }
185
}
186