Completed
Pull Request — master (#75)
by
unknown
05:07
created

WebApiContext::replacePlaceHolder()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Behat WebApiExtension.
5
 *
6
 * (c) Konstantin Kudryashov <[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
namespace Behat\WebApiExtension\Context;
13
14
use Behat\Gherkin\Node\PyStringNode;
15
use Behat\Gherkin\Node\TableNode;
16
use GuzzleHttp\Exception\GuzzleException;
17
use PHPUnit\Framework\Assert;
18
use Psr\Http\Message\RequestInterface;
19
20
/**
21
 * Provides web API description definitions.
22
 *
23
 * @author Konstantin Kudryashov <[email protected]>
24
 * @author Kevin Lot <[email protected]>
25
 * @author Keyclic team <[email protected]>
26
 */
27
class WebApiContext extends ApiClientContext implements ApiClientContextInterface
28
{
29
    /**
30
     * Adds Basic Authentication header to next request.
31
     *
32
     * @param string $username
33
     * @param string $password
34
     *
35
     * @Given /^I am basic authenticating as "([^"]*)" with "([^"]*)" password$/
36
     */
37
    public function iAmBasicAuthenticatingAs($username, $password)
38
    {
39
        $authorization = base64_encode($username.':'.$password);
40
41
        $this->removeHeader('Authorization');
42
        $this->addHeader('Authorization', 'Basic '.$authorization);
43
    }
44
45
    /**
46
     * Adds Basic Authentication header to next request.
47
     *
48
     * @param string $username
49
     * @param string $password
50
     *
51
     * @Given /^I am authenticating as "([^"]*)" with "([^"]*)" password$/
52
     *
53
     * @deprecated
54
     */
55
    public function iAmAuthenticatingAs($username, $password)
56
    {
57
        $this->iAmBasicAuthenticatingAs($username, $password);
58
    }
59
60
    /**
61
     * Sets a HTTP Header.
62
     *
63
     * @param string $name  header name
64
     * @param string $value header value
65
     *
66
     * @Given /^I set header "([^"]*)" with value "([^"]*)"$/
67
     */
68
    public function iSetHeaderWithValue($name, $value)
69
    {
70
        $this->addHeader($name, $value);
71
    }
72
73
    /**
74
     * Sends HTTP request to specific relative URL.
75
     *
76
     * @param string $method request method
77
     * @param string $url    relative url
78
     *
79
     * @throws GuzzleException
80
     *
81
     * @When /^(?:I )?send a ([A-Z]+) request to "([^"]+)"$/
82
     */
83
    public function iSendARequest($method, $url)
84
    {
85
        $url = $this->prepareUrl($url);
86
87
        $this->sendRequest($method, $url, $this->getHeaders());
88
    }
89
90
    /**
91
     * Sends HTTP request to specific URL with field values from Table.
92
     *
93
     * @param string    $method request method
94
     * @param string    $url    relative url
95
     * @param TableNode $values table of post values
96
     *
97
     * @throws GuzzleException
98
     *
99
     * @When /^(?:I )?send a ([A-Z]+) request to "([^"]+)" with values:$/
100
     */
101
    public function iSendARequestWithValues($method, $url, TableNode $values)
102
    {
103
        $url = $this->prepareUrl($url);
104
105
        $body = array_map(function ($value) {
106
            return $this->replacePlaceHolder($value);
107
        }, $values->getRowsHash());
108
109
        $body = json_encode($body);
110
111
        $this->sendRequest($method, $url, $this->getHeaders(), $body);
112
    }
113
114
    /**
115
     * Sends HTTP request to specific URL with raw body from PyString.
116
     *
117
     * @param string       $method request method
118
     * @param string       $url    relative url
119
     * @param PyStringNode $body   request body
120
     *
121
     * @throws GuzzleException
122
     *
123
     * @When /^(?:I )?send a ([A-Z]+) request to "([^"]+)" with body:$/
124
     */
125
    public function iSendARequestWithBody($method, $url, PyStringNode $body)
126
    {
127
        $url = $this->prepareUrl($url);
128
        $body = $this->replacePlaceHolder(trim($body));
129
130
        $this->sendRequest($method, $url, $this->getHeaders(), $body);
131
    }
132
133
    /**
134
     * Sends HTTP request to specific URL with form data from PyString.
135
     *
136
     * @param string       $method request method
137
     * @param string       $url    relative url
138
     * @param PyStringNode $body   request body
139
     *
140
     * @throws GuzzleException
141
     *
142
     * @When /^(?:I )?send a ([A-Z]+) request to "([^"]+)" with form data:$/
143
     */
144
    public function iSendARequestWithFormData($method, $url, PyStringNode $body)
145
    {
146
        $url = $this->prepareUrl($url);
147
        $body = $this->replacePlaceHolder(trim($body));
148
149
        $fields = [];
150
        parse_str(implode('&', explode("\n", $body)), $fields);
151
        $body = http_build_query($fields, null, '&');
152
153
        $this->addHeader('Content-Type', 'application/x-www-form-urlencoded');
154
155
        $this->sendRequest($method, $url, $this->getHeaders(), $body);
156
    }
157
158
    /**
159
     * Checks that response has specific status code.
160
     *
161
     * @param string $code status code
162
     *
163
     * @Then /^(?:the )?response code should be (\d+)$/
164
     */
165
    public function theResponseCodeShouldBe($code)
166
    {
167
        $expected = intval($code);
168
        $statusCode = intval($this->getResponse()->getStatusCode());
169
170
        Assert::assertSame($expected, $statusCode);
171
    }
172
173
    /**
174
     * Checks that response body contains specific text.
175
     *
176
     * @param string $text
177
     *
178
     * @Then /^(?:the )?response should contain "([^"]*)"$/
179
     */
180 View Code Duplication
    public function theResponseShouldContain($text)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
181
    {
182
        $expectedRegexp = '/'.preg_quote($text).'/i';
183
        $bodyResponse = (string) $this->getResponse()->getBody();
184
185
        Assert::assertRegExp($expectedRegexp, $bodyResponse);
186
    }
187
188
    /**
189
     * Checks that response body doesn't contains specific text.
190
     *
191
     * @param string $text
192
     *
193
     * @Then /^(?:the )?response should not contain "([^"]*)"$/
194
     */
195 View Code Duplication
    public function theResponseShouldNotContain($text)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
196
    {
197
        $expectedRegexp = '/'.preg_quote($text).'/';
198
        $bodyResponse = (string) $this->getResponse()->getBody();
199
200
        Assert::assertNotRegExp($expectedRegexp, $bodyResponse);
201
    }
202
203
    /**
204
     * Checks that response body contains JSON from PyString.
205
     *
206
     * Do not check that the response body /only/ contains the JSON from PyString,
207
     *
208
     * @param PyStringNode $jsonString
209
     *
210
     * @throws \RuntimeException
211
     *
212
     * @Then /^(?:the )?response should contain json:$/
213
     */
214
    public function theResponseShouldContainJson(PyStringNode $jsonString)
215
    {
216
        $rawJsonString = $this->replacePlaceHolder($jsonString->getRaw());
217
218
        $expected = json_decode($rawJsonString, true);
219
        $actual = json_decode((string) $this->getResponse()->getBody(), true);
220
221
        Assert::assertNotNull($expected, 'Can not convert expected to json:\n'.$rawJsonString);
222
        Assert::assertNotNull($actual, 'Can not convert body response to json:\n'.$this->getResponse()->getBody());
223
224
        Assert::assertGreaterThanOrEqual(count($expected), count($actual));
225
226
        foreach ($expected as $key => $needle) {
227
            Assert::assertArrayHasKey($key, $actual);
228
            Assert::assertEquals($expected[$key], $actual[$key]);
229
        }
230
    }
231
232
    /**
233
     * Check if the response header has a specific value.
234
     *
235
     * @param string $name
236
     * @param string $expected
237
     *
238
     * @Then /^the response "([^"]*)" header should be "([^"]*)"$/
239
     */
240
    public function theResponseHeaderShouldBe($name, $expected)
241
    {
242
        $actual = $this->getResponse()->getHeaderLine($name);
243
        Assert::assertEquals($expected, $actual);
244
    }
245
246
    /**
247
     * Prints last response body.
248
     *
249
     * @Then print response
250
     */
251
    public function printResponse()
252
    {
253
        $request = '';
254
        if ($this->getRequest() instanceof RequestInterface) {
255
            $request = sprintf(
256
                '%s %s',
257
                $this->getRequest()->getMethod(),
258
                (string) $this->getRequest()->getUri()
259
            );
260
        }
261
262
        $response = sprintf(
263
            "%d:\n%s",
264
            $this->getResponse()->getStatusCode(),
265
            (string) $this->getResponse()->getBody()
266
        );
267
268
        echo sprintf('%s => %s', $request, $response);
269
    }
270
}
271