Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
15403 manish.sha 1
<?php
2
/**
3
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
4
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
5
 *
6
 * Licensed under The MIT License
7
 * For full copyright and license information, please see the LICENSE.txt
8
 * Redistributions of files must retain the above copyright notice.
9
 *
10
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
11
 * @link          http://cakephp.org CakePHP(tm) Project
12
 * @package       Cake.Test.Case.Network
13
 * @since         CakePHP(tm) v 2.0
14
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
15
 */
16
 
17
App::uses('CakeResponse', 'Network');
18
App::uses('CakeRequest', 'Network');
19
 
20
/**
21
 * Class CakeResponseTest
22
 *
23
 * @package       Cake.Test.Case.Network
24
 */
25
class CakeResponseTest extends CakeTestCase {
26
 
27
/**
28
 * Setup for tests
29
 *
30
 * @return void
31
 */
32
	public function setUp() {
33
		parent::setUp();
34
		ob_start();
35
	}
36
 
37
/**
38
 * Cleanup after tests
39
 *
40
 * @return void
41
 */
42
	public function tearDown() {
43
		parent::tearDown();
44
		ob_end_clean();
45
	}
46
 
47
/**
48
 * Tests the request object constructor
49
 *
50
 * @return void
51
 */
52
	public function testConstruct() {
53
		$response = new CakeResponse();
54
		$this->assertNull($response->body());
55
		$this->assertEquals('UTF-8', $response->charset());
56
		$this->assertEquals('text/html', $response->type());
57
		$this->assertEquals(200, $response->statusCode());
58
 
59
		$options = array(
60
			'body' => 'This is the body',
61
			'charset' => 'my-custom-charset',
62
			'type' => 'mp3',
63
			'status' => '203'
64
		);
65
		$response = new CakeResponse($options);
66
		$this->assertEquals('This is the body', $response->body());
67
		$this->assertEquals('my-custom-charset', $response->charset());
68
		$this->assertEquals('audio/mpeg', $response->type());
69
		$this->assertEquals(203, $response->statusCode());
70
 
71
		$options = array(
72
			'body' => 'This is the body',
73
			'charset' => 'my-custom-charset',
74
			'type' => 'mp3',
75
			'status' => '422',
76
			'statusCodes' => array(
77
				422 => 'Unprocessable Entity'
78
			)
79
		);
80
		$response = new CakeResponse($options);
81
		$this->assertEquals($options['body'], $response->body());
82
		$this->assertEquals($options['charset'], $response->charset());
83
		$this->assertEquals($response->getMimeType($options['type']), $response->type());
84
		$this->assertEquals($options['status'], $response->statusCode());
85
	}
86
 
87
/**
88
 * Tests the body method
89
 *
90
 * @return void
91
 */
92
	public function testBody() {
93
		$response = new CakeResponse();
94
		$this->assertNull($response->body());
95
		$response->body('Response body');
96
		$this->assertEquals('Response body', $response->body());
97
		$this->assertEquals('Changed Body', $response->body('Changed Body'));
98
	}
99
 
100
/**
101
 * Tests the charset method
102
 *
103
 * @return void
104
 */
105
	public function testCharset() {
106
		$response = new CakeResponse();
107
		$this->assertEquals('UTF-8', $response->charset());
108
		$response->charset('iso-8859-1');
109
		$this->assertEquals('iso-8859-1', $response->charset());
110
		$this->assertEquals('UTF-16', $response->charset('UTF-16'));
111
	}
112
 
113
/**
114
 * Tests the statusCode method
115
 *
116
 * @expectedException CakeException
117
 * @return void
118
 */
119
	public function testStatusCode() {
120
		$response = new CakeResponse();
121
		$this->assertEquals(200, $response->statusCode());
122
		$response->statusCode(404);
123
		$this->assertEquals(404, $response->statusCode());
124
		$this->assertEquals(500, $response->statusCode(500));
125
 
126
		//Throws exception
127
		$response->statusCode(1001);
128
	}
129
 
130
/**
131
 * Tests the type method
132
 *
133
 * @return void
134
 */
135
	public function testType() {
136
		$response = new CakeResponse();
137
		$this->assertEquals('text/html', $response->type());
138
		$response->type('pdf');
139
		$this->assertEquals('application/pdf', $response->type());
140
		$this->assertEquals('application/crazy-mime', $response->type('application/crazy-mime'));
141
		$this->assertEquals('application/json', $response->type('json'));
142
		$this->assertEquals('text/vnd.wap.wml', $response->type('wap'));
143
		$this->assertEquals('application/vnd.wap.xhtml+xml', $response->type('xhtml-mobile'));
144
		$this->assertEquals('text/csv', $response->type('csv'));
145
 
146
		$response->type(array('keynote' => 'application/keynote', 'bat' => 'application/bat'));
147
		$this->assertEquals('application/keynote', $response->type('keynote'));
148
		$this->assertEquals('application/bat', $response->type('bat'));
149
 
150
		$this->assertFalse($response->type('wackytype'));
151
	}
152
 
153
/**
154
 * Tests the header method
155
 *
156
 * @return void
157
 */
158
	public function testHeader() {
159
		$response = new CakeResponse();
160
		$headers = array();
161
		$this->assertEquals($headers, $response->header());
162
 
163
		$response->header('Location', 'http://example.com');
164
		$headers += array('Location' => 'http://example.com');
165
		$this->assertEquals($headers, $response->header());
166
 
167
		//Headers with the same name are overwritten
168
		$response->header('Location', 'http://example2.com');
169
		$headers = array('Location' => 'http://example2.com');
170
		$this->assertEquals($headers, $response->header());
171
 
172
		$response->header(array('WWW-Authenticate' => 'Negotiate'));
173
		$headers += array('WWW-Authenticate' => 'Negotiate');
174
		$this->assertEquals($headers, $response->header());
175
 
176
		$response->header(array('WWW-Authenticate' => 'Not-Negotiate'));
177
		$headers['WWW-Authenticate'] = 'Not-Negotiate';
178
		$this->assertEquals($headers, $response->header());
179
 
180
		$response->header(array('Age' => 12, 'Allow' => 'GET, HEAD'));
181
		$headers += array('Age' => 12, 'Allow' => 'GET, HEAD');
182
		$this->assertEquals($headers, $response->header());
183
 
184
		// String headers are allowed
185
		$response->header('Content-Language: da');
186
		$headers += array('Content-Language' => 'da');
187
		$this->assertEquals($headers, $response->header());
188
 
189
		$response->header('Content-Language: da');
190
		$headers += array('Content-Language' => 'da');
191
		$this->assertEquals($headers, $response->header());
192
 
193
		$response->header(array('Content-Encoding: gzip', 'Vary: *', 'Pragma' => 'no-cache'));
194
		$headers += array('Content-Encoding' => 'gzip', 'Vary' => '*', 'Pragma' => 'no-cache');
195
		$this->assertEquals($headers, $response->header());
196
 
197
		$response->header('Access-Control-Allow-Origin', array('domain1', 'domain2'));
198
		$headers += array('Access-Control-Allow-Origin' => array('domain1', 'domain2'));
199
		$this->assertEquals($headers, $response->header());
200
	}
201
 
202
/**
203
 * Tests the send method
204
 *
205
 * @return void
206
 */
207
	public function testSend() {
208
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', '_setCookies'));
209
		$response->header(array(
210
			'Content-Language' => 'es',
211
			'WWW-Authenticate' => 'Negotiate',
212
			'Access-Control-Allow-Origin' => array('domain1', 'domain2'),
213
		));
214
		$response->body('the response body');
215
		$response->expects($this->once())->method('_sendContent')->with('the response body');
216
		$response->expects($this->at(0))->method('_setCookies');
217
		$response->expects($this->at(1))
218
			->method('_sendHeader')->with('HTTP/1.1 200 OK');
219
		$response->expects($this->at(2))
220
			->method('_sendHeader')->with('Content-Language', 'es');
221
		$response->expects($this->at(3))
222
			->method('_sendHeader')->with('WWW-Authenticate', 'Negotiate');
223
		$response->expects($this->at(4))
224
			->method('_sendHeader')->with('Access-Control-Allow-Origin', 'domain1');
225
		$response->expects($this->at(5))
226
			->method('_sendHeader')->with('Access-Control-Allow-Origin', 'domain2');
227
		$response->expects($this->at(6))
228
			->method('_sendHeader')->with('Content-Length', 17);
229
		$response->expects($this->at(7))
230
			->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8');
231
		$response->send();
232
	}
233
 
234
/**
235
 * Data provider for content type tests.
236
 *
237
 * @return array
238
 */
239
	public static function charsetTypeProvider() {
240
		return array(
241
			array('mp3', 'audio/mpeg'),
242
			array('js', 'application/javascript; charset=UTF-8'),
243
			array('json', 'application/json; charset=UTF-8'),
244
			array('xml', 'application/xml; charset=UTF-8'),
245
			array('txt', 'text/plain; charset=UTF-8'),
246
		);
247
	}
248
 
249
/**
250
 * Tests the send method and changing the content type
251
 *
252
 * @dataProvider charsetTypeProvider
253
 * @return void
254
 */
255
	public function testSendChangingContentType($original, $expected) {
256
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', '_setCookies'));
257
		$response->type($original);
258
		$response->body('the response body');
259
		$response->expects($this->once())->method('_sendContent')->with('the response body');
260
		$response->expects($this->at(0))->method('_setCookies');
261
		$response->expects($this->at(1))
262
			->method('_sendHeader')->with('HTTP/1.1 200 OK');
263
		$response->expects($this->at(2))
264
			->method('_sendHeader')->with('Content-Length', 17);
265
		$response->expects($this->at(3))
266
			->method('_sendHeader')->with('Content-Type', $expected);
267
		$response->send();
268
	}
269
 
270
/**
271
 * Tests the send method and changing the content type to JS without adding the charset
272
 *
273
 * @return void
274
 */
275
	public function testSendChangingContentTypeWithoutCharset() {
276
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', '_setCookies'));
277
		$response->type('js');
278
		$response->charset('');
279
 
280
		$response->body('var $foo = "bar";');
281
		$response->expects($this->once())->method('_sendContent')->with('var $foo = "bar";');
282
		$response->expects($this->at(0))->method('_setCookies');
283
		$response->expects($this->at(1))
284
			->method('_sendHeader')->with('HTTP/1.1 200 OK');
285
		$response->expects($this->at(2))
286
			->method('_sendHeader')->with('Content-Length', 17);
287
		$response->expects($this->at(3))
288
			->method('_sendHeader')->with('Content-Type', 'application/javascript');
289
		$response->send();
290
	}
291
 
292
/**
293
 * Tests the send method and changing the content type
294
 *
295
 * @return void
296
 */
297
	public function testSendWithLocation() {
298
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', '_setCookies'));
299
		$response->header('Location', 'http://www.example.com');
300
		$response->expects($this->at(0))->method('_setCookies');
301
		$response->expects($this->at(1))
302
			->method('_sendHeader')->with('HTTP/1.1 302 Found');
303
		$response->expects($this->at(2))
304
			->method('_sendHeader')->with('Location', 'http://www.example.com');
305
		$response->expects($this->at(3))
306
			->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8');
307
		$response->send();
308
	}
309
 
310
/**
311
 * Tests the disableCache method
312
 *
313
 * @return void
314
 */
315
	public function testDisableCache() {
316
		$response = new CakeResponse();
317
		$expected = array(
318
			'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT',
319
			'Last-Modified' => gmdate("D, d M Y H:i:s") . " GMT",
320
			'Cache-Control' => 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
321
		);
322
		$response->disableCache();
323
		$this->assertEquals($expected, $response->header());
324
	}
325
 
326
/**
327
 * Tests the cache method
328
 *
329
 * @return void
330
 */
331
	public function testCache() {
332
		$response = new CakeResponse();
333
		$since = time();
334
		$time = new DateTime('+1 day', new DateTimeZone('UTC'));
335
		$response->expires('+1 day');
336
		$expected = array(
337
			'Date' => gmdate("D, j M Y G:i:s ", $since) . 'GMT',
338
			'Last-Modified' => gmdate("D, j M Y H:i:s ", $since) . 'GMT',
339
			'Expires' => $time->format('D, j M Y H:i:s') . ' GMT',
340
			'Cache-Control' => 'public, max-age=' . ($time->format('U') - time())
341
		);
342
		$response->cache($since);
343
		$this->assertEquals($expected, $response->header());
344
 
345
		$response = new CakeResponse();
346
		$since = time();
347
		$time = '+5 day';
348
		$expected = array(
349
			'Date' => gmdate("D, j M Y G:i:s ", $since) . 'GMT',
350
			'Last-Modified' => gmdate("D, j M Y H:i:s ", $since) . 'GMT',
351
			'Expires' => gmdate("D, j M Y H:i:s", strtotime($time)) . " GMT",
352
			'Cache-Control' => 'public, max-age=' . (strtotime($time) - time())
353
		);
354
		$response->cache($since, $time);
355
		$this->assertEquals($expected, $response->header());
356
 
357
		$response = new CakeResponse();
358
		$since = time();
359
		$time = time();
360
		$expected = array(
361
			'Date' => gmdate("D, j M Y G:i:s ", $since) . 'GMT',
362
			'Last-Modified' => gmdate("D, j M Y H:i:s ", $since) . 'GMT',
363
			'Expires' => gmdate("D, j M Y H:i:s", $time) . " GMT",
364
			'Cache-Control' => 'public, max-age=0'
365
		);
366
		$response->cache($since, $time);
367
		$this->assertEquals($expected, $response->header());
368
	}
369
 
370
/**
371
 * Tests the compress method
372
 *
373
 * @return void
374
 */
375
	public function testCompress() {
376
		if (php_sapi_name() !== 'cli') {
377
			$this->markTestSkipped('The response compression can only be tested in cli.');
378
		}
379
 
380
		$response = new CakeResponse();
381
		if (ini_get("zlib.output_compression") === '1' || !extension_loaded("zlib")) {
382
			$this->assertFalse($response->compress());
383
			$this->markTestSkipped('Is not possible to test output compression');
384
		}
385
 
386
		$_SERVER['HTTP_ACCEPT_ENCODING'] = '';
387
		$result = $response->compress();
388
		$this->assertFalse($result);
389
 
390
		$_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip';
391
		$result = $response->compress();
392
		$this->assertTrue($result);
393
		$this->assertTrue(in_array('ob_gzhandler', ob_list_handlers()));
394
 
395
		ob_get_clean();
396
	}
397
 
398
/**
399
 * Tests the httpCodes method
400
 *
401
 * @expectedException CakeException
402
 * @return void
403
 */
404
	public function testHttpCodes() {
405
		$response = new CakeResponse();
406
		$result = $response->httpCodes();
407
		$this->assertEquals(41, count($result));
408
 
409
		$result = $response->httpCodes(100);
410
		$expected = array(100 => 'Continue');
411
		$this->assertEquals($expected, $result);
412
 
413
		$codes = array(
414
			381 => 'Unicorn Moved',
415
			555 => 'Unexpected Minotaur'
416
		);
417
 
418
		$result = $response->httpCodes($codes);
419
		$this->assertTrue($result);
420
		$this->assertEquals(43, count($response->httpCodes()));
421
 
422
		$result = $response->httpCodes(381);
423
		$expected = array(381 => 'Unicorn Moved');
424
		$this->assertEquals($expected, $result);
425
 
426
		$codes = array(404 => 'Sorry Bro');
427
		$result = $response->httpCodes($codes);
428
		$this->assertTrue($result);
429
		$this->assertEquals(43, count($response->httpCodes()));
430
 
431
		$result = $response->httpCodes(404);
432
		$expected = array(404 => 'Sorry Bro');
433
		$this->assertEquals($expected, $result);
434
 
435
		//Throws exception
436
		$response->httpCodes(array(
437
 
438
			-1 => 'Reverse Infinity',
439
			12345 => 'Universal Password',
440
			'Hello' => 'World'
441
		));
442
	}
443
 
444
/**
445
 * Tests the download method
446
 *
447
 * @return void
448
 */
449
	public function testDownload() {
450
		$response = new CakeResponse();
451
		$expected = array(
452
			'Content-Disposition' => 'attachment; filename="myfile.mp3"'
453
		);
454
		$response->download('myfile.mp3');
455
		$this->assertEquals($expected, $response->header());
456
	}
457
 
458
/**
459
 * Tests the mapType method
460
 *
461
 * @return void
462
 */
463
	public function testMapType() {
464
		$response = new CakeResponse();
465
		$this->assertEquals('wav', $response->mapType('audio/x-wav'));
466
		$this->assertEquals('pdf', $response->mapType('application/pdf'));
467
		$this->assertEquals('xml', $response->mapType('text/xml'));
468
		$this->assertEquals('html', $response->mapType('*/*'));
469
		$this->assertEquals('csv', $response->mapType('application/vnd.ms-excel'));
470
		$expected = array('json', 'xhtml', 'css');
471
		$result = $response->mapType(array('application/json', 'application/xhtml+xml', 'text/css'));
472
		$this->assertEquals($expected, $result);
473
	}
474
 
475
/**
476
 * Tests the outputCompressed method
477
 *
478
 * @return void
479
 */
480
	public function testOutputCompressed() {
481
		$response = new CakeResponse();
482
 
483
		$_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip';
484
		$result = $response->outputCompressed();
485
		$this->assertFalse($result);
486
 
487
		$_SERVER['HTTP_ACCEPT_ENCODING'] = '';
488
		$result = $response->outputCompressed();
489
		$this->assertFalse($result);
490
 
491
		if (!extension_loaded("zlib")) {
492
			$this->markTestSkipped('Skipping further tests for outputCompressed as zlib extension is not loaded');
493
		}
494
		if (php_sapi_name() !== 'cli') {
495
			$this->markTestSkipped('Testing outputCompressed method with compression enabled done only in cli');
496
		}
497
 
498
		if (ini_get("zlib.output_compression") !== '1') {
499
			ob_start('ob_gzhandler');
500
		}
501
		$_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip';
502
		$result = $response->outputCompressed();
503
		$this->assertTrue($result);
504
 
505
		$_SERVER['HTTP_ACCEPT_ENCODING'] = '';
506
		$result = $response->outputCompressed();
507
		$this->assertFalse($result);
508
		if (ini_get("zlib.output_compression") !== '1') {
509
			ob_get_clean();
510
		}
511
	}
512
 
513
/**
514
 * Tests the send and setting of Content-Length
515
 *
516
 * @return void
517
 */
518
	public function testSendContentLength() {
519
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
520
		$response->body('the response body');
521
		$response->expects($this->once())->method('_sendContent')->with('the response body');
522
		$response->expects($this->at(0))
523
			->method('_sendHeader')->with('HTTP/1.1 200 OK');
524
		$response->expects($this->at(2))
525
			->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8');
526
		$response->expects($this->at(1))
527
			->method('_sendHeader')->with('Content-Length', strlen('the response body'));
528
		$response->send();
529
 
530
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
531
		$body = '長い長い長いSubjectの場合はfoldingするのが正しいんだけどいったいどうなるんだろう?';
532
		$response->body($body);
533
		$response->expects($this->once())->method('_sendContent')->with($body);
534
		$response->expects($this->at(0))
535
			->method('_sendHeader')->with('HTTP/1.1 200 OK');
536
		$response->expects($this->at(2))
537
			->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8');
538
		$response->expects($this->at(1))
539
			->method('_sendHeader')->with('Content-Length', 116);
540
		$response->send();
541
 
542
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', 'outputCompressed'));
543
		$body = '長い長い長いSubjectの場合はfoldingするのが正しいんだけどいったいどうなるんだろう?';
544
		$response->body($body);
545
		$response->expects($this->once())->method('outputCompressed')->will($this->returnValue(true));
546
		$response->expects($this->once())->method('_sendContent')->with($body);
547
		$response->expects($this->exactly(2))->method('_sendHeader');
548
		$response->send();
549
 
550
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', 'outputCompressed'));
551
		$body = 'hwy';
552
		$response->body($body);
553
		$response->header('Content-Length', 1);
554
		$response->expects($this->never())->method('outputCompressed');
555
		$response->expects($this->once())->method('_sendContent')->with($body);
556
		$response->expects($this->at(1))
557
				->method('_sendHeader')->with('Content-Length', 1);
558
		$response->send();
559
 
560
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
561
		$body = 'content';
562
		$response->statusCode(301);
563
		$response->body($body);
564
		$response->expects($this->once())->method('_sendContent')->with($body);
565
		$response->expects($this->exactly(2))->method('_sendHeader');
566
		$response->send();
567
 
568
		ob_start();
569
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
570
		$goofyOutput = 'I am goofily sending output in the controller';
571
		echo $goofyOutput;
572
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
573
		$body = '長い長い長いSubjectの場合はfoldingするのが正しいんだけどいったいどうなるんだろう?';
574
		$response->body($body);
575
		$response->expects($this->once())->method('_sendContent')->with($body);
576
		$response->expects($this->at(0))
577
			->method('_sendHeader')->with('HTTP/1.1 200 OK');
578
		$response->expects($this->at(1))
579
			->method('_sendHeader')->with('Content-Length', strlen($goofyOutput) + 116);
580
		$response->expects($this->at(2))
581
			->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8');
582
		$response->send();
583
		ob_end_clean();
584
	}
585
 
586
/**
587
 * Tests getting/setting the protocol
588
 *
589
 * @return void
590
 */
591
	public function testProtocol() {
592
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
593
		$response->protocol('HTTP/1.0');
594
		$this->assertEquals('HTTP/1.0', $response->protocol());
595
		$response->expects($this->at(0))
596
			->method('_sendHeader')->with('HTTP/1.0 200 OK');
597
		$response->send();
598
	}
599
 
600
/**
601
 * Tests getting/setting the Content-Length
602
 *
603
 * @return void
604
 */
605
	public function testLength() {
606
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
607
		$response->length(100);
608
		$this->assertEquals(100, $response->length());
609
		$response->expects($this->at(1))
610
			->method('_sendHeader')->with('Content-Length', 100);
611
		$response->send();
612
 
613
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
614
		$response->length(false);
615
		$this->assertFalse($response->length());
616
		$response->expects($this->exactly(2))
617
			->method('_sendHeader');
618
		$response->send();
619
	}
620
 
621
/**
622
 * Tests that the response body is unset if the status code is 304 or 204
623
 *
624
 * @return void
625
 */
626
	public function testUnmodifiedContent() {
627
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
628
		$response->body('This is a body');
629
		$response->statusCode(204);
630
		$response->expects($this->once())
631
			->method('_sendContent')->with('');
632
		$response->send();
633
		$this->assertFalse(array_key_exists('Content-Type', $response->header()));
634
 
635
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
636
		$response->body('This is a body');
637
		$response->statusCode(304);
638
		$response->expects($this->once())
639
			->method('_sendContent')->with('');
640
		$response->send();
641
 
642
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
643
		$response->body('This is a body');
644
		$response->statusCode(200);
645
		$response->expects($this->once())
646
			->method('_sendContent')->with('This is a body');
647
		$response->send();
648
	}
649
 
650
/**
651
 * Tests setting the expiration date
652
 *
653
 * @return void
654
 */
655
	public function testExpires() {
656
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
657
		$now = new DateTime('now', new DateTimeZone('America/Los_Angeles'));
658
		$response->expires($now);
659
		$now->setTimeZone(new DateTimeZone('UTC'));
660
		$this->assertEquals($now->format('D, j M Y H:i:s') . ' GMT', $response->expires());
661
		$response->expects($this->at(1))
662
			->method('_sendHeader')->with('Expires', $now->format('D, j M Y H:i:s') . ' GMT');
663
		$response->send();
664
 
665
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
666
		$now = time();
667
		$response->expires($now);
668
		$this->assertEquals(gmdate('D, j M Y H:i:s', $now) . ' GMT', $response->expires());
669
		$response->expects($this->at(1))
670
			->method('_sendHeader')->with('Expires', gmdate('D, j M Y H:i:s', $now) . ' GMT');
671
		$response->send();
672
 
673
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
674
		$time = new DateTime('+1 day', new DateTimeZone('UTC'));
675
		$response->expires('+1 day');
676
		$this->assertEquals($time->format('D, j M Y H:i:s') . ' GMT', $response->expires());
677
		$response->expects($this->at(1))
678
			->method('_sendHeader')->with('Expires', $time->format('D, j M Y H:i:s') . ' GMT');
679
		$response->send();
680
	}
681
 
682
/**
683
 * Tests setting the modification date
684
 *
685
 * @return void
686
 */
687
	public function testModified() {
688
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
689
		$now = new DateTime('now', new DateTimeZone('America/Los_Angeles'));
690
		$response->modified($now);
691
		$now->setTimeZone(new DateTimeZone('UTC'));
692
		$this->assertEquals($now->format('D, j M Y H:i:s') . ' GMT', $response->modified());
693
		$response->expects($this->at(1))
694
			->method('_sendHeader')->with('Last-Modified', $now->format('D, j M Y H:i:s') . ' GMT');
695
		$response->send();
696
 
697
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
698
		$now = time();
699
		$response->modified($now);
700
		$this->assertEquals(gmdate('D, j M Y H:i:s', $now) . ' GMT', $response->modified());
701
		$response->expects($this->at(1))
702
			->method('_sendHeader')->with('Last-Modified', gmdate('D, j M Y H:i:s', $now) . ' GMT');
703
		$response->send();
704
 
705
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
706
		$time = new DateTime('+1 day', new DateTimeZone('UTC'));
707
		$response->modified('+1 day');
708
		$this->assertEquals($time->format('D, j M Y H:i:s') . ' GMT', $response->modified());
709
		$response->expects($this->at(1))
710
			->method('_sendHeader')->with('Last-Modified', $time->format('D, j M Y H:i:s') . ' GMT');
711
		$response->send();
712
	}
713
 
714
/**
715
 * Tests setting of public/private Cache-Control directives
716
 *
717
 * @return void
718
 */
719
	public function testSharable() {
720
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
721
		$this->assertNull($response->sharable());
722
		$response->sharable(true);
723
		$headers = $response->header();
724
		$this->assertEquals('public', $headers['Cache-Control']);
725
		$response->expects($this->at(1))
726
			->method('_sendHeader')->with('Cache-Control', 'public');
727
		$response->send();
728
 
729
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
730
		$response->sharable(false);
731
		$headers = $response->header();
732
		$this->assertEquals('private', $headers['Cache-Control']);
733
		$response->expects($this->at(1))
734
			->method('_sendHeader')->with('Cache-Control', 'private');
735
		$response->send();
736
 
737
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
738
		$response->sharable(true);
739
		$headers = $response->header();
740
		$this->assertEquals('public', $headers['Cache-Control']);
741
		$response->sharable(false);
742
		$headers = $response->header();
743
		$this->assertEquals('private', $headers['Cache-Control']);
744
		$response->expects($this->at(1))
745
			->method('_sendHeader')->with('Cache-Control', 'private');
746
		$response->send();
747
		$this->assertFalse($response->sharable());
748
		$response->sharable(true);
749
		$this->assertTrue($response->sharable());
750
 
751
		$response = new CakeResponse;
752
		$response->sharable(true, 3600);
753
		$headers = $response->header();
754
		$this->assertEquals('public, max-age=3600', $headers['Cache-Control']);
755
 
756
		$response = new CakeResponse;
757
		$response->sharable(false, 3600);
758
		$headers = $response->header();
759
		$this->assertEquals('private, max-age=3600', $headers['Cache-Control']);
760
		$response->send();
761
	}
762
 
763
/**
764
 * Tests setting of max-age Cache-Control directive
765
 *
766
 * @return void
767
 */
768
	public function testMaxAge() {
769
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
770
		$this->assertNull($response->maxAge());
771
		$response->maxAge(3600);
772
		$this->assertEquals(3600, $response->maxAge());
773
		$headers = $response->header();
774
		$this->assertEquals('max-age=3600', $headers['Cache-Control']);
775
		$response->expects($this->at(1))
776
			->method('_sendHeader')->with('Cache-Control', 'max-age=3600');
777
		$response->send();
778
 
779
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
780
		$response->maxAge(3600);
781
		$response->sharable(false);
782
		$headers = $response->header();
783
		$this->assertEquals('max-age=3600, private', $headers['Cache-Control']);
784
		$response->expects($this->at(1))
785
			->method('_sendHeader')->with('Cache-Control', 'max-age=3600, private');
786
		$response->send();
787
	}
788
 
789
/**
790
 * Tests setting of s-maxage Cache-Control directive
791
 *
792
 * @return void
793
 */
794
	public function testSharedMaxAge() {
795
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
796
		$this->assertNull($response->maxAge());
797
		$response->sharedMaxAge(3600);
798
		$this->assertEquals(3600, $response->sharedMaxAge());
799
		$headers = $response->header();
800
		$this->assertEquals('s-maxage=3600', $headers['Cache-Control']);
801
		$response->expects($this->at(1))
802
			->method('_sendHeader')->with('Cache-Control', 's-maxage=3600');
803
		$response->send();
804
 
805
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
806
		$response->sharedMaxAge(3600);
807
		$response->sharable(true);
808
		$headers = $response->header();
809
		$this->assertEquals('s-maxage=3600, public', $headers['Cache-Control']);
810
		$response->expects($this->at(1))
811
			->method('_sendHeader')->with('Cache-Control', 's-maxage=3600, public');
812
		$response->send();
813
	}
814
 
815
/**
816
 * Tests setting of must-revalidate Cache-Control directive
817
 *
818
 * @return void
819
 */
820
	public function testMustRevalidate() {
821
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
822
		$this->assertFalse($response->mustRevalidate());
823
		$response->mustRevalidate(true);
824
		$this->assertTrue($response->mustRevalidate());
825
		$headers = $response->header();
826
		$this->assertEquals('must-revalidate', $headers['Cache-Control']);
827
		$response->expects($this->at(1))
828
			->method('_sendHeader')->with('Cache-Control', 'must-revalidate');
829
		$response->send();
830
		$response->mustRevalidate(false);
831
		$this->assertFalse($response->mustRevalidate());
832
 
833
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
834
		$response->sharedMaxAge(3600);
835
		$response->mustRevalidate(true);
836
		$headers = $response->header();
837
		$this->assertEquals('s-maxage=3600, must-revalidate', $headers['Cache-Control']);
838
		$response->expects($this->at(1))
839
			->method('_sendHeader')->with('Cache-Control', 's-maxage=3600, must-revalidate');
840
		$response->send();
841
	}
842
 
843
/**
844
 * Tests getting/setting the Vary header
845
 *
846
 * @return void
847
 */
848
	public function testVary() {
849
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
850
		$response->vary('Accept-encoding');
851
		$this->assertEquals(array('Accept-encoding'), $response->vary());
852
		$response->expects($this->at(1))
853
			->method('_sendHeader')->with('Vary', 'Accept-encoding');
854
		$response->send();
855
 
856
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
857
		$response->vary(array('Accept-language', 'Accept-encoding'));
858
		$response->expects($this->at(1))
859
			->method('_sendHeader')->with('Vary', 'Accept-language, Accept-encoding');
860
		$response->send();
861
		$this->assertEquals(array('Accept-language', 'Accept-encoding'), $response->vary());
862
	}
863
 
864
/**
865
 * Tests getting/setting the Etag header
866
 *
867
 * @return void
868
 */
869
	public function testEtag() {
870
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
871
		$response->etag('something');
872
		$this->assertEquals('"something"', $response->etag());
873
		$response->expects($this->at(1))
874
			->method('_sendHeader')->with('Etag', '"something"');
875
		$response->send();
876
 
877
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
878
		$response->etag('something', true);
879
		$this->assertEquals('W/"something"', $response->etag());
880
		$response->expects($this->at(1))
881
			->method('_sendHeader')->with('Etag', 'W/"something"');
882
		$response->send();
883
	}
884
 
885
/**
886
 * Tests that the response is able to be marked as not modified
887
 *
888
 * @return void
889
 */
890
	public function testNotModified() {
891
		$response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
892
		$response->body('something');
893
		$response->statusCode(200);
894
		$response->length(100);
895
		$response->modified('now');
896
		$response->notModified();
897
 
898
		$this->assertEmpty($response->header());
899
		$this->assertEmpty($response->body());
900
		$this->assertEquals(304, $response->statusCode());
901
	}
902
 
903
/**
904
 * Test checkNotModified method
905
 *
906
 * @return void
907
 */
908
	public function testCheckNotModifiedByEtagStar() {
909
		$_SERVER['HTTP_IF_NONE_MATCH'] = '*';
910
		$response = $this->getMock('CakeResponse', array('notModified'));
911
		$response->etag('something');
912
		$response->expects($this->once())->method('notModified');
913
		$response->checkNotModified(new CakeRequest);
914
	}
915
 
916
/**
917
 * Test checkNotModified method
918
 *
919
 * @return void
920
 */
921
	public function testCheckNotModifiedByEtagExact() {
922
		$_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
923
		$response = $this->getMock('CakeResponse', array('notModified'));
924
		$response->etag('something', true);
925
		$response->expects($this->once())->method('notModified');
926
		$this->assertTrue($response->checkNotModified(new CakeRequest));
927
	}
928
 
929
/**
930
 * Test checkNotModified method
931
 *
932
 * @return void
933
 */
934
	public function testCheckNotModifiedByEtagAndTime() {
935
		$_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
936
		$_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
937
		$response = $this->getMock('CakeResponse', array('notModified'));
938
		$response->etag('something', true);
939
		$response->modified('2012-01-01 00:00:00');
940
		$response->expects($this->once())->method('notModified');
941
		$this->assertTrue($response->checkNotModified(new CakeRequest));
942
	}
943
 
944
/**
945
 * Test checkNotModified method
946
 *
947
 * @return void
948
 */
949
	public function testCheckNotModifiedByEtagAndTimeMismatch() {
950
		$_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
951
		$_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
952
		$response = $this->getMock('CakeResponse', array('notModified'));
953
		$response->etag('something', true);
954
		$response->modified('2012-01-01 00:00:01');
955
		$response->expects($this->never())->method('notModified');
956
		$this->assertFalse($response->checkNotModified(new CakeRequest));
957
	}
958
 
959
/**
960
 * Test checkNotModified method
961
 *
962
 * @return void
963
 */
964
	public function testCheckNotModifiedByEtagMismatch() {
965
		$_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something-else", "other"';
966
		$_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
967
		$response = $this->getMock('CakeResponse', array('notModified'));
968
		$response->etag('something', true);
969
		$response->modified('2012-01-01 00:00:00');
970
		$response->expects($this->never())->method('notModified');
971
		$this->assertFalse($response->checkNotModified(new CakeRequest));
972
	}
973
 
974
/**
975
 * Test checkNotModified method
976
 *
977
 * @return void
978
 */
979
	public function testCheckNotModifiedByTime() {
980
		$_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
981
		$response = $this->getMock('CakeResponse', array('notModified'));
982
		$response->modified('2012-01-01 00:00:00');
983
		$response->expects($this->once())->method('notModified');
984
		$this->assertTrue($response->checkNotModified(new CakeRequest));
985
	}
986
 
987
/**
988
 * Test checkNotModified method
989
 *
990
 * @return void
991
 */
992
	public function testCheckNotModifiedNoHints() {
993
		$_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
994
		$_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
995
		$response = $this->getMock('CakeResponse', array('notModified'));
996
		$response->expects($this->never())->method('notModified');
997
		$this->assertFalse($response->checkNotModified(new CakeRequest));
998
	}
999
 
1000
/**
1001
 * Test cookie setting
1002
 *
1003
 * @return void
1004
 */
1005
	public function testCookieSettings() {
1006
		$response = new CakeResponse();
1007
		$cookie = array(
1008
			'name' => 'CakeTestCookie[Testing]'
1009
		);
1010
		$response->cookie($cookie);
1011
		$expected = array(
1012
			'name' => 'CakeTestCookie[Testing]',
1013
			'value' => '',
1014
			'expire' => 0,
1015
			'path' => '/',
1016
			'domain' => '',
1017
			'secure' => false,
1018
			'httpOnly' => false);
1019
		$result = $response->cookie('CakeTestCookie[Testing]');
1020
		$this->assertEquals($expected, $result);
1021
 
1022
		$cookie = array(
1023
			'name' => 'CakeTestCookie[Testing2]',
1024
			'value' => '[a,b,c]',
1025
			'expire' => 1000,
1026
			'path' => '/test',
1027
			'secure' => true
1028
		);
1029
		$response->cookie($cookie);
1030
		$expected = array(
1031
			'CakeTestCookie[Testing]' => array(
1032
				'name' => 'CakeTestCookie[Testing]',
1033
				'value' => '',
1034
				'expire' => 0,
1035
				'path' => '/',
1036
				'domain' => '',
1037
				'secure' => false,
1038
				'httpOnly' => false
1039
			),
1040
			'CakeTestCookie[Testing2]' => array(
1041
				'name' => 'CakeTestCookie[Testing2]',
1042
				'value' => '[a,b,c]',
1043
				'expire' => 1000,
1044
				'path' => '/test',
1045
				'domain' => '',
1046
				'secure' => true,
1047
				'httpOnly' => false
1048
			)
1049
		);
1050
 
1051
		$result = $response->cookie();
1052
		$this->assertEquals($expected, $result);
1053
 
1054
		$cookie = $expected['CakeTestCookie[Testing]'];
1055
		$cookie['value'] = 'test';
1056
		$response->cookie($cookie);
1057
		$expected = array(
1058
			'CakeTestCookie[Testing]' => array(
1059
				'name' => 'CakeTestCookie[Testing]',
1060
				'value' => 'test',
1061
				'expire' => 0,
1062
				'path' => '/',
1063
				'domain' => '',
1064
				'secure' => false,
1065
				'httpOnly' => false
1066
			),
1067
			'CakeTestCookie[Testing2]' => array(
1068
				'name' => 'CakeTestCookie[Testing2]',
1069
				'value' => '[a,b,c]',
1070
				'expire' => 1000,
1071
				'path' => '/test',
1072
				'domain' => '',
1073
				'secure' => true,
1074
				'httpOnly' => false
1075
			)
1076
		);
1077
 
1078
		$result = $response->cookie();
1079
		$this->assertEquals($expected, $result);
1080
	}
1081
 
1082
/**
1083
 * Test CORS
1084
 *
1085
 * @dataProvider corsData
1086
 * @param CakeRequest $request
1087
 * @param string $origin
1088
 * @param string|array $domains
1089
 * @param string|array $methods
1090
 * @param string|array $headers
1091
 * @param string|bool $expectedOrigin
1092
 * @param string|bool $expectedMethods
1093
 * @param string|bool $expectedHeaders
1094
 * @return void
1095
 */
1096
	public function testCors($request, $origin, $domains, $methods, $headers, $expectedOrigin, $expectedMethods = false, $expectedHeaders = false) {
1097
		$_SERVER['HTTP_ORIGIN'] = $origin;
1098
 
1099
		$response = $this->getMock('CakeResponse', array('header'));
1100
 
1101
		$method = $response->expects(!$expectedOrigin ? $this->never() : $this->at(0))->method('header');
1102
		$expectedOrigin && $method->with('Access-Control-Allow-Origin', $expectedOrigin ? $expectedOrigin : $this->anything());
1103
 
1104
		$i = 1;
1105
		if ($expectedMethods) {
1106
			$response->expects($this->at($i++))
1107
				->method('header')
1108
				->with('Access-Control-Allow-Methods', $expectedMethods ? $expectedMethods : $this->anything());
1109
		}
1110
		if ($expectedHeaders) {
1111
			$response->expects($this->at($i++))
1112
				->method('header')
1113
				->with('Access-Control-Allow-Headers', $expectedHeaders ? $expectedHeaders : $this->anything());
1114
		}
1115
 
1116
		$response->cors($request, $domains, $methods, $headers);
1117
		unset($_SERVER['HTTP_ORIGIN']);
1118
	}
1119
 
1120
/**
1121
 * Feed for testCors
1122
 *
1123
 * @return array
1124
 */
1125
	public function corsData() {
1126
		$fooRequest = new CakeRequest();
1127
 
1128
		$secureRequest = $this->getMock('CakeRequest', array('is'));
1129
		$secureRequest->expects($this->any())
1130
			->method('is')
1131
			->with('ssl')
1132
			->will($this->returnValue(true));
1133
 
1134
		return array(
1135
			array($fooRequest, null, '*', '', '', false, false),
1136
			array($fooRequest, 'http://www.foo.com', '*', '', '', '*', false),
1137
			array($fooRequest, 'http://www.foo.com', 'www.foo.com', '', '', 'http://www.foo.com', false),
1138
			array($fooRequest, 'http://www.foo.com', '*.foo.com', '', '', 'http://www.foo.com', false),
1139
			array($fooRequest, 'http://www.foo.com', 'http://*.foo.com', '', '', 'http://www.foo.com', false),
1140
			array($fooRequest, 'http://www.foo.com', 'https://www.foo.com', '', '', false, false),
1141
			array($fooRequest, 'http://www.foo.com', 'https://*.foo.com', '', '', false, false),
1142
			array($fooRequest, 'http://www.foo.com', array('*.bar.com', '*.foo.com'), '', '', 'http://www.foo.com', false),
1143
 
1144
			array($secureRequest, 'https://www.bar.com', 'www.bar.com', '', '', 'https://www.bar.com', false),
1145
			array($secureRequest, 'https://www.bar.com', 'http://www.bar.com', '', '', false, false),
1146
			array($secureRequest, 'https://www.bar.com', '*.bar.com', '', '', 'https://www.bar.com', false),
1147
 
1148
			array($fooRequest, 'http://www.foo.com', '*', 'GET', '', '*', 'GET'),
1149
			array($fooRequest, 'http://www.foo.com', '*.foo.com', 'GET', '', 'http://www.foo.com', 'GET'),
1150
			array($fooRequest, 'http://www.foo.com', '*.foo.com', array('GET', 'POST'), '', 'http://www.foo.com', 'GET, POST'),
1151
 
1152
			array($fooRequest, 'http://www.foo.com', '*', '', 'X-CakePHP', '*', false, 'X-CakePHP'),
1153
			array($fooRequest, 'http://www.foo.com', '*', '', array('X-CakePHP', 'X-MyApp'), '*', false, 'X-CakePHP, X-MyApp'),
1154
			array($fooRequest, 'http://www.foo.com', '*', array('GET', 'OPTIONS'), array('X-CakePHP', 'X-MyApp'), '*', 'GET, OPTIONS', 'X-CakePHP, X-MyApp'),
1155
		);
1156
	}
1157
 
1158
/**
1159
 * testFileNotFound
1160
 *
1161
 * @expectedException NotFoundException
1162
 * @return void
1163
 */
1164
	public function testFileNotFound() {
1165
		$response = new CakeResponse();
1166
		$response->file('/some/missing/folder/file.jpg');
1167
	}
1168
 
1169
/**
1170
 * test file with ..
1171
 *
1172
 * @expectedException NotFoundException
1173
 * @expectedExceptionMessage The requested file contains `..` and will not be read.
1174
 * @return void
1175
 */
1176
	public function testFileWithPathTraversal() {
1177
		$response = new CakeResponse();
1178
		$response->file('my/../cat.gif');
1179
	}
1180
 
1181
/**
1182
 * Although unlikely, a file may contain dots in its filename.
1183
 * This should be allowed, as long as the dots doesn't specify a path (../ or ..\)
1184
 *
1185
 * @expectedException NotFoundException
1186
 * @execptedExceptionMessageRegExp #The requested file .+my/Some..cat.gif was not found or not readable#
1187
 * @return void
1188
 */
1189
	public function testFileWithDotsInFilename() {
1190
		$response = new CakeResponse();
1191
		$response->file('my/Some..cat.gif');
1192
	}
1193
 
1194
/**
1195
 * testFile method
1196
 *
1197
 * @return void
1198
 */
1199
	public function testFile() {
1200
		$response = $this->getMock('CakeResponse', array(
1201
			'header',
1202
			'type',
1203
			'_sendHeader',
1204
			'_setContentType',
1205
			'_isActive',
1206
			'_clearBuffer',
1207
			'_flushBuffer'
1208
		));
1209
 
1210
		$response->expects($this->exactly(1))
1211
			->method('type')
1212
			->with('css')
1213
			->will($this->returnArgument(0));
1214
 
1215
		$response->expects($this->at(1))
1216
			->method('header')
1217
			->with('Accept-Ranges', 'bytes');
1218
 
1219
		$response->expects($this->at(2))
1220
			->method('header')
1221
			->with('Content-Length', 38);
1222
 
1223
		$response->expects($this->once())->method('_clearBuffer');
1224
		$response->expects($this->once())->method('_flushBuffer');
1225
 
1226
		$response->expects($this->exactly(1))
1227
			->method('_isActive')
1228
			->will($this->returnValue(true));
1229
 
1230
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css');
1231
 
1232
		ob_start();
1233
		$result = $response->send();
1234
		$output = ob_get_clean();
1235
		$this->assertEquals("/* this is the test asset css file */\n", $output);
1236
		$this->assertNotSame(false, $result);
1237
	}
1238
 
1239
/**
1240
 * testFileWithUnknownFileTypeGeneric method
1241
 *
1242
 * @return void
1243
 */
1244
	public function testFileWithUnknownFileTypeGeneric() {
1245
		$currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
1246
		$_SERVER['HTTP_USER_AGENT'] = 'Some generic browser';
1247
 
1248
		$response = $this->getMock('CakeResponse', array(
1249
			'header',
1250
			'type',
1251
			'download',
1252
			'_sendHeader',
1253
			'_setContentType',
1254
			'_isActive',
1255
			'_clearBuffer',
1256
			'_flushBuffer'
1257
		));
1258
 
1259
		$response->expects($this->exactly(1))
1260
			->method('type')
1261
			->with('ini')
1262
			->will($this->returnValue(false));
1263
 
1264
		$response->expects($this->once())
1265
			->method('download')
1266
			->with('no_section.ini');
1267
 
1268
		$response->expects($this->at(2))
1269
			->method('header')
1270
			->with('Content-Transfer-Encoding', 'binary');
1271
 
1272
		$response->expects($this->at(3))
1273
			->method('header')
1274
			->with('Accept-Ranges', 'bytes');
1275
 
1276
		$response->expects($this->at(4))
1277
			->method('header')
1278
			->with('Content-Length', 35);
1279
 
1280
		$response->expects($this->once())->method('_clearBuffer');
1281
		$response->expects($this->once())->method('_flushBuffer');
1282
 
1283
		$response->expects($this->exactly(1))
1284
			->method('_isActive')
1285
			->will($this->returnValue(true));
1286
 
1287
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini');
1288
 
1289
		ob_start();
1290
		$result = $response->send();
1291
		$output = ob_get_clean();
1292
		$this->assertEquals("some_key = some_value\nbool_key = 1\n", $output);
1293
		$this->assertNotSame(false, $result);
1294
		if ($currentUserAgent !== null) {
1295
			$_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
1296
		}
1297
	}
1298
 
1299
/**
1300
 * testFileWithUnknownFileTypeOpera method
1301
 *
1302
 * @return void
1303
 */
1304
	public function testFileWithUnknownFileTypeOpera() {
1305
		$currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
1306
		$_SERVER['HTTP_USER_AGENT'] = 'Opera/9.80 (Windows NT 6.0; U; en) Presto/2.8.99 Version/11.10';
1307
 
1308
		$response = $this->getMock('CakeResponse', array(
1309
			'header',
1310
			'type',
1311
			'download',
1312
			'_sendHeader',
1313
			'_setContentType',
1314
			'_isActive',
1315
			'_clearBuffer',
1316
			'_flushBuffer'
1317
		));
1318
 
1319
		$response->expects($this->at(0))
1320
			->method('type')
1321
			->with('ini')
1322
			->will($this->returnValue(false));
1323
 
1324
		$response->expects($this->at(1))
1325
			->method('type')
1326
			->with('application/octet-stream')
1327
			->will($this->returnValue(false));
1328
 
1329
		$response->expects($this->once())
1330
			->method('download')
1331
			->with('no_section.ini');
1332
 
1333
		$response->expects($this->at(3))
1334
			->method('header')
1335
			->with('Content-Transfer-Encoding', 'binary');
1336
 
1337
		$response->expects($this->at(4))
1338
			->method('header')
1339
			->with('Accept-Ranges', 'bytes');
1340
 
1341
		$response->expects($this->at(5))
1342
			->method('header')
1343
			->with('Content-Length', 35);
1344
 
1345
		$response->expects($this->once())->method('_clearBuffer');
1346
		$response->expects($this->once())->method('_flushBuffer');
1347
		$response->expects($this->exactly(1))
1348
			->method('_isActive')
1349
			->will($this->returnValue(true));
1350
 
1351
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini');
1352
 
1353
		ob_start();
1354
		$result = $response->send();
1355
		$output = ob_get_clean();
1356
		$this->assertEquals("some_key = some_value\nbool_key = 1\n", $output);
1357
		$this->assertNotSame(false, $result);
1358
		if ($currentUserAgent !== null) {
1359
			$_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
1360
		}
1361
	}
1362
 
1363
/**
1364
 * testFileWithUnknownFileTypeIE method
1365
 *
1366
 * @return void
1367
 */
1368
	public function testFileWithUnknownFileTypeIE() {
1369
		$currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
1370
		$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; Media Center PC 4.0; SLCC1; .NET CLR 3.0.04320)';
1371
 
1372
		$response = $this->getMock('CakeResponse', array(
1373
			'header',
1374
			'type',
1375
			'download',
1376
			'_sendHeader',
1377
			'_setContentType',
1378
			'_isActive',
1379
			'_clearBuffer',
1380
			'_flushBuffer'
1381
		));
1382
 
1383
		$response->expects($this->at(0))
1384
			->method('type')
1385
			->with('ini')
1386
			->will($this->returnValue(false));
1387
 
1388
		$response->expects($this->at(1))
1389
			->method('type')
1390
			->with('application/force-download')
1391
			->will($this->returnValue(false));
1392
 
1393
		$response->expects($this->once())
1394
			->method('download')
1395
			->with('config.ini');
1396
 
1397
		$response->expects($this->at(3))
1398
			->method('header')
1399
			->with('Content-Transfer-Encoding', 'binary');
1400
 
1401
		$response->expects($this->at(4))
1402
			->method('header')
1403
			->with('Accept-Ranges', 'bytes');
1404
 
1405
		$response->expects($this->at(5))
1406
			->method('header')
1407
			->with('Content-Length', 35);
1408
 
1409
		$response->expects($this->once())->method('_clearBuffer');
1410
		$response->expects($this->once())->method('_flushBuffer');
1411
		$response->expects($this->exactly(1))
1412
			->method('_isActive')
1413
			->will($this->returnValue(true));
1414
 
1415
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini', array(
1416
			'name' => 'config.ini'
1417
		));
