admin()->create([ 'email' => 'admin@example.com', ]); Livewire::test(Login::class) ->set('data.email', $admin->email) ->set('data.password', 'password') ->call('authenticate') ->assertHasNoFormErrors() ->assertRedirect(route('filament.admin.pages.dashboard')); $this->assertAuthenticatedAs($admin); } public function test_active_assistant_can_log_in_to_filament_panel(): void { $assistant = User::factory()->assistant()->create([ 'email' => 'assistant@example.com', ]); Livewire::test(Login::class) ->set('data.email', $assistant->email) ->set('data.password', 'password') ->call('authenticate') ->assertHasNoFormErrors() ->assertRedirect(route('filament.admin.pages.dashboard')); $this->assertAuthenticatedAs($assistant); } public function test_inactive_user_is_denied_panel_access(): void { $inactiveUser = User::factory()->admin()->inactive()->create([ 'email' => 'inactive@example.com', ]); Livewire::test(Login::class) ->set('data.email', $inactiveUser->email) ->set('data.password', 'password') ->call('authenticate') ->assertHasFormErrors(['email']); $this->assertGuest(); } public function test_unverified_user_is_denied_panel_access(): void { $unverifiedUser = User::factory()->admin()->unverified()->create([ 'email' => 'unverified@example.com', ]); Livewire::test(Login::class) ->set('data.email', $unverifiedUser->email) ->set('data.password', 'password') ->call('authenticate') ->assertHasFormErrors(['email']); $this->assertGuest(); } public function test_assistant_cannot_access_user_management(): void { $assistant = User::factory()->assistant()->create(); $this->actingAs($assistant); Livewire::test(ListUsers::class) ->assertForbidden(); } public function test_admin_can_access_user_management(): void { $admin = User::factory()->admin()->create(); $this->actingAs($admin); Livewire::test(ListUsers::class) ->assertSuccessful(); } public function test_user_role_is_limited_to_admin_and_assistant(): void { $this->assertSame(['admin', 'assistant'], array_column(UserRole::cases(), 'value')); } /** * Regression test for the admin-managed-verification decision: a user * created through the panel's own CreateUser form (not the factory, * which sets email_verified_at directly) must come out verified and * able to log in — UserForm has no email_verified_at field, so without * CreateUser::handleRecordCreation setting it explicitly, every * admin-created user would be permanently locked out with no in-app * recovery path (the password-reset callback silently skips users that * fail canAccessPanel()). */ public function test_admin_created_user_is_verified_and_can_log_in(): void { $admin = User::factory()->admin()->create(); $this->actingAs($admin); Livewire::test(CreateUser::class) ->set('data.name', 'Novo Assistente') ->set('data.email', 'novo-assistente@example.com') ->set('data.role', UserRole::Assistant->value) ->set('data.is_active', true) ->set('data.password', 'password') ->call('create') ->assertHasNoFormErrors(); $created = User::query()->where('email', 'novo-assistente@example.com')->firstOrFail(); $this->assertTrue($created->hasVerifiedEmail()); // Log the creating admin back out — Login::mount() redirects an // already-authenticated user away instead of rendering the form. auth()->logout(); Livewire::test(Login::class) ->set('data.email', $created->email) ->set('data.password', 'password') ->call('authenticate') ->assertHasNoFormErrors() ->assertRedirect(route('filament.admin.pages.dashboard')); $this->assertAuthenticatedAs($created); } /** * Regression test for DatabaseSeeder's local admin/assistant: both must * come out verified. `User::query()->updateOrCreate(...)` alone would * silently drop `email_verified_at` — it isn't in User's #[Fillable] * list — but `php artisan db:seed` (which is what `$this->seed()` below * runs, and what `composer setup` runs too) wraps seeder execution in * `Illuminate\Database\Eloquent\Model::unguarded()` * (see Illuminate\Database\Console\Seeds\SeedCommand), which lifts mass- * assignment guarding for the duration of the seed. That's what makes * DatabaseSeeder's plain `updateOrCreate([...], ['email_verified_at' => * now(), ...])` work without a `forceFill()` — confirmed by exercising * the actual `db:seed` path here rather than calling the seeder's * `updateOrCreate` call inline. */ public function test_seeded_local_admin_and_assistant_are_verified(): void { $this->seed(DatabaseSeeder::class); $admin = User::query()->where('email', 'admin@amare.local')->firstOrFail(); $assistant = User::query()->where('email', 'assistant@amare.local')->firstOrFail(); $this->assertTrue($admin->hasVerifiedEmail()); $this->assertTrue($assistant->hasVerifiedEmail()); } }