Skip to content

Conversation

@terabytesoftw
Copy link
Member

@terabytesoftw terabytesoftw commented Aug 25, 2025

Q A
Is bugfix? ✔️
New feature?
Breaks BC?

Summary by CodeRabbit

  • Tests
    • Added tests for output-buffer clearing and for when output-cleaning fails; introduced deterministic test helpers/mocks; removed an obsolete RunKit-dependent test and cleaned up related imports.
  • Chores
    • Minor cleanup of coverage/annotation pragmas and test scaffolding; no user-facing behavior changes.

@terabytesoftw terabytesoftw added the bug Something isn't working label Aug 25, 2025
@coderabbitai
Copy link

coderabbitai bot commented Aug 25, 2025

Warning

Rate limit exceeded

@terabytesoftw has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 13 minutes and 54 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between a4c7d8e and 1e2d7ea.

📒 Files selected for processing (2)
  • tests/http/ErrorHandlerTest.php (2 hunks)
  • tests/http/stateless/ApplicationErrorHandlerTest.php (2 hunks)

Walkthrough

Removes coverage-ignore pragmas around the ob_clean() fallback in ErrorHandler::clearOutput(). Adds tests and mocks to simulate ob_end_clean() failure and non-test buffer clearing, moves a debug-mode display_errors test into the stateless suite, and extends test mocking to control ob_end_clean() behavior.

Changes

Cohort / File(s) Summary of changes
Error handling core
src/http/ErrorHandler.php
Removed code-coverage ignore pragmas around the ob_clean() fallback in clearOutput(); no functional or control-flow changes.
ErrorHandler tests
tests/http/ErrorHandlerTest.php
Added tests for clearing buffers in non-test env and for ob_end_clean() failure; imported MockerFunctions; adjusted runkit calls to reference global scope.
Stateless error-handler tests
tests/http/stateless/ApplicationErrorHandlerTest.php, tests/http/stateless/ApplicationTest.php
Added testRenderExceptionSetsDisplayErrorsInDebugMode() to ApplicationErrorHandlerTest; removed the same test from ApplicationTest; updated imports and RunKit-based env toggling.
Mocking infrastructure
tests/support/MockerExtension.php, tests/support/stub/MockerFunctions.php
Registered mock for ob_end_clean in MockerExtension::load() and implemented MockerFunctions::ob_end_clean() with call-counting, configurable first-call failure, setObEndCleanShouldFail(), and reset behavior.

Sequence Diagram(s)

sequenceDiagram
  participant Test as Test harness / MockerFunctions
  participant EH as ErrorHandler::clearOutput()
  participant PHP as PHP output buffers

  Note over Test,EH: Tests may register a mock for ob_end_clean()
  EH->>PHP: call ob_end_clean()
  alt ob_end_clean() succeeds
    PHP-->>EH: returns true (buffer closed)
  else ob_end_clean() fails
    PHP-->>EH: returns false
    loop while buffers > target
      EH->>PHP: call ob_clean()
      PHP-->>EH: cleaned one buffer
    end
  end
  Note right of EH: tests assert buffer level and restore env/INI
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

I hopped through buffers, one by one,
ob_end_clean tripped — ob_clean got the job done.
Mocks steadied my paw when the first call went awry,
Tests checked the burrow, then let out a sigh.
A rabbit commits, then hops toward the sky. 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-mini-125

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@codecov
Copy link

codecov bot commented Aug 25, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (393f3e8) to head (1e2d7ea).

Additional details and impacted files
@@             Coverage Diff             @@
##                main      #144   +/-   ##
===========================================
  Coverage     100.00%   100.00%           
  Complexity       318       318           
===========================================
  Files             12        12           
  Lines            808       809    +1     
===========================================
+ Hits             808       809    +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
tests/http/ErrorHandlerTest.php (2)

23-49: Either remove this duplicate non-test clearOutput() check or harden it with try/finally

This method overlaps with testClearOutputCleansAllBuffersInNonTestEnvironment(). If you keep it, wrap the YII_ENV_TEST toggling and buffer restoration in try/finally to avoid leaving the suite in a bad state on failure.