1418
 
1419
		ob_start();
1420
		$result = $response->send();
1421
		$output = ob_get_clean();
1422
		$this->assertEquals("some_key = some_value\nbool_key = 1\n", $output);
1423
		$this->assertNotSame(false, $result);
1424
		if ($currentUserAgent !== null) {
1425
			$_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
1426
		}
1427
	}
1428
/**
1429
 * testFileWithUnknownFileNoDownload method
1430
 *
1431
 * @return void
1432
 */
1433
	public function testFileWithUnknownFileNoDownload() {
1434
		$currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
1435
		$_SERVER['HTTP_USER_AGENT'] = 'Some generic browser';
1436
 
1437
		$response = $this->getMock('CakeResponse', array(
1438
			'header',
1439
			'type',
1440
			'download',
1441
			'_sendHeader',
1442
			'_setContentType',
1443
			'_isActive',
1444
			'_clearBuffer',
1445
			'_flushBuffer'
1446
		));
1447
 
1448
		$response->expects($this->exactly(1))
1449
			->method('type')
1450
			->with('ini')
1451
			->will($this->returnValue(false));
1452
 
1453
		$response->expects($this->at(1))
1454
			->method('header')
1455
			->with('Accept-Ranges', 'bytes');
1456
 
1457
		$response->expects($this->never())
1458
			->method('download');
1459
 
1460
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini', array(
1461
			'download' => false
1462
		));
