'newuser', 'phone' => '09120000000', 'fullname' => 'کاربر جدید', 'email' => 'new@example.com', 'password' => 'secret123', 'password_confirmation' => 'secret123', 'level' => UserEnum::Doctor->value, 'national_code' => '0012345678', ], $overrides); } public function test_guest_is_redirected(): void { $this->get(route('admin.users.index'))->assertRedirect(route('login')); } public function test_admin_without_permission_is_forbidden(): void { $admin = $this->adminWithoutPermissions(); $this->actingAs($admin)->get(route('admin.users.index'))->assertForbidden(); $this->actingAs($admin)->post(route('admin.users.store'), $this->payload())->assertForbidden(); $this->actingAs($admin)->post('/admin/users-bulk-delete', ['ids' => []])->assertForbidden(); $this->actingAs($admin)->get('/admin/doctors-options')->assertForbidden(); } public function test_index_renders_with_filters(): void { $admin = $this->adminWithAllPermissions(); User::factory()->create(['level' => UserEnum::Doctor->value, 'fullname' => 'دکتر الف']); User::factory()->create(['level' => UserEnum::Vet->value]); $this->actingAs($admin)->get(route('admin.users.index'))->assertOk()->assertInertia(fn (Assert $page) => $page->component('Users/index')->has('users.data', 3)); $this->actingAs($admin)->get(route('admin.users.index', ['level' => UserEnum::Doctor->value]))->assertInertia(fn (Assert $page) => $page->has('users.data', 1)); $this->actingAs($admin)->get(route('admin.users.index', ['search' => 'الف']))->assertInertia(fn (Assert $page) => $page->has('users.data', 1)); } public function test_create_and_edit_pages_render_with_roles(): void { $admin = $this->adminWithAllPermissions(); $user = User::factory()->create(); $this->actingAs($admin)->get(route('admin.users.create'))->assertInertia(fn (Assert $page) => $page->component('Users/create_and_edit')->has('roles', 1)); $this->actingAs($admin)->get(route('admin.users.edit', $user))->assertInertia(fn (Assert $page) => $page->component('Users/create_and_edit')->where('is_edit', true)->where('user.id', $user->id)->where('user.role', [])); } public function test_store_creates_user_with_hashed_password_and_roles(): void { $admin = $this->adminWithAllPermissions(); $role = Role::first(); $this->actingAs($admin)->post(route('admin.users.store'), $this->payload(['role' => [$role->id]]))->assertOk()->assertSessionHas('success'); $user = User::where('username', 'newuser')->first(); $this->assertNotNull($user); $this->assertTrue(Hash::check('secret123', $user->password)); $this->assertSame(UserEnum::Doctor->value, $user->level); $this->assertTrue($user->hasRole($role)); } public function test_store_validates_input(): void { $this->actingAs($this->adminWithAllPermissions())->postJson(route('admin.users.store'), ['level' => UserEnum::Vet->value]) ->assertUnprocessable() ->assertJsonValidationErrors(['phone', 'password', 'level']); } public function test_update_changes_user_and_syncs_roles(): void { $admin = $this->adminWithAllPermissions(); $role = Role::first(); $user = User::factory()->create(['level' => UserEnum::Doctor->value]); $user->assignRole($role); $originalPassword = $user->password; $this->actingAs($admin)->put(route('admin.users.update', $user), $this->payload([ 'username' => 'renamed', 'level' => UserEnum::Supervisor->value, 'password' => null, 'password_confirmation' => null, ]))->assertOk(); $user->refresh(); $this->assertSame('renamed', $user->username); $this->assertSame(UserEnum::Supervisor->value, $user->level); $this->assertSame($originalPassword, $user->password); $this->assertFalse($user->hasRole($role)); } public function test_update_changes_password_when_provided(): void { $user = User::factory()->create(); $this->actingAs($this->adminWithAllPermissions())->put(route('admin.users.update', $user), $this->payload([ 'password' => 'newsecret1', 'password_confirmation' => 'newsecret1', ]))->assertOk(); $this->assertTrue(Hash::check('newsecret1', $user->fresh()->password)); } public function test_destroy_and_bulk_delete_soft_delete_users(): void { $admin = $this->adminWithAllPermissions(); $users = User::factory()->count(3)->create(); $this->actingAs($admin)->delete(route('admin.users.destroy', $users[0]))->assertOk(); $this->actingAs($admin)->post('/admin/users-bulk-delete', ['ids' => [$users[1]->id, $users[2]->id]])->assertOk(); foreach ($users as $user) { $this->assertDatabaseMissing('users', ['id' => $user->id]); } } public function test_get_doctors_options_returns_only_doctors(): void { $doctor = User::factory()->create(['level' => UserEnum::Doctor->value, 'fullname' => 'دکتر ب']); User::factory()->create(['level' => UserEnum::Vet->value, 'fullname' => 'دکتر ب']); $this->actingAs($this->adminWithAllPermissions())->getJson('/admin/doctors-options?search=ب') ->assertOk() ->assertJsonCount(1, 'data') ->assertJsonPath('data.0.value', $doctor->id); } public function test_export_data_downloads_excel(): void { Excel::fake(); $this->actingAs($this->adminWithAllPermissions())->get('/admin/users-export-data')->assertOk(); Excel::assertDownloaded('users.xlsx'); } }