diff --git a/src/http/ErrorHandler.php b/src/http/ErrorHandler.php index a85f5518..61072954 100644 --- a/src/http/ErrorHandler.php +++ b/src/http/ErrorHandler.php @@ -86,9 +86,7 @@ public function clearOutput(): void while ($currentLevel > $minLevel) { if (@ob_end_clean() === false) { - // @codeCoverageIgnoreStart ob_clean(); - // @codeCoverageIgnoreEnd } $currentLevel = ob_get_level(); diff --git a/tests/http/stateless/ApplicationErrorHandlerTest.php b/tests/http/stateless/ApplicationErrorHandlerTest.php index b8a1099e..bbe500f8 100644 --- a/tests/http/stateless/ApplicationErrorHandlerTest.php +++ b/tests/http/stateless/ApplicationErrorHandlerTest.php @@ -346,6 +346,80 @@ static function ($errno, $errstr, $errfile, $errline) use (&$warningsCaptured): } } + /** + * @throws InvalidConfigException if the configuration is invalid or incomplete. + */ + #[RequiresPhpExtension('runkit7')] + public function testRenderExceptionSetsDisplayErrorsInDebugMode(): void + { + @\runkit_constant_redefine('YII_ENV_TEST', false); + + $bufferBeforeLevel = ob_get_level(); + + $_SERVER = [ + 'REQUEST_METHOD' => 'GET', + 'REQUEST_URI' => 'site/trigger-exception', + ]; + + ob_start(); + echo 'buffer content that should be cleared'; + ob_start(); + echo 'nested buffer content'; + + $originalDisplayErrors = ini_get('display_errors'); + + $app = $this->statelessApplication( + [ + 'components' => [ + 'errorHandler' => [ + 'discardExistingOutput' => true, + 'errorAction' => null, + ], + ], + ], + ); + + $response = $app->handle(FactoryHelper::createServerRequestCreator()->createFromGlobals()); + + self::assertSame( + 500, + $response->getStatusCode(), + "Expected HTTP '500' for route 'site/trigger-exception'.", + ); + self::assertSame( + 'text/html; charset=UTF-8', + $response->getHeaderLine('Content-Type'), + "Expected Content-Type 'text/html; charset=UTF-8' for route 'site/trigger-exception'.", + ); + self::assertSame( + '1', + ini_get('display_errors'), + "'display_errors' should be set to '1' in debug mode when rendering exception.", + ); + + $bufferAfterLevel = ob_get_level(); + + self::assertLessThanOrEqual( + $bufferBeforeLevel, + $bufferAfterLevel, + "'clearOutput()' should properly clean output buffers", + ); + + while (ob_get_level() < $bufferBeforeLevel) { + ob_start(); + } + + self::assertSame( + $bufferBeforeLevel, + ob_get_level(), + 'Output buffers should be restored to initial level.', + ); + + ini_set('display_errors', $originalDisplayErrors); + + @\runkit_constant_redefine('YII_ENV_TEST', true); + } + /** * @throws InvalidConfigException if the configuration is invalid or incomplete. * diff --git a/tests/http/stateless/ApplicationTest.php b/tests/http/stateless/ApplicationTest.php index f4b367ce..f4923db8 100644 --- a/tests/http/stateless/ApplicationTest.php +++ b/tests/http/stateless/ApplicationTest.php @@ -4,16 +4,11 @@ namespace yii2\extensions\psrbridge\tests\http\stateless; -use PHPUnit\Framework\Attributes\{Group, RequiresPhpExtension}; +use PHPUnit\Framework\Attributes\{Group}; use yii\base\InvalidConfigException; use yii2\extensions\psrbridge\tests\support\FactoryHelper; use yii2\extensions\psrbridge\tests\TestCase; -use function ini_get; -use function ini_set; -use function ob_get_level; -use function ob_start; - #[Group('http')] final class ApplicationTest extends TestCase { @@ -24,65 +19,6 @@ protected function tearDown(): void parent::tearDown(); } - /** - * @throws InvalidConfigException if the configuration is invalid or incomplete. - */ - #[RequiresPhpExtension('runkit7')] - public function testRenderExceptionSetsDisplayErrorsInDebugMode(): void - { - @\runkit_constant_redefine('YII_ENV_TEST', false); - - $initialBufferLevel = ob_get_level(); - - $_SERVER = [ - 'REQUEST_METHOD' => 'GET', - 'REQUEST_URI' => 'site/trigger-exception', - ]; - - $originalDisplayErrors = ini_get('display_errors'); - - try { - $app = $this->statelessApplication( - [ - 'components' => [ - 'errorHandler' => ['errorAction' => null], - ], - ], - ); - - $response = $app->handle(FactoryHelper::createServerRequestCreator()->createFromGlobals()); - - self::assertSame( - 500, - $response->getStatusCode(), - "Expected HTTP '500' for route 'site/trigger-exception'.", - ); - self::assertSame( - 'text/html; charset=UTF-8', - $response->getHeaderLine('Content-Type'), - "Expected Content-Type 'text/html; charset=UTF-8' for route 'site/trigger-exception'.", - ); - self::assertSame( - '1', - ini_get('display_errors'), - "'display_errors' should be set to '1' when YII_DEBUG mode is enabled and rendering exception view.", - ); - self::assertStringContainsString( - 'yii\base\Exception: Exception error message.', - $response->getBody()->getContents(), - 'Response should contain exception details when YII_DEBUG mode is enabled.', - ); - } finally { - ini_set('display_errors', $originalDisplayErrors); - - while (ob_get_level() < $initialBufferLevel) { - ob_start(); - } - - @\runkit_constant_redefine('YII_ENV_TEST', true); - } - } - /** * @throws InvalidConfigException if the configuration is invalid or incomplete. */