1463
 
1464
		if ($currentUserAgent !== null) {
1465
			$_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
1466
		}
1467
	}
1468
 
1469
/**
1470
 * testConnectionAbortedOnBuffering method
1471
 *
1472
 * @return void
1473
 */
1474
	public function testConnectionAbortedOnBuffering() {
1475
		$response = $this->getMock('CakeResponse', array(
1476
			'header',
1477
			'type',
1478
			'download',
1479
			'_sendHeader',
1480
			'_setContentType',
1481
			'_isActive',
1482
			'_clearBuffer',
1483
			'_flushBuffer'
1484
		));
1485
 
1486
		$response->expects($this->any())
1487
			->method('type')
1488
			->with('css')
1489
			->will($this->returnArgument(0));
1490
 
1491
		$response->expects($this->at(0))
1492
			->method('_isActive')
1493
			->will($this->returnValue(false));
1494
 
1495
		$response->expects($this->once())->method('_clearBuffer');
1496
		$response->expects($this->never())->method('_flushBuffer');
1497
 
1498
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css');
1499
 
1500
		$result = $response->send();
1501
		$this->assertNull($result);
1502
	}
1503
 
1504
/**
1505
 * Test downloading files with UPPERCASE extensions.
1506
 *
1507
 * @return void
1508
 */
