render($exception, $request); // THEN expect($response)->toBeNull(); }); it('dispatches api/v1 requests to V1ApiExceptionRenderer', function (): void { // GIVEN $config = resolve(AppConfig::class); $renderer = new V1ApiExceptionRenderer($config); $dispatcher = new ApiExceptionDispatcher($renderer); $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'); }); it('falls back to V1ApiExceptionRenderer for unversioned api requests', function (): void { // GIVEN $config = resolve(AppConfig::class); $renderer = new V1ApiExceptionRenderer($config); $dispatcher = new ApiExceptionDispatcher($renderer); $request = Request::create('http://localhost/api/unknown-endpoint', 'GET'); $request->headers->set('Accept', 'application/json'); $exception = new NotFoundException('Resource 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'); }); it('dispatches to V1ApiExceptionRenderer when request accepts JSON even on non-api path', function (): void { // GIVEN $config = resolve(AppConfig::class); $renderer = new V1ApiExceptionRenderer($config); $dispatcher = new ApiExceptionDispatcher($renderer); $request = Request::create('http://localhost/something-else', 'GET'); $request->headers->set('Accept', 'application/json'); $exception = new NotFoundException('Something 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'); }); });