1 | <?php |
||||
2 | |||||
3 | declare(strict_types=1); |
||||
4 | |||||
5 | namespace Cerbero\JsonApiError\Services; |
||||
6 | |||||
7 | use Cerbero\JsonApiError\Data\Dot; |
||||
8 | use Closure; |
||||
9 | use Illuminate\Testing\Assert; |
||||
10 | use Illuminate\Testing\TestResponse; |
||||
11 | use Symfony\Component\HttpFoundation\Response; |
||||
12 | |||||
13 | /** |
||||
14 | * The mixin to test JSON:API error responses. |
||||
15 | */ |
||||
16 | final class TestResponseMixin |
||||
17 | { |
||||
18 | /** |
||||
19 | * Assert that the response contains the given JSON:API error. |
||||
20 | * |
||||
21 | * @return Closure(string, int): TestResponse |
||||
22 | */ |
||||
23 | 12 | public function assertJsonApiError(): Closure |
|||
24 | { |
||||
25 | 12 | return function (string $detail, int $status = Response::HTTP_BAD_REQUEST) { |
|||
26 | /** |
||||
27 | * @var TestResponse $this |
||||
28 | */ |
||||
29 | 1 | return $this // @phpstan-ignore-line |
|||
30 | 1 | ->assertJsonApiErrorStructure() |
|||
31 | 1 | ->assertJsonPath('errors.0.status', (string) $status) |
|||
32 | 1 | ->assertJsonPath('errors.0.title', __("json-api-error::statuses.{$status}.title")) |
|||
33 | 1 | ->assertJsonPath('errors.0.detail', $detail); |
|||
34 | 12 | }; |
|||
35 | } |
||||
36 | |||||
37 | /** |
||||
38 | * Assert that the response contains the given JSON:API validation errors. |
||||
39 | * |
||||
40 | * @return Closure(array<string|int, string>): TestResponse |
||||
41 | */ |
||||
42 | 12 | public function assertJsonApiValidation(): Closure |
|||
43 | { |
||||
44 | 12 | return function (array $expected) { |
|||
45 | /** |
||||
46 | * @var TestResponse $this |
||||
47 | */ |
||||
48 | 1 | $this // @phpstan-ignore-line |
|||
49 | 1 | ->assertJsonApiErrorStructure() |
|||
50 | 1 | ->assertJsonPath('errors', fn(array $errors) => collect($errors)->every(function (array $error) { |
|||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
51 | 1 | return $error['status'] === '422' && $error['title'] === __('json-api-error::statuses.422.title'); |
|||
52 | 1 | })); |
|||
53 | |||||
54 | 1 | if (array_is_list($expected)) { |
|||
0 ignored issues
–
show
The function
array_is_list was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
55 | 1 | Assert::assertEqualsCanonicalizing($expected, $this->json('errors.*.detail')); |
|||
56 | |||||
57 | 1 | return $this; |
|||
58 | } |
||||
59 | |||||
60 | 1 | $actual = $this->collect('errors')->pluck('detail', 'source.pointer')->all(); |
|||
61 | |||||
62 | 1 | foreach ($expected as $dot => $detail) { |
|||
63 | 1 | $pointer = (new Dot($dot))->toJsonPointer(); |
|||
64 | 1 | $message = "The field [{$dot}] does not have the error [{$detail}]."; |
|||
65 | |||||
66 | 1 | Assert::assertSame($detail, $actual[$pointer] ?? null, $message); |
|||
67 | |||||
68 | 1 | unset($actual[$pointer]); |
|||
69 | } |
||||
70 | |||||
71 | 1 | Assert::assertEmpty($actual, 'Other unexpected validation errors occurred.'); |
|||
72 | |||||
73 | 1 | return $this; |
|||
74 | 12 | }; |
|||
75 | } |
||||
76 | |||||
77 | /** |
||||
78 | * Assert that the response contains the JSON:API error for the given HTTP status. |
||||
79 | * |
||||
80 | * @return Closure(int): TestResponse |
||||
81 | */ |
||||
82 | 12 | public function assertJsonApiErrorStatus(): Closure |
|||
83 | { |
||||
84 | 12 | return function (int $status) { |
|||
85 | /** |
||||
86 | * @var TestResponse $this |
||||
87 | */ |
||||
88 | 7 | return $this // @phpstan-ignore-line |
|||
89 | 7 | ->assertJsonApiErrorStructure() |
|||
90 | 7 | ->assertJsonPath('errors.0.status', (string) $status) |
|||
91 | 7 | ->assertJsonPath('errors.0.title', __("json-api-error::statuses.{$status}.title")) |
|||
92 | 7 | ->assertJsonPath('errors.0.detail', __("json-api-error::statuses.{$status}.detail")); |
|||
93 | 12 | }; |
|||
94 | } |
||||
95 | |||||
96 | /** |
||||
97 | * Assert that the response contains JSON:API compliant errors. |
||||
98 | * |
||||
99 | * @return Closure(): TestResponse |
||||
100 | */ |
||||
101 | 12 | public function assertJsonApiErrorStructure(): Closure |
|||
102 | { |
||||
103 | 12 | return function () { |
|||
104 | /** |
||||
105 | * @var TestResponse $this |
||||
106 | */ |
||||
107 | 9 | return $this->assertJsonStructure([ |
|||
108 | 9 | 'errors' => [ |
|||
109 | 9 | '*' => [ |
|||
110 | 9 | 'status', |
|||
111 | 9 | 'title', |
|||
112 | 9 | 'detail', |
|||
113 | 9 | ], |
|||
114 | 9 | ], |
|||
115 | 9 | ]); |
|||
116 | 12 | }; |
|||
117 | } |
||||
118 | } |
||||
119 |