Skip to content

Commit 9e8f5be

Browse files
committed
wip
1 parent be5fba2 commit 9e8f5be

File tree

2 files changed

+131
-6
lines changed

2 files changed

+131
-6
lines changed

src/Recorders/ValidationErrors.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ protected function parseJsonValidationErrors(Request $request, BaseResponse $res
113113
! is_array($response->original) ||
114114
! array_key_exists('errors', $response->original) ||
115115
! is_array($response->original['errors']) ||
116-
! array_is_list($response->original['errors'])
116+
array_is_list($response->original['errors'])
117117
) {
118118
return null;
119119
}

tests/Feature/Recorders/ValidationErrorsTest.php

Lines changed: 130 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
<?php
22

3+
use Illuminate\Http\JsonResponse as IlluminateJsonResponse;
34
use Illuminate\Support\Facades\DB;
45
use Illuminate\Support\Facades\Request;
56
use Illuminate\Support\Facades\Route;
67
use Laravel\Pulse\Facades\Pulse;
78
use Laravel\Pulse\Recorders\ValidationErrors;
9+
use Symfony\Component\HttpFoundation\JsonResponse as SymfonyJsonResponse;
810

911
use function Pest\Laravel\post;
12+
use function Pest\Laravel\postJson;
1013

1114
beforeEach(fn () => Pulse::register([ValidationErrors::class => []]));
1215

@@ -17,19 +20,46 @@
1720

1821
$response = post('users');
1922

23+
$response->assertStatus(302);
2024
$response->assertInvalid('email');
21-
2225
$entries = Pulse::ignore(fn () => DB::table('pulse_entries')->whereType('validation_error')->get());
2326
expect($entries)->toHaveCount(1);
2427
expect($entries[0]->key)->toBe('["POST","\/users","Closure","email"]');
25-
2628
$aggregates = Pulse::ignore(fn () => DB::table('pulse_aggregates')->whereType('validation_error')->orderBy('period')->get());
2729
expect($aggregates->pluck('key')->all())->toBe(array_fill(0, 4, '["POST","\/users","Closure","email"]'));
2830
expect($aggregates->pluck('aggregate')->all())->toBe(array_fill(0, 4, 'count'));
2931
expect($aggregates->pluck('value')->all())->toBe(array_fill(0, 4, '1.00'));
3032
});
3133

