CorsServiceTest   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 305
Duplicated Lines 0 %

Importance

Changes 15
Bugs 2 Features 0
Metric Value
eloc 157
c 15
b 2
f 0
dl 0
loc 305
rs 10
wmc 7

7 Methods

Rating   Name   Duplication   Size   Complexity  
A testIsPreflightRequest() 0 20 1
A testDenyOriginIfDoesNotMatchPattern() 0 17 1
A testHandleRequest() 0 86 1
A testAllowOriginIfMatchPattern() 0 17 1
A testIsCorsRequest() 0 12 1
A testServiceConfig() 0 5 1
B testHandlePreflightRequest() 0 100 1
1
<?php
2
3
namespace Nord\Lumen\Cors\Tests;
4
5
use Closure;
6
use Nord\Lumen\Cors\CorsService;
7
use Symfony\Component\HttpFoundation\Request;
8
use Symfony\Component\HttpFoundation\Response;
9
10
class CorsServiceTest extends \Codeception\Test\Unit
11
{
12
    use \Codeception\Specify;
13
    use \Codeception\AssertThrows;
14
15
    /**
16
     * @var \UnitTester
17
     */
18
    protected $tester;
19
20
    /**
21
     * @var CorsService
22
     */
23
    protected $service;
24
25
    /**
26
     * @var Request
27
     */
28
    protected $request;
29
30
    /**
31
     * @var Response
32
     */
33
    protected $response;
34
35
    /**
36
     * @var Closure
37
     */
38
    protected $closure;
39
40
    public function testServiceConfig()
41
    {
42
        // service config max_age is less than zero
43
        $this->assertThrows(\InvalidArgumentException::class, function () {
44
            new CorsService(['max_age' => -1]);
45
        });
46
    }
47
48
    public function testHandlePreflightRequest()
49
    {
50
        $this->service = new CorsService([
51
            'allow_origins' => ['http://foo.com'],
52
            'allow_methods' => ['post'],
53
            'allow_headers' => ['accept', 'authorization', 'content-type'],
54
        ]);
55
56
        $this->request = new Request;
57
58
        $this->specify('200 response when origin, method and headers are allowed', function () {
59
            $this->request->headers->set('Origin', 'http://foo.com');
60
            $this->request->headers->set('Access-Control-Request-Method', 'POST');
61
            $this->request->headers->set('Access-Control-Request-Headers', 'accept, authorization, content-type');
62
63
            $response = $this->service->handlePreflightRequest($this->request);
64
65
            verify($response->getStatusCode())->equals(200);
66
        });
67
68
        $this->service = new CorsService([
69
            'allow_origins' => ['http://foo.com'],
70
            'allow_methods' => ['post'],
71
            'allow_headers' => ['accept', 'authorization', 'content-type'],
72
        ]);
73
74
        $this->request = new Request;
75
76
        $this->specify('response headers are set', function () {
77
            $this->request->headers->set('Origin', 'http://foo.com');
78
            $this->request->headers->set('Access-Control-Request-Method', 'POST');
79
            $this->request->headers->set('Access-Control-Request-Headers', 'accept, authorization, content-type');
80
81
            $response = $this->service->handlePreflightRequest($this->request);
82
83
            verify($response->headers->get('Access-Control-Allow-Origin'))->equals('http://foo.com');
84
            verify($response->headers->get('Access-Control-Allow-Methods'))->equals('POST');
85
            verify($response->headers->get('Access-Control-Allow-Headers'))->equals('accept, authorization, content-type');
86
            verify($response->headers->has('Access-Control-Allow-Credentials'))->false();
87
            verify($response->headers->has('Access-Control-Max-Age'))->false();
88
        });
89
90
        $this->service = new CorsService([
91
            'allow_origins' => ['http://foo.com'],
92
            'allow_methods' => ['post'],
93
            'allow_headers' => ['accept', 'authorization', 'content-type'],
94
        ]);
95
96
        $this->request = new Request;
97
98
        $this->specify('regression test for issue #31', function () {
99
            $this->request->headers->set('Origin', 'http://foo.com');
100
            $this->request->headers->set('Access-Control-Request-Method', 'POST');
101
            $this->request->headers->set('Access-Control-Request-Headers', 'accept,authorization, content-type');
102
103
            $response = $this->service->handlePreflightRequest($this->request);
104
105
            verify($response->headers->get('Access-Control-Allow-Origin'))->equals('http://foo.com');
106
            verify($response->headers->get('Access-Control-Allow-Methods'))->equals('POST');
107
            verify($response->headers->get('Access-Control-Allow-Headers'))->equals('accept, authorization, content-type');
108
            verify($response->headers->has('Access-Control-Allow-Credentials'))->false();
109
            verify($response->headers->has('Access-Control-Max-Age'))->false();
110
        });
111
112
        $this->service = new CorsService([
113
            'allow_origins'     => ['*'],
114
            'allow_methods'     => ['*'],
115
            'allow_headers'     => ['*'],
116
            'allow_credentials' => true,
117
        ]);
118
119
        $this->request = new Request;
120
121
        $this->specify('response credentials header is set', function () {
122
            $this->request->headers->set('Origin', 'http://foo.com');
123
            $this->request->headers->set('Access-Control-Request-Method', 'POST');
124
            $this->request->headers->set('Access-Control-Request-Headers', 'accept, authorization, content-type');
125
126
            $response = $this->service->handlePreflightRequest($this->request);
127
128
            verify($response->headers->get('Access-Control-Allow-Credentials'))->equals('true');
129
        });
130
131
        $this->service = new CorsService([
132
            'allow_origins' => ['*'],
133
            'allow_methods' => ['*'],
134
            'allow_headers' => ['*'],
135
            'max_age'       => 3600,
136
        ]);
137
138
        $this->request = new Request;
139
140
        $this->specify('response max-age header is set', function () {
141
            $this->request->headers->set('Origin', 'http://foo.com');
142
            $this->request->headers->set('Access-Control-Request-Method', 'POST');
143
            $this->request->headers->set('Access-Control-Request-Headers', 'accept, authorization, content-type');
144
145
            $response = $this->service->handlePreflightRequest($this->request);
146
147
            verify($response->headers->get('Access-Control-Max-Age'))->equals(3600);
148
        });
149
    }
150
151
    public function testHandleRequest()
152
    {
153
        $this->request = new Request;
154
155
        $this->response = new Response;
156
157
        $this->service = new CorsService([
158
            'allow_origins' => ['*'],
159
        ]);
160
161
        $this->specify('response origin header is set', function () {
162
            $this->request->headers->set('Origin', 'http://foo.com');
163
164
            $response = $this->service->handleRequest($this->request, new Response());
165
166
            verify($response->headers->get('Access-Control-Allow-Origin'))->equals('*');
167
        });
168
169
        $this->service = new CorsService([
170
            'allow_origins' => ['*'],
171
        ]);
172
173
        $this->specify('response vary header is not set when all origins are allowed', function () {
174
            $this->request->headers->set('Origin', 'http://foo.com');
175
176
            $response = new Response();
177
            $response->headers->set('Vary', 'Accept-Encoding');
178
            $response = $this->service->handleRequest($this->request, $response);
179
180
            verify($response->headers->get('Vary'))->equals('Accept-Encoding');
181
        });
182
183
        $this->service = new CorsService([
184
            'allow_origins' => ['http://foo.com'],
185
        ]);
186
187
        $this->specify('response vary header is set', function () {
188
            $this->request->headers->set('Origin', 'http://foo.com');
189
            $this->request->headers->set('Vary', 'Accept-Encoding');
190
191
            $response = $this->service->handleRequest($this->request, new Response());
192
193
            verify($response->headers->get('Vary'))->equals('Accept-Encoding, Origin');
194
        });
195
196
        $this->service = new CorsService([
197
            'allow_origins'     => ['*'],
198
            'allow_methods'     => ['*'],
199
            'allow_headers'     => ['*'],
200
            'allow_credentials' => true,
201
        ]);
202
203
        $this->specify('response credentials header is set', function () {
204
            $this->request->headers->set('Origin', 'http://foo.com');
205
206
            $response = $this->service->handleRequest($this->request, new Response());
207
208
            verify($response->headers->get('Access-Control-Allow-Credentials'))->equals('true');
209
        });
210
211
        $this->service = new CorsService([
212
            'allow_origins'  => ['*'],
213
            'allow_methods'  => ['*'],
214
            'allow_headers'  => ['*'],
215
            'expose_headers' => ['Accept', 'Authorization', 'Content-Type'],
216
        ]);
217
218
        $this->specify('response expose headers header is set', function () {
219
            $this->request->headers->set('Origin', 'http://foo.com');
220
221
            $response = $this->service->handleRequest($this->request, new Response());
222
223
            verify($response->headers->get('Access-Control-Expose-Headers'))->equals('accept, authorization, content-type');
224
        });
225
226
        $this->service = new CorsService([
227
            'allow_origins' => ['http://foo.com', 'http://notbar.com'],
228
        ]);
229
230
        $this->specify('response origin header is not set when origin is not allowed', function () {
231
            $this->request->headers->set('Origin', 'http://bar.com');
232
233
            $response = $this->service->handleRequest($this->request, new Response());
234
235
            verify($response->getStatusCode())->equals(200);
236
            verify($response->headers->get('Access-Control-Allow-Origin'))->equals(null);
237
        });
238
    }
239
240
    public function testIsCorsRequest()
241
    {
242
        $this->service = new CorsService;
243
244
        $this->request = new Request;
245
246
        $this->specify('cors request is recognized', function () {
247
            verify($this->service->isCorsRequest($this->request))->false();
248
249
            $this->request->headers->set('Origin', 'http://foo.com');
250
251
            verify($this->service->isCorsRequest($this->request))->true();
252
        });
253
    }
254
255
    public function testIsPreflightRequest()
256
    {
257
        $this->service = new CorsService;
258
259
        $this->request = new Request;
260
261
        $this->specify('preflight request is recognized', function () {
262
            verify($this->service->isPreflightRequest($this->request))->false();
263
264
            $this->request->setMethod('OPTIONS');
265
266
            verify($this->service->isPreflightRequest($this->request))->false();
267
268
            $this->request->headers->set('Access-Control-Request-Method', 'POST');
269
270
            verify($this->service->isPreflightRequest($this->request))->false();
271
272
            $this->request->headers->set('Origin', 'http://foo.com');
273
274
            verify($this->service->isPreflightRequest($this->request))->true();
275
        });
276
    }
277
278
    public function testAllowOriginIfMatchPattern()
279
    {
280
        $this->request = new Request;
281
282
        $this->response = new Response;
283
284
        $this->service = new CorsService([
285
            'allow_origins' => ['http://*.foo.com', 'http://notbar.com'],
286
        ]);
287
288
        $this->specify('response origin header is set when origin is match to a pattern', function () {
289
            $this->request->headers->set('Origin', 'http://bar.foo.com');
290
291
            $response = $this->service->handleRequest($this->request, new Response());
292
293
            verify($response->getStatusCode())->equals(200);
294
            verify($response->headers->get('Access-Control-Allow-Origin'))->equals('http://bar.foo.com');
295
        });
296
    }
297
298
    public function testDenyOriginIfDoesNotMatchPattern()
299
    {
300
        $this->request = new Request;
301
302
        $this->response = new Response;
303
304
        $this->service = new CorsService([
305
            'allow_origins' => ['http://*.foo.com', 'http://notbar.com'],
306
        ]);
307
308
        $this->specify('response origin header is not set when origin is not a match to a pattern', function () {
309
            $this->request->headers->set('Origin', 'http://bar.com');
310
311
            $response = $this->service->handleRequest($this->request, new Response());
312
313
            verify($response->getStatusCode())->equals(200);
314
            verify($response->headers->get('Access-Control-Allow-Origin'))->equals(null);
315
        });
316
    }
317
}
318