1509
	public function testFileUpperExtension() {
1510
		$response = $this->getMock('CakeResponse', array(
1511
			'header',
1512
			'type',
1513
			'download',
1514
			'_sendHeader',
1515
			'_setContentType',
1516
			'_isActive',
1517
			'_clearBuffer',
1518
			'_flushBuffer'
1519
		));
1520
 
1521
		$response->expects($this->any())
1522
			->method('type')
1523
			->with('jpg')
1524
			->will($this->returnArgument(0));
1525
 
1526
		$response->expects($this->at(0))
1527
			->method('_isActive')
1528
			->will($this->returnValue(true));
1529
 
1530
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'img' . DS . 'test_2.JPG');
1531
	}
1532
 
1533
/**
1534
 * Test downloading files with extension not explicitly set.
1535
 *
1536
 * @return void
1537
 */
1538
	public function testFileExtensionNotSet() {
1539
		$response = $this->getMock('CakeResponse', array(
1540
			'header',
1541
			'type',
1542
			'download',
1543
			'_sendHeader',
1544
			'_setContentType',
1545
			'_isActive',
1546
			'_clearBuffer',
1547
			'_flushBuffer'
1548
		));
1549
 
1550
		$response->expects($this->any())
1551
			->method('type')
1552
			->with('jpg')
1553
			->will($this->returnArgument(0));
1554
 
1555
		$response->expects($this->at(0))
1556
			->method('_isActive')
1557
			->will($this->returnValue(true));
1558
 
1559
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'img' . DS . 'test_2.JPG');
1560
	}
