Completed
Push — master ( c30d82...c114e4 )
by Eric
8s
created

ApiContext::setClient()   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 $method
119
     * @param string $url
120
     *
121
     * @When I send a ":method" request to ":url"
122
     */
123
    public function send($method, $url)
124
    {
125
        $this->request = $this->requestFactory->createRequest($method, $this->prepareUrl($url), $this->headers);
126
127
        $this->sendRequest();
128
    }
129
130
    /**
131
     * @param string       $method
132
     * @param string       $url
133
     * @param PyStringNode $string
134
     *
135
     * @When I send a ":method" request to ":url" with body:
136
     */
137
    public function sendWith($method, $url, PyStringNode $string)
138
    {
139
        $this->request = $this->requestFactory->createRequest(
140
            $method,
141
            $this->prepareUrl($url),
142
            $this->headers,
143
            trim($string->getRaw())
144
        );
145
146
        $this->sendRequest();
147
    }
148
149
    /**
150
     * @param string $statusCode
151
     *
152
     * @Then the response status code should be ":statusCode"
153
     */
154
    public function assertResponseStatusCode($statusCode)
155
    {
156
        \PHPUnit_Framework_Assert::assertSame((int) $statusCode, $this->getResponse()->getStatusCode());
157
    }
158
159
    /**
160
     * @param PyStringNode $json
161
     *
162
     * @Then the response should contain:
163
     */
164
    public function assertResponseContains(PyStringNode $json)
165
    {
166
        $this->matcher->match((string) $this->response->getBody(), $json->getRaw());
167
168
        \PHPUnit_Framework_Assert::assertNull($this->matcher->getError());
169
    }
170
171
    /**
172
     * @Then the response should be empty
173
     */
174
    public function assertResponseEmpty()
175
    {
176
        \PHPUnit_Framework_Assert::assertEmpty((string) $this->getResponse()->getBody());
177
    }
178
179
    /**
180
     * @Then I print the response
181
     */
182
    public function printResponse()
183
    {
184
        echo sprintf(
185
            "%s %s => %d:\n%s",
186
            $this->getRequest()->getMethod(),
187
            (string) $this->getRequest()->getUri(),
188
            $this->getResponse()->getStatusCode(),
189
            (string) $this->getResponse()->getBody()
190
        );
191
    }
192
193
    /**
194
     * @return RequestInterface
195
     */
196
    public function getRequest()
197
    {
198
        if ($this->request === null) {
199
            throw new \RuntimeException('You should create a request before using it.');
200
        }
201
202
        return $this->request;
203
    }
204
205
    /**
206
     * @return ResponseInterface
207
     */
208
    public function getResponse()
209
    {
210
        if ($this->response === null) {
211
            throw new \RuntimeException('You should send a request before using the response.');
212
        }
213
214
        return $this->response;
215
    }
216
217
    /**
218
     * @param string $url
219
     *
220
     * @return string
221
     */
222
    private function prepareUrl($url)
223
    {
224
        return $this->baseUrl.$url;
225
    }
226
227
    private function sendRequest()
228
    {
229
        try {
230
            $this->response = $this->client->sendRequest($this->getRequest());
231
        } catch (HttpException $e) {
232
            $this->response = $e->getResponse();
233
234
            if ($this->response === null) {
235
                throw $e;
236
            }
237
        }
238
    }
239
}
240