Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
12345 anikendra 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(40, 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(42, 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(42, 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
 * @return void
1174
 */
1175
	public function testFileWithPathTraversal() {
1176
		$response = new CakeResponse();
1177
		$response->file('my/../cat.gif');
1178
	}
1179
 
1180
/**
1181
 * testFile method
1182
 *
1183
 * @return void
1184
 */
1185
	public function testFile() {
1186
		$response = $this->getMock('CakeResponse', array(
1187
			'header',
1188
			'type',
1189
			'_sendHeader',
1190
			'_setContentType',
1191
			'_isActive',
1192
			'_clearBuffer',
1193
			'_flushBuffer'
1194
		));
1195
 
1196
		$response->expects($this->exactly(1))
1197
			->method('type')
1198
			->with('css')
1199
			->will($this->returnArgument(0));
1200
 
1201
		$response->expects($this->at(1))
1202
			->method('header')
1203
			->with('Content-Length', 38);
1204
 
1205
		$response->expects($this->once())->method('_clearBuffer');
1206
		$response->expects($this->once())->method('_flushBuffer');
1207
 
1208
		$response->expects($this->exactly(1))
1209
			->method('_isActive')
1210
			->will($this->returnValue(true));
1211
 
1212
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css');
1213
 
1214
		ob_start();
1215
		$result = $response->send();
1216
		$output = ob_get_clean();
1217
		$this->assertEquals("/* this is the test asset css file */\n", $output);
1218
		$this->assertTrue($result !== false);
1219
	}
1220
 
1221
/**
1222
 * testFileWithUnknownFileTypeGeneric method
1223
 *
1224
 * @return void
1225
 */
1226
	public function testFileWithUnknownFileTypeGeneric() {
1227
		$currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
1228
		$_SERVER['HTTP_USER_AGENT'] = 'Some generic browser';
1229
 
1230
		$response = $this->getMock('CakeResponse', array(
1231
			'header',
1232
			'type',
1233
			'download',
1234
			'_sendHeader',
1235
			'_setContentType',
1236
			'_isActive',
1237
			'_clearBuffer',
1238
			'_flushBuffer'
1239
		));
1240
 
1241
		$response->expects($this->exactly(1))
1242
			->method('type')
1243
			->with('ini')
1244
			->will($this->returnValue(false));
1245
 
1246
		$response->expects($this->once())
1247
			->method('download')
1248
			->with('no_section.ini');
1249
 
1250
		$response->expects($this->at(2))
1251
			->method('header')
1252
			->with('Accept-Ranges', 'bytes');
1253
 
1254
		$response->expects($this->at(3))
1255
			->method('header')
1256
			->with('Content-Transfer-Encoding', 'binary');
1257
 
1258
		$response->expects($this->at(4))
1259
			->method('header')
1260
			->with('Content-Length', 35);
1261
 
1262
		$response->expects($this->once())->method('_clearBuffer');
1263
		$response->expects($this->once())->method('_flushBuffer');
1264
 
1265
		$response->expects($this->exactly(1))
1266
			->method('_isActive')
1267
			->will($this->returnValue(true));
1268
 
1269
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini');
1270
 
1271
		ob_start();
1272
		$result = $response->send();
1273
		$output = ob_get_clean();
1274
		$this->assertEquals("some_key = some_value\nbool_key = 1\n", $output);
1275
		$this->assertTrue($result !== false);
1276
		if ($currentUserAgent !== null) {
1277
			$_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
1278
		}
1279
	}
1280
 
1281
/**
1282
 * testFileWithUnknownFileTypeOpera method
1283
 *
1284
 * @return void
1285
 */
1286
	public function testFileWithUnknownFileTypeOpera() {
1287
		$currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
1288
		$_SERVER['HTTP_USER_AGENT'] = 'Opera/9.80 (Windows NT 6.0; U; en) Presto/2.8.99 Version/11.10';
1289
 
1290
		$response = $this->getMock('CakeResponse', array(
1291
			'header',
1292
			'type',
1293
			'download',
1294
			'_sendHeader',
1295
			'_setContentType',
1296
			'_isActive',
1297
			'_clearBuffer',
1298
			'_flushBuffer'
1299
		));
1300
 
1301
		$response->expects($this->at(0))
1302
			->method('type')
1303
			->with('ini')
1304
			->will($this->returnValue(false));
1305
 
1306
		$response->expects($this->at(1))
1307
			->method('type')
1308
			->with('application/octet-stream')
1309
			->will($this->returnValue(false));
1310
 
1311
		$response->expects($this->once())
1312
			->method('download')
1313
			->with('no_section.ini');
1314
 
1315
		$response->expects($this->at(3))
1316
			->method('header')
1317
			->with('Accept-Ranges', 'bytes');
1318
 
1319
		$response->expects($this->at(4))
1320
			->method('header')
1321
			->with('Content-Transfer-Encoding', 'binary');
1322
 
1323
		$response->expects($this->at(5))
1324
			->method('header')
1325
			->with('Content-Length', 35);
1326
 
1327
		$response->expects($this->once())->method('_clearBuffer');
1328
		$response->expects($this->once())->method('_flushBuffer');
1329
		$response->expects($this->exactly(1))
1330
			->method('_isActive')
1331
			->will($this->returnValue(true));
1332
 
1333
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini');
1334
 
1335
		ob_start();
1336
		$result = $response->send();
1337
		$output = ob_get_clean();
1338
		$this->assertEquals("some_key = some_value\nbool_key = 1\n", $output);
1339
		$this->assertTrue($result !== false);
1340
		if ($currentUserAgent !== null) {
1341
			$_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
1342
		}
1343
	}
1344
 
1345
/**
1346
 * testFileWithUnknownFileTypeIE method
1347
 *
1348
 * @return void
1349
 */
1350
	public function testFileWithUnknownFileTypeIE() {
1351
		$currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
1352
		$_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)';
1353
 
1354
		$response = $this->getMock('CakeResponse', array(
1355
			'header',
1356
			'type',
1357
			'download',
1358
			'_sendHeader',
1359
			'_setContentType',
1360
			'_isActive',
1361
			'_clearBuffer',
1362
			'_flushBuffer'
1363
		));
1364
 
1365
		$response->expects($this->at(0))
1366
			->method('type')
1367
			->with('ini')
1368
			->will($this->returnValue(false));
1369
 
1370
		$response->expects($this->at(1))
1371
			->method('type')
1372
			->with('application/force-download')
1373
			->will($this->returnValue(false));
1374
 
1375
		$response->expects($this->once())
1376
			->method('download')
1377
			->with('config.ini');
1378
 
1379
		$response->expects($this->at(3))
1380
			->method('header')
1381
			->with('Accept-Ranges', 'bytes');
1382
 
1383
		$response->expects($this->at(4))
1384
			->method('header')
1385
			->with('Content-Transfer-Encoding', 'binary');
1386
 
1387
		$response->expects($this->at(5))
1388
			->method('header')
1389
			->with('Content-Length', 35);
1390
 
1391
		$response->expects($this->once())->method('_clearBuffer');
1392
		$response->expects($this->once())->method('_flushBuffer');
1393
		$response->expects($this->exactly(1))
1394
			->method('_isActive')
1395
			->will($this->returnValue(true));
1396
 
1397
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini', array(
1398
			'name' => 'config.ini'
1399
		));
1400
 
1401
		ob_start();
1402
		$result = $response->send();
1403
		$output = ob_get_clean();
1404
		$this->assertEquals("some_key = some_value\nbool_key = 1\n", $output);
1405
		$this->assertTrue($result !== false);
1406
		if ($currentUserAgent !== null) {
1407
			$_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
1408
		}
1409
	}