1561
 
1562
/**
1563
 * A data provider for testing various ranges
1564
 *
1565
 * @return array
1566
 */
1567
	public static function rangeProvider() {
1568
		return array(
1569
			// suffix-byte-range
1570
			array(
1571
				'bytes=-25', 25, 'bytes 13-37/38'
1572
			),
1573
 
1574
			array(
1575
				'bytes=0-', 38, 'bytes 0-37/38'
1576
			),
1577
			array(
1578
				'bytes=10-', 28, 'bytes 10-37/38'
1579
			),
1580
			array(
1581
				'bytes=10-20', 11, 'bytes 10-20/38'
1582
			),
1583
		);
1584
	}
1585
 
1586
/**
1587
 * Test the various range offset types.
1588
 *
1589
 * @dataProvider rangeProvider
1590
 * @return void
1591
 */
1592
	public function testFileRangeOffsets($range, $length, $offsetResponse) {
1593
		$_SERVER['HTTP_RANGE'] = $range;
1594
		$response = $this->getMock('CakeResponse', array(
1595
			'header',
1596
			'type',
1597
			'_sendHeader',
1598
			'_isActive',
1599
			'_clearBuffer',
1600
			'_flushBuffer'
1601
		));
1602
 
1603
		$response->expects($this->at(1))
1604
			->method('header')
1605
			->with('Content-Disposition', 'attachment; filename="test_asset.css"');
1606
 
1607
		$response->expects($this->at(2))
1608
			->method('header')
1609
			->with('Content-Transfer-Encoding', 'binary');
1610
 
1611
		$response->expects($this->at(3))
1612
			->method('header')
1613
			->with('Accept-Ranges', 'bytes');
1614
 
1615
		$response->expects($this->at(4))
1616
			->method('header')
1617
			->with(array(
1618
				'Content-Length' => $length,
1619
				'Content-Range' => $offsetResponse,
1620
			));
1621
 
1622
		$response->expects($this->any())
1623
			->method('_isActive')
1624
			->will($this->returnValue(true));
1625
 
1626
		$response->file(
1627
			CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1628
			array('download' => true)
1629
		);
1630
 
1631
		ob_start();
1632
		$result = $response->send();
1633
		ob_get_clean();
1634
	}
