From f31f87aaf66940b82bed9bd7b578b2e75467e5b8 Mon Sep 17 00:00:00 2001 From: soheil khaledabadi Date: Wed, 9 Sep 2026 00:37:37 +0330 Subject: [PATCH] fix(users): pass mobile rule as a nested closure Filament can evaluate Filament evaluates each entry of ->rules() as its own closure and tries to inject dependencies, so a bare Laravel validation closure blew up with "[$attribute] was unresolvable" when opening/saving the user form. Wrap it so the outer closure returns the Laravel rule. Co-Authored-By: Claude Sonnet 5 --- .../Resources/Users/Schemas/UserForm.php | 12 +++-- tests/Feature/UserFormMobileTest.php | 48 +++++++++++++++++++ 2 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 tests/Feature/UserFormMobileTest.php diff --git a/app/Filament/Resources/Users/Schemas/UserForm.php b/app/Filament/Resources/Users/Schemas/UserForm.php index d3c40d0..a57e2d4 100644 --- a/app/Filament/Resources/Users/Schemas/UserForm.php +++ b/app/Filament/Resources/Users/Schemas/UserForm.php @@ -28,11 +28,13 @@ class UserForm ->tel() ->helperText('مثال درست: 09123456789') ->dehydrateStateUsing(fn (?string $state): ?string => Mobile::normalize($state)) - ->rules([static function (string $attribute, mixed $value, \Closure $fail): void { - if (filled($value) && ! preg_match(Mobile::REGEX, (string) Mobile::normalize((string) $value))) { - $fail('فرمت شماره موبایل صحیح نیست. مثال درست: 09123456789'); - } - }]) + ->rules([ + fn (): \Closure => function (string $attribute, mixed $value, \Closure $fail): void { + if (filled($value) && ! preg_match(Mobile::REGEX, (string) Mobile::normalize((string) $value))) { + $fail('فرمت شماره موبایل صحیح نیست. مثال درست: 09123456789'); + } + }, + ]) ->unique(ignoreRecord: true) ->maxLength(20), TextInput::make('password') diff --git a/tests/Feature/UserFormMobileTest.php b/tests/Feature/UserFormMobileTest.php new file mode 100644 index 0000000..2af3708 --- /dev/null +++ b/tests/Feature/UserFormMobileTest.php @@ -0,0 +1,48 @@ +create(); + $role = Role::query()->firstOrCreate(['slug' => 'admin'], ['name' => 'مدیر']); + $admin->roles()->sync([$role->id]); + actingAs($admin); +}); + +it('opens the create user form without the unresolvable-closure error', function (): void { + Livewire\Livewire::test(CreateUser::class) + ->assertOk(); +}); + +it('accepts a +98 mobile and normalizes it, rejects a malformed one', function (): void { + Livewire\Livewire::test(CreateUser::class) + ->fillForm([ + 'name' => 'کاربر تست', + 'email' => 'ok@example.com', + 'mobile' => '+98 912 345 6789', + 'password' => 'password12', + ]) + ->call('create') + ->assertHasNoFormErrors(); + + expect(User::query()->where('email', 'ok@example.com')->value('mobile'))->toBe('09123456789'); + + Livewire\Livewire::test(CreateUser::class) + ->fillForm([ + 'name' => 'کاربر بد', + 'email' => 'bad@example.com', + 'mobile' => '123', + 'password' => 'password12', + ]) + ->call('create') + ->assertHasFormErrors(['mobile']); +});