1410
/**
1411
 * testFileWithUnknownFileNoDownload method
1412
 *
1413
 * @return void
1414
 */
1415
	public function testFileWithUnknownFileNoDownload() {
1416
		$currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
1417
		$_SERVER['HTTP_USER_AGENT'] = 'Some generic browser';
1418
 
1419
		$response = $this->getMock('CakeResponse', array(
1420
			'header',
1421
			'type',
1422
			'download',
1423
			'_sendHeader',
1424
			'_setContentType',
1425
			'_isActive',
1426
			'_clearBuffer',
1427
			'_flushBuffer'
1428
		));
1429
 
1430
		$response->expects($this->exactly(1))
1431
			->method('type')
1432
			->with('ini')
1433
			->will($this->returnValue(false));
1434
 
1435
		$response->expects($this->never())
1436
			->method('download');
1437
 
1438
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini', array(
1439
			'download' => false
1440
		));
1441
 
1442
		if ($currentUserAgent !== null) {
1443
			$_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
1444
		}
1445
	}
1446
 
1447
/**
1448
 * testConnectionAbortedOnBuffering method
1449
 *
1450
 * @return void
1451
 */
1452
	public function testConnectionAbortedOnBuffering() {
1453
		$response = $this->getMock('CakeResponse', array(
1454
			'header',
1455
			'type',
1456
			'download',
1457
			'_sendHeader',
1458
			'_setContentType',
1459
			'_isActive',
1460
			'_clearBuffer',
1461
			'_flushBuffer'
1462
		));
1463
 
1464
		$response->expects($this->any())
1465
			->method('type')
1466
			->with('css')
1467
			->will($this->returnArgument(0));
1468
 
1469
		$response->expects($this->at(0))
1470
			->method('_isActive')
1471
			->will($this->returnValue(false));
1472
 
1473
		$response->expects($this->once())->method('_clearBuffer');
1474
		$response->expects($this->never())->method('_flushBuffer');
1475
 
1476
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css');
1477
 
1478
		$result = $response->send();
1479
		$this->assertNull($result);
1480
	}
