UserControllerTest.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. <?php
  2. namespace Tests\Feature;
  3. use App\Models\Role;
  4. use App\Models\User;
  5. use Illuminate\Foundation\Testing\RefreshDatabase;
  6. use Tests\TestCase;
  7. class UserControllerTest extends TestCase
  8. {
  9. use RefreshDatabase;
  10. protected $seed = true;
  11. private User $adminUser;
  12. private User $managerUser;
  13. protected function setUp(): void
  14. {
  15. parent::setUp();
  16. $this->adminUser = User::factory()->create(['role' => Role::ADMIN]);
  17. $this->managerUser = User::factory()->create(['role' => Role::MANAGER]);
  18. }
  19. private function validUserData(): array
  20. {
  21. return [
  22. 'name' => 'Тест Пользователь',
  23. 'email' => 'test_new@example.com',
  24. 'password' => 'password123',
  25. 'role' => Role::MANAGER,
  26. ];
  27. }
  28. // ==================== Guest redirects ====================
  29. public function test_guest_cannot_access_users_index(): void
  30. {
  31. $response = $this->get(route('user.index'));
  32. $response->assertRedirect(route('login'));
  33. }
  34. public function test_guest_cannot_access_user_create(): void
  35. {
  36. $response = $this->get(route('user.create'));
  37. $response->assertRedirect(route('login'));
  38. }
  39. public function test_guest_cannot_store_user(): void
  40. {
  41. $response = $this->post(route('user.store'), $this->validUserData());
  42. $response->assertRedirect(route('login'));
  43. }
  44. public function test_guest_cannot_delete_user(): void
  45. {
  46. $user = User::factory()->create(['role' => Role::MANAGER]);
  47. $response = $this->delete(route('user.destroy', $user));
  48. $response->assertRedirect(route('login'));
  49. }
  50. // ==================== Authorization - manager gets 403 ====================
  51. public function test_manager_cannot_access_users_index(): void
  52. {
  53. $response = $this->actingAs($this->managerUser)
  54. ->get(route('user.index'));
  55. $response->assertStatus(403);
  56. }
  57. public function test_manager_cannot_create_user(): void
  58. {
  59. $response = $this->actingAs($this->managerUser)
  60. ->post(route('user.store'), $this->validUserData());
  61. $response->assertStatus(403);
  62. }
  63. public function test_manager_cannot_delete_user(): void
  64. {
  65. $user = User::factory()->create(['role' => Role::MANAGER]);
  66. $response = $this->actingAs($this->managerUser)
  67. ->delete(route('user.destroy', $user));
  68. $response->assertStatus(403);
  69. }
  70. // ==================== Index ====================
  71. public function test_admin_can_access_users_index(): void
  72. {
  73. $response = $this->actingAs($this->adminUser)
  74. ->get(route('user.index'));
  75. $response->assertStatus(200);
  76. $response->assertViewIs('users.index');
  77. }
  78. // ==================== Create form ====================
  79. public function test_admin_can_access_user_create(): void
  80. {
  81. $response = $this->actingAs($this->adminUser)
  82. ->get(route('user.create'));
  83. $response->assertStatus(200);
  84. $response->assertViewIs('users.edit');
  85. }
  86. // ==================== Show ====================
  87. public function test_admin_can_view_user(): void
  88. {
  89. $user = User::factory()->create(['role' => Role::MANAGER]);
  90. $response = $this->actingAs($this->adminUser)
  91. ->get(route('user.show', $user));
  92. $response->assertStatus(200);
  93. $response->assertViewIs('users.edit');
  94. }
  95. public function test_user_edit_shows_permission_overrides_and_inherited_role_permissions(): void
  96. {
  97. $managerRole = Role::query()->where('slug', Role::MANAGER)->firstOrFail();
  98. $user = User::factory()->create([
  99. 'role' => Role::MANAGER,
  100. 'role_id' => $managerRole->id,
  101. ]);
  102. $response = $this->actingAs($this->adminUser)
  103. ->get(route('user.show', $user));
  104. $response->assertOk();
  105. $response->assertSee('id="permissions-pane"', false);
  106. $response->assertSee('name="permission_effects[', false);
  107. $response->assertSee('orders.view');
  108. $response->assertSee('По роли: разрешено');
  109. }
  110. public function test_user_show_uses_nav_context_back_url(): void
  111. {
  112. $user = User::factory()->create(['role' => Role::MANAGER]);
  113. $response = $this->actingAs($this->adminUser)
  114. ->withSession([
  115. 'navigation' => [
  116. 'user-nav' => [
  117. 'updated_at' => now()->timestamp,
  118. 'stack' => [
  119. route('user.index', ['page' => 2]),
  120. ],
  121. ],
  122. ],
  123. ])
  124. ->get(route('user.show', ['user' => $user, 'nav' => 'user-nav']));
  125. $response->assertOk();
  126. $response->assertViewHas('nav', 'user-nav');
  127. $response->assertViewHas('back_url', route('user.index', ['page' => 2, 'nav' => 'user-nav']));
  128. }
  129. // ==================== Store - create new user ====================
  130. public function test_admin_can_create_user(): void
  131. {
  132. $data = $this->validUserData();
  133. $response = $this->actingAs($this->adminUser)
  134. ->post(route('user.store'), $data);
  135. $response->assertRedirect(route('user.index'));
  136. $this->assertDatabaseHas('users', ['email' => $data['email']]);
  137. }
  138. public function test_store_requires_name(): void
  139. {
  140. $data = $this->validUserData();
  141. unset($data['name']);
  142. $response = $this->actingAs($this->adminUser)
  143. ->post(route('user.store'), $data);
  144. $response->assertSessionHasErrors('name');
  145. }
  146. public function test_store_requires_password_for_new_user(): void
  147. {
  148. $data = $this->validUserData();
  149. unset($data['password']);
  150. $response = $this->actingAs($this->adminUser)
  151. ->post(route('user.store'), $data);
  152. $response->assertSessionHasErrors('password');
  153. }
  154. // ==================== Update existing user ====================
  155. public function test_admin_can_update_user(): void
  156. {
  157. $user = User::factory()->create(['role' => Role::MANAGER]);
  158. $newName = 'Обновлённое Имя';
  159. $response = $this->actingAs($this->adminUser)
  160. ->post(route('user.store'), [
  161. 'id' => $user->id,
  162. 'name' => $newName,
  163. 'role' => Role::MANAGER,
  164. ]);
  165. $response->assertRedirect(route('user.index'));
  166. $this->assertDatabaseHas('users', ['id' => $user->id, 'name' => $newName]);
  167. }
  168. // ==================== Delete ====================
  169. public function test_admin_can_delete_user(): void
  170. {
  171. $user = User::factory()->create(['role' => Role::MANAGER]);
  172. $response = $this->actingAs($this->adminUser)
  173. ->delete(route('user.destroy', $user));
  174. $response->assertRedirect(route('user.index'));
  175. $this->assertSoftDeleted('users', ['id' => $user->id]);
  176. }
  177. public function test_admin_cannot_delete_self(): void
  178. {
  179. $response = $this->actingAs($this->adminUser)
  180. ->delete(route('user.destroy', $this->adminUser));
  181. $response->assertRedirect(route('user.index'));
  182. $response->assertSessionHas('danger');
  183. }
  184. // ==================== Undelete ====================
  185. public function test_admin_can_restore_deleted_user(): void
  186. {
  187. $user = User::factory()->create(['role' => Role::MANAGER]);
  188. $user->delete();
  189. $response = $this->actingAs($this->adminUser)
  190. ->post(route('user.undelete', $user->id));
  191. $response->assertRedirect();
  192. $this->assertDatabaseHas('users', ['id' => $user->id, 'deleted_at' => null]);
  193. }
  194. // ==================== Impersonate ====================
  195. public function test_admin_can_impersonate_user(): void
  196. {
  197. $targetUser = User::factory()->create(['role' => Role::MANAGER]);
  198. $response = $this->actingAs($this->adminUser)
  199. ->post(route('user.impersonate', $targetUser));
  200. $response->assertRedirect(route('home'));
  201. $response->assertSessionHas('impersonator_id', $this->adminUser->id);
  202. }
  203. public function test_impersonated_session_can_leave_only_to_admin(): void
  204. {
  205. $targetUser = User::factory()->create(['role' => Role::MANAGER]);
  206. $response = $this->actingAs($targetUser)
  207. ->withSession(['impersonator_id' => $this->adminUser->id])
  208. ->post(route('user.impersonate.leave'));
  209. $response->assertRedirect(route('user.index'));
  210. }
  211. public function test_impersonated_session_cannot_leave_to_non_admin(): void
  212. {
  213. $targetUser = User::factory()->create(['role' => Role::BRIGADIER]);
  214. $response = $this->actingAs($targetUser)
  215. ->withSession(['impersonator_id' => $this->managerUser->id])
  216. ->post(route('user.impersonate.leave'));
  217. $response->assertForbidden();
  218. }
  219. }