|
|
@@ -0,0 +1,232 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace Tests\Feature;
|
|
|
+
|
|
|
+use App\Models\Role;
|
|
|
+use App\Models\User;
|
|
|
+use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
+use Tests\TestCase;
|
|
|
+
|
|
|
+class UserControllerTest extends TestCase
|
|
|
+{
|
|
|
+ use RefreshDatabase;
|
|
|
+
|
|
|
+ protected $seed = true;
|
|
|
+
|
|
|
+ private User $adminUser;
|
|
|
+ private User $managerUser;
|
|
|
+
|
|
|
+ protected function setUp(): void
|
|
|
+ {
|
|
|
+ parent::setUp();
|
|
|
+ $this->adminUser = User::factory()->create(['role' => Role::ADMIN]);
|
|
|
+ $this->managerUser = User::factory()->create(['role' => Role::MANAGER]);
|
|
|
+ }
|
|
|
+
|
|
|
+ private function validUserData(): array
|
|
|
+ {
|
|
|
+ return [
|
|
|
+ 'name' => 'Тест Пользователь',
|
|
|
+ 'email' => 'test_new@example.com',
|
|
|
+ 'password' => 'password123',
|
|
|
+ 'role' => Role::MANAGER,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== Guest redirects ====================
|
|
|
+
|
|
|
+ public function test_guest_cannot_access_users_index(): void
|
|
|
+ {
|
|
|
+ $response = $this->get(route('user.index'));
|
|
|
+
|
|
|
+ $response->assertRedirect(route('login'));
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_guest_cannot_access_user_create(): void
|
|
|
+ {
|
|
|
+ $response = $this->get(route('user.create'));
|
|
|
+
|
|
|
+ $response->assertRedirect(route('login'));
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_guest_cannot_store_user(): void
|
|
|
+ {
|
|
|
+ $response = $this->post(route('user.store'), $this->validUserData());
|
|
|
+
|
|
|
+ $response->assertRedirect(route('login'));
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_guest_cannot_delete_user(): void
|
|
|
+ {
|
|
|
+ $user = User::factory()->create(['role' => Role::MANAGER]);
|
|
|
+
|
|
|
+ $response = $this->delete(route('user.destroy', $user));
|
|
|
+
|
|
|
+ $response->assertRedirect(route('login'));
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== Authorization - manager gets 403 ====================
|
|
|
+
|
|
|
+ public function test_manager_cannot_access_users_index(): void
|
|
|
+ {
|
|
|
+ $response = $this->actingAs($this->managerUser)
|
|
|
+ ->get(route('user.index'));
|
|
|
+
|
|
|
+ $response->assertStatus(403);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_manager_cannot_create_user(): void
|
|
|
+ {
|
|
|
+ $response = $this->actingAs($this->managerUser)
|
|
|
+ ->post(route('user.store'), $this->validUserData());
|
|
|
+
|
|
|
+ $response->assertStatus(403);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_manager_cannot_delete_user(): void
|
|
|
+ {
|
|
|
+ $user = User::factory()->create(['role' => Role::MANAGER]);
|
|
|
+
|
|
|
+ $response = $this->actingAs($this->managerUser)
|
|
|
+ ->delete(route('user.destroy', $user));
|
|
|
+
|
|
|
+ $response->assertStatus(403);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== Index ====================
|
|
|
+
|
|
|
+ public function test_admin_can_access_users_index(): void
|
|
|
+ {
|
|
|
+ $response = $this->actingAs($this->adminUser)
|
|
|
+ ->get(route('user.index'));
|
|
|
+
|
|
|
+ $response->assertStatus(200);
|
|
|
+ $response->assertViewIs('users.index');
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== Create form ====================
|
|
|
+
|
|
|
+ public function test_admin_can_access_user_create(): void
|
|
|
+ {
|
|
|
+ $response = $this->actingAs($this->adminUser)
|
|
|
+ ->get(route('user.create'));
|
|
|
+
|
|
|
+ $response->assertStatus(200);
|
|
|
+ $response->assertViewIs('users.edit');
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== Show ====================
|
|
|
+
|
|
|
+ public function test_admin_can_view_user(): void
|
|
|
+ {
|
|
|
+ $user = User::factory()->create(['role' => Role::MANAGER]);
|
|
|
+
|
|
|
+ $response = $this->actingAs($this->adminUser)
|
|
|
+ ->get(route('user.show', $user));
|
|
|
+
|
|
|
+ $response->assertStatus(200);
|
|
|
+ $response->assertViewIs('users.edit');
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== Store - create new user ====================
|
|
|
+
|
|
|
+ public function test_admin_can_create_user(): void
|
|
|
+ {
|
|
|
+ $data = $this->validUserData();
|
|
|
+
|
|
|
+ $response = $this->actingAs($this->adminUser)
|
|
|
+ ->post(route('user.store'), $data);
|
|
|
+
|
|
|
+ $response->assertRedirect(route('user.index'));
|
|
|
+ $this->assertDatabaseHas('users', ['email' => $data['email']]);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_store_requires_name(): void
|
|
|
+ {
|
|
|
+ $data = $this->validUserData();
|
|
|
+ unset($data['name']);
|
|
|
+
|
|
|
+ $response = $this->actingAs($this->adminUser)
|
|
|
+ ->post(route('user.store'), $data);
|
|
|
+
|
|
|
+ $response->assertSessionHasErrors('name');
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_store_requires_password_for_new_user(): void
|
|
|
+ {
|
|
|
+ $data = $this->validUserData();
|
|
|
+ unset($data['password']);
|
|
|
+
|
|
|
+ $response = $this->actingAs($this->adminUser)
|
|
|
+ ->post(route('user.store'), $data);
|
|
|
+
|
|
|
+ $response->assertSessionHasErrors('password');
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== Update existing user ====================
|
|
|
+
|
|
|
+ public function test_admin_can_update_user(): void
|
|
|
+ {
|
|
|
+ $user = User::factory()->create(['role' => Role::MANAGER]);
|
|
|
+ $newName = 'Обновлённое Имя';
|
|
|
+
|
|
|
+ $response = $this->actingAs($this->adminUser)
|
|
|
+ ->post(route('user.store'), [
|
|
|
+ 'id' => $user->id,
|
|
|
+ 'name' => $newName,
|
|
|
+ 'role' => Role::MANAGER,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $response->assertRedirect(route('user.index'));
|
|
|
+ $this->assertDatabaseHas('users', ['id' => $user->id, 'name' => $newName]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== Delete ====================
|
|
|
+
|
|
|
+ public function test_admin_can_delete_user(): void
|
|
|
+ {
|
|
|
+ $user = User::factory()->create(['role' => Role::MANAGER]);
|
|
|
+
|
|
|
+ $response = $this->actingAs($this->adminUser)
|
|
|
+ ->delete(route('user.destroy', $user));
|
|
|
+
|
|
|
+ $response->assertRedirect(route('user.index'));
|
|
|
+ $this->assertSoftDeleted('users', ['id' => $user->id]);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_admin_cannot_delete_self(): void
|
|
|
+ {
|
|
|
+ $response = $this->actingAs($this->adminUser)
|
|
|
+ ->delete(route('user.destroy', $this->adminUser));
|
|
|
+
|
|
|
+ $response->assertRedirect(route('user.index'));
|
|
|
+ $response->assertSessionHas('danger');
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== Undelete ====================
|
|
|
+
|
|
|
+ public function test_admin_can_restore_deleted_user(): void
|
|
|
+ {
|
|
|
+ $user = User::factory()->create(['role' => Role::MANAGER]);
|
|
|
+ $user->delete();
|
|
|
+
|
|
|
+ $response = $this->actingAs($this->adminUser)
|
|
|
+ ->post(route('user.undelete', $user->id));
|
|
|
+
|
|
|
+ $response->assertRedirect();
|
|
|
+ $this->assertDatabaseHas('users', ['id' => $user->id, 'deleted_at' => null]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== Impersonate ====================
|
|
|
+
|
|
|
+ public function test_admin_can_impersonate_user(): void
|
|
|
+ {
|
|
|
+ $targetUser = User::factory()->create(['role' => Role::MANAGER]);
|
|
|
+
|
|
|
+ $response = $this->actingAs($this->adminUser)
|
|
|
+ ->post(route('user.impersonate', $targetUser));
|
|
|
+
|
|
|
+ $response->assertRedirect(route('home'));
|
|
|
+ $response->assertSessionHas('impersonator_id', $this->adminUser->id);
|
|
|
+ }
|
|
|
+}
|