1635
 
1636
/**
1637
 * Test fetching ranges from a file.
1638
 *
1639
 * @return void
1640
 */
1641
	public function testFileRange() {
1642
		$_SERVER['HTTP_RANGE'] = 'bytes=8-25';
1643
		$response = $this->getMock('CakeResponse', array(
1644
			'header',
1645
			'type',
1646
			'_sendHeader',
1647
			'_setContentType',
1648
			'_isActive',
1649
			'_clearBuffer',
1650
			'_flushBuffer'
1651
		));
1652
 
1653
		$response->expects($this->exactly(1))
1654
			->method('type')
1655
			->with('css')
1656
			->will($this->returnArgument(0));
1657
 
1658
		$response->expects($this->at(1))
1659
			->method('header')
1660
			->with('Content-Disposition', 'attachment; filename="test_asset.css"');
1661
 
1662
		$response->expects($this->at(2))
1663
			->method('header')
1664
			->with('Content-Transfer-Encoding', 'binary');
1665
 
1666
		$response->expects($this->at(3))
1667
			->method('header')
1668
			->with('Accept-Ranges', 'bytes');
1669
 
1670
		$response->expects($this->at(4))
1671
			->method('header')
1672
			->with(array(
1673
				'Content-Length' => 18,
1674
				'Content-Range' => 'bytes 8-25/38',
1675
			));
1676
 
1677
		$response->expects($this->once())->method('_clearBuffer');
1678
 
1679
		$response->expects($this->any())
1680
			->method('_isActive')
1681
			->will($this->returnValue(true));
1682
 
1683
		$response->file(
1684
			CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1685
			array('download' => true)
1686
		);
1687
 
1688
		ob_start();
1689
		$result = $response->send();
1690
		$output = ob_get_clean();
1691
		$this->assertEquals(206, $response->statusCode());
1692
		$this->assertEquals("is the test asset ", $output);
1693
		$this->assertNotSame(false, $result);
1694
	}
