Skip to content

Commit 9fdca05

Browse files
fix: error props resolution
1 parent 18fd480 commit 9fdca05

6 files changed

Lines changed: 94 additions & 6 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/vendor/
22
.cache
3-
.tempest
3+
.tempest
4+
log

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ It should be very familiar if you have used inertia before, with some small diff
1414

1515
- No configuration is done in the middleware, use the the config file, a provider class or your own middleware to set your "globally-shared-props".
1616
- No automatic redirect back handling in non get requests, since all tempest routes must return a response you have to return your own `Back` response.
17-
- No `Inertia::defer/lazy/always` method, in favor of just using the prop classes (`new DeferProp/LazyProp/AlwaysProp`) (unless people like that syntax more?)
17+
- Includes all validation errors for each field by default, instead of just the first one.
1818

1919
We provide an installer that you can use to set up some of the boilerplate code, but you can also do it manually.
2020

src/Support/ResolveErrorProps.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,26 @@
66

77
use Tempest\Http\Session\Session;
88
use Tempest\Validation\Rule;
9+
use Tempest\Validation\Validator;
910

1011
use function Tempest\Support\arr;
1112

1213
final readonly class ResolveErrorProps
1314
{
1415
public function __construct(
1516
private Session $session,
17+
private Validator $validator,
1618
) {}
1719

1820
public function resolve(): array
1921
{
20-
return array_map(
21-
fn(array $rules) => array_map(fn(Rule $rule) => arr($rule->message())->first(), $rules),
22-
$this->session->get(Session::VALIDATION_ERRORS) ?? [],
23-
);
22+
/** @var Rule[][] */
23+
$failingRules = $this->session->get(Session::VALIDATION_ERRORS) ?? [];
24+
25+
return arr($failingRules)->map(
26+
fn(array $rules): array => arr($rules)->map(
27+
fn(Rule $rule): string => $this->validator->getErrorMessage($rule),
28+
)->toArray(),
29+
)->toArray();
2430
}
2531
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace NeoIsRecursive\Inertia\Tests\Fixtures\Requests;
6+
7+
use Tempest\Http\IsRequest;
8+
use Tempest\Http\Request;
9+
use Tempest\Validation\Rules\IsBetween;
10+
use Tempest\Validation\Rules\IsEmail;
11+
use Tempest\Validation\Rules\IsNotEmptyString;
12+
use Tempest\Validation\Rules\IsNumeric;
13+
14+
final class CreatePerson implements Request
15+
{
16+
use IsRequest;
17+
18+
#[IsNotEmptyString]
19+
public string $firstName;
20+
#[IsNotEmptyString]
21+
public string $lastName;
22+
#[IsNumeric, IsBetween(min: 0, max: 130)]
23+
public int $age;
24+
#[IsEmail]
25+
public ?string $email;
26+
}

tests/Fixtures/TestController.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use NeoIsRecursive\Inertia\Inertia;
1010
use NeoIsRecursive\Inertia\Props\AlwaysProp;
1111
use NeoIsRecursive\Inertia\Props\LazyProp;
12+
use NeoIsRecursive\Inertia\Tests\Fixtures\Requests\CreatePerson;
1213
use Tempest\Http\Responses\Ok;
1314
use Tempest\Http\Responses\Redirect;
1415
use Tempest\Router\Get;
@@ -118,4 +119,11 @@ public function testCanMergeProps(Inertia $inertia): InertiaResponse
118119
],
119120
);
120121
}
122+
123+
#[Post(uri: '/test-validation-errors')]
124+
public function testValidationErrors(CreatePerson $request, Inertia $inertia): Redirect
125+
{
126+
// If we reach here, the request is valid.
127+
return new Redirect(to: uri([static::class, 'index']));
128+
}
121129
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace NeoIsRecursive\Inertia\Tests\Integration;
6+
7+
use NeoIsRecursive\Inertia\PageData;
8+
use NeoIsRecursive\Inertia\Tests\Fixtures\TestController;
9+
use NeoIsRecursive\Inertia\Tests\TestCase;
10+
use Tempest\Http\Session\Session;
11+
12+
use function Tempest\Router\uri;
13+
14+
final class ErrorPropsTest extends TestCase
15+
{
16+
public function test_error_props(): void
17+
{
18+
$this->http->post(
19+
uri([TestController::class, 'testValidationErrors']),
20+
body: [
21+
'firstName' => '',
22+
'lastName' => '',
23+
'email' => 'not-an-email',
24+
'age' => -2,
25+
],
26+
headers: [
27+
'X-Inertia' => 'true',
28+
'X-Version' => '1.0',
29+
],
30+
);
31+
32+
$response = $this->http->get(uri([TestController::class, 'index']), headers: [
33+
'X-Inertia' => 'true',
34+
'X-Version' => '1.0',
35+
]);
36+
37+
/** @var PageData */
38+
$body = $response->body;
39+
40+
$response->assertHasSession(Session::VALIDATION_ERRORS);
41+
42+
$this->assertArrayHasKey('errors', $body->props);
43+
$this->assertArrayHasKey('firstName', $body->props['errors']);
44+
$this->assertCount(1, $body->props['errors']['firstName']);
45+
$this->assertCount(2, $body->props['errors']['age']);
46+
}
47+
}

0 commit comments

Comments
 (0)