@@ -17,6 +17,7 @@ public function setUp(): void
1717 {
1818 date_default_timezone_set ("UTC " );
1919 ExceptionCapture::resetForTests ();
20+ ExceptionCapture::enableThrowOnUnhandledForTests ();
2021
2122 global $ errorMessages ;
2223 $ errorMessages = [];
@@ -144,21 +145,31 @@ public function testExceptionHandlerCapturesFlushesAndChainsPreviousHandler(): v
144145 }
145146 }
146147
147- public function testExceptionHandlerRethrowsWhenNoPreviousHandlerExists (): void
148+ public function testExceptionHandlerWithoutPreviousHandlerLogsAndExits (): void
148149 {
149- $ this ->buildClient (['error_tracking ' => ['enabled ' => true ]]);
150- $ exception = new \RuntimeException ('uncaught without previous ' );
150+ $ result = $ this ->runStandaloneScript (<<<'PHP'
151+ $http = new \PostHog\Test\MockedHttpClient("app.posthog.com");
152+ new \PostHog\Client("key", ["debug" => true, "error_tracking" => ["enabled" => true]], $http, null, false);
151153
152- try {
153- ExceptionCapture::handleException ($ exception );
154- $ this ->fail ('Expected the uncaught exception to be rethrown ' );
155- } catch (\RuntimeException $ caught ) {
156- $ this ->assertSame ($ exception , $ caught );
157- }
154+ register_shutdown_function(static function () use ($http): void {
155+ global $errorMessages;
158156
159- $ event = $ this ->findExceptionEvent ();
157+ echo json_encode([
158+ 'calls' => $http->calls,
159+ 'error_messages' => $errorMessages,
160+ ], JSON_THROW_ON_ERROR);
161+ });
162+
163+ throw new \RuntimeException('uncaught without previous');
164+ PHP, 255 , false );
165+
166+ $ this ->assertCount (1 , $ result ['calls ' ]);
167+ $ payload = json_decode ($ result ['calls ' ][0 ]['payload ' ], true );
168+ $ event = $ payload ['batch ' ][0 ];
160169 $ this ->assertFalse ($ event ['properties ' ]['$exception_handled ' ]);
161170 $ this ->assertSame ('php_exception_handler ' , $ event ['properties ' ]['$exception_source ' ]);
171+ $ this ->assertNotEmpty ($ result ['error_messages ' ]);
172+ $ this ->assertStringContainsString ('uncaught without previous ' , $ result ['error_messages ' ][0 ]);
162173 }
163174
164175 public function testErrorHandlerCapturesNonFatalErrorsWithoutCaptureFrames (): void
@@ -609,14 +620,20 @@ private function framesContainFunction(array $frames, string $function): bool
609620 /**
610621 * @return array<string, mixed>
611622 */
612- private function runStandaloneScript (string $ body ): array
613- {
623+ private function runStandaloneScript (
624+ string $ body ,
625+ int $ expectedExitCode = 0 ,
626+ bool $ throwOnUnhandledInTests = true
627+ ): array {
614628 $ scriptPath = tempnam (sys_get_temp_dir (), 'posthog-error-tracking- ' );
615629 $ this ->assertNotFalse ($ scriptPath );
616630
617631 $ autoloadPath = var_export (realpath (__DIR__ . '/../vendor/autoload.php ' ), true );
618632 $ errorLogMockPath = var_export (realpath (__DIR__ . '/error_log_mock.php ' ), true );
619633 $ mockedHttpClientPath = var_export (realpath (__DIR__ . '/MockedHttpClient.php ' ), true );
634+ $ throwOnUnhandledBootstrap = $ throwOnUnhandledInTests
635+ ? "\n\\PostHog \\ExceptionCapture::enableThrowOnUnhandledForTests(); "
636+ : '' ;
620637
621638 $ script = <<<PHP
622639<?php
@@ -625,6 +642,7 @@ private function runStandaloneScript(string $body): array
625642require {$ mockedHttpClientPath };
626643
627644\PostHog\ExceptionCapture::resetForTests();
645+ {$ throwOnUnhandledBootstrap }
628646{$ body }
629647PHP ;
630648
@@ -636,7 +654,7 @@ private function runStandaloneScript(string $body): array
636654
637655 exec (PHP_BINARY . ' ' . escapeshellarg ($ scriptPath ), $ output , $ exitCode );
638656
639- $ this ->assertSame (0 , $ exitCode , implode ("\n" , $ output ));
657+ $ this ->assertSame ($ expectedExitCode , $ exitCode , implode ("\n" , $ output ));
640658
641659 $ decoded = json_decode (implode ("\n" , $ output ), true );
642660 $ this ->assertIsArray ($ decoded );
0 commit comments