Passed
Pull Request — master (#43)
by Baptiste
02:06
created

Context   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 252
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 11

Importance

Changes 0
Metric Value
wmc 32
lcom 2
cbo 11
dl 0
loc 252
rs 9.6
c 0
b 0
f 0

25 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A createARequest() 0 10 1
A sendARequest() 0 5 1
A addAParameter() 0 16 3
A setTheParameters() 0 8 2
A setContentType() 0 5 1
A setTheBody() 0 7 1
A addHeader() 0 5 1
A setHeaders() 0 10 2
A sendRequest() 0 20 3
A statusCodeShouldBe() 0 5 1
A statusCodeShouldNotBe() 0 5 1
A contentTypeShouldBe() 0 5 1
A headerShouldBe() 0 5 1
A headerShouldContain() 0 5 1
A responseShouldHaveHeader() 0 5 1
A responseShouldHaveSentSomeData() 0 7 1
A responseShouldNotHaveAnyData() 0 5 1
A responseShouldContain() 0 5 1
A responseShouldNotContain() 0 5 1
A responseShouldBe() 0 5 1
A responseShouldNotBe() 0 5 1
A clearCache() 0 6 1
A getRequest() 0 8 2
A getDefaultContentType() 0 4 1
1
<?php declare(strict_types=1);
2
namespace Behapi\Http;
3
4
use RuntimeException;
5
6
use Psr\Http\Message\RequestInterface;
7
8
use Behat\Behat\Context\Context as BehatContext;
9
use Behat\Gherkin\Node\TableNode;
10
11
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
12
13
use Http\Client\HttpClient;
14
use Http\Message\StreamFactory;
15
use Http\Message\MessageFactory;
16
17
use Behapi\EventListener\Events;
18
use Behapi\EventListener\RequestEvent;
19
20
use Behapi\HttpHistory\History as HttpHistory;
21
22
use function trim;
23
use function is_array;
24
use function http_build_query;
25
26
class Context implements BehatContext
27
{
28
    use Client;
29
30
    /** @var RequestInterface */
31
    private $request;
32
33
    /** @var mixed[] Query args to add */
34
    private $query;
35
36
    /** @var EventDispatcherInterface */
37
    private $dispatcher;
38
39
    public function __construct(HttpClient $client, StreamFactory $streamFactory, MessageFactory $messageFactory, HttpHistory $history, EventDispatcherInterface $dispatcher)
40
    {
41
        $this->client = $client;
42
        $this->history = $history;
43
        $this->dispatcher = $dispatcher;
44
        $this->streamFactory = $streamFactory;
45
        $this->messageFactory = $messageFactory;
46
    }
47
48
    /** @When /^I create a "(?P<method>GET|POST|PATCH|PUT|DELETE|OPTIONS|HEAD)" request to "(?P<url>.+?)"$/ */
49
    public function createARequest(string $method, string $url)
50
    {
51
        $url = trim($url);
52
53
        $this->query = [];
54
        $this->request = $this->messageFactory->createRequest(strtoupper($method), $url);
55
56
        // let's set a default content-type
57
        $this->setContentType($this->getDefaultContentType());
58
    }
59
60
    /**
61
     * @When /^I send a "(?P<method>GET|POST|PATCH|PUT|DELETE|OPTIONS|HEAD)" request to "(?P<url>.+?)"$/
62
     *
63
     * -------
64
     *
65
     * Shortcut for `When I create a X request to Then send the request`
66
     */
67
    public function sendARequest($method, $url)
68
    {
69
        $this->createARequest($method, $url);
70
        $this->sendRequest();
71
    }
72
73
    /** @When I add/set the value :value to the parameter :parameter */
74
    public function addAParameter(string $parameter, string $value)
75
    {
76
        if (!isset($this->query[$parameter])) {
77
            $this->query[$parameter] = $value;
78
            return;
79
        }
80
81
        $current = &$this->query[$parameter];
82
83
        if (is_array($current)) {
84
            $current[] = $value;
85
            return;
86
        }
87
88
        $current = [$current, $value];
89
    }
90
91
    /** @When I set the following query arguments: */
92
    public function setTheParameters(TableNode $parameters)
93
    {
94
        $this->query = [];
95
96
        foreach ($parameters->getRowsHash() as $parameter => $value) {
97
            $this->addAParameter($parameter, $value);
98
        }
99
    }
100
101
    /** @When I set the content-type to :type */
102
    public function setContentType(string $type)
103
    {
104
        $request = $this->getRequest();
105
        $this->request = $request->withHeader('Content-Type', $type);
106
    }
107
108
    /** @When I set the following body: */
109
    public function setTheBody(string $body)
110
    {
111
        $stream = $this->streamFactory->createStream($body);
112
113
        $request = $this->getRequest();
114
        $this->request = $request->withBody($stream);
115
    }
116
117
    /** @When I add/set the value :value to the header :header */
118
    public function addHeader(string $header, string $value)
119
    {
120
        $request = $this->getRequest();
121
        $this->request = $request->withAddedHeader($header, $value);
122
    }
123
124
    /** @When I set the headers: */
125
    public function setHeaders(TableNode $headers)
126
    {
127
        $request = $this->getRequest();
128
129
        foreach ($headers->getRowsHash() as $header => $value) {
130
            $request = $request->withHeader($header, $value);
131
        }
132
133
        $this->request = $request;
134
    }
135
136
    /** @When I send the request */
137
    public function sendRequest()
138
    {
139
        $request = $this->getRequest();
140
141
        if (!empty($this->query)) {
142
            $uri = $request->getUri();
143
            $current = $uri->getQuery();
144
            $query = http_build_query($this->query);
145
146
            if (!empty($current)) {
147
                $query = "{$current}&{$query}";
148
            }
149
150
            $uri = $uri->withQuery($query);
151
            $request = $request->withUri($uri);
152
        }
153
154
        $this->dispatcher->dispatch(Events::REQUEST_PRE_SENDING, $event = new RequestEvent($request));
155
        $this->client->sendRequest($event->getRequest());
156
    }
157
158
    /** @Then the status code should be :expected */
159
    public function statusCodeShouldBe(int $expected)
160
    {
161
        $response = $this->getResponse();
162
        Assert::same((int) $response->getStatusCode(), $expected);
163
    }
164
165
    /** @Then the status code should not be :expected */
166
    public function statusCodeShouldNotBe(int $expected)
167
    {
168
        $response = $this->getResponse();
169
        Assert::notSame((int) $response->getStatusCode(), $expected);
170
    }
171
172
    /** @Then the content-type should be equal to :expected */
173
    public function contentTypeShouldBe(string $expected)
174
    {
175
        $response = $this->getResponse();
176
        Assert::same($response->getHeaderLine('Content-type'), $expected);
177
    }
178
179
    /** @Then the response header :header should be equal to :expected */
180
    public function headerShouldBe(string $header, string $expected)
181
    {
182
        $response = $this->getResponse();
183
        Assert::same($response->getHeaderLine($header), $expected);
184
    }
185
186
    /** @Then the response header :header should contain :expected */
187
    public function headerShouldContain(string $header, string $expected)
188
    {
189
        $response = $this->getResponse();
190
        Assert::contains((string) $response->getHeaderLine($header), $expected);
191
    }
192
193
    /** @Then the response should have a header :header */
194
    public function responseShouldHaveHeader(string $header)
195
    {
196
        $response = $this->getResponse();
197
        Assert::true($response->hasHeader($header));
198
    }
199
200
    /** @Then the response should have sent some data */
201
    public function responseShouldHaveSentSomeData()
202
    {
203
        $body = $this->getResponse()->getBody();
204
205
        Assert::notNull($body->getSize());
206
        Assert::greaterThan($body->getSize(), 0);
207
    }
208
209
    /** @Then the response should not have sent any data */
210
    public function responseShouldNotHaveAnyData()
211
    {
212
        $body = $this->getResponse()->getBody();
213
        Assert::nullOrSame($body->getSize(), 0);
214
    }
215
216
    /** @Then the response should contain :data */
217
    public function responseShouldContain(string $data)
218
    {
219
        $response = $this->getResponse();
220
        Assert::contains((string) $response->getBody(), $data);
221
    }
222
223
    /** @Then the response should not contain :data */
224
    public function responseShouldNotContain(string $data)
225
    {
226
        $response = $this->getResponse();
227
        Assert::notContains((string) $response->getBody(), $data);
228
    }
229
230
    /** @Then the response should be :data */
231
    public function responseShouldBe(string $data)
232
    {
233
        $response = $this->getResponse();
234
        Assert::eq((string) $response->getBody(), $data);
235
    }
236
237
    /** @Then the response should not be :data */
238
    public function responseShouldNotBe(string $data)
239
    {
240
        $response = $this->getResponse();
241
        Assert::NotEq((string) $response->getBody(), $data);
242
    }
243
244
    /**
245
     * @AfterScenario @api
246
     * @AfterScenario @rest
247
     */
248
    public function clearCache()
249
    {
250
        $this->query = [];
251
        $this->request = null;
252
        // the history is resetted in its own event listener
253
    }
254
255
    /**
256
     * @return RequestInterface
257
     * @throws RuntimeException
258
     */
259
    public function getRequest(): RequestInterface
260
    {
261
        if (null === $this->request) {
262
            throw new RuntimeException('No request initiated');
263
        }
264
265
        return $this->request;
266
    }
267
268
    /**
269
     * Get the default content type, used when makeRequest is called
270
     *
271
     * @return string
272
     */
273
    protected function getDefaultContentType(): string
274
    {
275
        return 'application/json';
276
    }
277
}
278