Option A — remove the duplicate:

-    #[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);
-    }

Option B — keep it but add safety:

     #[RequiresPhpExtension('runkit7')]
-    public function test(): void
+    public function testClearOutputCleansAllBuffersInNonTestEnvironment_ShortCase(): void
     {
-        @\runkit_constant_redefine('YII_ENV_TEST', false);
-
-        $initialBufferLevel = ob_get_level();
+        $initialBufferLevel = ob_get_level();
+        try {
+            @\runkit_constant_redefine('YII_ENV_TEST', false);
 
             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);
+        } finally {
+            while (ob_get_level() < $initialBufferLevel) {
+                ob_start();
+            }
+            @\runkit_constant_redefine('YII_ENV_TEST', true);
+        }
     }

50-72: Ensure stub state is restored after simulating ob_end_clean failure

The test resets output buffers but leaves the failure flag enabled. If a global reset isn’t guaranteed per-test, this can bleed into other tests. Explicitly restore here for safety.

Apply this diff:

         } finally {
             while (ob_get_level() > 1) {
                 @ob_end_clean();
             }
+            // Restore default behavior to avoid test-order dependencies.
+            MockerFunctions::setObEndCleanShouldFail(false);
         }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 393f3e8 and feed312.

📒 Files selected for processing (6)
  • src/http/ErrorHandler.php (0 hunks)
  • tests/http/ErrorHandlerTest.php (3 hunks)
  • tests/http/stateless/ApplicationErrorHandlerTest.php (0 hunks)
  • tests/http/stateless/ApplicationTest.php (1 hunks)
  • tests/support/MockerExtension.php (1 hunks)
  • tests/support/stub/MockerFunctions.php (4 hunks)
💤 Files with no reviewable changes (2)
  • src/http/ErrorHandler.php
  • tests/http/stateless/ApplicationErrorHandlerTest.php
🧰 Additional context used
🧠 Learnings (11)
📚 Learning: 2025-08-24T11:52:50.524Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#141
File: tests/http/stateless/ApplicationRoutingTest.php:1-164
Timestamp: 2025-08-24T11:52:50.524Z
Learning: In yii2-extensions/psr-bridge, tests that manipulate PHP superglobals ($_POST, $_GET, $_SERVER) in the http group do not require process isolation and work fine with the current PHPUnit configuration.

Applied to files:

  • tests/http/stateless/ApplicationTest.php
  • tests/http/ErrorHandlerTest.php
📚 Learning: 2025-07-20T16:35:15.341Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#6
File: tests/http/RequestTest.php:1536-1552
Timestamp: 2025-07-20T16:35:15.341Z
Learning: In the yii2-extensions/psr-bridge project, the base TestCase class already handles $_SERVER cleanup in setUp() and tearDown() methods, so individual test methods that extend TestCase don't need manual $_SERVER restoration.

Applied to files:

  • tests/http/stateless/ApplicationTest.php
  • tests/http/ErrorHandlerTest.php
📚 Learning: 2025-07-20T16:35:15.341Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#6
File: tests/http/RequestTest.php:1536-1552
Timestamp: 2025-07-20T16:35:15.341Z
Learning: In the yii2-extensions/psr-bridge project, the base TestCase class already handles $_SERVER cleanup in setUp() and tearDown() methods (lines 28 and 32), so individual test methods that extend TestCase don't need manual $_SERVER restoration.

Applied to files:

  • tests/http/stateless/ApplicationTest.php
  • tests/http/ErrorHandlerTest.php
📚 Learning: 2025-07-20T16:33:57.495Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#6
File: tests/http/RequestTest.php:1564-1578
Timestamp: 2025-07-20T16:33:57.495Z
Learning: The TestCase class in yii2-extensions/psr-bridge automatically handles $_SERVER superglobal cleanup by saving its original state before each test and restoring it afterward in setUp() and tearDown() methods. Manual $_SERVER cleanup in individual test methods is unnecessary when extending this TestCase.

Applied to files:

  • tests/http/stateless/ApplicationTest.php
  • tests/http/ErrorHandlerTest.php
