Failed Conditions
Push — master ( 516359...a8b39a )
by Florent
04:00
created

ResponseContext   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 294
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 10

Importance

Changes 0
Metric Value
wmc 33
lcom 2
cbo 10
dl 0
loc 294
rs 9.3999
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2017 Spomky-Labs
9
 *
10
 * This software may be modified and distributed under the terms
11
 * of the MIT license.  See the LICENSE file for details.
12
 */
13
14
namespace OAuth2Framework\Bundle\Server\Tests\Context;
15
16
/*
17
 * The MIT License (MIT)
18
 *
19
 * Copyright (c) 2014-2017 Spomky-Labs
20
 *
21
 * This software may be modified and distributed under the terms
22
 * of the MIT license.  See the LICENSE file for details.
23
 */
24
25
use Assert\Assertion;
26
use Behat\Behat\Context\Context;
27
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
28
use Behat\Gherkin\Node\PyStringNode;
29
use Behat\MinkExtension\Context\MinkContext;
30
use Behat\Symfony2Extension\Context\KernelDictionary;
31
use Http\Factory\Diactoros\UriFactory;
32
use OAuth2Framework\Bundle\Server\Tests\TestBundle\Listener;
33
34
final class ResponseContext implements Context
35
{
36
    use KernelDictionary;
37
38
    /**
39
     * @var MinkContext
40
     */
41
    private $minkContext;
42
43
    /**
44
     * @BeforeScenario
45
     *
46
     * @param BeforeScenarioScope $scope
47
     */
48
    public function gatherContexts(BeforeScenarioScope $scope)
49
    {
50
        $environment = $scope->getEnvironment();
51
52
        $this->minkContext = $environment->getContext(MinkContext::class);
53
    }
54
55
    /**
56
     * @var null|array
57
     */
58
    private $error = null;
59
60
    /**
61
     * @Then the response code is :code
62
     */
63
    public function theResponseCodeIs($code)
64
    {
65
        Assertion::eq((int) $code, $this->minkContext->getSession()->getStatusCode());
66
    }
67
68
    /**
69
     * @Then the response contains
70
     */
71
    public function theResponseContains(PyStringNode $response)
72
    {
73
        Assertion::eq($response->getRaw(), $this->minkContext->getSession()->getPage()->getContent());
74
    }
75
76
    /**
77
     * @Then the response contains an error with code :code
78
     */
79
    public function theResponseContainsAnError($code)
80
    {
81
        Assertion::eq((int) $code, $this->minkContext->getSession()->getStatusCode());
82
        Assertion::greaterOrEqualThan($this->minkContext->getSession()->getStatusCode(), 400);
83
        if (401 === $this->minkContext->getSession()->getStatusCode()) {
84
            $header = $this->minkContext->getSession()->getResponseHeader('WWW-Authenticate');
85
            Assertion::notNull($header);
86
            preg_match_all('/(\w+\*?)="((?:[^"\\\\]|\\\\.)+)"|([^\s,$]+)/', substr($header, strpos($header, ' ')), $matches, PREG_SET_ORDER);
87
            if (!is_array($matches)) {
88
                throw new \InvalidArgumentException('Unable to parse header');
89
            }
90
            foreach ($matches as $match) {
91
                $this->error[$match[1]] = $match[2];
92
            }
93
        } else {
94
            $response = $this->minkContext->getSession()->getPage()->getContent();
95
            $json = json_decode($response, true);
96
            Assertion::isArray($json);
97
            Assertion::keyExists($json, 'error');
98
            $this->error = $json;
99
        }
100
    }
101
102
    /**
103
     * @Then the error is :error
104
     *
105
     * @param string $error
106
     */
107
    public function theErrorIs($error)
108
    {
109
        Assertion::notNull($this->error);
110
        Assertion::keyExists($this->error, 'error');
111
        Assertion::eq($error, $this->error['error']);
112
    }
113
114
    /**
115
     * @Then the error description is :errorDescription
116
     *
117
     * @param string $errorDescription
118
     */
119
    public function theErrorDescriptionIs($errorDescription)
120
    {
121
        Assertion::notNull($this->error);
122
        Assertion::keyExists($this->error, 'error_description');
123
        Assertion::eq($errorDescription, $this->error['error_description']);
124
    }
125
126
    /**
127
     * @Then the client should be redirected
128
     */
129
    public function theClientShouldBeRedirected()
130
    {
131
        Assertion::eq(302, $this->minkContext->getSession()->getStatusCode());
132
        $location = $this->minkContext->getSession()->getResponseHeader('Location');
133
        Assertion::notNull($location);
134
        Assertion::true(!empty($location));
135
    }
136
137
    /**
138
     * @Then no access token creation event is thrown
139
     */
140
    public function noAccessTokenCreationEventIsThrown()
141
    {
142
        $events = $this->getContainer()->get(Listener\AccessTokenCreatedListener::class)->getEvents();
143
        Assertion::eq(0, count($events));
144
    }
145
146
    /**
147
     * @Then the response contains an access token
148
     */
149
    public function theResponseContainsAnAccessToken()
150
    {
151
        $content = $this->minkContext->getSession()->getPage()->getContent();
152
        $data = json_decode($content, true);
153
        Assertion::isArray($data);
154
        Assertion::keyExists($data, 'access_token');
155
    }
156
157
    /**
158
     * @Then an access token creation event is thrown
159
     */
160
    public function anAccessTokenCreationEventIsThrown()
161
    {
162
        $events = $this->getContainer()->get(Listener\AccessTokenCreatedListener::class)->getEvents();
163
        Assertion::greaterThan(count($events), 0);
164
    }
165
166
    /**
167
     * @Then a refresh token creation event is thrown
168
     */
169
    public function aRefreshTokenCreationEventIsThrown()
170
    {
171
        $events = $this->getContainer()->get(Listener\RefreshTokenCreatedListener::class)->getEvents();
172
        Assertion::greaterThan(count($events), 0);
173
    }
174
175
    /**
176
     * @Then the response contains something like :pattern
177
     */
178
    public function theResponseContainsSomethingLike($pattern)
179
    {
180
        $content = $this->minkContext->getSession()->getPage()->getContent();
181
        Assertion::regex($content, $pattern);
182
    }
183
184
    /**
185
     * @Then the content type of the response is :content_type
186
     */
187
    public function theContentTypeOfTheResponseIs($content_type)
188
    {
189
        Assertion::eq($content_type, $this->minkContext->getSession()->getResponseHeader('Content-Type'));
190
    }
191
192
    /**
193
     * @Then the redirection Uri starts with :pattern
194
     */
195
    public function theRedirectionUriStartsWith($pattern)
196
    {
197
        $location = $this->minkContext->getSession()->getResponseHeader('Location');
198
        if (mb_substr($location, 0, mb_strlen($pattern, '8bit'), '8bit') === $pattern) {
199
            return;
200
        }
201
        throw new \InvalidArgumentException(sprintf('The location header is "%s".', $location));
202
    }
203
204
    /**
205
     * @Then the redirection Uri query should contain a parameter :parameter
206
     */
207
    public function theRedirectionUriQueryShouldContainAParameter($parameter)
208
    {
209
        $uriFactory = new UriFactory();
210
        $location = $this->minkContext->getSession()->getResponseHeader('Location');
211
        $uri = $uriFactory->createUri($location);
212
        $query = $uri->getQuery();
213
        parse_str($query, $data);
214
        if (array_key_exists($parameter, $data)) {
215
            return;
216
        }
217
        throw new \InvalidArgumentException(sprintf('The location header is "%s".', $location));
218
    }
219
220
    /**
221
     * @Then the redirection Uri query should contain a parameter :parameter with value :value
222
     */
223
    public function theRedirectionUriQueryShouldContainAParameterWithValue($parameter, $value)
224
    {
225
        $uriFactory = new UriFactory();
226
        $location = $this->minkContext->getSession()->getResponseHeader('Location');
227
        $uri = $uriFactory->createUri($location);
228
        $query = $uri->getQuery();
229
        parse_str($query, $data);
230
        if (array_key_exists($parameter, $data)) {
231
            Assertion::eq($data[$parameter], $value, sprintf('The parameter \'%s\' value is \'%s\'.', $parameter, $data[$parameter]));
232
233
            return;
234
        }
235
        throw new \InvalidArgumentException(sprintf('The location header is "%s".', $location));
236
    }
237
238
    /**
239
     * @Then the redirection Uri fragment should contain a parameter :parameter
240
     */
241
    public function theRedirectionUriFragmentShouldContainAParameter($parameter)
242
    {
243
        $uriFactory = new UriFactory();
244
        $location = $this->minkContext->getSession()->getResponseHeader('Location');
245
        $uri = $uriFactory->createUri($location);
246
        $fragment = $uri->getFragment();
247
        parse_str($fragment, $data);
248
        if (array_key_exists($parameter, $data)) {
249
            return;
250
        }
251
        throw new \InvalidArgumentException(sprintf('The location header is "%s".', $location));
252
    }
253
254
    /**
255
     * @Then the redirection Uri fragment should contain a parameter :parameter with value :value
256
     */
257
    public function theRedirectionUriFragmentShouldContainAParameterWithValue($parameter, $value)
258
    {
259
        $uriFactory = new UriFactory();
260
        $location = $this->minkContext->getSession()->getResponseHeader('Location');
261
        $uri = $uriFactory->createUri($location);
262
        $fragment = $uri->getFragment();
263
        parse_str($fragment, $data);
264
        if (array_key_exists($parameter, $data)) {
265
            Assertion::eq($data[$parameter], $value, sprintf('The parameter \'%s\' value is \'%s\'.', $parameter, $data[$parameter]));
266
267
            return;
268
        }
269
        throw new \InvalidArgumentException(sprintf('The location header is "%s".', $location));
270
    }
271
272
    /**
273
     * @Then the redirection ends with :pattern
274
     */
275
    public function theRedirectionEndsWith($pattern)
276
    {
277
        $location = $this->minkContext->getSession()->getResponseHeader('Location');
278
        if (mb_substr($location, -mb_strlen($pattern, '8bit'), null, '8bit') === $pattern) {
279
            return;
280
        }
281
        throw new \InvalidArgumentException(sprintf('The location header is "%s".', $location));
282
    }
283
284
    /**
285
     * @Then the redirect query should contain parameter :parameter with value :value
286
     */
287
    public function theRedirectQueryShouldContainParameterWithValue($parameter, $value)
288
    {
289
        $uriFactory = new UriFactory();
290
        $location = $this->minkContext->getSession()->getResponseHeader('Location');
291
        $uri = $uriFactory->createUri($location);
292
        $query = $uri->getQuery();
293
        parse_str($query, $data);
294
        if (array_key_exists($parameter, $data)) {
295
            Assertion::eq($data[$parameter], $value);
296
297
            return;
298
        }
299
        throw new \InvalidArgumentException(sprintf('The location header is "%s".', $location));
300
    }
301
302
    /**
303
     * @Then I should be on the login screen
304
     */
305
    public function iShouldBeOnTheLoginScreen()
306
    {
307
        $location = $this->minkContext->getSession()->getResponseHeader('Location');
308
        Assertion::eq($location, 'https://oauth2.test/login');
309
    }
310
311
    /**
312
     * @Then I should be on the consent screen
313
     */
314
    public function iShouldBeOnTheConsentScreen()
315
    {
316
        Assertion::eq($this->minkContext->getSession()->getCurrentUrl(), 'https://oauth2.test/authorize');
317
    }
318
319
    /**
320
     * @Then a cookie is in the response header
321
     */
322
    public function aCookieIsInTheResponseHeader()
323
    {
324
        $headers = $this->minkContext->getSession()->getResponseHeaders();
325
        Assertion::keyExists($headers, 'set-cookie');
326
    }
327
}
328