1695
 
1696
/**
1697
 * Test invalid file ranges.
1698
 *
1699
 * @return void
1700
 */
1701
	public function testFileRangeInvalid() {
1702
		$_SERVER['HTTP_RANGE'] = 'bytes=30-2';
1703
		$response = $this->getMock('CakeResponse', array(
1704
			'header',
1705
			'type',
1706
			'_sendHeader',
1707
			'_setContentType',
1708
			'_isActive',
1709
			'_clearBuffer',
1710
			'_flushBuffer'
1711
		));
1712
 
1713
		$response->expects($this->at(1))
1714
			->method('header')
1715
			->with('Content-Disposition', 'attachment; filename="test_asset.css"');
1716
 
1717
		$response->expects($this->at(2))
1718
			->method('header')
1719
			->with('Content-Transfer-Encoding', 'binary');
1720
 
1721
		$response->expects($this->at(3))
1722
			->method('header')
1723
			->with('Accept-Ranges', 'bytes');
1724
 
1725
		$response->expects($this->at(4))
1726
			->method('header')
1727
			->with(array(
1728
				'Content-Range' => 'bytes 0-37/38',
1729
			));
1730
 
1731
		$response->file(
1732
			CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1733
			array('download' => true)
1734
		);
1735
 
1736
		$this->assertEquals(416, $response->statusCode());
1737
		$result = $response->send();
1738
	}
