Passed
Push — master ( 77b152...1f79c1 )
by Baptiste
02:41
created

Http::sendARequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
1
<?php
2
namespace Behapi\Context;
3
4
use RuntimeException;
5
6
use Psr\Http\Message\RequestInterface;
7
8
use Behat\Behat\Context\Context;
9
use Behat\Gherkin\Node\TableNode;
10
11
use Http\Client\HttpClient;
12
use Http\Message\StreamFactory;
13
use Http\Message\MessageFactory;
14
15
use Twig_Environment;
16
17
use Behapi\Extension\Context\ApiTrait;
18
use Behapi\Extension\Context\TwigTrait;
19
20
use Behapi\Extension\Tools\Assert;
21
use Behapi\Extension\Tools\HttpHistory;
22
23
class Http implements Context
24
{
25
    use ApiTrait;
26
    use TwigTrait;
27
28
    /** @var RequestInterface */
29
    private $request;
30
31
    /** @var mixed[] Query args to add */
32
    private $query;
33
34
    public function __construct(HttpClient $client, StreamFactory $streamFactory, MessageFactory $messageFactory, HttpHistory $history, Twig_Environment $twig = null)
35
    {
36
        $this->client = $client;
37
        $this->history = $history;
38
        $this->streamFactory = $streamFactory;
39
        $this->messageFactory = $messageFactory;
40
41
        $this->twig = $twig;
42
    }
43
44
    /** @When /^I create a "(?P<method>GET|POST|PATCH|PUT|DELETE|OPTIONS|HEAD)" request to "(?P<url>.+?)"$/ */
45
    public function createARequest(string $method, string $url)
46
    {
47
        $url = trim($url);
48
49
        $this->query = [];
50
        $this->request = $this->messageFactory->createRequest(strtoupper($method), $url);
51
52
        // let's set a default content-type
53
        $this->setContentType($this->getDefaultContentType());
54
    }
55
56
    /**
57
     * @When /^I send a "(?P<method>GET|POST|PATCH|PUT|DELETE|OPTIONS|HEAD)" request to "(?P<url>.+?)"$/
58
     *
59
     * -------
60
     *
61
     * Shortcut for `When I create a X request to Then send the request`
62
     */
63
    public function sendARequest($method, $url)
64
    {
65
        $this->createARequest($method, $url);
66
        $this->sendRequest();
67
    }
68
69
    /** @When I add/set the value :value to the parameter :parameter */
70
    public function addAParameter(string $parameter, string $value)
71
    {
72
        if (!isset($this->query[$parameter])) {
73
            $this->query[$parameter] = $value;
74
            return;
75
        }
76
77
        $current = &$this->query[$parameter];
78
79
        if (is_array($current)) {
80
            $current[] = $value;
81
            return;
82
        }
83
84
        $current = [$current, $value];
85
    }
86
87
    /** @When I set the following query arguments: */
88
    public function setTheParameters(TableNode $parameters)
89
    {
90
        $this->query = [];
91
92
        foreach ($parameters->getRowsHash() as $parameter => $value) {
93
            if (is_string($value)) {
94
                $value = $this->renderString($value);
95
            }
96
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
        $body = $this->renderString($body);
112
        $stream = $this->streamFactory->createStream($body);
113
114
        $request = $this->getRequest();
115
        $this->request = $request->withBody($stream);
116
    }
117
118
    /** @When I add/set the value :value to the header :header */
119
    public function addHeader(string $header, string $value)
120
    {
121
        $request = $this->getRequest();
122
        $this->request = $request->withAddedHeader($header, $value);
123
    }
124
125
    /** @When I set the headers: */
126
    public function setHeaders(TableNode $headers)
127
    {
128
        $request = $this->getRequest();
129
130
        foreach ($headers->getRowsHash() as $header => $value) {
131
            $request = $request->withHeader($header, $value);
132
        }
133
134
        $this->request = $request;
135
    }
136
137
    /** @When I send the request */
138
    public function sendRequest()
139
    {
140
        $request = $this->getRequest();
141
142
        if (!empty($this->query)) {
143
            $uri = $request->getUri();
144
            $current = $uri->getQuery();
145
            $query = http_build_query($this->query);
146
147
            if (!empty($current)) {
148
                $query = "{$current}&{$query}";
149
            }
150
151
            $uri = $uri->withQuery($query);
152
            $request = $request->withUri($uri);
153
        }
154
155
        $this->client->sendRequest($request);
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