Completed
Push — develop ( 2faf16...be2583 )
by ANTHONIUS
15s queued 11s
created

RemoteCoverageListener::doBeforeCoverageStart()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 2

Importance

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