Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make reporting of client-safe errors configurable #2647

Merged
Prev Previous commit
Next Next commit
CS fixes
remipelhate committed Dec 29, 2024
commit af3442b5c7a4c8cede77e36b42041dc615be60d3
15 changes: 6 additions & 9 deletions tests/FakeExceptionHandler.php
Original file line number Diff line number Diff line change
@@ -5,21 +5,18 @@
use Illuminate\Contracts\Debug\ExceptionHandler;
use PHPUnit\Framework\Assert;
use Symfony\Component\HttpFoundation\Response;
use Throwable;

final class FakeExceptionHandler implements ExceptionHandler
{
/**
* @var array<Throwable>
*/
/** @var array<\Throwable> */
private array $reported = [];

public function report(Throwable $e): void
public function report(\Throwable $e): void
{
$this->reported[] = $e;
}

public function shouldReport(Throwable $e): bool
public function shouldReport(\Throwable $e): bool
{
return true;
}
@@ -29,15 +26,15 @@ public function assertNothingReported(): void
Assert::assertEmpty($this->reported);
}

public function assertReported(Throwable $e): void
public function assertReported(\Throwable $e): void
{
Assert::assertContainsEquals($e, $this->reported);
}

public function render($request, Throwable $e): Response
public function render($request, \Throwable $e): Response
{
throw $e;
}

public function renderForConsole($output, Throwable $e) {}
public function renderForConsole($output, \Throwable $e) {}
}
42 changes: 18 additions & 24 deletions tests/Integration/Execution/ReportingErrorHandlerTest.php
Original file line number Diff line number Diff line change
@@ -2,18 +2,13 @@

namespace Tests\Integration\Execution;

use Exception;
use Generator;
use GraphQL\Error\ClientAware;
use GraphQL\Error\Error;
use Illuminate\Contracts\Config\Repository;
use LogicException;
use Nuwave\Lighthouse\Execution\ReportingErrorHandler;
use Tests\FakeExceptionHandler;
use Tests\TestCase;

use function compact;

final class ReportingErrorHandlerTest extends TestCase
{
private FakeExceptionHandler $handler;
@@ -35,7 +30,7 @@ public function testHandlingWhenThereIsNoError(): void
$config = $this->app->make(Repository::class);
$next = fn (?Error $error): array => match ($error) {
null => ['error' => 'No error to report'],
default => throw new LogicException('Unexpected error: ' . $error::class),
default => throw new \LogicException('Unexpected error: ' . $error::class),
};

$result = (new ReportingErrorHandler($this->handler, $config))(null, $next);
@@ -44,79 +39,78 @@ public function testHandlingWhenThereIsNoError(): void
$this->handler->assertNothingReported();
}

public static function shouldAlwaysReport(): Generator
public static function shouldAlwaysReport(): \Generator
{
yield 'Previous error is not client aware' => [new Exception('Not client aware')];
yield 'Previous error is not client aware' => [new \Exception('Not client aware')];
yield 'Previous error is not client safe' => [self::clientSafeError(false)];
}

/** @dataProvider shouldAlwaysReport */
public function testErrorsThatShouldAlwaysReportWithDefaultConfig(Exception $previousError): void
public function testErrorsThatShouldAlwaysReportWithDefaultConfig(\Exception $previousError): void
{
$config = $this->app->make(Repository::class);
$error = new Error(previous: $previousError);
$next = fn (Error $error): array => compact('error');
$next = fn (Error $error): array => \compact('error');

$result = (new ReportingErrorHandler($this->handler, $config))($error, $next);

$this->assertSame(compact('error'), $result);
$this->assertSame(\compact('error'), $result);
$this->handler->assertReported($previousError);
}

/** @dataProvider shouldAlwaysReport */
public function testErrorsThatShouldAlwaysReportWithReportClientSafeEnabled(Exception $previousError): void
public function testErrorsThatShouldAlwaysReportWithReportClientSafeEnabled(\Exception $previousError): void
{
$config = $this->app->make(Repository::class);
$config->set('lighthouse.report_client_safe_errors', true);
$error = new Error(previous: $previousError);
$next = fn (Error $error): array => compact('error');
$next = fn (Error $error): array => \compact('error');

$result = (new ReportingErrorHandler($this->handler, $config))($error, $next);

$this->assertSame(compact('error'), $result);
$this->assertSame(\compact('error'), $result);
$this->handler->assertReported($previousError);
}

public static function clientSafeErrors(): Generator
public static function clientSafeErrors(): \Generator
{
yield 'No previous error' => [null];
yield 'Previous error is client safe' => [self::clientSafeError(true)];
}

/** @dataProvider clientSafeErrors */
public function testClientSafeErrorsWithDefaultConfig(?Exception $previousError): void
public function testClientSafeErrorsWithDefaultConfig(?\Exception $previousError): void
{
$config = $this->app->make(Repository::class);
$error = new Error(previous: $previousError);
$next = fn (Error $error): array => compact('error');
$next = fn (Error $error): array => \compact('error');

$result = (new ReportingErrorHandler($this->handler, $config))($error, $next);

$this->assertSame(compact('error'), $result);
$this->assertSame(\compact('error'), $result);
$this->handler->assertNothingReported();
}

/** @dataProvider clientSafeErrors */
public function testClientSafeErrorsWithReportClientSafeEnabled(?Exception $previousError): void
public function testClientSafeErrorsWithReportClientSafeEnabled(?\Exception $previousError): void
{
$config = $this->app->make(Repository::class);
$config->set('lighthouse.report_client_safe_errors', true);
$error = new Error(previous: $previousError);
$next = fn (Error $error): array => compact('error');
$next = fn (Error $error): array => \compact('error');

$result = (new ReportingErrorHandler($this->handler, $config))($error, $next);

$this->assertSame(compact('error'), $result);
$this->assertSame(\compact('error'), $result);
$this->handler->assertReported(match ($previousError) {
null => $error,
default => $previousError,
});
}

private static function clientSafeError(bool $clientSafe): Exception
private static function clientSafeError(bool $clientSafe): \Exception
{
return new class ($clientSafe) extends Exception implements ClientAware
{
return new class($clientSafe) extends \Exception implements ClientAware {
public function __construct(
private bool $clientSafe,
) {