ldc-arcadia-api/tests/Integration/Presentation/Api/ApiExceptionDispatcherTest.php
Jérémy Munsch 52d0e6f0fd
test(ApiExceptionDispatcher): add integration tests for exception handling
Added integration tests for ApiExceptionDispatcher to ensure proper handling of exceptions
for various API request scenarios, including JSON acceptance and unversioned requests.
2026-08-13 12:34:44 +02:00

81 lines
3.1 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Integration\Presentation\Api;
use Domain\Exceptions\NotFoundException;
use Illuminate\Http\Request;
use Presentation\Api\Exceptions\ApiExceptionDispatcher;
use Presentation\Api\V1\Exceptions\ApiExceptionRenderer as V1ApiExceptionRenderer;
covers(ApiExceptionDispatcher::class);
describe('API Exception Dispatcher Integration', function (): void {
it('returns null for non-API web requests that do not accept JSON', function (): void {
// GIVEN
$dispatcher = new ApiExceptionDispatcher(new V1ApiExceptionRenderer());
$request = Request::create('/some-web-route', 'GET');
$exception = new NotFoundException('Not found');
// WHEN
$response = $dispatcher->render($exception, $request);
// THEN
expect($response)->toBeNull();
});
it('dispatches api/v1 requests to V1ApiExceptionRenderer', function (): void {
// GIVEN
$dispatcher = new ApiExceptionDispatcher(new V1ApiExceptionRenderer());
$request = Request::create('http://localhost/api/v1/employees/999', 'GET');
$exception = new NotFoundException('Employee not found');
// WHEN
$response = $dispatcher->render($exception, $request);
// THEN
expect($response)->not->toBeNull()
->and($response?->getStatusCode())->toBe(404)
->and($response?->headers->get('Content-Type'))->toBe('application/problem+json');
/** @var array<string, mixed> $data */
$data = json_decode((string) $response?->getContent(), true);
expect($data['status'])->toBe(404)
->and($data['title'])->toBe('Resource Not Found')
->and($data['detail'])->toBe('Employee not found');
});
it('falls back to V1ApiExceptionRenderer for unversioned api requests', function (): void {
// GIVEN
$dispatcher = new ApiExceptionDispatcher(new V1ApiExceptionRenderer());
$request = Request::create('http://localhost/api/ping', 'GET');
$exception = new \DomainException('Domain invariant error');
// WHEN
$response = $dispatcher->render($exception, $request);
// THEN
expect($response)->not->toBeNull()
->and($response?->getStatusCode())->toBe(422);
/** @var array<string, mixed> $data */
$data = json_decode((string) $response?->getContent(), true);
expect($data['status'])->toBe(422)
->and($data['detail'])->toBe('Domain invariant error');
});
it('dispatches to V1ApiExceptionRenderer when request accepts JSON even on non-api path', function (): void {
// GIVEN
$dispatcher = new ApiExceptionDispatcher(new V1ApiExceptionRenderer());
$request = Request::create('http://localhost/custom-endpoint', 'GET', [], [], [], ['HTTP_ACCEPT' => 'application/json']);
$exception = new NotFoundException('Custom endpoint not found');
// WHEN
$response = $dispatcher->render($exception, $request);
// THEN
expect($response)->not->toBeNull()
->and($response?->getStatusCode())->toBe(404);
});
});