Added integration tests for ApiExceptionDispatcher to ensure proper handling of exceptions for various API request scenarios, including JSON acceptance and unversioned requests.
81 lines
3.1 KiB
PHP
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);
|
|
});
|
|
});
|