Completed
Pull Request — master (#216)
by
unknown
08:46
created

ApiContext::iSpecifiedFiles()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 12
rs 9.4285
c 1
b 0
f 0
cc 3
eloc 6
nc 3
nop 1
1
<?php
2
3
namespace Knp\FriendlyContexts\Context;
4
5
use Behat\Gherkin\Node\TableNode;
6
use Behat\Gherkin\Node\PyStringNode;
7
use Guzzle\Http\Exception\BadResponseException;
8
use Knp\FriendlyContexts\Http\Security\HttpExtension;
9
10
class ApiContext extends RawPageContext
11
{
12
    protected $response;
13
14
    public function getResponse()
15
    {
16
        return $this->response;
17
    }
18
19
    /**
20
     * @Given /^I prepare a (?<method>[A-Za-z]+) request on "(?<page>[^"].*)?"$/
21
     * @Given /^I prepare a (?<method>[A-Za-z]+) request on the (.*) (?<hasPage>page|resource)$/
22
     * @Given /^I prepare a (?<method>[A-Za-z]+) request on the (.*) (?<hasPage>page|resource) with:?$/
23
     */
24
    public function iPrepareRequest($method, $page, $hasPage = false, TableNode $table = null)
25
    {
26
        $hasPage = (bool)$hasPage;
27
        $method  = strtoupper($method);
28
29
        $this->getRequestBuilder()->setMethod($method);
30
31
        if ($hasPage) {
32
            $path = $this->getPagePath($page, $table);
33
        } else {
34
            $path = $page;
35
        }
36
37
        $this->getRequestBuilder()->setUri($path);
38
    }
39
40
    /**
41
     * @Given /^I specified the following request http (?<scheme>[a-z]+) credentials:?$/
42
     */
43
    public function iSpecifiedTheFollowingHttpAuthentication(TableNode $credentialsTable, $scheme)
44
    {
45
        $this
46
            ->getRequestBuilder()
47
            ->setCredentials($credentialsTable->getRowsHash())
48
            ->addSecurityExtension(new HttpExtension($scheme))
49
        ;
50
    }
51
52
    /**
53
     * @Given /^I specified the following request oauth credentials:?$/
54
     */
55
    public function iSpecifiedTheFollowingOauthCredentials(TableNode $credentialsTable)
56
    {
57
        $this
58
            ->getRequestBuilder()
59
            ->setCredentials($credentialsTable->getRowsHash())
60
            ->addSecurityExtension(new OauthExtension)
61
        ;
62
    }
63
64
    /**
65
     * @Given /^I specified the following request headers:?$/
66
     */
67
    public function iSpecifiedHeaders(TableNode $table)
68
    {
69
        $this->getRequestBuilder()->setHeaders($table->getRowsHash());
70
    }
71
72
    /**
73
     * @Given /^I specified the following request queries:?$/
74
     */
75
    public function iSpecifiedQueries(TableNode $table)
76
    {
77
        $this->getRequestBuilder()->setQueries($table->getRowsHash());
78
    }
79
80
    /**
81
     * @Given /^I specified the following request body:?$/
82
     */
83
    public function iSpecifiedTheBody($data)
84
    {
85
        if (is_object($data) and $data instanceof TableNode) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
86
            $data = $data->getRowsHash();
87
        }
88
89
        if (is_object($data) and $data instanceof PyStringNode) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
90
            $data = (string)$data;
91
        }
92
93
        $this->getRequestBuilder()->setBody($data);
94
    }
95
96
    /**
97
     * @Given /^I specified the following request data:?$/
98
     */
99
    public function iSpecifiedData(TableNode $dataTable)
100
    {
101
        $requestBuilder = $this->getRequestBuilder();
102
103
        if ('POST' === $requestBuilder->getMethod()) {
104
            $requestBuilder->setPostBody($dataTable->getRowsHash());
105
        } else {
106
            $requestBuilder->setBody($dataTable->getRowsHash());
107
        }
108
    }
109
110
    /**
111
     * @Given /^I specified the following request files:?$/
112
     */
113
    public function iSpecifiedFiles(TableNode $fileTable)
114
    {
115
        $requestBuilder = $this->getRequestBuilder();
116
117
        if ('POST' !== $requestBuilder->getMethod()) {
118
            throw new \RuntimeException('You can\'t send files with a non POST method');
119
        }
120
121
        foreach ($fileTable->getRowsHash() as $name => $path) {
122
            $requestBuilder->addFile($name, $path);
123
        }
124
    }
125
126
    /**
127
     * @Given /^I specified the following request cookies:?$/
128
     */
129
    public function iSpecifiedCookies(TableNode $cookiesTable)
130
    {
131
        $this->getRequestBuilder()->setCookies($cookiesTable->getRowsHash());
132
    }
