~artur-barczynski/azsystem/trunk

« back to all changes in this revision

Viewing changes to lib/Cake/Test/Case/Error/ExceptionRendererTest.php

  • Committer: Artur Barczynski
  • Date: 2012-09-20 16:31:07 UTC
  • Revision ID: artur@arturkb.pl-20120920163107-oakeg1a4h9e6d37f
Init

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * ExceptionRendererTest file
 
4
 *
 
5
 * PHP 5
 
6
 *
 
7
 * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
 
8
 * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
 
9
 *
 
10
 * Licensed under The MIT License
 
11
 * Redistributions of files must retain the above copyright notice
 
12
 *
 
13
 * @copyright     Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
 
14
 * @link          http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
 
15
 * @package       Cake.Test.Case.Error
 
16
 * @since         CakePHP(tm) v 2.0
 
17
 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
 
18
 */
 
19
 
 
20
App::uses('ExceptionRenderer', 'Error');
 
21
App::uses('Controller', 'Controller');
 
22
App::uses('AppController', 'Controller');
 
23
App::uses('Component', 'Controller');
 
24
App::uses('Router', 'Routing');
 
25
 
 
26
/**
 
27
 * Short description for class.
 
28
 *
 
29
 * @package       Cake.Test.Case.Error
 
30
 */
 
31
class AuthBlueberryUser extends CakeTestModel {
 
32
 
 
33
/**
 
34
 * name property
 
35
 *
 
36
 * @var string 'AuthBlueberryUser'
 
37
 */
 
38
        public $name = 'AuthBlueberryUser';
 
39
 
 
40
/**
 
41
 * useTable property
 
42
 *
 
43
 * @var string
 
44
 */
 
45
        public $useTable = false;
 
46
}
 
47
 
 
48
/**
 
49
 * BlueberryComponent class
 
50
 *
 
51
 * @package       Cake.Test.Case.Error
 
52
 */
 
53
class BlueberryComponent extends Component {
 
54
 
 
55
/**
 
56
 * testName property
 
57
 *
 
58
 * @return void
 
59
 */
 
60
        public $testName = null;
 
61
 
 
62
/**
 
63
 * initialize method
 
64
 *
 
65
 * @return void
 
66
 */
 
67
        public function initialize(Controller $controller) {
 
68
                $this->testName = 'BlueberryComponent';
 
69
        }
 
70
 
 
71
}
 
72
 
 
73
/**
 
74
 * TestErrorController class
 
75
 *
 
76
 * @package       Cake.Test.Case.Error
 
77
 */
 
78
class TestErrorController extends Controller {
 
79
 
 
80
/**
 
81
 * uses property
 
82
 *
 
83
 * @var array
 
84
 */
 
85
        public $uses = array();
 
86
 
 
87
/**
 
88
 * components property
 
89
 *
 
90
 * @return void
 
91
 */
 
92
        public $components = array('Blueberry');
 
93
 
 
94
/**
 
95
 * beforeRender method
 
96
 *
 
97
 * @return void
 
98
 */
 
99
        public function beforeRender() {
 
100
                echo $this->Blueberry->testName;
 
101
        }
 
102
 
 
103
/**
 
104
 * index method
 
105
 *
 
106
 * @return void
 
107
 */
 
108
        public function index() {
 
109
                $this->autoRender = false;
 
110
                return 'what up';
 
111
        }
 
112
 
 
113
}
 
114
 
 
115
/**
 
116
 * MyCustomExceptionRenderer class
 
117
 *
 
118
 * @package       Cake.Test.Case.Error
 
119
 */
 
120
class MyCustomExceptionRenderer extends ExceptionRenderer {
 
121
 
 
122
/**
 
123
 * custom error message type.
 
124
 *
 
125
 * @return void
 
126
 */
 
127
        public function missingWidgetThing() {
 
128
                echo 'widget thing is missing';
 
129
        }
 
130
 
 
131
}
 
