Files
radicall/tests/Feature/Http/Admin/UserControllerTest.php
T

156 lines
6.3 KiB
PHP

<?php
namespace Tests\Feature\Http\Admin;
use App\Enums\UserEnum;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Hash;
use Inertia\Testing\AssertableInertia as Assert;
use Maatwebsite\Excel\Facades\Excel;
use Spatie\Permission\Models\Role;
use Tests\Concerns\InteractsWithAdmin;
use Tests\TestCase;
class UserControllerTest extends TestCase
{
use InteractsWithAdmin, RefreshDatabase;
protected function payload(array $overrides = []): array
{
return array_merge([
'username' => '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');
}
}