32-
it('captures one entry for field when multiple errors are present for the given field from the session', function () {
34+
it('does not capture validation errors from redirects when there is no session', function () {
35+
Route::post('users', fn () => Request::validate([
36+
'email' => 'required',
37+
]));
38+
39+
$response = post('users');
40+
41+
$response->assertStatus(302);
42+
$response->assertInvalid('email');
43+
$entries = Pulse::ignore(fn () => DB::table('pulse_entries')->whereType('validation_error')->get());
44+
expect($entries)->toHaveCount(0);
45+
$aggregates = Pulse::ignore(fn () => DB::table('pulse_aggregates')->whereType('validation_error')->orderBy('period')->get());
46+
expect($aggregates)->toHaveCount(0);
47+
});
48+
49+
it('does not capture validation errors from redirects when the "errors" key is not a ViewErrorBag with session', function () {
50+
Route::post('users', fn () => redirect()->back()->with('errors', 'Something happened!'))->middleware('web');
51+
52+
$response = post('users');
53+
54+
$response->assertStatus(302);
55+
$entries = Pulse::ignore(fn () => DB::table('pulse_entries')->whereType('validation_error')->get());
56+
expect($entries)->toHaveCount(0);
57+
$aggregates = Pulse::ignore(fn () => DB::table('pulse_aggregates')->whereType('validation_error')->orderBy('period')->get());
58+
expect($aggregates)->toHaveCount(0);
59+
});
60+
61+
62+
it('captures one entry for a field when multiple errors are present for the given field from the session', function () {
3363
Route::post('users', fn () => Request::validate([
3464
'email' => 'string|min:5',
3565
]))->middleware('web');
@@ -46,11 +76,9 @@
4676
],
4777
]);
4878
$response->assertInvalid(['email' => 'The email field must be at least 5 characters.']);
49-
5079
$entries = Pulse::ignore(fn () => DB::table('pulse_entries')->whereType('validation_error')->get());
5180
expect($entries)->toHaveCount(1);
5281
expect($entries[0]->key)->toBe('["POST","\/users","Closure","email"]');
53-
5482
$aggregates = Pulse::ignore(fn () => DB::table('pulse_aggregates')->whereType('validation_error')->orderBy('period')->get());
5583
expect($aggregates->pluck('key')->all())->toBe(array_fill(0, 4, '["POST","\/users","Closure","email"]'));
5684
expect($aggregates->pluck('aggregate')->all())->toBe(array_fill(0, 4, 'count'));
@@ -63,11 +91,108 @@
6391
$response = post('users');
6492

6593
$response->assertStatus(422);
94+
$entries = Pulse::ignore(fn () => DB::table('pulse_entries')->whereType('validation_error')->get());
95+
expect($entries)->toHaveCount(1);
96+
expect($entries[0]->key)->toBe('["POST","\/users","Closure","__unknown"]');
97+
$aggregates = Pulse::ignore(fn () => DB::table('pulse_aggregates')->whereType('validation_error')->orderBy('period')->get());
98+
expect($aggregates->pluck('key')->all())->toBe(array_fill(0, 4, '["POST","\/users","Closure","__unknown"]'));
99+
expect($aggregates->pluck('aggregate')->all())->toBe(array_fill(0, 4, 'count'));
100+
expect($aggregates->pluck('value')->all())->toBe(array_fill(0, 4, '1.00'));
101+
});
102+
103+
it('captures API validation errors', function () {
104+
Route::post('users', fn () => Request::validate([
105+
'email' => 'required',
106+
]))->middleware('api');
107+
108+
$response = postJson('users');
66109

110+
$response->assertStatus(422);
111+
$response->assertInvalid('email');
112+
$entries = Pulse::ignore(fn () => DB::table('pulse_entries')->whereType('validation_error')->get());
113+
expect($entries)->toHaveCount(1);
114+
expect($entries[0]->key)->toBe('["POST","\/users","Closure","email"]');
115+
$aggregates = Pulse::ignore(fn () => DB::table('pulse_aggregates')->whereType('validation_error')->orderBy('period')->get());
116+
expect($aggregates->pluck('key')->all())->toBe(array_fill(0, 4, '["POST","\/users","Closure","email"]'));
117+
expect($aggregates->pluck('aggregate')->all())->toBe(array_fill(0, 4, 'count'));
118+
expect($aggregates->pluck('value')->all())->toBe(array_fill(0, 4, '1.00'));
119+
});
120+
121+
it('captures "unknown" API validation error for non Illuminate Json responses', function () {
122+
Route::post('users', fn () => new SymfonyJsonResponse(['errors' => ['email' => 'Is required.']], 422))
123+
->middleware('api');
124+
125+
$response = postJson('users');
126+
127+
$response->assertStatus(422);
128+
$response->assertInvalid('email');
67129
$entries = Pulse::ignore(fn () => DB::table('pulse_entries')->whereType('validation_error')->get());
68130
expect($entries)->toHaveCount(1);
69131
expect($entries[0]->key)->toBe('["POST","\/users","Closure","__unknown"]');
132+
$aggregates = Pulse::ignore(fn () => DB::table('pulse_aggregates')->whereType('validation_error')->orderBy('period')->get());
133+
expect($aggregates->pluck('key')->all())->toBe(array_fill(0, 4, '["POST","\/users","Closure","__unknown"]'));
134+
expect($aggregates->pluck('aggregate')->all())->toBe(array_fill(0, 4, 'count'));
135+
expect($aggregates->pluck('value')->all())->toBe(array_fill(0, 4, '1.00'));
136+
});
70137

