Completed
Push — master ( 0fa665...23167a )
by Eric
34:47 queued 24:34
created

ApiContext::setRequestFactory()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Lug package.
5
 *
6
 * (c) Eric GELOEN <[email protected]>
7
 *
8
 * For the full copyright and license information, please read the LICENSE
9
 * file that was distributed with this source statusCode.
10
 */
11
12
namespace Lug\Component\Behat\Extension\Api\Context;
13
14
use Behat\Gherkin\Node\PyStringNode;
15
use Coduo\PHPMatcher\Matcher;
16
use Http\Client\Exception\HttpException;
17
use Http\Client\HttpClient;
18
use Http\Message\RequestFactory;
19
use Lug\Component\Behat\Extension\Api\Matcher\MatcherFactory;
20
use Psr\Http\Message\RequestInterface;
21
use Psr\Http\Message\ResponseInterface;
22
23
/**
24
 * @author GeLo <[email protected]>
25
 */
26
class ApiContext implements ApiContextInterface
27
{
28
    /**
29
     * @var HttpClient
30
     */
31
    private $client;
32
33
    /**
34
     * @var RequestFactory
35
     */
36
    private $requestFactory;
37
38
    /**
39
     * @var string
40
     */
41
    private $baseUrl;
42
43
    /**
44
     * @var string[][]
45
     */
46
    private $headers = [];
47
48
    /**
49
     * @var RequestInterface|null
50
     */
51
    private $request;
52
53
    /**
54
     * @var ResponseInterface|null
55
     */
56
    private $response;
57
58
    /**
59
     * @var Matcher
60
     */
61
    private $matcher;
62
63
    public function __construct()
64
    {
65
        $this->matcher = (new MatcherFactory())->createMatcher();
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function setClient(HttpClient $client)
72
    {
73
        $this->client = $client;
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79
    public function setRequestFactory(RequestFactory $requestFactory)
80
    {
81
        $this->requestFactory = $requestFactory;
82
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87
    public function setBaseUrl($baseUrl)
88
    {
89
        if (strrpos($baseUrl, '/') === strlen($baseUrl) - 1) {
90
            $baseUrl = substr($baseUrl, 0, -1);
91
        }
92
93
        $this->baseUrl = $baseUrl;
94
    }
95
96
    /**
97
     * @BeforeScenario
98
     */
99
    public function reset()
100
    {
101
        $this->headers = [];
102
        $this->request = null;
103
        $this->response = null;
104
    }
105
106
    /**
107
     * @param string $header
108
     * @param string $value
109
     *
110
     * @Given I set the header ":header" with value ":value"
111
     */
112
    public function setHeader($header, $value)
113
    {
114
        $this->headers[$header][] = $value;
115
    }
116
117
    /**
118
     * @param string $header
119
     *
120
     * @Given I remove the header ":header"
121
     */
122
    public function removeHeader($header)
123
    {
124
        unset($this->headers[$header]);
125
    }
126
127
    /**
128
     * @param string $method
129
     * @param string $url
130
     *
131
     * @When I send a ":method" request to ":url"
132
     */
133
    public function send($method, $url)
134
    {
135
        $this->request = $this->requestFactory->createRequest($method, $this->prepareUrl($url), $this->headers);
136
137
        $this->sendRequest();
138
    }
139
140
    /**
141
     * @param string       $method
142
     * @param string       $url
143
     * @param PyStringNode $string
144
     *
145
     * @When I send a ":method" request to ":url" with body:
146
     */
147
    public function sendWith($method, $url, PyStringNode $string)
148
    {
149
        $this->request = $this->requestFactory->createRequest(
150
            $method,
151
            $this->prepareUrl($url),
152
            $this->headers,
153
            trim($string->getRaw())
154
        );
155
156
        $this->sendRequest();
157
    }
158
159
    /**
160
     * @param string $statusCode
161
     *
162
     * @Then the response status code should be ":statusCode"
163
     */
164
    public function assertResponseStatusCode($statusCode)
165
    {
166
        \PHPUnit_Framework_Assert::assertSame((int) $statusCode, $this->getResponse()->getStatusCode());
167
    }
168
169
    /**
170
     * @param PyStringNode $json
171
     *
172
     * @Then the response should contain:
173
     */
174
    public function assertResponseContains(PyStringNode $json)
175
    {
176
        $this->matcher->match((string) $this->response->getBody(), $json->getRaw());
177
178
        \PHPUnit_Framework_Assert::assertNull($this->matcher->getError());
179
    }
180
181
    /**
182
     * @Then the response should be empty
183
     */
184
    public function assertResponseEmpty()
185
    {
186
        \PHPUnit_Framework_Assert::assertEmpty((string) $this->getResponse()->getBody());
187
    }
188
189
    /**
190
     * @Then I print the response
191
     */
192
    public function printResponse()
193
    {
194
        echo sprintf(
195
            "%s %s => %d:\n%s",
196
            $this->getRequest()->getMethod(),
197
            (string) $this->getRequest()->getUri(),
198
            $this->getResponse()->getStatusCode(),
199
            (string) $this->getResponse()->getBody()
200
        );
201
    }
202
203
    /**
204
     * @return RequestInterface
205
     */
206
    public function getRequest()
207
    {
208
        if ($this->request === null) {
209
            throw new \RuntimeException('You should create a request before using it.');
210
        }
211
212
        return $this->request;
213
    }
214
215
    /**
216
     * @return ResponseInterface
217
     */
218
    public function getResponse()
219
    {
220
        if ($this->response === null) {
221
            throw new \RuntimeException('You should send a request before using the response.');
222
        }
223
224
        return $this->response;
225
    }
226
227
    /**
228
     * @param string $url
229
     *
230
     * @return string
231
     */
232
    private function prepareUrl($url)
233
    {
234
        return $this->baseUrl.$url;
235
    }
236
237
    private function sendRequest()
238
    {
239
        try {
240
            $this->response = $this->client->sendRequest($this->getRequest());
241
        } catch (HttpException $e) {
242
            $this->response = $e->getResponse();
243
244
            if ($this->response === null) {
245
                throw $e;
246
            }
247
        }
248
    }
249
}
250