133
134
    /**
135
     * @Given /^I specified the following request options:?$/
136
     */
137
    public function iSpecifiedOptions(TableNode $optionsTable)
138
    {
139
        $this->getRequestBuilder()->setOptions($optionsTable->getRowsHash());
140
    }
141
142
    /**
143
     * @When /^I send the request$/
144
     */
145
    public function iSendTheRequest()
146
    {
147
        try {
148
            $this->response = $this->getRequestBuilder()->build()->send();
149
        } catch (BadResponseException $e) {
150
            $this->response = $e->getResponse();
151
        }
152
    }
153
	
154
    /**
155
     * @Then /^I print last URL requested$/
156
     */
157
    public function iPrintLastUrlRequest()
158
    {
159
        $uri = $this->getRequestBuilder()->getUri();
160
        $uri = substr($uri, 0, 1) === '/' ? substr($uri, 1) : $uri;
161
162
        echo $this->getRequestBuilder()->getClient()->getBaseUrl(). DIRECTORY_SEPARATOR .$uri;
163
    }
164
165
    /**
166
     * @Then /^I should receive a (?<httpCode>[0-9]+) response$/
167
     * @Then /^I should receive a (?<httpCode>[0-9]+) (?<shortType>[a-zA-Z]+) response$/
168
     */
169
    public function iShouldReceiveResponse($httpCode, $shortType = null)
170
    {
171
        $httpCode = (int)$httpCode;
172
173
        if (null === $this->response) {
174
            throw new \RuntimeException('You must send a request before testing a response.');
175
        }
176
177
        $this->getAsserter()->assertEquals(
178
            $httpCode,
179
            $this->response->getStatusCode(),
180
            sprintf(
181
                'Expecting response code to be "%d" but "%d" given',
182
                $httpCode,
183
                $this->response->getStatusCode()
184
            )
185
        );
186
187
        if (null !== $shortType) {
188
            $contentTypes = $this->getHttpContentTypeGuesser()->guess($shortType);
189
190
            foreach ($contentTypes as $contentType) {
191
                try {
192
                    $formatedContentType = explode(';', $this->response->getContentType());
193
                    $formatedContentType = $formatedContentType[0];
194
195
                    $this
196
                        ->getAsserter()
197
                        ->assertEquals($contentType, $formatedContentType)
198
                     ;
199
                    return;
200
                } catch (\Exception $e) {
201
                    continue;
202
                }
203
            }
204
205
            throw new \Exception(sprintf(
206
                'The response Content-Type ("%s") is not a(n) "%s" response type',
207
                $formatedContentType,
208
                $shortType
209
            ));
210
        }
211
    }
212
213
    /**
214
     * @Then /^the response should contains? the following headers:?$/
215
     */
216
    public function theResponseShouldContainsHeaders(TableNode $headerTable)
217
    {
218
        if (null === $this->response) {
219
            throw new \RuntimeException('You must send a request before testing a response.');
220
        }
221
222
        $expectedHeaders = $headerTable->getRowsHash();
223
        $this->getAsserter()->assertArrayContains(
224
            $expectedHeaders,
225
            $this->response->getHeaders()
226
        );
227
    }
228
229
    /**
230
     * @Then /^the response should contains? the following json:?$/
231
     */
232
    public function theResponsShouldContainsJson($jsonData)
233
    {
234
        if (!is_object($jsonData)) {
235
            throw new \InvalidArgumentException('Invalid json data');
236
        }
237
238
        $json = false;
239
240
        if ($jsonData instanceof PyStringNode) {
241
            $json = json_decode($jsonData->getRaw(), true);
242
        } elseif ($jsonData instanceof TableNode) {
243
            $json = $jsonData->getRowsHash();
244
        } elseif ($jsonData instanceof \stdClass || true === is_array($jsonData)) {
245
            $json = $jsonData;
246
        }
247
248
        if (false === $json) {
249
            throw new \InvalidArgumentException(sprintf(
250
                'Invalid json data class ("%s")',
251
                get_class($jsonData)
252
            ));
253
        }
254
255
        $expected = json_encode($json);
256
        $real     = json_encode($this->response->json());
257
258
        $this->getAsserter()->assertEquals(
259
            $expected,
260
            $real,
261
            sprintf("The given json\r\n\r\n%s\r\nis not equal to the expected\r\n\r\n%s",
262
                $real,
263
                $expected
264
            )
265
        );
266
    }
267
268
    /**
269
     * @Then /^the response should contains?:?$/
270
     */
271
    public function theResponseShouldContains(PyStringNode $bodyNode)
272
    {
273
        $this->getAsserter()->assertEquals($bodyNode->getRaw(), $this->response->getBody(true));
274
    }
275
}
276