RemoteCoverageListener::setMink()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the doyo/behat-code-coverage project.
5
 *
6
 * (c) Anthonius Munthi <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Doyo\Behat\Coverage\Listener;
15
16
use Doyo\Behat\Coverage\Event\CoverageEvent;
17
use Doyo\Bridge\CodeCoverage\Exception\SessionException;
18
use Doyo\Bridge\CodeCoverage\Session\RemoteSession;
19
use GuzzleHttp\ClientInterface;
20
use GuzzleHttp\Exception\RequestException;
21
use Psr\Http\Message\ResponseInterface;
22
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
23
24
class RemoteCoverageListener extends AbstractSessionCoverageListener implements EventSubscriberInterface
25
{
26
    /**
27
     * @var \Behat\Mink\Mink
28
     */
29
    private $mink;
30
31
    /**
32
     * @var ClientInterface
33
     */
34
    private $httpClient;
35
36
    private $remoteUrl;
37
38
    /**
39
     * @var bool
40
     */
41
    private $initialized = false;
42
43
    /**
44
     * @var SessionException
45
     */
46
    private $refreshException;
47
48 5
    public static function getSubscribedEvents()
49
    {
50
        return [
51 5
            CoverageEvent::BEFORE_START => 'beforeCoverageStart',
52
            CoverageEvent::REFRESH      => 'coverageRefresh',
53
            CoverageEvent::COMPLETED    => 'coverageCompleted',
54
        ];
55
    }
56
57 5
    public function setMink($mink)
58
    {
59 5
        $this->mink = $mink;
60
    }
61
62 12
    public function setRemoteUrl($url)
63
    {
64 12
        $this->remoteUrl = $url;
65
    }
66
67 12
    public function setHttpClient(ClientInterface $httpClient)
68
    {
69 12
        $this->httpClient = $httpClient;
70
    }
71
72 9
    public function coverageRefresh()
73
    {
74 9
        $client          = $this->httpClient;
75 9
        $session         = $this->session;
76 9
        $processor       = $session->getProcessor();
77 9
        $filter          = $processor->getCodeCoverageFilter();
78 9
        $coverageOptions = $processor->getCodeCoverageOptions();
79 9
        $url             = $this->remoteUrl;
80
81
        $data = [
82
            'filterOptions'       => [
83 9
                'whitelistedFiles' => $filter->getWhitelistedFiles(),
84
            ],
85 9
            'codeCoverageOptions' => $coverageOptions,
86
        ];
87 9
        $body    = json_encode($data);
88
        $options = [
89 9
            'body'  => $body,
90
            'query' => [
91 9
                'action'  => 'init',
92 9
                'session' => $this->session->getName(),
93
            ],
94
        ];
95
96
        try {
97 9
            $this->initialized = false;
98 9
            $client->request('POST', $url, $options);
99 8
            $this->initialized = true;
100 1
        } catch (\Exception $e) {
101 1
            $message                = $this->getExceptionMessage($e);
102 1
            $this->initialized      = false;
103 1
            $this->refreshException = new SessionException($message);
104
        }
105
    }
106
107 4
    public function beforeCoverageStart(CoverageEvent $event)
108
    {
109 4
        if ($this->initialized) {
110 4
            $this->doBeforeCoverageStart($event);
111
        }
112
    }
113
114 6
    public function coverageCompleted(CoverageEvent $event)
115
    {
116 6
        if ($this->initialized) {
117 6
            $this->doCoverageComplete($event);
118
        }
119
    }
120
121 4
    private function doBeforeCoverageStart(CoverageEvent $event)
122
    {
123 4
        $sessionName  = $this->session->getName();
124 4
        $testCaseName = $event->getTestCase()->getName();
125
126 4
        $mink = $this->mink;
127
128
        /** @var \Behat\Mink\Driver\Goutte\Client $client */
129 4
        $driver = $mink->getSession()->getDriver();
130 4
        $driver->setRequestHeader(RemoteSession::HEADER_SESSION_KEY, $sessionName);
131 4
        $driver->setRequestHeader(RemoteSession::HEADER_TEST_CASE_KEY, $testCaseName);
132
133
        /* patch for browserkit driver */
134 4
        if (method_exists($driver, 'getClient')) {
135 4
            $client = $driver->getClient();
136 4
            $client->setServerParameters([
137 4
                RemoteSession::HEADER_SESSION_KEY   => $sessionName,
138 4
                RemoteSession::HEADER_TEST_CASE_KEY => $testCaseName,
139
            ]);
140
        }
141
    }
142
143 6
    private function doCoverageComplete(CoverageEvent $event)
144
    {
145 6
        $session = $this->session;
146 6
        $client  = $this->httpClient;
147 6
        $uri     = $this->remoteUrl;
148
149
        $options = [
150
            'query' => [
151 6
                'action'  => 'read',
152 6
                'session' => $session->getName(),
153
            ],
154
        ];
155
156
        try {
157 6
            $response  = $client->request('GET', $uri, $options);
158 4
            $data      = $response->getBody()->getContents();
159 4
            $session   = unserialize($data);
160 4
            $processor = $session->getProcessor();
161 4
            $event->getProcessor()->merge($processor);
162 2
        } catch (\Exception $exception) {
163 2
            $message = $this->getExceptionMessage($exception);
164 2
            $event->getConsoleIO()->sessionError($session->getName(), $message);
165
        }
166
    }
167
168 3
    private function getExceptionMessage(\Exception $exception): string
169
    {
170 3
        $message = $exception->getMessage();
171
172 3
        if (!$exception instanceof RequestException) {
173 1
            return $message;
174
        }
175
176 2
        $response = $exception->getResponse();
177 2
        if (!$response instanceof ResponseInterface) {
0 ignored issues
show
introduced by
$response is always a sub-type of Psr\Http\Message\ResponseInterface.
Loading history...
178
            return $message;
179
        }
180
181 2
        $contentType = $response->getHeader('Content-Type');
182 2
        if (\in_array('application/json', $contentType, true)) {
183 2
            $data    = json_decode($response->getBody()->getContents(), true);
184 2
            $message = $data['message'];
185
        }
186
187 2
        return $message;
188
    }
189
}
190