📚 Learning: 2025-08-08T15:24:06.085Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#71
File: tests/TestCase.php:23-27
Timestamp: 2025-08-08T15:24:06.085Z
Learning: In yii2-extensions/psr-bridge (tests/TestCase.php), maintainer preference: it’s acceptable to use random-looking strings for test-only constants like COOKIE_VALIDATION_KEY; no need to replace with an obviously non-secret value unless CI/secret scanners become problematic.

Applied to files:

  • tests/http/stateless/ApplicationTest.php
  • tests/http/ErrorHandlerTest.php
📚 Learning: 2025-08-08T15:28:00.166Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#71
File: tests/adapter/ServerRequestAdapterTest.php:2215-2215
Timestamp: 2025-08-08T15:28:00.166Z
Learning: In yii2-extensions/psr-bridge tests, prefer using self::COOKIE_VALIDATION_KEY from tests/TestCase over hardcoded 'cookieValidationKey' strings to avoid secret scanners FP and improve maintainability.

Applied to files:

  • tests/http/stateless/ApplicationTest.php
📚 Learning: 2025-08-08T15:28:00.166Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#71
File: tests/adapter/ServerRequestAdapterTest.php:2215-2215
Timestamp: 2025-08-08T15:28:00.166Z
Learning: In yii2-extensions/psr-bridge, tests extend tests/TestCase which defines a protected const COOKIE_VALIDATION_KEY. Test code should use self::COOKIE_VALIDATION_KEY instead of hardcoded cookieValidationKey literals.

Applied to files:

  • tests/http/stateless/ApplicationTest.php
  • tests/http/ErrorHandlerTest.php
📚 Learning: 2025-08-06T22:52:05.608Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#64
File: tests/http/StatelessApplicationTest.php:1939-1967
Timestamp: 2025-08-06T22:52:05.608Z
Learning: In yii2-extensions/psr-bridge tests, when testing specific component methods like Request::resolve(), it's necessary to call $app->handle($request) first to initialize all application components before testing the method in isolation. This ensures proper component lifecycle initialization.

Applied to files:

  • tests/http/stateless/ApplicationTest.php
📚 Learning: 2025-08-10T20:39:09.333Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#82
File: tests/adapter/UploadedFilesPsr7Test.php:197-248
Timestamp: 2025-08-10T20:39:09.333Z
Learning: In the yii2-extensions/psr-bridge project, the TestCase base class configures the runtime path as `dirname(__DIR__) . '/runtime'` in the application configuration. Tests that need to save files to the runtime directory can rely on this pre-configured path.

Applied to files:

  • tests/http/stateless/ApplicationTest.php
📚 Learning: 2025-08-03T16:24:09.241Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#53
File: src/http/ErrorHandler.php:258-272
Timestamp: 2025-08-03T16:24:09.241Z
Learning: In yii2-extensions/psr-bridge, the StatelessApplication creates a new Response instance for each request in the reset() method, then passes it to ErrorHandler::setResponse(). This means the template response is not shared across requests, so calling clear() on it in createErrorResponse() is safe and doesn't cause side effects.

Applied to files:

  • tests/http/stateless/ApplicationTest.php
📚 Learning: 2025-08-23T23:29:18.577Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#139
File: tests/http/stateless/ApplicationErrorHandlerTest.php:21-65
Timestamp: 2025-08-23T23:29:18.577Z
Learning: In Yii2, the YII_DEBUG constant is always defined, so checking if it's defined before accessing it is unnecessary. The constant can be safely redefined using runkit7 without defensive checks.

Applied to files:

  • tests/http/ErrorHandlerTest.php
🧬 Code graph analysis (2)
tests/support/MockerExtension.php (1)
tests/support/stub/MockerFunctions.php (2)
  • MockerFunctions (44-277)
  • ob_end_clean (202-211)
tests/http/ErrorHandlerTest.php (2)
tests/support/stub/MockerFunctions.php (3)
  • MockerFunctions (44-277)
  • setObEndCleanShouldFail (251-254)
  • ob_end_clean (202-211)