138+
it('captures "unknown" API validation error for non array Json content', function () {
139+
Route::post('users', fn () => new IlluminateJsonResponse('An error occurred.', 422))
140+
->middleware('api');
141+
142+
$response = postJson('users');
143+
144+
$response->assertStatus(422);
145+
$entries = Pulse::ignore(fn () => DB::table('pulse_entries')->whereType('validation_error')->get());
146+
expect($entries)->toHaveCount(1);
147+
expect($entries[0]->key)->toBe('["POST","\/users","Closure","__unknown"]');
148+
$aggregates = Pulse::ignore(fn () => DB::table('pulse_aggregates')->whereType('validation_error')->orderBy('period')->get());
149+
expect($aggregates->pluck('key')->all())->toBe(array_fill(0, 4, '["POST","\/users","Closure","__unknown"]'));
150+
expect($aggregates->pluck('aggregate')->all())->toBe(array_fill(0, 4, 'count'));
151+
expect($aggregates->pluck('value')->all())->toBe(array_fill(0, 4, '1.00'));
152+
});
153+
154+
it('captures "unknown" API validation error for array content mising "errors" key', function () {
155+
Route::post('users', fn () => new IlluminateJsonResponse(['An error occurred.'], 422))
156+
->middleware('api');
157+
158+
$response = postJson('users');
159+
160+
$response->assertStatus(422);
161+
$entries = Pulse::ignore(fn () => DB::table('pulse_entries')->whereType('validation_error')->get());
162+
expect($entries)->toHaveCount(1);
163+
expect($entries[0]->key)->toBe('["POST","\/users","Closure","__unknown"]');
164+
$aggregates = Pulse::ignore(fn () => DB::table('pulse_aggregates')->whereType('validation_error')->orderBy('period')->get());
165+
expect($aggregates->pluck('key')->all())->toBe(array_fill(0, 4, '["POST","\/users","Closure","__unknown"]'));
166+
expect($aggregates->pluck('aggregate')->all())->toBe(array_fill(0, 4, 'count'));
167+
expect($aggregates->pluck('value')->all())->toBe(array_fill(0, 4, '1.00'));
168+
});
169+
170+
it('captures "unknown" API validation error for "errors" key that does not contain an array', function () {
171+
Route::post('users', fn () => new IlluminateJsonResponse(['errors' => 'An error occurred.'], 422))
172+
->middleware('api');
173+
174+
$response = postJson('users');
175+
176+
$response->assertStatus(422);
177+
$entries = Pulse::ignore(fn () => DB::table('pulse_entries')->whereType('validation_error')->get());
178+
expect($entries)->toHaveCount(1);
179+
expect($entries[0]->key)->toBe('["POST","\/users","Closure","__unknown"]');
180+
$aggregates = Pulse::ignore(fn () => DB::table('pulse_aggregates')->whereType('validation_error')->orderBy('period')->get());
181+
expect($aggregates->pluck('key')->all())->toBe(array_fill(0, 4, '["POST","\/users","Closure","__unknown"]'));
182+
expect($aggregates->pluck('aggregate')->all())->toBe(array_fill(0, 4, 'count'));
183+
expect($aggregates->pluck('value')->all())->toBe(array_fill(0, 4, '1.00'));
184+
});
185+
186+
it('captures "unknown" API validation error for "errors" key that contains a list', function () {
187+
Route::post('users', fn () => new IlluminateJsonResponse(['errors' => ['An error occurred.']], 422))
188+
->middleware('api');
189+
190+
$response = postJson('users');
191+
192+
$response->assertStatus(422);
193+
$entries = Pulse::ignore(fn () => DB::table('pulse_entries')->whereType('validation_error')->get());
194+
expect($entries)->toHaveCount(1);
195+
expect($entries[0]->key)->toBe('["POST","\/users","Closure","__unknown"]');
71196
$aggregates = Pulse::ignore(fn () => DB::table('pulse_aggregates')->whereType('validation_error')->orderBy('period')->get());
72197
expect($aggregates->pluck('key')->all())->toBe(array_fill(0, 4, '["POST","\/users","Closure","__unknown"]'));
73198
expect($aggregates->pluck('aggregate')->all())->toBe(array_fill(0, 4, 'count'));

0 commit comments

Comments
 (0)