1481
 
1482
/**
1483
 * Test downloading files with UPPERCASE extensions.
1484
 *
1485
 * @return void
1486
 */
1487
	public function testFileUpperExtension() {
1488
		$response = $this->getMock('CakeResponse', array(
1489
			'header',
1490
			'type',
1491
			'download',
1492
			'_sendHeader',
1493
			'_setContentType',
1494
			'_isActive',
1495
			'_clearBuffer',
1496
			'_flushBuffer'
1497
		));
1498
 
1499
		$response->expects($this->any())
1500
			->method('type')
1501
			->with('jpg')
1502
			->will($this->returnArgument(0));
1503
 
1504
		$response->expects($this->at(0))
1505
			->method('_isActive')
1506
			->will($this->returnValue(true));
1507
 
1508
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'img' . DS . 'test_2.JPG');
1509
	}
1510
 
1511
/**
1512
 * Test downloading files with extension not explicitly set.
1513
 *
1514
 * @return void
1515
 */
1516
	public function testFileExtensionNotSet() {
1517
		$response = $this->getMock('CakeResponse', array(
1518
			'header',
1519
			'type',
1520
			'download',
1521
			'_sendHeader',
1522
			'_setContentType',
1523
			'_isActive',
1524
			'_clearBuffer',
1525
			'_flushBuffer'
1526
		));
1527
 
1528
		$response->expects($this->any())
1529
			->method('type')
1530
			->with('jpg')
1531
			->will($this->returnArgument(0));
1532
 
1533
		$response->expects($this->at(0))
1534
			->method('_isActive')
1535
			->will($this->returnValue(true));
1536
 
1537
		$response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'img' . DS . 'test_2.JPG');
1538
	}
1539
 
1540
/**
1541
 * A data provider for testing various ranges
1542
 *
1543
 * @return array
1544
 */
1545
	public static function rangeProvider() {
1546
		return array(
1547
			// suffix-byte-range
1548
			array(
1549
				'bytes=-25', 25, 'bytes 13-37/38'
1550
			),
1551
 
1552
			array(
1553
				'bytes=0-', 38, 'bytes 0-37/38'
1554
			),
1555
			array(
1556
				'bytes=10-', 28, 'bytes 10-37/38'
1557
			),
1558
			array(
1559
				'bytes=10-20', 11, 'bytes 10-20/38'
1560
			),
1561
		);
1562
	}
1563
 
1564
/**
1565
 * Test the various range offset types.
1566
 *
1567
 * @dataProvider rangeProvider
1568
 * @return void
1569
 */
1570
	public function testFileRangeOffsets($range, $length, $offsetResponse) {
1571
		$_SERVER['HTTP_RANGE'] = $range;
1572
		$response = $this->getMock('CakeResponse', array(
1573
			'header',
1574
			'type',
1575
			'_sendHeader',
1576
			'_isActive',
1577
			'_clearBuffer',
1578
			'_flushBuffer'
1579
		));
1580
 
1581
		$response->expects($this->at(1))
1582
			->method('header')
1583
			->with('Content-Disposition', 'attachment; filename="test_asset.css"');
1584
 
1585
		$response->expects($this->at(2))
1586
			->method('header')
1587
			->with('Accept-Ranges', 'bytes');
1588
 
1589
		$response->expects($this->at(3))
1590
			->method('header')
1591
			->with('Content-Transfer-Encoding', 'binary');
1592
 
1593
		$response->expects($this->at(4))
1594
			->method('header')
1595
			->with(array(
1596
				'Content-Length' => $length,
1597
				'Content-Range' => $offsetResponse,
1598
			));
1599
 
1600
		$response->expects($this->any())
1601
			->method('_isActive')
1602
			->will($this->returnValue(true));
1603
 
1604
		$response->file(
1605
			CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1606
			array('download' => true)
1607
		);
1608
 
1609
		ob_start();
1610
		$result = $response->send();
1611
		ob_get_clean();
1612
	}
