10000 [Bugfix] Fix parsing exceptions in exception parser class · chris-doehring/laravel-json-api@9bfa073 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9bfa073

Browse files
committed
[Bugfix] Fix parsing exceptions in exception parser class
See cloudcreativity#566
1 parent dc096dd commit 9bfa073

File tree

6 files changed

+177
-9
lines changed

6 files changed

+177
-9
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22
All notable changes to this project will be documented in this file. This project adheres to
33
[Semantic Versioning](http://semver.org/) and [this changelog format](http://keepachangelog.com/).
44

5+
## Unreleased
6+
7+
### Added
8+
- [#563](https://github.com/cloudcreativity/laravel-json-api/pull/563)
9+
Added Dutch translation files for validation and errors.
10+
11+
### Fixed
12+
- [#566](https://github.com/cloudcreativity/laravel-json-api/issues/566)
13+
Ensure the exception parser correctly parses an instance of this package's `JsonApiException`.
14+
- Exception parser now correctly uses the Symfony `HttpExceptionInterface` instead of the
15+
actual `HttpException` instance. Although this change would break consuming applications
16+
that have extended the `ExceptionParser` class, it is considered a bug fix as it should
17+
have been type-hinting the interface in `v3.0.0`.
18+
519
## [3.0.1] - 2020-10-14
620

721
### Fixed

src/Exceptions/ExceptionParser.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,14 @@
2121
use CloudCreativity\LaravelJsonApi\Contracts\Exceptions\ExceptionParserInterface;
2222
use CloudCreativity\LaravelJsonApi\Document\Error\Translator;
2323
use CloudCreativity\LaravelJsonApi\Encoder\Neomerx\Document\Errors as NeomerxErrors;
24-
use Exception;
2524
use Illuminate\Auth\Access\AuthorizationException;
2625
use Illuminate\Auth\AuthenticationException;
2726
use Illuminate\Http\Response;
2827
use Illuminate\Session\TokenMismatchException;
2928
use Illuminate\Validation\ValidationException as IlluminateValidationException;
3029
use Neomerx\JsonApi\Contracts\Document\ErrorInterface;
3130
use Neomerx\JsonApi\Document\Error;
32-
use Neomerx\JsonApi\Exceptions\JsonApiException;
33-
use Symfony\Component\HttpKernel\Exception\HttpException;
31+
use Neomerx\JsonApi\Exceptions\JsonApiException as NeomerxJsonApiException;
3432
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
3533

3634
/**
@@ -62,6 +60,10 @@ public function __construct(Translator $translator)
6260
public function parse(\Throwable $e): DocumentInterface
6361
{
6462
if ($e instanceof JsonApiException) {
63+
return $e->getErrors();
64+
}
65+
66+
if ($e instanceof NeomerxJsonApiException) {
6567
return NeomerxErrors::cast($e);
6668
}
6769

@@ -95,7 +97,7 @@ protected function getErrors(\Throwable $e): array
9597
return [$this->translator->tokenMismatch()];
9698
}
9799

98-
if ($e instanceof HttpException) {
100+
if ($e instanceof HttpExceptionInterface) {
99101
return [$this->getHttpError($e)];
100102
}
101103

@@ -112,10 +114,10 @@ protected function getValidationError(IlluminateValidationException $e): array
112114
}
113115

114116
/**
115-
* @param HttpException $e
117+
* @param HttpExceptionInterface $e
116118
* @return ErrorInterface
117119
*/
118-
protected function getHttpError(HttpException $e): ErrorInterface
120+
protected function getHttpError(HttpExceptionInterface $e): ErrorInterface
119121
{
120122
$status = $e->getStatusCode();
121123
$title = $this->getDefaultTitle($status);

src/Exceptions/JsonApiException.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,22 @@ public function getHeaders()
9292
return $this->headers;
9393
}
9494

95+
/**
96+
* @return Errors
97+
*/
98+
public function getErrors(): Errors
99+
{
100+
return $this->errors
101+
->withHeaders($this->headers);
102+
}
103+
95104
/**
96105
* @inheritDoc
97106
*/
98107
public function toResponse($request)
99108
{
100-
return $this->errors
101-
->withHeaders($this->headers)
109+
return $this
110+
->getErrors()
102111
->toResponse($request);
103112
}
104113

tests/lib/Integration/ErrorsTest.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use DummyApp\Post;
2727
use Illuminate\Contracts\Validation\Validator;
2828
use Illuminate\Foundation\Http\Exceptions\MaintenanceModeException;
29+
use Illuminate\Http\Response;
2930
use Illuminate\Session\TokenMismatchException;
3031
use Illuminate\Support\Facades\Route;
3132
use Illuminate\Support\MessageBag;
@@ -261,7 +262,7 @@ public function testNeomerxJsonApiException()
261262
->assertSee('My foobar error message.');
262263
}
263264

264-
public function testJsonApiException(): void
265+
public function testJsonApiException1(): void
265266
{
266267
Route::get('/test', function () {
267268
throw JsonApiException::make(Error::fromArray([
@@ -286,6 +287,35 @@ public function testJsonApiException(): void
286287
->assertExactJson($expected);
287288
}
288289

290+
/**
291+
* @see https://github.com/cloudcreativity/laravel-json-api/issues/566
292+
*/
293+
public function testJsonApiException2(): void
294+
{
295+
Route::get('/test', function () {
296+
$error = Error::fromArray([
297+
'title' => 'The language you want to use is not active',
298+
'status' => Response::HTTP_UNPROCESSABLE_ENTITY,
299+
]);
300+
301+
throw new JsonApiException($error);
302+
});
303+
304+
$expected = [
305+
'errors' => [
306+
[
307+
'status' => '422',
308+
'title' => 'The language you want to use is not active',
309+
],
310+
],
311+
];
312+
313+
$this->get('/test')
314+
->assertStatus(422)
315+
->assertHeader('Content-Type', 'application/vnd.api+json')
316+
->assertExactJson($expected);
317+
}
318+
28 10000 9319
public function testMaintenanceMode()
290320
{
291321
$ex = new MaintenanceModeException(Carbon::now()->getTimestamp(), 60, "We'll be back soon.");
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
/**
3+
* Copyright 2020 Cloud Creativity Limited
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
declare(strict_types=1);
19+
20+
namespace CloudCreativity\LaravelJsonApi\Tests\Integration\Issue566;
21+
22+
use CloudCreativity\LaravelJsonApi\Document\Error\Error;
23+
use CloudCreativity\LaravelJsonApi\Document\ResourceObject;
24+
use CloudCreativity\LaravelJsonApi\Exceptions\JsonApiException;
25+
use DummyApp\JsonApi\Posts\Adapter as PostAdapter;
26+
use DummyApp\Post;
27+
use Illuminate\Http\Response;
28+
29+
class Adapter extends PostAdapter
30+
{
31+
32+
/**
33+
* @param Post $post
34+
* @param ResourceObject $resource
35+
* @throws JsonApiException
36+
*/
37+
protected function creating(Post $post, ResourceObject $resource): void
38+
{
39+
$error = Error::fromArray([
40+
'title' => 'The language you want to use is not active',
41+
'status' => Response::HTTP_UNPROCESSABLE_ENTITY,
42+
]);
43+
44+
throw new JsonApiException($error);
45+
}
46+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
/**
3+
* Copyright 2020 Cloud Creativity Limited
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
declare(strict_types=1);
19+
20+
namespace CloudCreativity\LaravelJsonApi\Tests\Integration\Issue566;
21+
22+
use CloudCreativity\LaravelJsonApi\Tests\Integration\TestCase;
23+
use DummyApp\Post;
24+
25+
class Test extends TestCase
26+
{
27+
28+
/**
29+
* @return void
30+
*/
31+
protected function setUp(): void
32+
{
33+
parent::setUp();
34+
35+
$this->app->bind(\DummyApp\JsonApi\Posts\Adapter::class, Adapter::class);
36+
}
37+
38+
public function test(): void
39+
{
40+
$model = factory(Post::class)->make();
41+
42+
$data = [
43+
'type' => 'posts',
44+
'attributes' => [
45+
'title' => $model->title,
46+
'slug' => $model->slug,
47+
'content' => $model->content,
48+
],
49+
'relationships' => [
50+
'author' => [
51+
'data' => [
52+
'type' => 'users',
53+
'id' => (string) $model->author->getRouteKey(),
54+
],
55+
],
56+
],
57+
];
58+
59+
$expected = [
60+
'title' => 'The language you want to use is not active',
61+
'status' => '422',
62+
];
63+
64+
$response = $this->jsonApi()->withData($data)->post('/api/v1/posts');
65+
$response->assertExactErrorStatus($expected);
66+
}
67+
}

0 commit comments

Comments
 (0)
0