iSpecifiedTheFollowingOauthCredentials()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
c 0
b 0
f 0
rs 9.4285
cc 1
eloc 5
nc 1
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 should receive a (?<httpCode>[0-9]+) response$/
156
     * @Then /^I should receive a (?<httpCode>[0-9]+) (?<shortType>[a-zA-Z]+) response$/
157
     */
158
    public function iShouldReceiveResponse($httpCode, $shortType = null)
159
    {
160
        $httpCode = (int)$httpCode;
161
162
        if (null === $this->response) {
163
            throw new \RuntimeException('You must send a request before testing a response.');
164
        }
165
166
        $this->getAsserter()->assertEquals(
167
            $httpCode,
168
            $this->response->getStatusCode(),
169
            sprintf(
170
                'Expecting response code to be "%d" but "%d" given',
171
                $httpCode,
172
                $this->response->getStatusCode()
173
            )
174
        );
175
176
        if (null !== $shortType) {
177
            $contentTypes = $this->getHttpContentTypeGuesser()->guess($shortType);
178
179
            foreach ($contentTypes as $contentType) {
180
                try {
181
                    $formatedContentType = explode(';', $this->response->getContentType());
182
                    $formatedContentType = $formatedContentType[0];
183
184
                    $this
185
                        ->getAsserter()
186
                        ->assertEquals($contentType, $formatedContentType)
187
                     ;
188
                    return;
189
                } catch (\Exception $e) {
190
                    continue;
191
                }
192
            }
193
194
            throw new \Exception(sprintf(
195
                'The response Content-Type ("%s") is not a(n) "%s" response type',
196
                $formatedContentType,
197
                $shortType
198
            ));
199
        }
200
    }
201
202
    /**
203
     * @Then /^the response should contains? the following headers:?$/
204
     */
205
    public function theResponseShouldContainsHeaders(TableNode $headerTable)
206
    {
207
        if (null === $this->response) {
208
            throw new \RuntimeException('You must send a request before testing a response.');
209
        }
210
211
        $expectedHeaders = $headerTable->getRowsHash();
212
        $this->getAsserter()->assertArrayContains(
213
            $expectedHeaders,
214
            $this->response->getHeaders()
215
        );
216
    }
217
218
    /**
219
     * @Then /^the response should contains? the following json:?$/
220
     */
221
    public function theResponsShouldContainsJson($jsonData)
222
    {
223
        if (!is_object($jsonData)) {
224
            throw new \InvalidArgumentException('Invalid json data');
225
        }
226
227
        $json = false;
228
229
        if ($jsonData instanceof PyStringNode) {
230
            $json = json_decode($jsonData->getRaw(), true);
231
        } elseif ($jsonData instanceof TableNode) {
232
            $json = $jsonData->getRowsHash();
233
        } elseif ($jsonData instanceof \stdClass || true === is_array($jsonData)) {
234
            $json = $jsonData;
235
        }
236
237
        if (false === $json) {
238
            throw new \InvalidArgumentException(sprintf(
239
                'Invalid json data class ("%s")',
240
                get_class($jsonData)
241
            ));
242
        }
243
244
        $expected = json_encode($json);
245
        $real     = json_encode($this->response->json());
246
247
        $this->getAsserter()->assertEquals(
248
            $expected,
249
            $real,
250
            sprintf("The given json\r\n\r\n%s\r\nis not equal to the expected\r\n\r\n%s",
251
                $real,
252
                $expected
253
            )
254
        );
255
    }
256
257
    /**
258
     * @Then /^the response should contains?:?$/
259
     */
260
    public function theResponseShouldContains(PyStringNode $bodyNode)
261
    {
262
        $this->getAsserter()->assertEquals($bodyNode->getRaw(), $this->response->getBody(true));
263
    }
264
}
265