77declare (strict_types=1 );
88
99use Nette \Application \Application ;
10+ use Nette \Application \ApplicationException ;
1011use Nette \Application \BadRequestException ;
1112use Nette \Application \IPresenterFactory ;
1213use Nette \Application \IResponse ;
1314use Nette \Application \IRouter ;
1415use Nette \Application \Request ;
16+ use Nette \Application \Responses \ForwardResponse ;
1517use Nette \Application \Responses \TextResponse ;
1618use Tester \Assert ;
1719
@@ -32,6 +34,15 @@ class GoodPresenter implements Nette\Application\IPresenter
3234}
3335
3436
37+ class InfinityForwardingPresenter implements Nette \Application \IPresenter
38+ {
39+ public function run (Request $ request )
40+ {
41+ return new ForwardResponse ($ request );
42+ }
43+ }
44+
45+
3546class BadException extends Exception
3647{
3748}
@@ -260,3 +271,70 @@ Assert::noError(function () use ($httpRequest, $httpResponse) {
260271 Assert::equal ($ requests [0 ], $ presenter ->request );
261272 Assert::null ($ errorPresenter ->request );
262273});
274+
275+
276+ // error during onShutdown with catchException + errorPresenter
277+ Assert::noError (function () use ($ httpRequest , $ httpResponse ) {
278+ $ presenter = new ErrorPresenter ;
279+
280+ $ presenterFactory = Mockery::mock (IPresenterFactory::class);
281+ $ presenterFactory ->shouldReceive ('createPresenter ' )->with ('Error ' )->andReturn ($ presenter );
282+
283+ $ router = Mockery::mock (IRouter::class);
284+
285+ $ errors = [];
286+
287+ $ app = new Application ($ presenterFactory , $ router , $ httpRequest , $ httpResponse );
288+ $ app ->onStartup [] = function () {
289+ throw new RuntimeException ('Error at startup ' , 1 );
290+ };
291+ $ app ->onShutdown [] = function () {
292+ throw new RuntimeException ('Error at shutdown ' , 2 );
293+ };
294+ $ app ->onError [] = function ($ app , $ e ) use (&$ errors ) {
295+ $ errors [] = $ e ;
296+ };
297+ $ app ->catchExceptions = true ;
298+ $ app ->errorPresenter = 'Error ' ;
299+
300+ Assert::exception (function () use ($ app ) {
301+ $ app ->run ();
302+ }, RuntimeException::class, 'Error at shutdown ' );
303+
304+ Assert::count (2 , $ errors );
305+ Assert::equal ('Error at startup ' , $ errors [0 ]->getMessage ());
306+ Assert::equal ('Error at shutdown ' , $ errors [1 ]->getMessage ());
307+ });
308+
309+
310+ // check maxLoop
311+ Assert::noError (function () use ($ httpRequest , $ httpResponse ) {
312+ $ presenter = new InfinityForwardingPresenter ;
313+
314+ $ presenterFactory = Mockery::mock (IPresenterFactory::class);
315+ $ presenterFactory ->shouldReceive ('createPresenter ' )->with ('Infinity ' )->andReturn ($ presenter );
316+
317+ $ router = Mockery::mock (IRouter::class);
318+ $ router ->shouldReceive ('match ' )->andReturn (new Request ('Infinity ' , 'GET ' ));
319+
320+ $ app = new Application ($ presenterFactory , $ router , $ httpRequest , $ httpResponse );
321+ $ app ->catchExceptions = true ;
322+ $ app ->errorPresenter = 'Error ' ;
323+
324+ // Use default maxLoop
325+ $ app1 = clone $ app ;
326+ Assert::exception (function () use ($ app1 ) {
327+ $ app1 ->run ();
328+ }, ApplicationException::class, 'Too many loops detected in application life cycle. ' );
329+
330+ Assert::count (21 , $ app1 ->getRequests ());
331+
332+ // Redefine maxLoop
333+ Application::$ maxLoop = 2 ;
334+ $ app2 = clone $ app ;
335+ Assert::exception (function () use ($ app2 ) {
336+ $ app2 ->run ();
337+ }, ApplicationException::class, 'Too many loops detected in application life cycle. ' );
338+
339+ Assert::count (3 , $ app2 ->getRequests ());
340+ });
0 commit comments