ldc-arcadia-api/tests/Integration/Presentation/Api/ApiExceptionDispatcherTest.php
Jérémy Munsch 6ba04fe009
feat(exceptions): add NotFoundException for entity handling
Introduces a NotFoundException to standardize error handling for missing entities.
2026-08-13 16:24:08 +02:00

81 lines
3.1 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Integration\Presentation\Api;
use Application\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);
});
});