1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Klein (klein.php) - A fast & flexible router for PHP |
4
|
|
|
* |
5
|
|
|
* @author Chris O'Hara <[email protected]> |
6
|
|
|
* @author Trevor Suarez (Rican7) (contributor and v2 refactorer) |
7
|
|
|
* @copyright (c) Chris O'Hara |
8
|
|
|
* @link https://github.com/chriso/klein.php |
9
|
|
|
* @license MIT |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Klein\Tests; |
13
|
|
|
|
14
|
|
|
use Klein\DataCollection\HeaderDataCollection; |
15
|
|
|
use Klein\DataCollection\ResponseCookieDataCollection; |
16
|
|
|
use Klein\Exceptions\LockedResponseException; |
17
|
|
|
use Klein\HttpStatus; |
18
|
|
|
use Klein\Klein; |
19
|
|
|
use Klein\Response; |
20
|
|
|
use Klein\ResponseCookie; |
21
|
|
|
use Klein\Tests\Mocks\MockRequestFactory; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* ResponsesTest |
25
|
|
|
*/ |
26
|
|
|
class ResponsesTest extends AbstractKleinTest |
27
|
|
|
{ |
28
|
|
|
|
29
|
|
View Code Duplication |
public function testProtocolVersionGetSet() |
|
|
|
|
30
|
|
|
{ |
31
|
|
|
$version_reg_ex = '/^[0-9]\.[0-9]$/'; |
32
|
|
|
|
33
|
|
|
// Empty constructor |
34
|
|
|
$response = new Response(); |
35
|
|
|
|
36
|
|
|
$this->assertNotNull($response->protocolVersion()); |
37
|
|
|
$this->assertInternalType('string', $response->protocolVersion()); |
38
|
|
|
$this->assertRegExp($version_reg_ex, $response->protocolVersion()); |
39
|
|
|
|
40
|
|
|
// Set in method |
41
|
|
|
$response = new Response(); |
42
|
|
|
$response->protocolVersion('2.0'); |
43
|
|
|
|
44
|
|
|
$this->assertSame('2.0', $response->protocolVersion()); |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
public function testBodyGetSet() |
48
|
|
|
{ |
49
|
|
|
// Empty constructor |
50
|
|
|
$response = new Response(); |
51
|
|
|
|
52
|
|
|
$this->assertEmpty($response->body()); |
53
|
|
|
|
54
|
|
|
// Body set in constructor |
55
|
|
|
$response = new Response('dog'); |
56
|
|
|
|
57
|
|
|
$this->assertSame('dog', $response->body()); |
58
|
|
|
|
59
|
|
|
// Body set in method |
60
|
|
|
$response = new Response(); |
61
|
|
|
$response->body('testing'); |
62
|
|
|
|
63
|
|
|
$this->assertSame('testing', $response->body()); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
View Code Duplication |
public function testCodeGetSet() |
|
|
|
|
67
|
|
|
{ |
68
|
|
|
// Empty constructor |
69
|
|
|
$response = new Response(); |
70
|
|
|
|
71
|
|
|
$this->assertNotNull($response->code()); |
72
|
|
|
$this->assertInternalType('int', $response->code()); |
73
|
|
|
|
74
|
|
|
// Code set in constructor |
75
|
|
|
$response = new Response(null, 503); |
76
|
|
|
|
77
|
|
|
$this->assertSame(503, $response->code()); |
78
|
|
|
|
79
|
|
|
// Code set in method |
80
|
|
|
$response = new Response(); |
81
|
|
|
$response->code(204); |
82
|
|
|
|
83
|
|
|
$this->assertSame(204, $response->code()); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
public function testStatusGetter() |
87
|
|
|
{ |
88
|
|
|
$response = new Response(); |
89
|
|
|
|
90
|
|
|
$this->assertInternalType('object', $response->status()); |
91
|
|
|
$this->assertTrue($response->status() instanceof HttpStatus); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
public function testHeadersGetter() |
95
|
|
|
{ |
96
|
|
|
$response = new Response(); |
97
|
|
|
|
98
|
|
|
$this->assertInternalType('object', $response->headers()); |
99
|
|
|
$this->assertTrue($response->headers() instanceof HeaderDataCollection); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
public function testCookiesGetter() |
103
|
|
|
{ |
104
|
|
|
$response = new Response(); |
105
|
|
|
|
106
|
|
|
$this->assertInternalType('object', $response->cookies()); |
107
|
|
|
$this->assertTrue($response->cookies() instanceof ResponseCookieDataCollection); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
public function testPrepend() |
111
|
|
|
{ |
112
|
|
|
$response = new Response('ein'); |
113
|
|
|
$response->prepend('Kl'); |
114
|
|
|
|
115
|
|
|
$this->assertSame('Klein', $response->body()); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
public function testAppend() |
119
|
|
|
{ |
120
|
|
|
$response = new Response('Kl'); |
121
|
|
|
$response->append('ein'); |
122
|
|
|
|
123
|
|
|
$this->assertSame('Klein', $response->body()); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
public function testLockToggleAndGetters() |
127
|
|
|
{ |
128
|
|
|
$response = new Response(); |
129
|
|
|
|
130
|
|
|
$this->assertFalse($response->isLocked()); |
131
|
|
|
|
132
|
|
|
$response->lock(); |
133
|
|
|
|
134
|
|
|
$this->assertTrue($response->isLocked()); |
135
|
|
|
|
136
|
|
|
$response->unlock(); |
137
|
|
|
|
138
|
|
|
$this->assertFalse($response->isLocked()); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
public function testLockedNotModifiable() |
142
|
|
|
{ |
143
|
|
|
$response = new Response(); |
144
|
|
|
$response->lock(); |
145
|
|
|
|
146
|
|
|
// Get initial values |
147
|
|
|
$protocol_version = $response->protocolVersion(); |
148
|
|
|
$body = $response->body(); |
149
|
|
|
$code = $response->code(); |
150
|
|
|
|
151
|
|
|
// Attempt to modify |
152
|
|
|
try { |
153
|
|
|
$response->protocolVersion('2.0'); |
154
|
|
|
} catch (LockedResponseException $e) { |
|
|
|
|
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
try { |
158
|
|
|
$response->body('WOOT!'); |
159
|
|
|
} catch (LockedResponseException $e) { |
|
|
|
|
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
try { |
163
|
|
|
$response->code(204); |
164
|
|
|
} catch (LockedResponseException $e) { |
|
|
|
|
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
try { |
168
|
|
|
$response->prepend('cat'); |
169
|
|
|
} catch (LockedResponseException $e) { |
|
|
|
|
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
try { |
173
|
|
|
$response->append('dog'); |
174
|
|
|
} catch (LockedResponseException $e) { |
|
|
|
|
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
|
178
|
|
|
// Assert nothing has changed |
179
|
|
|
$this->assertSame($protocol_version, $response->protocolVersion()); |
180
|
|
|
$this->assertSame($body, $response->body()); |
181
|
|
|
$this->assertSame($code, $response->code()); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Testing headers is a pain in the ass. ;) |
186
|
|
|
* |
187
|
|
|
* Technically... we can't. So, yea. |
188
|
|
|
* |
189
|
|
|
* Attempt to run in a separate process so we can |
190
|
|
|
* at least call our internal methods |
191
|
|
|
*/ |
192
|
|
|
public function testSendHeaders() |
193
|
|
|
{ |
194
|
|
|
$response = new Response('woot!'); |
195
|
|
|
$response->headers()->set('test', 'sure'); |
196
|
|
|
$response->headers()->set('Authorization', 'Basic asdasd'); |
197
|
|
|
|
198
|
|
|
$response->sendHeaders(); |
199
|
|
|
|
200
|
|
|
$this->expectOutputString(null); |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
/** |
204
|
|
|
* @runInSeparateProcess |
205
|
|
|
*/ |
206
|
|
|
public function testSendHeadersInIsolateProcess() |
207
|
|
|
{ |
208
|
|
|
$this->testSendHeaders(); |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* Testing cookies is exactly like testing headers |
213
|
|
|
* ... So, yea. |
214
|
|
|
*/ |
215
|
|
|
public function testSendCookies() |
216
|
|
|
{ |
217
|
|
|
$response = new Response(); |
218
|
|
|
$response->cookies()->set('test', 'woot!'); |
219
|
|
|
$response->cookies()->set('Cookie-name', 'wtf?'); |
220
|
|
|
|
221
|
|
|
$response->sendCookies(); |
222
|
|
|
|
223
|
|
|
$this->expectOutputString(null); |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* @runInSeparateProcess |
228
|
|
|
*/ |
229
|
|
|
public function testSendCookiesInIsolateProcess() |
230
|
|
|
{ |
231
|
|
|
$this->testSendCookies(); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
public function testSendBody() |
235
|
|
|
{ |
236
|
|
|
$response = new Response('woot!'); |
237
|
|
|
$response->sendBody(); |
238
|
|
|
|
239
|
|
|
$this->expectOutputString('woot!'); |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
public function testSend() |
243
|
|
|
{ |
244
|
|
|
$response = new Response('woot!'); |
245
|
|
|
$response->send(); |
246
|
|
|
|
247
|
|
|
$this->expectOutputString('woot!'); |
248
|
|
|
$this->assertTrue($response->isLocked()); |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
/** |
252
|
|
|
* @expectedException \Klein\Exceptions\ResponseAlreadySentException |
253
|
|
|
*/ |
254
|
|
|
public function testSendWhenAlreadySent() |
255
|
|
|
{ |
256
|
|
|
$response = new Response(); |
257
|
|
|
$response->send(); |
258
|
|
|
|
259
|
|
|
$this->assertTrue($response->isLocked()); |
260
|
|
|
|
261
|
|
|
$response->send(); |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
/** |
265
|
|
|
* This uses some crazy exploitation to make sure that the |
266
|
|
|
* `fastcgi_finish_request()` function gets called. |
267
|
|
|
* Because of this, this MUST be run in a separate process |
268
|
|
|
* |
269
|
|
|
* @runInSeparateProcess |
270
|
|
|
*/ |
271
|
|
|
public function testSendCallsFastCGIFinishRequest() |
272
|
|
|
{ |
273
|
|
|
// Custom fastcgi function |
274
|
|
|
implement_custom_fastcgi_function(); |
275
|
|
|
|
276
|
|
|
$response = new Response(); |
277
|
|
|
$response->send(); |
278
|
|
|
|
279
|
|
|
$this->expectOutputString('fastcgi_finish_request'); |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
public function testChunk() |
283
|
|
|
{ |
284
|
|
|
$content = array( |
285
|
|
|
'initial content', |
286
|
|
|
'more', |
287
|
|
|
'content', |
288
|
|
|
); |
289
|
|
|
|
290
|
|
|
$response = new Response($content[0]); |
291
|
|
|
|
292
|
|
|
$response->chunk(); |
293
|
|
|
$response->chunk($content[1]); |
294
|
|
|
$response->chunk($content[2]); |
295
|
|
|
|
296
|
|
|
$this->expectOutputString( |
297
|
|
|
dechex(strlen($content[0]))."\r\n" |
298
|
|
|
."$content[0]\r\n" |
299
|
|
|
.dechex(strlen($content[1]))."\r\n" |
300
|
|
|
."$content[1]\r\n" |
301
|
|
|
.dechex(strlen($content[2]))."\r\n" |
302
|
|
|
."$content[2]\r\n" |
303
|
|
|
); |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
public function testHeader() |
307
|
|
|
{ |
308
|
|
|
$headers = array( |
309
|
|
|
'test' => 'woot!', |
310
|
|
|
'test' => 'sure', |
311
|
|
|
'okay' => 'yup', |
312
|
|
|
); |
313
|
|
|
|
314
|
|
|
$response = new Response(); |
315
|
|
|
|
316
|
|
|
// Make sure the headers are initially empty |
317
|
|
|
$this->assertEmpty($response->headers()->all()); |
318
|
|
|
|
319
|
|
|
// Set the headers |
320
|
|
|
foreach ($headers as $name => $value) { |
321
|
|
|
$response->header($name, $value); |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
$this->assertNotEmpty($response->headers()->all()); |
325
|
|
|
|
326
|
|
|
// Set the headers |
327
|
|
|
foreach ($headers as $name => $value) { |
328
|
|
|
$this->assertSame($value, $response->headers()->get($name)); |
329
|
|
|
} |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
/** |
333
|
|
|
* @group testCookie |
334
|
|
|
*/ |
335
|
|
|
public function testCookie() |
336
|
|
|
{ |
337
|
|
|
$test_cookie_data = array( |
338
|
|
|
'name' => 'name', |
339
|
|
|
'value' => 'value', |
340
|
|
|
'expiry' => null, |
341
|
|
|
'path' => '/path', |
342
|
|
|
'domain' => 'whatever.com', |
343
|
|
|
'secure' => true, |
344
|
|
|
'httponly' => true |
345
|
|
|
); |
346
|
|
|
|
347
|
|
|
$test_cookie = new ResponseCookie( |
|
|
|
|
348
|
|
|
$test_cookie_data['name'], |
349
|
|
|
$test_cookie_data['value'], |
350
|
|
|
$test_cookie_data['expiry'], |
351
|
|
|
$test_cookie_data['path'], |
352
|
|
|
$test_cookie_data['domain'], |
353
|
|
|
$test_cookie_data['secure'], |
354
|
|
|
$test_cookie_data['httponly'] |
355
|
|
|
); |
356
|
|
|
|
357
|
|
|
$response = new Response(); |
358
|
|
|
|
359
|
|
|
// Make sure the cookies are initially empty |
360
|
|
|
$this->assertEmpty($response->cookies()->all()); |
361
|
|
|
|
362
|
|
|
// Set a cookies |
363
|
|
|
$response->cookie( |
364
|
|
|
$test_cookie_data['name'], |
365
|
|
|
$test_cookie_data['value'], |
366
|
|
|
$test_cookie_data['expiry'], |
367
|
|
|
$test_cookie_data['path'], |
368
|
|
|
$test_cookie_data['domain'], |
369
|
|
|
$test_cookie_data['secure'], |
370
|
|
|
$test_cookie_data['httponly'] |
371
|
|
|
); |
372
|
|
|
|
373
|
|
|
$this->assertNotEmpty($response->cookies()->all()); |
374
|
|
|
|
375
|
|
|
$the_cookie = $response->cookies()->get($test_cookie_data['name']); |
376
|
|
|
|
377
|
|
|
$this->assertNotNull($the_cookie); |
378
|
|
|
$this->assertTrue($the_cookie instanceof ResponseCookie); |
379
|
|
|
$this->assertSame($test_cookie_data['name'], $the_cookie->getName()); |
380
|
|
|
$this->assertSame($test_cookie_data['value'], $the_cookie->getValue()); |
381
|
|
|
$this->assertSame($test_cookie_data['path'], $the_cookie->getPath()); |
382
|
|
|
$this->assertSame($test_cookie_data['domain'], $the_cookie->getDomain()); |
383
|
|
|
$this->assertSame($test_cookie_data['secure'], $the_cookie->getSecure()); |
384
|
|
|
$this->assertSame($test_cookie_data['httponly'], $the_cookie->getHttpOnly()); |
385
|
|
|
$this->assertNotNull($the_cookie->getExpire()); |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
public function testNoCache() |
389
|
|
|
{ |
390
|
|
|
$response = new Response(); |
391
|
|
|
|
392
|
|
|
// Make sure the headers are initially empty |
393
|
|
|
$this->assertEmpty($response->headers()->all()); |
394
|
|
|
|
395
|
|
|
$response->noCache(); |
396
|
|
|
|
397
|
|
|
$this->assertContains('no-cache', $response->headers()->all()); |
398
|
|
|
} |
399
|
|
|
|
400
|
|
|
public function testRedirect() |
401
|
|
|
{ |
402
|
|
|
$url = 'http://google.com/'; |
403
|
|
|
$code = 302; |
404
|
|
|
|
405
|
|
|
$response = new Response(); |
406
|
|
|
$response->redirect($url, $code); |
407
|
|
|
|
408
|
|
|
$this->assertSame($code, $response->code()); |
409
|
|
|
$this->assertSame($url, $response->headers()->get('location')); |
410
|
|
|
$this->assertTrue($response->isLocked()); |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
public function testDump() |
414
|
|
|
{ |
415
|
|
|
$response = new Response(); |
416
|
|
|
|
417
|
|
|
$this->assertEmpty($response->body()); |
418
|
|
|
|
419
|
|
|
$response->dump('test'); |
420
|
|
|
|
421
|
|
|
$this->assertContains('test', $response->body()); |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
public function testDumpArray() |
425
|
|
|
{ |
426
|
|
|
$response = new Response(); |
427
|
|
|
|
428
|
|
|
$this->assertEmpty($response->body()); |
429
|
|
|
|
430
|
|
|
$response->dump(array('sure', 1, 10, 17, 'ok' => 'no')); |
431
|
|
|
|
432
|
|
|
$this->assertNotEmpty($response->body()); |
433
|
|
|
$this->assertNotEquals('<pre></pre>', $response->body()); |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
public function testFileSend() |
437
|
|
|
{ |
438
|
|
|
$file_name = 'testing'; |
439
|
|
|
$file_mime = 'text/plain'; |
440
|
|
|
|
441
|
|
|
$this->klein_app->respond( |
442
|
|
|
function ($request, $response, $service) use ($file_name, $file_mime) { |
|
|
|
|
443
|
|
|
$response->file(__FILE__, $file_name, $file_mime); |
444
|
|
|
} |
445
|
|
|
); |
446
|
|
|
|
447
|
|
|
$this->klein_app->dispatch(); |
448
|
|
|
|
449
|
|
|
// Expect our output to match our json encoded test object |
450
|
|
|
$this->expectOutputString( |
451
|
|
|
file_get_contents(__FILE__) |
452
|
|
|
); |
453
|
|
|
|
454
|
|
|
// Assert headers were passed |
455
|
|
|
$this->assertEquals( |
456
|
|
|
$file_mime, |
457
|
|
|
$this->klein_app->response()->headers()->get('Content-Type') |
458
|
|
|
); |
459
|
|
|
$this->assertEquals( |
460
|
|
|
filesize(__FILE__), |
461
|
|
|
$this->klein_app->response()->headers()->get('Content-Length') |
462
|
|
|
); |
463
|
|
|
$this->assertContains( |
464
|
|
|
$file_name, |
465
|
|
|
$this->klein_app->response()->headers()->get('Content-Disposition') |
466
|
|
|
); |
467
|
|
|
} |
468
|
|
|
|
469
|
|
|
public function testFileSendLooseArgs() |
470
|
|
|
{ |
471
|
|
|
$this->klein_app->respond( |
472
|
|
|
function ($request, $response, $service) { |
|
|
|
|
473
|
|
|
$response->file(__FILE__); |
474
|
|
|
} |
475
|
|
|
); |
476
|
|
|
|
477
|
|
|
$this->klein_app->dispatch(); |
478
|
|
|
|
479
|
|
|
// Expect our output to match our json encoded test object |
480
|
|
|
$this->expectOutputString( |
481
|
|
|
file_get_contents(__FILE__) |
482
|
|
|
); |
483
|
|
|
|
484
|
|
|
// Assert headers were passed |
485
|
|
|
$this->assertEquals( |
486
|
|
|
filesize(__FILE__), |
487
|
|
|
$this->klein_app->response()->headers()->get('Content-Length') |
488
|
|
|
); |
489
|
|
|
$this->assertNotNull( |
490
|
|
|
$this->klein_app->response()->headers()->get('Content-Type') |
491
|
|
|
); |
492
|
|
|
$this->assertNotNull( |
493
|
|
|
$this->klein_app->response()->headers()->get('Content-Disposition') |
494
|
|
|
); |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
public function testJSON() |
498
|
|
|
{ |
499
|
|
|
// Create a test object to be JSON encoded/decoded |
500
|
|
|
$test_object = (object) array( |
501
|
|
|
'cheese', |
502
|
|
|
'dog' => 'bacon', |
503
|
|
|
1.5 => 'should be 1 (thanks PHP casting...)', |
504
|
|
|
'integer' => 1, |
505
|
|
|
'double' => 1.5, |
506
|
|
|
'_weird' => true, |
507
|
|
|
'uniqid' => uniqid(), |
508
|
|
|
); |
509
|
|
|
|
510
|
|
|
$this->klein_app->respond( |
511
|
|
|
function ($request, $response, $service) use ($test_object) { |
|
|
|
|
512
|
|
|
$response->json($test_object); |
513
|
|
|
} |
514
|
|
|
); |
515
|
|
|
|
516
|
|
|
$this->klein_app->dispatch(); |
517
|
|
|
|
518
|
|
|
// Expect our output to match our json encoded test object |
519
|
|
|
$this->expectOutputString( |
520
|
|
|
json_encode($test_object) |
521
|
|
|
); |
522
|
|
|
|
523
|
|
|
// Assert headers were passed |
524
|
|
|
$this->assertEquals( |
525
|
|
|
'no-cache', |
526
|
|
|
$this->klein_app->response()->headers()->get('Pragma') |
527
|
|
|
); |
528
|
|
|
$this->assertEquals( |
529
|
|
|
'no-store, no-cache', |
530
|
|
|
$this->klein_app->response()->headers()->get('Cache-Control') |
531
|
|
|
); |
532
|
|
|
$this->assertEquals( |
533
|
|
|
'application/json', |
534
|
|
|
$this->klein_app->response()->headers()->get('Content-Type') |
535
|
|
|
); |
536
|
|
|
} |
537
|
|
|
|
538
|
|
|
public function testJSONWithPrefix() |
539
|
|
|
{ |
540
|
|
|
// Create a test object to be JSON encoded/decoded |
541
|
|
|
$test_object = array( |
542
|
|
|
'cheese', |
543
|
|
|
); |
544
|
|
|
$prefix = 'dogma'; |
545
|
|
|
|
546
|
|
|
$this->klein_app->respond( |
547
|
|
|
function ($request, $response, $service) use ($test_object, $prefix) { |
|
|
|
|
548
|
|
|
$response->json($test_object, $prefix); |
549
|
|
|
} |
550
|
|
|
); |
551
|
|
|
|
552
|
|
|
$this->klein_app->dispatch(); |
553
|
|
|
|
554
|
|
|
// Expect our output to match our json encoded test object |
555
|
|
|
$this->expectOutputString( |
556
|
|
|
'dogma('. json_encode($test_object) .');' |
557
|
|
|
); |
558
|
|
|
|
559
|
|
|
// Assert headers were passed |
560
|
|
|
$this->assertEquals( |
561
|
|
|
'no-cache', |
562
|
|
|
$this->klein_app->response()->headers()->get('Pragma') |
563
|
|
|
); |
564
|
|
|
$this->assertEquals( |
565
|
|
|
'no-store, no-cache', |
566
|
|
|
$this->klein_app->response()->headers()->get('Cache-Control') |
567
|
|
|
); |
568
|
|
|
$this->assertEquals( |
569
|
|
|
'text/javascript', |
570
|
|
|
$this->klein_app->response()->headers()->get('Content-Type') |
571
|
|
|
); |
572
|
|
|
} |
573
|
|
|
} |
574
|
|
|
|
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.