132
 
 
133
/**
 
134
 * Exception class for testing app error handlers and custom errors.
 
135
 *
 
136
 * @package       Cake.Test.Case.Error
 
137
 */
 
138
class MissingWidgetThingException extends NotFoundException {
 
139
}
 
140
 
 
141
 
 
142
/**
 
143
 * ExceptionRendererTest class
 
144
 *
 
145
 * @package       Cake.Test.Case.Error
 
146
 */
 
147
class ExceptionRendererTest extends CakeTestCase {
 
148
 
 
149
        protected $_restoreError = false;
 
150
 
 
151
/**
 
152
 * setup create a request object to get out of router later.
 
153
 *
 
154
 * @return void
 
155
 */
 
156
        public function setUp() {
 
157
                parent::setUp();
 
158
                App::build(array(
 
159
                        'View' => array(
 
160
                                CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS
 
161
                        )
 
162
                ), App::RESET);
 
163
                Router::reload();
 
164
 
 
165
                $request = new CakeRequest(null, false);
 
166
                $request->base = '';
 
167
                Router::setRequestInfo($request);
 
168
                Configure::write('debug', 2);
 
169
        }
 
170
 
 
171
/**
 
172
 * tearDown
 
173
 *
 
174
 * @return void
 
175
 */
 
176
        public function tearDown() {
 
177
                parent::tearDown();
 
178
                if ($this->_restoreError) {
 
179
                        restore_error_handler();
 
180
                }
 
181
        }
 
182
 
 
183
/**
 
184
 * Mocks out the response on the ExceptionRenderer object so headers aren't modified.
 
185
 *
 
186
 * @return void
 
187
 */
 
188
        protected function _mockResponse($error) {
 
189
                $error->controller->response = $this->getMock('CakeResponse', array('_sendHeader'));
 
190
                return $error;
 
191
        }
 
192
 
 
193
/**
 
194
 * test that methods declared in an ExceptionRenderer subclass are not converted
 
195
 * into error400 when debug > 0
 
196
 *
 
197
 * @return void
 
198
 */
 
199
        public function testSubclassMethodsNotBeingConvertedToError() {
 
200
                Configure::write('debug', 2);
 
201
 
 
202
                $exception = new MissingWidgetThingException('Widget not found');
 
203
                $ExceptionRenderer = $this->_mockResponse(new MyCustomExceptionRenderer($exception));
 
204
 
 
205
                ob_start();
 
206
                $ExceptionRenderer->render();
 
207
                $result = ob_get_clean();
 
208
 
 
209
                $this->assertEquals('widget thing is missing', $result);
 
210
        }
 
211
 
 
212
/**
 
213
 * test that subclass methods are not converted when debug = 0
 
214
 *
 
215
 * @return void
 
216
 */
 
217
        public function testSubclassMethodsNotBeingConvertedDebug0() {
 
218
                Configure::write('debug', 0);
 
219
                $exception = new MissingWidgetThingException('Widget not found');
 
220
                $ExceptionRenderer = $this->_mockResponse(new MyCustomExceptionRenderer($exception));
 
221
 
 
222
                $this->assertEquals('missingWidgetThing', $ExceptionRenderer->method);
 
223
 
 
224
                ob_start();
 
225
                $ExceptionRenderer->render();
 
226
                $result = ob_get_clean();
 
227
 
 
228
                $this->assertEquals('widget thing is missing', $result, 'Method declared in subclass converted to error400');
 
229
        }
 
230
 
 
231
/**
 
232
 * test that ExceptionRenderer subclasses properly convert framework errors.
 
233
 *
 
234
 * @return void
 
235
 */
 
236
        public function testSubclassConvertingFrameworkErrors() {
 
237
                Configure::write('debug', 0);
 
238
 
 
239
                $exception = new MissingControllerException('PostsController');
 
240
                $ExceptionRenderer = $this->_mockResponse(new MyCustomExceptionRenderer($exception));
 
241
 
 
242
                $this->assertEquals('error400', $ExceptionRenderer->method);
 
243
 
 
244
                ob_start();
 
245
                $ExceptionRenderer->render();
 
246
                $result = ob_get_clean();
 
247
 
 
248
                $this->assertRegExp('/Not Found/', $result, 'Method declared in error handler not converted to error400. %s');
 
249
        }
 
250
 
 
251
/**
 
252
 * test things in the constructor.
 
253
 *
 
254
 * @return void
 
255
 */
 
256
        public function testConstruction() {
 
257
                $exception = new NotFoundException('Page not found');
 
258
                $ExceptionRenderer = new ExceptionRenderer($exception);
 
259
 
 
260
                $this->assertInstanceOf('CakeErrorController', $ExceptionRenderer->controller);
 
261
                $this->assertEquals('error400', $ExceptionRenderer->method);
 
262
                $this->assertEquals($exception, $ExceptionRenderer->error);
 
263
        }
 
264
 
 
265
/**
 
266
 * test that method gets coerced when debug = 0
 
267
 *
 
268
 * @return void
 
269
 */
 
270
        public function testErrorMethodCoercion() {
 
271
                Configure::write('debug', 0);
 
272
                $exception = new MissingActionException('Page not found');
 
273
                $ExceptionRenderer = new ExceptionRenderer($exception);
 
274
 
 
275
                $this->assertInstanceOf('CakeErrorController', $ExceptionRenderer->controller);
 
276
                $this->assertEquals('error400', $ExceptionRenderer->method);
 
277
                $this->assertEquals($exception, $ExceptionRenderer->error);
 
278
        }
 
279
 
 
280
/**
 
281
 * test that helpers in custom CakeErrorController are not lost
 
282
 */
 
283
        public function testCakeErrorHelpersNotLost() {
 
284
                $testApp = CAKE . 'Test' . DS . 'test_app' . DS;
 
285
                App::build(array(
 
286
                        'Controller' => array(
 
287
                                $testApp . 'Controller' . DS
 
288
                        ),
 
289
                        'View/Helper' => array(
 
290
                                $testApp . 'View' . DS . 'Helper' . DS
 
291
                        ),
 
292
                        'View/Layouts' => array(
 
293
                                $testApp . 'View' . DS . 'Layouts' . DS
 
294
                        ),
 
295
                        'Error' => array(
 
296
                                $testApp . 'Error' . DS
 
297
                        ),
 
298
                ), App::RESET);
 
299
 
 
300
                App::uses('TestAppsExceptionRenderer', 'Error');
 
301
                $exception = new SocketException('socket exception');
 
302
                $renderer = new TestAppsExceptionRenderer($exception);
 
303
 
 
304
                ob_start();
 
305
                $renderer->render();
 
306
                $result = ob_get_clean();
 
307
                $this->assertContains('<b>peeled</b>', $result);
 
308
        }
 
309
 
 
310
/**
 
311
 * test that unknown exception types with valid status codes are treated correctly.
 
312
 *
 
313
 * @return void
 
314
 */
 
315
        public function testUnknownExceptionTypeWithExceptionThatHasA400Code() {
 
316
                $exception = new MissingWidgetThingException('coding fail.');
 
317
                $ExceptionRenderer = new ExceptionRenderer($exception);
 
318
                $ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
 
319
                $ExceptionRenderer->controller->response->expects($this->once())->method('statusCode')->with(404);
 
320
 
 
321
                ob_start();
 
322
                $ExceptionRenderer->render();
 
323
                $result = ob_get_clean();
 
324
 
 
325
                $this->assertFalse(method_exists($ExceptionRenderer, 'missingWidgetThing'), 'no method should exist.');
 
326
                $this->assertEquals('error400', $ExceptionRenderer->method, 'incorrect method coercion.');
 
327
                $this->assertContains('coding fail', $result, 'Text should show up.');
 
328
        }
 
329
 
 
330
/**
 
331
 * test that unknown exception types with valid status codes are treated correctly.
 
332
 *
 
333
 * @return void
 
334
 */
 
335
        public function testUnknownExceptionTypeWithNoCodeIsA500() {
 
336
                $exception = new OutOfBoundsException('foul ball.');
 
337
                $ExceptionRenderer = new ExceptionRenderer($exception);
 
338
                $ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
 
339
                $ExceptionRenderer->controller->response->expects($this->once())
 
340
                        ->method('statusCode')
 
341
                        ->with(500);
 
342
 
 
343
                ob_start();
 
344
                $ExceptionRenderer->render();
 
345
                $result = ob_get_clean();
 
346
 
 
347
                $this->assertEquals('error500', $ExceptionRenderer->method, 'incorrect method coercion.');
 
348
                $this->assertContains('foul ball.', $result, 'Text should show up as its debug mode.');
 
349
        }
 
350
 
 
351
/**
 
352
 * test that unknown exceptions have messages ignored.
 
353
 *
 
354
 * @return void
 
355
 */
 
356
        public function testUnknownExceptionInProduction() {
 
357
                Configure::write('debug', 0);
 
358
 
 
359
                $exception = new OutOfBoundsException('foul ball.');
 
360
                $ExceptionRenderer = new ExceptionRenderer($exception);
 
361
                $ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
 
362
                $ExceptionRenderer->controller->response->expects($this->once())
 
363
                        ->method('statusCode')
 
364
                        ->with(500);
 
365
 
 
366
                ob_start();
 
367
                $ExceptionRenderer->render();
 
368
                $result = ob_get_clean();
 
369
 
 
370
                $this->assertEquals('error500', $ExceptionRenderer->method, 'incorrect method coercion.');
 
371
                $this->assertNotContains('foul ball.', $result, 'Text should no show up.');
 
372
                $this->assertContains('Internal Error', $result, 'Generic message only.');
 
373
        }
 
374
 
 
375
/**
 
376
 * test that unknown exception types with valid status codes are treated correctly.
 
377
 *
 
378
 * @return void
 
379
 */
 
380
        public function testUnknownExceptionTypeWithCodeHigherThan500() {
 
381
                $exception = new OutOfBoundsException('foul ball.', 501);
 
382
                $ExceptionRenderer = new ExceptionRenderer($exception);
 
383
                $ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
 
384
                $ExceptionRenderer->controller->response->expects($this->once())->method('statusCode')->with(501);
 
385
 
 
386
                ob_start();
 
387
                $ExceptionRenderer->render();
 
388
                $result = ob_get_clean();
 
389
 
 
390
                $this->assertEquals('error500', $ExceptionRenderer->method, 'incorrect method coercion.');
 
391
                $this->assertContains('foul ball.', $result, 'Text should show up as its debug mode.');
 
392
        }
 
393
 
 
394
/**
 
395
 * testerror400 method
 
396
 *
 
397
 * @return void
 
398
 */
 
399
        public function testError400() {
 
400
                Router::reload();
 
401
 
 
402
                $request = new CakeRequest('posts/view/1000', false);
 
403
                Router::setRequestInfo($request);
 
404
 
 
405
                $exception = new NotFoundException('Custom message');
 
406
                $ExceptionRenderer = new ExceptionRenderer($exception);
 
407
                $ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
 
408
                $ExceptionRenderer->controller->response->expects($this->once())->method('statusCode')->with(404);
 
409
 
 
410
                ob_start();
 
411
                $ExceptionRenderer->render();
 
412
                $result = ob_get_clean();
 
413
 
 
414
                $this->assertRegExp('/<h2>Custom message<\/h2>/', $result);
 
415
                $this->assertRegExp("/<strong>'.*?\/posts\/view\/1000'<\/strong>/", $result);
 
416
        }
 
417
 
 
418
/**
 
419
 * test that error400 only modifies the messages on CakeExceptions.
 
420
 *
 
421
 * @return void
 
422
 */
 
423
        public function testerror400OnlyChangingCakeException() {
 
424
                Configure::write('debug', 0);
 
425
 
 
426
                $exception = new NotFoundException('Custom message');
 
427
                $ExceptionRenderer = $this->_mockResponse(new ExceptionRenderer($exception));
 
428
 
 
429
                ob_start();
 
430
                $ExceptionRenderer->render();
 
431
                $result = ob_get_clean();
 
432
                $this->assertContains('Custom message', $result);
 
433
 
 
434
                $exception = new MissingActionException(array('controller' => 'PostsController', 'action' => 'index'));
 
435
                $ExceptionRenderer = $this->_mockResponse(new ExceptionRenderer($exception));
 
436
 
 
437
                ob_start();
 
438
                $ExceptionRenderer->render();
 
439
                $result = ob_get_clean();
 
440
                $this->assertContains('Not Found', $result);
 
441
        }
 
442
 
 
443
/**
 
444
 * test that error400 doesn't expose XSS
 
445
 *
 
446
 * @return void
 
447
 */
 
448
        public function testError400NoInjection() {
 
449
                Router::reload();
 
450
 
 
451
                $request = new CakeRequest('pages/<span id=333>pink</span></id><script>document.body.style.background = t=document.getElementById(333).innerHTML;window.alert(t);</script>', false);
 
452
                Router::setRequestInfo($request);
 
453
 
 
454
                $exception = new NotFoundException('Custom message');
 
455
                $ExceptionRenderer = $this->_mockResponse(new ExceptionRenderer($exception));
 
456
 
 
457
                ob_start();
 
458
                $ExceptionRenderer->render();
 
459
                $result = ob_get_clean();
 
460
 
 
461
                $this->assertNotRegExp('#<script>document#', $result);
 
462
                $this->assertNotRegExp('#alert\(t\);</script>#', $result);
 
463
        }
 
464
 
 
465
/**
 
466
 * testError500 method
 
467
 *
 
468
 * @return void
 
469
 */
 
470
        public function testError500Message() {
 
471
                $exception = new InternalErrorException('An Internal Error Has Occurred');
 
472
                $ExceptionRenderer = new ExceptionRenderer($exception);
 
473
                $ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
 
474
                $ExceptionRenderer->controller->response->expects($this->once())->method('statusCode')->with(500);
 
475
 
 
476
                ob_start();
 
477
                $ExceptionRenderer->render();
 
478
                $result = ob_get_clean();
 
479
 
 
480
                $this->assertRegExp('/<h2>An Internal Error Has Occurred<\/h2>/', $result);
 
481
        }
 
482
 
 
483
/**
 
484
 * testMissingController method
 
485
 *
 
486
 * @return void
 
487
 */
 
488
        public function testMissingController() {
 
489
                $exception = new MissingControllerException(array('class' => 'PostsController'));
 
490
                $ExceptionRenderer = $this->_mockResponse(new ExceptionRenderer($exception));
 
491
 
 
492
                ob_start();
 
493
                $ExceptionRenderer->render();
 
494
                $result = ob_get_clean();
 
495
 
 
496
                $this->assertRegExp('/<h2>Missing Controller<\/h2>/', $result);
 
497
                $this->assertRegExp('/<em>PostsController<\/em>/', $result);
 
498
        }
 
499
 
 
500
/**
 
501
 * Returns an array of tests to run for the various CakeException classes.
 
502
 *
 
503
 * @return void
 
504
 */
 
505
        public static function testProvider() {
 
506
                return array(
 
507
                        array(
 
508
                                new MissingActionException(array('controller' => 'PostsController', 'action' => 'index')),
 
509
                                array(
 
510
                                        '/<h2>Missing Method in PostsController<\/h2>/',
 
511
                                        '/<em>PostsController::<\/em><em>index\(\)<\/em>/'
 
512
                                ),
 
513
                                404
 
514
                        ),
 
515
                        array(
 
516
                                new PrivateActionException(array('controller' => 'PostsController' , 'action' => '_secretSauce')),
 
517
                                array(
 
518
                                        '/<h2>Private Method in PostsController<\/h2>/',
 
519
                                        '/<em>PostsController::<\/em><em>_secretSauce\(\)<\/em>/'
 
520
                                ),
 
521
                                404
 
522
                        ),
 
523
                        array(
 
524
                                new MissingTableException(array('table' => 'articles', 'class' => 'Article', 'ds' => 'test')),
 
525
                                array(
 
526
                                        '/<h2>Missing Database Table<\/h2>/',
 
527
                                        '/Table <em>articles<\/em> for model <em>Article<\/em> was not found in datasource <em>test<\/em>/'
 
528
                                ),
 
529
                                500
 
530
                        ),
 
531
                        array(
 
532
                                new MissingDatabaseException(array('connection' => 'default')),
 
533
                                array(
 
534
                                        '/<h2>Missing Database Connection<\/h2>/',
 
535
                                        '/Confirm you have created the file/'
 
536
                                ),
 
537
                                500
 
538
                        ),
 
539
                        array(
 
540
                                new MissingViewException(array('file' => '/posts/about.ctp')),
 
541
                                array(
 
542
                                        "/posts\/about.ctp/"
 
543
                                ),
 
544
                                500
 
545
                        ),
 
546
                        array(
 
547
                                new MissingLayoutException(array('file' => 'layouts/my_layout.ctp')),
 
548
                                array(
 
549
                                        "/Missing Layout/",
 
550
                                        "/layouts\/my_layout.ctp/"
 
551
                                ),
 
552
                                500
 
553
                        ),
 
554
                        array(
 
555
                                new MissingConnectionException(array('class' => 'Article')),
 
556
                                array(
 
557
                                        '/<h2>Missing Database Connection<\/h2>/',
 
558
                                        '/Article requires a database connection/'
 
559
                                ),
 
560
                                500
 
561
                        ),
 
562
                        array(
 
563
                                new MissingConnectionException(array('class' => 'Mysql', 'enabled' => false)),
 
564
                                array(
 
565
                                        '/<h2>Missing Database Connection<\/h2>/',
 
566
                                        '/Mysql requires a database connection/',
 
567
                                        '/Mysql driver is NOT enabled/'
 
568
                                ),
 
569
                                500
 
570
                        ),
 
571
                        array(
 
572
                                new MissingDatasourceConfigException(array('config' => 'default')),
 
573
                                array(
 
574
                                        '/<h2>Missing Datasource Configuration<\/h2>/',
 
575
                                        '/The datasource configuration <em>default<\/em> was not found in database.php/'
 
576
                                ),
 
577
                                500
 
578
                        ),
 
579
                        array(
 
580
                                new MissingDatasourceException(array('class' => 'MyDatasource', 'plugin' => 'MyPlugin')),
 
581
                                array(
 
582
                                        '/<h2>Missing Datasource<\/h2>/',
 
583
                                        '/Datasource class <em>MyPlugin.MyDatasource<\/em> could not be found/'
 
584
                                ),
 
585
                                500
 
586
                        ),
 
587
                        array(
 
588
                                new MissingHelperException(array('class' => 'MyCustomHelper')),
 
589
                                array(
 
590
                                        '/<h2>Missing Helper<\/h2>/',
 
591
                                        '/<em>MyCustomHelper<\/em> could not be found./',
 
592
                                        '/Create the class <em>MyCustomHelper<\/em> below in file:/',
 
593
                                        '/(\/|\\\)MyCustomHelper.php/'
 
594
                                ),
 
595
                                500
 
596
                        ),
 
597
                        array(
 
598
                                new MissingBehaviorException(array('class' => 'MyCustomBehavior')),
 
599
                                array(
 
600
                                        '/<h2>Missing Behavior<\/h2>/',
 
601
                                        '/Create the class <em>MyCustomBehavior<\/em> below in file:/',
 
602
                                        '/(\/|\\\)MyCustomBehavior.php/'
 
603
                                ),
 
604
                                500
 
605
                        ),
 
606
                        array(
 
607
                                new MissingComponentException(array('class' => 'SideboxComponent')),
 
608
                                array(
 
609
                                        '/<h2>Missing Component<\/h2>/',
 
610
                                        '/Create the class <em>SideboxComponent<\/em> below in file:/',
 
611
                                        '/(\/|\\\)SideboxComponent.php/'
 
612
                                ),
 
613
                                500
 
614
                        ),
 
615
                        array(
 
616
                                new Exception('boom'),
 
617
                                array(
 
618
                                        '/Internal Error/'
 
619
                                ),
 
620
                                500
 
621
                        ),
 
622
                        array(
 
623
                                new RuntimeException('another boom'),
 
624
                                array(
 
625
                                        '/Internal Error/'
 
626
                                ),
 
627
                                500
 
628
                        ),
 
629
                        array(
 
630
                                new CakeException('base class'),
 
631
                                array('/Internal Error/'),
 
632
                                500
 
633
                        ),
 
634
                        array(
 
635
                                new ConfigureException('No file'),
 
636
                                array('/Internal Error/'),
 
637
                                500
 
638
                        )
 
639
                );
 
640
        }
 
641
 
 
642
/**
 
643
 * Test the various CakeException sub classes
 
644
 *
 
645
 * @dataProvider testProvider
 
646
 * @return void
 
647
 */
 
648
        public function testCakeExceptionHandling($exception, $patterns, $code) {
 
649
                $ExceptionRenderer = new ExceptionRenderer($exception);
 
650
                $ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
 
651
                $ExceptionRenderer->controller->response->expects($this->once())
 
652
                        ->method('statusCode')
 
653
                        ->with($code);
 
654
 
 
655
                ob_start();
 
656
                $ExceptionRenderer->render();
 
657
                $result = ob_get_clean();
 
658
 
 
659
                foreach ($patterns as $pattern) {
 
660
                        $this->assertRegExp($pattern, $result);
 
661
                }
 
662
        }
 
663
 
 
664
/**
 
665
 * Test exceptions being raised when helpers are missing.
 
666
 *
 
667
 * @return void
 
668
 */
 
669
        public function testMissingRenderSafe() {
 
670
                $exception = new MissingHelperException(array('class' => 'Fail'));
 
671
                $ExceptionRenderer = new ExceptionRenderer($exception);
 
672
 
 
673
                $ExceptionRenderer->controller = $this->getMock('Controller');
 
674
                $ExceptionRenderer->controller->helpers = array('Fail', 'Boom');
 
675
                $ExceptionRenderer->controller->request = $this->getMock('CakeRequest');
 
676
                $ExceptionRenderer->controller->expects($this->at(2))
 
677
                        ->method('render')
 
678
                        ->with('missingHelper')
 
679
                        ->will($this->throwException($exception));
 
680
 
 
681
                $ExceptionRenderer->controller->expects($this->at(4))
 
682
                        ->method('render')
 
683
                        ->with('error500')
 
684
                        ->will($this->returnValue(true));
 
685
 
 
686
                $ExceptionRenderer->controller->response = $this->getMock('CakeResponse');
 
687
                $ExceptionRenderer->render();
 
688
                sort($ExceptionRenderer->controller->helpers);
 
689
                $this->assertEquals(array('Form', 'Html', 'Session'), $ExceptionRenderer->controller->helpers);
 
690
        }
 
691
 
 
692
/**
 
693
 * Test that missing subDir/layoutPath don't cause other fatal errors.
 
694
 *
 
695
 * @return void
 
696
 */
 
697
        public function testMissingSubdirRenderSafe() {
 
698
                $exception = new NotFoundException();
 
699
                $ExceptionRenderer = new ExceptionRenderer($exception);
 
700
 
 
701
                $ExceptionRenderer->controller = $this->getMock('Controller');
 
702
                $ExceptionRenderer->controller->helpers = array('Fail', 'Boom');
 
703
                $ExceptionRenderer->controller->layoutPath = 'json';
 
704
                $ExceptionRenderer->controller->subDir = 'json';
 
705
                $ExceptionRenderer->controller->viewClass = 'Json';
 
706
                $ExceptionRenderer->controller->request = $this->getMock('CakeRequest');
 
707
 
 
708
                $ExceptionRenderer->controller->expects($this->at(1))
 
709
                        ->method('render')
 
710
                        ->with('error400')
 
711
                        ->will($this->throwException($exception));
 
712
 
 
713
                $ExceptionRenderer->controller->expects($this->at(3))
 
714
                        ->method('render')
 
715
                        ->with('error500')
 
716
                        ->will($this->returnValue(true));
 
717
 
 
718
                $ExceptionRenderer->controller->response = $this->getMock('CakeResponse');
 
719
                $ExceptionRenderer->controller->response->expects($this->once())
 
720
                        ->method('type')
 
721
                        ->with('html');
 
722
 
 
723
                $ExceptionRenderer->render();
 
724
                $this->assertEquals('', $ExceptionRenderer->controller->layoutPath);
 
725
                $this->assertEquals('', $ExceptionRenderer->controller->subDir);
 
726
                $this->assertEquals('View', $ExceptionRenderer->controller->viewClass);
 
727
                $this->assertEquals('Errors/', $ExceptionRenderer->controller->viewPath);
 
728
        }
 
729
 
 
730
/**
 
731
 * Test that exceptions can be rendered when an request hasn't been registered
 
732
 * with Router
 
733
 *
 
734
 * @return void
 
735
 */
 
736
        public function testRenderWithNoRequest() {
 
737
                Router::reload();
 
738
                $this->assertNull(Router::getRequest(false));
 
739
 
 
740
                $exception = new Exception('Terrible');
 
741
                $ExceptionRenderer = new ExceptionRenderer($exception);
 
742
                $ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
 
743
                $ExceptionRenderer->controller->response->expects($this->once())
 
744
                        ->method('statusCode')
 
745
                        ->with(500);
 
746
 
 
747
                ob_start();
 
748
                $ExceptionRenderer->render();
 
749
                $result = ob_get_clean();
 
750
 
 
751
                $this->assertContains('Internal Error', $result);
 
752
        }
 
753
 
 
754
/**
 
755
 * Tests the output of rendering a PDOException
 
756
 *
 
757
 * @return void
 
758
 */
 
759
        public function testPDOException() {
 
760
                $exception = new PDOException('There was an error in the SQL query');
 
761
                $exception->queryString = 'SELECT * from poo_query < 5 and :seven';
 
762
                $exception->params = array('seven' => 7);
 
763
                $ExceptionRenderer = new ExceptionRenderer($exception);
 
764
                $ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
 
765
                $ExceptionRenderer->controller->response->expects($this->once())->method('statusCode')->with(500);
 
766
 
 
767
                ob_start();
 
768
                $ExceptionRenderer->render();
 
769
                $result = ob_get_clean();
 
770
 
 
771
                $this->assertContains('<h2>Database Error</h2>', $result);
 
772
                $this->assertContains('There was an error in the SQL query', $result);
 
773
                $this->assertContains('SELECT * from poo_query < 5 and :seven', $result);
 
774
                $this->assertContains("'seven' => (int) 7", $result);
 
775
        }
 
776
}