1739
 
1740
/**
1741
 * testFileRangeOffsetsNoDownload method
1742
 *
1743
 * @dataProvider rangeProvider
1744
 * @return void
1745
 */
1746
	public function testFileRangeOffsetsNoDownload($range, $length, $offsetResponse) {
1747
		$_SERVER['HTTP_RANGE'] = $range;
1748
		$response = $this->getMock('CakeResponse', array(
1749
			'header',
1750
			'type',
1751
			'_sendHeader',
1752
			'_isActive',
1753
			'_clearBuffer',
1754
			'_flushBuffer'
1755
		));
1756
 
1757
		$response->expects($this->at(1))
1758
			->method('header')
1759
			->with('Accept-Ranges', 'bytes');
1760
 
1761
		$response->expects($this->at(2))
1762
			->method('header')
1763
			->with(array(
1764
				'Content-Length' => $length,
1765
				'Content-Range' => $offsetResponse,
1766
			));
1767
 
1768
		$response->expects($this->any())
1769
			->method('_isActive')
1770
			->will($this->returnValue(true));
1771
 
1772
		$response->file(
1773
			CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1774
			array('download' => false)
1775
		);
1776
 
1777
		ob_start();
1778
		$result = $response->send();
1779
		ob_get_clean();
1780
	}
1781
 
1782
/**
1783
 * testFileRangeNoDownload method
1784
 *
1785
 * @return void
1786
 */
1787
	public function testFileRangeNoDownload() {
1788
		$_SERVER['HTTP_RANGE'] = 'bytes=8-25';
1789
		$response = $this->getMock('CakeResponse', array(
1790
			'header',
1791
			'type',
1792
			'_sendHeader',
1793
			'_setContentType',
1794
			'_isActive',
1795
			'_clearBuffer',
1796
			'_flushBuffer'
1797
		));
1798
 
1799
		$response->expects($this->exactly(1))
1800
			->method('type')
1801
			->with('css')
1802
			->will($this->returnArgument(0));
1803
 
1804
		$response->expects($this->at(1))
1805
			->method('header')
1806
			->with('Accept-Ranges', 'bytes');
1807
 
1808
		$response->expects($this->at(2))
1809
			->method('header')
1810
			->with(array(
1811
				'Content-Length' => 18,
1812
				'Content-Range' => 'bytes 8-25/38',
1813
			));
1814
 
1815
		$response->expects($this->once())->method('_clearBuffer');
1816
 
1817
		$response->expects($this->any())
1818
			->method('_isActive')
1819
			->will($this->returnValue(true));
1820
 
1821
		$response->file(
1822
			CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1823
			array('download' => false)
1824
		);
1825
 
1826
		ob_start();
1827
		$result = $response->send();
1828
		$output = ob_get_clean();
1829
		$this->assertEquals(206, $response->statusCode());
1830
		$this->assertEquals("is the test asset ", $output);
1831
		$this->assertNotSame(false, $result);
1832
	}
1833
 
1834
/**
1835
 * testFileRangeInvalidNoDownload method
1836
 *
1837
 * @return void
1838
 */
1839
	public function testFileRangeInvalidNoDownload() {
1840
		$_SERVER['HTTP_RANGE'] = 'bytes=30-2';
1841
		$response = $this->getMock('CakeResponse', array(
1842
			'header',
1843
			'type',
1844
			'_sendHeader',
1845
			'_setContentType',
1846
			'_isActive',
1847
			'_clearBuffer',
1848
			'_flushBuffer'
1849
		));
1850
 
1851
		$response->expects($this->at(1))
1852
			->method('header')
1853
			->with('Accept-Ranges', 'bytes');
1854
 
1855
		$response->expects($this->at(2))
1856
			->method('header')
1857
			->with(array(
1858
				'Content-Range' => 'bytes 0-37/38',
1859
			));
1860
 
1861
		$response->file(
1862
			CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1863
			array('download' => false)
1864
		);
1865
 
1866
		$this->assertEquals(416, $response->statusCode());
1867
		$result = $response->send();
1868
	}
1869
 
1870
/**
1871
 * Test the location method.
1872
 *
1873
 * @return void
1874
 */
1875
	public function testLocation() {
1876
		$response = new CakeResponse();
1877
		$this->assertNull($response->location(), 'No header should be set.');
1878
		$this->assertNull($response->location('http://example.org'), 'Setting a location should return null');
1879
		$this->assertEquals('http://example.org', $response->location(), 'Reading a location should return the value.');
1880
	}
1881
 
1882
}