1613
 
1614
/**
1615
 * Test fetching ranges from a file.
1616
 *
1617
 * @return void
1618
 */
1619
	public function testFileRange() {
1620
		$_SERVER['HTTP_RANGE'] = 'bytes=8-25';
1621
		$response = $this->getMock('CakeResponse', array(
1622
			'header',
1623
			'type',
1624
			'_sendHeader',
1625
			'_setContentType',
1626
			'_isActive',
1627
			'_clearBuffer',
1628
			'_flushBuffer'
1629
		));
1630
 
1631
		$response->expects($this->exactly(1))
1632
			->method('type')
1633
			->with('css')
1634
			->will($this->returnArgument(0));
1635
 
1636
		$response->expects($this->at(1))
1637
			->method('header')
1638
			->with('Content-Disposition', 'attachment; filename="test_asset.css"');
1639
 
1640
		$response->expects($this->at(2))
1641
			->method('header')
1642
			->with('Accept-Ranges', 'bytes');
1643
 
1644
		$response->expects($this->at(3))
1645
			->method('header')
1646
			->with('Content-Transfer-Encoding', 'binary');
1647
 
1648
		$response->expects($this->at(4))
1649
			->method('header')
1650
			->with(array(
1651
				'Content-Length' => 18,
1652
				'Content-Range' => 'bytes 8-25/38',
1653
			));
1654
 
1655
		$response->expects($this->once())->method('_clearBuffer');
1656
 
1657
		$response->expects($this->any())
1658
			->method('_isActive')
1659
			->will($this->returnValue(true));
1660
 
1661
		$response->file(
1662
			CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1663
			array('download' => true)
1664
		);
1665
 
1666
		ob_start();
1667
		$result = $response->send();
1668
		$output = ob_get_clean();
1669
		$this->assertEquals(206, $response->statusCode());
1670
		$this->assertEquals("is the test asset ", $output);
1671
		$this->assertTrue($result !== false);
1672
	}
1673
 
1674
/**
1675
 * Test invalid file ranges.
1676
 *
1677
 * @return void
1678
 */
1679
	public function testFileRangeInvalid() {
1680
		$_SERVER['HTTP_RANGE'] = 'bytes=30-2';
1681
		$response = $this->getMock('CakeResponse', array(
1682
			'header',
1683
			'type',
1684
			'_sendHeader',
1685
			'_setContentType',
1686
			'_isActive',
1687
			'_clearBuffer',
1688
			'_flushBuffer'
1689
		));
1690
 
1691
		$response->expects($this->at(1))
1692
			->method('header')
1693
			->with('Content-Disposition', 'attachment; filename="test_asset.css"');
1694
 
1695
		$response->expects($this->at(2))
1696
			->method('header')
1697
			->with('Accept-Ranges', 'bytes');
1698
 
1699
		$response->expects($this->at(3))
1700
			->method('header')
1701
			->with('Content-Transfer-Encoding', 'binary');
1702
 
1703
		$response->expects($this->at(4))
1704
			->method('header')
1705
			->with(array(
1706
				'Content-Range' => 'bytes 0-37/38',
1707
			));
1708
 
1709
		$response->file(
1710
			CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1711
			array('download' => true)
1712
		);
1713
 
1714
		$this->assertEquals(416, $response->statusCode());
1715
		$result = $response->send();
1716
	}
1717
 
1718
/**
1719
 * Test the location method.
1720
 *
1721
 * @return void
1722
 */
1723
	public function testLocation() {
1724
		$response = new CakeResponse();
1725
		$this->assertNull($response->location(), 'No header should be set.');
1726
		$this->assertNull($response->location('http://example.org'), 'Setting a location should return null');
1727
		$this->assertEquals('http://example.org', $response->location(), 'Reading a location should return the value.');
1728
	}
1729
 
1730
}