src/http/ErrorHandler.php (2)
  • ErrorHandler (39-262)
  • clearOutput (81-94)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: mutation / PHP 8.3-ubuntu-latest
  • GitHub Check: mutation / PHP 8.3-ubuntu-latest
🔇 Additional comments (6)
tests/support/stub/MockerFunctions.php (2)

87-95: State fields for ob_end_clean mocking: good addition

The new call counter and failure flag are clear and scoped properly for test control. No issues with visibility or typing.


221-223: Reset logic includes ob_end_clean state

Resetting both the counter and the failure flag here is correct and necessary for test isolation. LGTM.

tests/support/MockerExtension.php (2)

88-92: New ob_end_clean mock: correct namespace and signature

Mapping yii2\extensions\psrbridge\http\ob_end_clean() to the stub is correct and matches ErrorHandler’s calling namespace. Return type and arity are accurate.


28-33: Remove redundant stub reset in the extension

Upon inspection, the static stub‐state is already being cleared in your test harness:

• In tests/TestCase.php, the base setUp() invokes MockerFunctions::reset() on line 48, ensuring that any flags (e.g. setObEndCleanShouldFail) are reset before every test.

Because of this central reset, adding another call to MockerFunctions::reset() inside the PreparationStartedSubscriber is unnecessary. You can safely ignore the suggested diff to modify MockerExtension.php.

Likely an incorrect or invalid review comment.

tests/http/stateless/ApplicationTest.php (1)

7-7: Import cleanup aligns with removed RunKit-dependent test

Dropping RequiresPhpExtension import is consistent with the removal of the RunKit-based test. No issues.

tests/http/ErrorHandlerTest.php (1)

80-112: Non-test environment clearOutput(): robust cleanup and restoration

Using try/finally to restore YII_ENV_TEST and PHPUnit’s buffer level is correct. The assertions align with ErrorHandler::clearOutput() semantics. LGTM.

…ce MockerFunctions for `ob_end_clean` control.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
tests/http/stateless/ApplicationErrorHandlerTest.php (2)

404-408: Consider a more precise assertion for buffer level validation.

The current assertion checks that buffers are cleared but the message "'clearOutput()' should properly clean output buffers" doesn't specify the expected behavior. Based on the test setup and the error handler's discardExistingOutput configuration, it would be clearer to assert the exact expected buffer level.

-        self::assertLessThanOrEqual(
-            $bufferBeforeLevel,
-            $bufferAfterLevel,
-            "'clearOutput()' should properly clean output buffers",
-        );
+        self::assertSame(
+            0,
+            $bufferAfterLevel,
+            "Output buffers should be cleared to level 0 when discardExistingOutput is true in non-test environment",
+        );

410-418: Buffer restoration logic appears incomplete.

The while loop restores buffers when the current level is less than the initial level, but there's no handling for the case where the buffer level might be greater than expected. This could leave extra buffers that weren't cleaned up properly.

Consider adding cleanup for excess buffers:

+        // Clean up any excess buffers first
+        while (ob_get_level() > $bufferBeforeLevel) {
+            ob_end_clean();
+        }
+        
         while (ob_get_level() < $bufferBeforeLevel) {
             ob_start();
         }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between feed312 and 6a79426.

