From 59a74797659374fb56c466977546b5f114d80cf3 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Mon, 25 Aug 2025 09:53:06 -0400 Subject: [PATCH 1/6] test(http): Enhance `ErrorHandlerTest` class with output buffer handling and mocking support. --- src/http/ErrorHandler.php | 2 - tests/http/ErrorHandlerTest.php | 55 ++++++++- .../stateless/ApplicationErrorHandlerTest.php | 105 ------------------ tests/http/stateless/ApplicationTest.php | 66 +---------- tests/support/MockerExtension.php | 5 + tests/support/stub/MockerFunctions.php | 28 +++++ 6 files changed, 87 insertions(+), 174 deletions(-) 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/ErrorHandlerTest.php b/tests/http/ErrorHandlerTest.php index f0aea969..6c730569 100644 --- a/tests/http/ErrorHandlerTest.php +++ b/tests/http/ErrorHandlerTest.php @@ -10,6 +10,7 @@ use yii\base\{Exception, UserException}; use yii\web\HttpException; use yii2\extensions\psrbridge\http\{ErrorHandler, Response}; +use yii2\extensions\psrbridge\tests\support\stub\MockerFunctions; use yii2\extensions\psrbridge\tests\TestCase; use function ob_get_level; @@ -19,13 +20,63 @@ #[Group('http')] final class ErrorHandlerTest extends TestCase { + #[RequiresPhpExtension('runkit7')] + public function test(): void + { + @\runkit_constant_redefine('YII_ENV_TEST', false); + + $initialBufferLevel = ob_get_level(); + + ob_start(); + ob_start(); + + $errorHandler = new ErrorHandler(['discardExistingOutput' => true]); + + $errorHandler->clearOutput(); + + self::assertSame( + 0, + ob_get_level(), + "All output buffers should be cleared to level '0' in non-test environment.", + ); + + while (ob_get_level() < $initialBufferLevel) { + ob_start(); + } + + @\runkit_constant_redefine('YII_ENV_TEST', true); + } + + public function testClearOutputCallsObCleanWhenObEndCleanFails(): void + { + MockerFunctions::setObEndCleanShouldFail(true); + + ob_start(); + ob_start(); + + $errorHandler = new ErrorHandler(['discardExistingOutput' => true]); + + try { + $errorHandler->clearOutput(); + + self::assertSame( + 1, + ob_get_level(), + "All output buffers should be cleared to level '1' in test environment.", + ); + } finally { + while (ob_get_level() > 1) { + @ob_end_clean(); + } + } + } #[RequiresPhpExtension('runkit7')] public function testClearOutputCleansAllBuffersInNonTestEnvironment(): void { $initialLevel = ob_get_level(); try { - @runkit_constant_redefine('YII_ENV_TEST', false); + @\runkit_constant_redefine('YII_ENV_TEST', false); $errorHandler = new ErrorHandler(); @@ -56,7 +107,7 @@ public function testClearOutputCleansAllBuffersInNonTestEnvironment(): void ob_start(); } - @runkit_constant_redefine('YII_ENV_TEST', true); + @\runkit_constant_redefine('YII_ENV_TEST', true); } } diff --git a/tests/http/stateless/ApplicationErrorHandlerTest.php b/tests/http/stateless/ApplicationErrorHandlerTest.php index b8a1099e..491b0b1d 100644 --- a/tests/http/stateless/ApplicationErrorHandlerTest.php +++ b/tests/http/stateless/ApplicationErrorHandlerTest.php @@ -15,12 +15,7 @@ use yii2\extensions\psrbridge\tests\support\FactoryHelper; use yii2\extensions\psrbridge\tests\TestCase; -use function array_filter; use function is_array; -use function ob_get_level; -use function ob_start; -use function restore_error_handler; -use function set_error_handler; use function str_contains; #[Group('http')] @@ -246,106 +241,6 @@ public function testLogExceptionIsCalledWhenHandlingException(): void ); } - /** - * @throws InvalidConfigException if the configuration is invalid or incomplete. - */ - #[RequiresPhpExtension('runkit7')] - public function testRenderExceptionPassesExceptionParameterToTemplateView(): void - { - @\runkit_constant_redefine('YII_ENV_TEST', false); - - $initialBufferLevel = ob_get_level(); - - $_SERVER = [ - 'REQUEST_METHOD' => 'GET', - 'REQUEST_URI' => 'site/trigger-exception', - ]; - - $warningsCaptured = []; - - set_error_handler( - static function ($errno, $errstr, $errfile, $errline) use (&$warningsCaptured): bool { - if ($errno === E_WARNING || $errno === E_NOTICE) { - $warningsCaptured[] = [ - 'type' => $errno, - 'message' => $errstr, - 'file' => $errfile, - 'line' => $errline, - ]; - } - - return false; - }, - ); - - 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'.", - ); - - $undefinedExceptionWarnings = array_filter( - $warningsCaptured, - static fn(array $warning): bool => str_contains($warning['message'], 'Undefined variable'), - ); - - self::assertEmpty( - $undefinedExceptionWarnings, - "Should be no 'Undefined variable' warnings, confirming that exception parameter is defined in the " . - 'view context when rendering exception.', - ); - - $responseBody = $response->getBody()->getContents(); - - self::assertStringContainsString( - Exception::class, - $responseBody, - "Response body should contain exception class when exception parameter is passed to 'renderFile()'.", - ); - self::assertStringContainsString( - 'Stack trace:', - $responseBody, - "Response body should contain 'Stack trace:' section, confirming exception object is available to template.", - ); - self::assertStringContainsString( - 'Exception error message.', - $responseBody, - "Response body should contain the exact exception message 'Exception error message.', confirming " . - 'the exception object was properly passed to the view.', - ); - self::assertStringContainsString( - 'SiteController.php', - $responseBody, - "Response body should contain reference to 'SiteController.php' where the exception was throw, " . - 'confirming full exception details are available in the view.', - ); - } finally { - restore_error_handler(); - - while (ob_get_level() < $initialBufferLevel) { - ob_start(); - } - - @\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..2d4fe9bc 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. */ diff --git a/tests/support/MockerExtension.php b/tests/support/MockerExtension.php index 10abdcdf..bb871d09 100644 --- a/tests/support/MockerExtension.php +++ b/tests/support/MockerExtension.php @@ -85,6 +85,11 @@ public static function load(): void 'name' => 'microtime', 'function' => static fn(bool $as_float = false): float|string => MockerFunctions::microtime($as_float), ], + [ + 'namespace' => 'yii2\extensions\psrbridge\http', + 'name' => 'ob_end_clean', + 'function' => static fn(): bool => MockerFunctions::ob_end_clean(), + ], [ 'namespace' => 'yii2\extensions\psrbridge\adapter', 'name' => 'stream_get_contents', diff --git a/tests/support/stub/MockerFunctions.php b/tests/support/stub/MockerFunctions.php index c7d7b7f4..7e61dc3e 100644 --- a/tests/support/stub/MockerFunctions.php +++ b/tests/support/stub/MockerFunctions.php @@ -84,6 +84,15 @@ final class MockerFunctions */ private static int|null $mockedTime = null; + /** + * Tracks the number of times {@see \ob_end_clean()} was called. + */ + private static int $obEndCleanCallCount = 0; + /** + * Indicates whether {@see \ob_end_clean()} should fail. + */ + private static bool $obEndCleanShouldFail = false; + /** * Tracks the HTTP response code. */ @@ -190,6 +199,17 @@ public static function microtime(bool $as_float = false): float|string return \microtime($as_float); } + public static function ob_end_clean(): bool + { + if (self::$obEndCleanShouldFail && self::$obEndCleanCallCount === 0) { + self::$obEndCleanCallCount++; + + return false; + } + + return @\ob_end_clean(); + } + public static function reset(): void { self::$flushedTimes = 0; @@ -198,8 +218,11 @@ public static function reset(): void self::$headersSentFile = ''; self::$headersSentLine = 0; self::$mockedTime = null; + self::$obEndCleanCallCount = 0; + self::$obEndCleanShouldFail = false; self::$responseCode = 200; self::$streamGetContentsShouldFail = false; + self::clearMockedMicrotime(); } @@ -225,6 +248,11 @@ public static function setMockedTime(int $time): void self::$mockedTime = $time; } + public static function setObEndCleanShouldFail(bool $shouldFail = true): void + { + self::$obEndCleanShouldFail = $shouldFail; + } + public static function stream_get_contents(mixed $resource, int $maxlength = -1, int $offset = -1): string|false { if (self::$streamGetContentsShouldFail) { From feed312d3c40b26fefee2ab3ea2f1cdc563c3ba2 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Mon, 25 Aug 2025 13:53:39 +0000 Subject: [PATCH 2/6] Apply fixes from StyleCI --- tests/http/ErrorHandlerTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/http/ErrorHandlerTest.php b/tests/http/ErrorHandlerTest.php index 6c730569..5ec61740 100644 --- a/tests/http/ErrorHandlerTest.php +++ b/tests/http/ErrorHandlerTest.php @@ -70,6 +70,7 @@ public function testClearOutputCallsObCleanWhenObEndCleanFails(): void } } } + #[RequiresPhpExtension('runkit7')] public function testClearOutputCleansAllBuffersInNonTestEnvironment(): void { From 62fd920ac590d9d1ac7a9968e4f20b3e6cd2de6a Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Mon, 25 Aug 2025 09:58:41 -0400 Subject: [PATCH 3/6] Revert changes. --- .../stateless/ApplicationErrorHandlerTest.php | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/tests/http/stateless/ApplicationErrorHandlerTest.php b/tests/http/stateless/ApplicationErrorHandlerTest.php index 491b0b1d..b8a1099e 100644 --- a/tests/http/stateless/ApplicationErrorHandlerTest.php +++ b/tests/http/stateless/ApplicationErrorHandlerTest.php @@ -15,7 +15,12 @@ use yii2\extensions\psrbridge\tests\support\FactoryHelper; use yii2\extensions\psrbridge\tests\TestCase; +use function array_filter; use function is_array; +use function ob_get_level; +use function ob_start; +use function restore_error_handler; +use function set_error_handler; use function str_contains; #[Group('http')] @@ -241,6 +246,106 @@ public function testLogExceptionIsCalledWhenHandlingException(): void ); } + /** + * @throws InvalidConfigException if the configuration is invalid or incomplete. + */ + #[RequiresPhpExtension('runkit7')] + public function testRenderExceptionPassesExceptionParameterToTemplateView(): void + { + @\runkit_constant_redefine('YII_ENV_TEST', false); + + $initialBufferLevel = ob_get_level(); + + $_SERVER = [ + 'REQUEST_METHOD' => 'GET', + 'REQUEST_URI' => 'site/trigger-exception', + ]; + + $warningsCaptured = []; + + set_error_handler( + static function ($errno, $errstr, $errfile, $errline) use (&$warningsCaptured): bool { + if ($errno === E_WARNING || $errno === E_NOTICE) { + $warningsCaptured[] = [ + 'type' => $errno, + 'message' => $errstr, + 'file' => $errfile, + 'line' => $errline, + ]; + } + + return false; + }, + ); + + 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'.", + ); + + $undefinedExceptionWarnings = array_filter( + $warningsCaptured, + static fn(array $warning): bool => str_contains($warning['message'], 'Undefined variable'), + ); + + self::assertEmpty( + $undefinedExceptionWarnings, + "Should be no 'Undefined variable' warnings, confirming that exception parameter is defined in the " . + 'view context when rendering exception.', + ); + + $responseBody = $response->getBody()->getContents(); + + self::assertStringContainsString( + Exception::class, + $responseBody, + "Response body should contain exception class when exception parameter is passed to 'renderFile()'.", + ); + self::assertStringContainsString( + 'Stack trace:', + $responseBody, + "Response body should contain 'Stack trace:' section, confirming exception object is available to template.", + ); + self::assertStringContainsString( + 'Exception error message.', + $responseBody, + "Response body should contain the exact exception message 'Exception error message.', confirming " . + 'the exception object was properly passed to the view.', + ); + self::assertStringContainsString( + 'SiteController.php', + $responseBody, + "Response body should contain reference to 'SiteController.php' where the exception was throw, " . + 'confirming full exception details are available in the view.', + ); + } finally { + restore_error_handler(); + + while (ob_get_level() < $initialBufferLevel) { + ob_start(); + } + + @\runkit_constant_redefine('YII_ENV_TEST', true); + } + } + /** * @throws InvalidConfigException if the configuration is invalid or incomplete. * From 6a794261c044016a9de0798ed75ea3fb72aa2649 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Mon, 25 Aug 2025 10:14:52 -0400 Subject: [PATCH 4/6] test(http): Add test for rendering exceptions in debug mode and enhance MockerFunctions for `ob_end_clean` control. --- .../stateless/ApplicationErrorHandlerTest.php | 76 +++++++++++++++++++ tests/support/stub/MockerFunctions.php | 11 ++- 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/tests/http/stateless/ApplicationErrorHandlerTest.php b/tests/http/stateless/ApplicationErrorHandlerTest.php index b8a1099e..d3798097 100644 --- a/tests/http/stateless/ApplicationErrorHandlerTest.php +++ b/tests/http/stateless/ApplicationErrorHandlerTest.php @@ -16,6 +16,8 @@ use yii2\extensions\psrbridge\tests\TestCase; use function array_filter; +use function ini_get; +use function ini_set; use function is_array; use function ob_get_level; use function ob_start; @@ -346,6 +348,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/support/stub/MockerFunctions.php b/tests/support/stub/MockerFunctions.php index 7e61dc3e..55af651d 100644 --- a/tests/support/stub/MockerFunctions.php +++ b/tests/support/stub/MockerFunctions.php @@ -33,6 +33,7 @@ * - {@see \headers_sent()} (with file/line tracking). * - {@see \http_response_code()} (get/set response code). * - {@see \microtime()} (mockable time for timing tests). + * - {@see \ob_end_clean()} (controllable success/failure). * - {@see \stream_get_contents()} (controllable stream read/failure). * - {@see \time()} (mockable time for timing tests). * - Consistent behavior matching PHP native functions for test reliability. @@ -88,6 +89,7 @@ final class MockerFunctions * Tracks the number of times {@see \ob_end_clean()} was called. */ private static int $obEndCleanCallCount = 0; + /** * Indicates whether {@see \ob_end_clean()} should fail. */ @@ -201,9 +203,10 @@ public static function microtime(bool $as_float = false): float|string public static function ob_end_clean(): bool { - if (self::$obEndCleanShouldFail && self::$obEndCleanCallCount === 0) { - self::$obEndCleanCallCount++; + self::$obEndCleanCallCount++; + // simulate failure only on the first call after enabling + if (self::$obEndCleanShouldFail && self::$obEndCleanCallCount === 1) { return false; } @@ -251,6 +254,10 @@ public static function setMockedTime(int $time): void public static function setObEndCleanShouldFail(bool $shouldFail = true): void { self::$obEndCleanShouldFail = $shouldFail; + + if ($shouldFail) { + self::$obEndCleanCallCount = 0; + } } public static function stream_get_contents(mixed $resource, int $maxlength = -1, int $offset = -1): string|false From a4c7d8e3dc01098fc0ae2392a080442986476f46 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Mon, 25 Aug 2025 10:24:37 -0400 Subject: [PATCH 5/6] Apply fixed review coderabbitai nitpick comments. --- tests/http/stateless/ApplicationErrorHandlerTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/http/stateless/ApplicationErrorHandlerTest.php b/tests/http/stateless/ApplicationErrorHandlerTest.php index d3798097..c8c9eb36 100644 --- a/tests/http/stateless/ApplicationErrorHandlerTest.php +++ b/tests/http/stateless/ApplicationErrorHandlerTest.php @@ -401,10 +401,10 @@ public function testRenderExceptionSetsDisplayErrorsInDebugMode(): void $bufferAfterLevel = ob_get_level(); - self::assertLessThanOrEqual( - $bufferBeforeLevel, + self::assertSame( + 0, $bufferAfterLevel, - "'clearOutput()' should properly clean output buffers", + "Output buffers should be cleared to level '0' when 'discardExistingOutput' is 'true'.", ); while (ob_get_level() < $bufferBeforeLevel) { From 1e2d7ea91eb3981cd8465958a2aa03432f45309f Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Mon, 25 Aug 2025 10:33:00 -0400 Subject: [PATCH 6/6] refactor(tests): Remove redundant tests and improve output buffer handling in `ErrorHandlerTest`. --- tests/http/ErrorHandlerTest.php | 52 ------------------- .../stateless/ApplicationErrorHandlerTest.php | 3 ++ 2 files changed, 3 insertions(+), 52 deletions(-) diff --git a/tests/http/ErrorHandlerTest.php b/tests/http/ErrorHandlerTest.php index 5ec61740..22d86464 100644 --- a/tests/http/ErrorHandlerTest.php +++ b/tests/http/ErrorHandlerTest.php @@ -10,7 +10,6 @@ use yii\base\{Exception, UserException}; use yii\web\HttpException; use yii2\extensions\psrbridge\http\{ErrorHandler, Response}; -use yii2\extensions\psrbridge\tests\support\stub\MockerFunctions; use yii2\extensions\psrbridge\tests\TestCase; use function ob_get_level; @@ -20,57 +19,6 @@ #[Group('http')] final class ErrorHandlerTest extends TestCase { - #[RequiresPhpExtension('runkit7')] - public function test(): void - { - @\runkit_constant_redefine('YII_ENV_TEST', false); - - $initialBufferLevel = ob_get_level(); - - ob_start(); - ob_start(); - - $errorHandler = new ErrorHandler(['discardExistingOutput' => true]); - - $errorHandler->clearOutput(); - - self::assertSame( - 0, - ob_get_level(), - "All output buffers should be cleared to level '0' in non-test environment.", - ); - - while (ob_get_level() < $initialBufferLevel) { - ob_start(); - } - - @\runkit_constant_redefine('YII_ENV_TEST', true); - } - - public function testClearOutputCallsObCleanWhenObEndCleanFails(): void - { - MockerFunctions::setObEndCleanShouldFail(true); - - ob_start(); - ob_start(); - - $errorHandler = new ErrorHandler(['discardExistingOutput' => true]); - - try { - $errorHandler->clearOutput(); - - self::assertSame( - 1, - ob_get_level(), - "All output buffers should be cleared to level '1' in test environment.", - ); - } finally { - while (ob_get_level() > 1) { - @ob_end_clean(); - } - } - } - #[RequiresPhpExtension('runkit7')] public function testClearOutputCleansAllBuffersInNonTestEnvironment(): void { diff --git a/tests/http/stateless/ApplicationErrorHandlerTest.php b/tests/http/stateless/ApplicationErrorHandlerTest.php index c8c9eb36..00b54529 100644 --- a/tests/http/stateless/ApplicationErrorHandlerTest.php +++ b/tests/http/stateless/ApplicationErrorHandlerTest.php @@ -13,6 +13,7 @@ use yii2\extensions\psrbridge\http\Response; use yii2\extensions\psrbridge\tests\provider\StatelessApplicationProvider; use yii2\extensions\psrbridge\tests\support\FactoryHelper; +use yii2\extensions\psrbridge\tests\support\stub\MockerFunctions; use yii2\extensions\psrbridge\tests\TestCase; use function array_filter; @@ -356,6 +357,8 @@ public function testRenderExceptionSetsDisplayErrorsInDebugMode(): void { @\runkit_constant_redefine('YII_ENV_TEST', false); + MockerFunctions::setObEndCleanShouldFail(true); + $bufferBeforeLevel = ob_get_level(); $_SERVER = [