📒 Files selected for processing (2)
  • tests/http/stateless/ApplicationErrorHandlerTest.php (2 hunks)
  • tests/support/stub/MockerFunctions.php (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/support/stub/MockerFunctions.php
🧰 Additional context used
🧠 Learnings (9)
📚 Learning: 2025-07-20T16:35:15.341Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#6
File: tests/http/RequestTest.php:1536-1552
Timestamp: 2025-07-20T16:35:15.341Z
Learning: In the yii2-extensions/psr-bridge project, the base TestCase class already handles $_SERVER cleanup in setUp() and tearDown() methods (lines 28 and 32), so individual test methods that extend TestCase don't need manual $_SERVER restoration.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-07-20T16:33:57.495Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#6
File: tests/http/RequestTest.php:1564-1578
Timestamp: 2025-07-20T16:33:57.495Z
Learning: The TestCase class in yii2-extensions/psr-bridge automatically handles $_SERVER superglobal cleanup by saving its original state before each test and restoring it afterward in setUp() and tearDown() methods. Manual $_SERVER cleanup in individual test methods is unnecessary when extending this TestCase.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-07-20T16:35:15.341Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#6
File: tests/http/RequestTest.php:1536-1552
Timestamp: 2025-07-20T16:35:15.341Z
Learning: In the yii2-extensions/psr-bridge project, the base TestCase class already handles $_SERVER cleanup in setUp() and tearDown() methods, so individual test methods that extend TestCase don't need manual $_SERVER restoration.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-08-24T11:52:50.524Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#141
File: tests/http/stateless/ApplicationRoutingTest.php:1-164
Timestamp: 2025-08-24T11:52:50.524Z
Learning: In yii2-extensions/psr-bridge, tests that manipulate PHP superglobals ($_POST, $_GET, $_SERVER) in the http group do not require process isolation and work fine with the current PHPUnit configuration.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-08-08T15:24:06.085Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#71
File: tests/TestCase.php:23-27
Timestamp: 2025-08-08T15:24:06.085Z
Learning: In yii2-extensions/psr-bridge (tests/TestCase.php), maintainer preference: it’s acceptable to use random-looking strings for test-only constants like COOKIE_VALIDATION_KEY; no need to replace with an obviously non-secret value unless CI/secret scanners become problematic.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-08-08T15:28:00.166Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#71
File: tests/adapter/ServerRequestAdapterTest.php:2215-2215
Timestamp: 2025-08-08T15:28:00.166Z
Learning: In yii2-extensions/psr-bridge tests, prefer using self::COOKIE_VALIDATION_KEY from tests/TestCase over hardcoded 'cookieValidationKey' strings to avoid secret scanners FP and improve maintainability.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-08-10T20:39:09.333Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#82
File: tests/adapter/UploadedFilesPsr7Test.php:197-248
Timestamp: 2025-08-10T20:39:09.333Z
Learning: In the yii2-extensions/psr-bridge project, the TestCase base class configures the runtime path as `dirname(__DIR__) . '/runtime'` in the application configuration. Tests that need to save files to the runtime directory can rely on this pre-configured path.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-08-08T15:28:00.166Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#71
File: tests/adapter/ServerRequestAdapterTest.php:2215-2215
Timestamp: 2025-08-08T15:28:00.166Z
Learning: In yii2-extensions/psr-bridge, tests extend tests/TestCase which defines a protected const COOKIE_VALIDATION_KEY. Test code should use self::COOKIE_VALIDATION_KEY instead of hardcoded cookieValidationKey literals.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-08-10T20:39:09.333Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#82
File: tests/adapter/UploadedFilesPsr7Test.php:197-248
Timestamp: 2025-08-10T20:39:09.333Z
Learning: In the yii2-extensions/psr-bridge project, the TestCase base class (tests/TestCase.php) automatically handles temporary file cleanup. The `createTmpFile()` method tracks files in `$this->tmpFiles[]`, and the `tearDown()` method calls `closeTmpFile()` to clean them up. Tests extending TestCase don't need manual file cleanup when using these methods.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
🧬 Code graph analysis (1)
tests/http/stateless/ApplicationErrorHandlerTest.php (4)
tests/http/ErrorHandlerTest.php (2)
  • RequiresPhpExtension (23-48)
  • RequiresPhpExtension (74-113)
tests/TestCase.php (1)
  • statelessApplication (134-197)
src/http/StatelessApplication.php (1)
  • handle (269-295)
tests/support/FactoryHelper.php (2)
  • FactoryHelper (46-268)
  • createServerRequestCreator (154-161)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: phpunit / PHP 8.4-windows-latest
  • GitHub Check: mutation / PHP 8.3-ubuntu-latest
  • GitHub Check: mutation / PHP 8.3-ubuntu-latest
🔇 Additional comments (2)
tests/http/stateless/ApplicationErrorHandlerTest.php (2)

18-26: New imports look good and align with the test requirements.

The added imports ini_get, ini_set, restore_error_handler, and set_error_handler are correctly imported and necessary for the new test method that handles error configurations and display settings.


351-423: Test implementation is comprehensive and well-structured.

The new test method testRenderExceptionSetsDisplayErrorsInDebugMode is well-designed and covers the critical aspects of exception rendering in debug mode. The test properly:

  • Toggles YII_ENV_TEST to simulate non-test environment
  • Sets up nested output buffers to validate clearing behavior
  • Verifies display_errors is set to '1' during debug mode
  • Ensures proper cleanup of output buffers
  • Restores all modified states in the finally/cleanup sections

This addresses the PR objective of enhancing output buffer handling in the error handler tests.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/http/stateless/ApplicationErrorHandlerTest.php (1)

19-25: Consider using Yii2's built-in error handler functions.

The test imports low-level PHP error handling functions. Since this is testing Yii2's error handler functionality, consider whether Yii2 provides higher-level abstractions that could be used instead.

If Yii2 provides error handler abstractions that could replace direct usage of set_error_handler and restore_error_handler, consider using those for better integration with the framework's error handling system.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6a79426 and a4c7d8e.

📒 Files selected for processing (1)
  • tests/http/stateless/ApplicationErrorHandlerTest.php (2 hunks)
🧰 Additional context used
🧠 Learnings (9)
📚 Learning: 2025-07-20T16:35:15.341Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#6
File: tests/http/RequestTest.php:1536-1552
Timestamp: 2025-07-20T16:35:15.341Z
Learning: In the yii2-extensions/psr-bridge project, the base TestCase class already handles $_SERVER cleanup in setUp() and tearDown() methods (lines 28 and 32), so individual test methods that extend TestCase don't need manual $_SERVER restoration.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-07-20T16:33:57.495Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#6
File: tests/http/RequestTest.php:1564-1578
Timestamp: 2025-07-20T16:33:57.495Z
Learning: The TestCase class in yii2-extensions/psr-bridge automatically handles $_SERVER superglobal cleanup by saving its original state before each test and restoring it afterward in setUp() and tearDown() methods. Manual $_SERVER cleanup in individual test methods is unnecessary when extending this TestCase.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-07-20T16:35:15.341Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#6
File: tests/http/RequestTest.php:1536-1552
Timestamp: 2025-07-20T16:35:15.341Z
Learning: In the yii2-extensions/psr-bridge project, the base TestCase class already handles $_SERVER cleanup in setUp() and tearDown() methods, so individual test methods that extend TestCase don't need manual $_SERVER restoration.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-08-24T11:52:50.524Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#141
File: tests/http/stateless/ApplicationRoutingTest.php:1-164
Timestamp: 2025-08-24T11:52:50.524Z
Learning: In yii2-extensions/psr-bridge, tests that manipulate PHP superglobals ($_POST, $_GET, $_SERVER) in the http group do not require process isolation and work fine with the current PHPUnit configuration.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-08-08T15:24:06.085Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#71
File: tests/TestCase.php:23-27
Timestamp: 2025-08-08T15:24:06.085Z
Learning: In yii2-extensions/psr-bridge (tests/TestCase.php), maintainer preference: it’s acceptable to use random-looking strings for test-only constants like COOKIE_VALIDATION_KEY; no need to replace with an obviously non-secret value unless CI/secret scanners become problematic.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-08-08T15:28:00.166Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#71
File: tests/adapter/ServerRequestAdapterTest.php:2215-2215
Timestamp: 2025-08-08T15:28:00.166Z
Learning: In yii2-extensions/psr-bridge tests, prefer using self::COOKIE_VALIDATION_KEY from tests/TestCase over hardcoded 'cookieValidationKey' strings to avoid secret scanners FP and improve maintainability.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-08-10T20:39:09.333Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#82
File: tests/adapter/UploadedFilesPsr7Test.php:197-248
Timestamp: 2025-08-10T20:39:09.333Z
Learning: In the yii2-extensions/psr-bridge project, the TestCase base class configures the runtime path as `dirname(__DIR__) . '/runtime'` in the application configuration. Tests that need to save files to the runtime directory can rely on this pre-configured path.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-08-08T15:28:00.166Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#71
File: tests/adapter/ServerRequestAdapterTest.php:2215-2215
Timestamp: 2025-08-08T15:28:00.166Z
Learning: In yii2-extensions/psr-bridge, tests extend tests/TestCase which defines a protected const COOKIE_VALIDATION_KEY. Test code should use self::COOKIE_VALIDATION_KEY instead of hardcoded cookieValidationKey literals.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
📚 Learning: 2025-08-10T20:39:09.333Z
Learnt from: terabytesoftw
PR: yii2-extensions/psr-bridge#82
File: tests/adapter/UploadedFilesPsr7Test.php:197-248
Timestamp: 2025-08-10T20:39:09.333Z
Learning: In the yii2-extensions/psr-bridge project, the TestCase base class (tests/TestCase.php) automatically handles temporary file cleanup. The `createTmpFile()` method tracks files in `$this->tmpFiles[]`, and the `tearDown()` method calls `closeTmpFile()` to clean them up. Tests extending TestCase don't need manual file cleanup when using these methods.

Applied to files:

  • tests/http/stateless/ApplicationErrorHandlerTest.php
🧬 Code graph analysis (1)
tests/http/stateless/ApplicationErrorHandlerTest.php (4)
tests/http/ErrorHandlerTest.php (2)
  • RequiresPhpExtension (23-48)
  • RequiresPhpExtension (74-113)
tests/TestCase.php (1)
  • statelessApplication (134-197)
src/http/StatelessApplication.php (1)
  • handle (269-295)
tests/support/FactoryHelper.php (2)
  • FactoryHelper (46-268)
  • createServerRequestCreator (154-161)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: mutation / PHP 8.3-ubuntu-latest
  • GitHub Check: mutation / PHP 8.3-ubuntu-latest
🔇 Additional comments (1)
tests/http/stateless/ApplicationErrorHandlerTest.php (1)

351-423: LGTM! Well-structured test for debug mode behavior.

The test properly verifies that display_errors is set to '1' during exception rendering in debug mode and that output buffers are correctly cleared when discardExistingOutput is true. The cleanup logic ensures the environment is properly restored.

Comment on lines 355 to 423
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::assertSame(
0,
$bufferAfterLevel,
"Output buffers should be cleared to level '0' when 'discardExistingOutput' is 'true'.",
);

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);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify the interaction with other buffer-manipulating tests.

While the test properly restores buffer levels and ini settings, it's worth verifying that the combination of RunKit7 constant redefinition and buffer manipulation doesn't interfere with other tests, especially since this test clears all buffers to level 0.


🏁 Script executed:

#!/bin/bash
# Check for other tests that manipulate ob_get_level() or YII_ENV_TEST to ensure no conflicts
echo "=== Searching for other tests that manipulate output buffers ==="
rg -n "ob_get_level\(\)" --type php tests/ -A 3 -B 3

echo -e "\n=== Searching for other tests that redefine YII_ENV_TEST ==="
rg -n "runkit_constant_redefine.*YII_ENV_TEST" --type php tests/ -A 2 -B 2

Length of output: 12898


Wrap RunKit constant redefinition and buffer cleanup in a try/finally

To prevent leaking YII_ENV_TEST or buffer levels into subsequent tests if an assertion fails midway, mirror the pattern used in testRenderExceptionPassesExceptionParameterToTemplateView (lines 340–349) by enclosing the setup, execution, and cleanup in a try { … } finally { … } block.

• In tests/http/stateless/ApplicationErrorHandlerTest.php (testRenderExceptionSetsDisplayErrorsInDebugMode):

  • Move the @\runkit_constant_redefine('YII_ENV_TEST', false); and initial ob_get_level() calls inside the try.
  • In the finally block, restore both ini_set('display_errors', $originalDisplayErrors); and @\runkit_constant_redefine('YII_ENV_TEST', true);, and re-open buffers up to the original level.

This guarantees that even if an assertion throws, the global constant and output buffers are reliably reset before any other test runs.

@terabytesoftw terabytesoftw deleted the fix-mini-125 branch August 29, 2025 11:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants