AdminDistrictControllerTest.php 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. <?php
  2. namespace Tests\Feature;
  3. use App\Models\Dictionary\Area;
  4. use App\Models\Dictionary\District;
  5. use App\Models\Role;
  6. use App\Models\User;
  7. use Illuminate\Foundation\Testing\RefreshDatabase;
  8. use Illuminate\Http\UploadedFile;
  9. use Illuminate\Support\Facades\Storage;
  10. use Tests\TestCase;
  11. class AdminDistrictControllerTest extends TestCase
  12. {
  13. use RefreshDatabase;
  14. protected $seed = true;
  15. private User $adminUser;
  16. private User $managerUser;
  17. protected function setUp(): void
  18. {
  19. parent::setUp();
  20. $this->adminUser = User::factory()->create(['role' => Role::ADMIN]);
  21. $this->managerUser = User::factory()->create(['role' => Role::MANAGER]);
  22. }
  23. // ==================== Authentication & Authorization ====================
  24. public function test_guest_cannot_access_districts_index(): void
  25. {
  26. $response = $this->get(route('admin.district.index'));
  27. $response->assertRedirect(route('login'));
  28. }
  29. public function test_manager_cannot_access_districts_index(): void
  30. {
  31. $response = $this->actingAs($this->managerUser)
  32. ->get(route('admin.district.index'));
  33. $response->assertStatus(403);
  34. }
  35. public function test_admin_can_access_districts_index(): void
  36. {
  37. $response = $this->actingAs($this->adminUser)
  38. ->get(route('admin.district.index'));
  39. $response->assertStatus(200);
  40. $response->assertViewIs('admin.districts.index');
  41. }
  42. // ==================== Index ====================
  43. public function test_districts_index_displays_districts(): void
  44. {
  45. $district = District::factory()->create(['name' => 'Тестовый округ']);
  46. $response = $this->actingAs($this->adminUser)
  47. ->get(route('admin.district.index'));
  48. $response->assertStatus(200);
  49. $response->assertSee('Тестовый округ');
  50. }
  51. public function test_districts_index_displays_areas_count(): void
  52. {
  53. $district = District::factory()->create();
  54. Area::factory()->count(3)->create(['district_id' => $district->id]);
  55. $response = $this->actingAs($this->adminUser)
  56. ->get(route('admin.district.index'));
  57. $response->assertStatus(200);
  58. $response->assertSee('3');
  59. }
  60. // ==================== Show ====================
  61. public function test_admin_can_view_district_edit_form(): void
  62. {
  63. $district = District::factory()->create();
  64. $response = $this->actingAs($this->adminUser)
  65. ->get(route('admin.district.show', $district->id));
  66. $response->assertStatus(200);
  67. $response->assertViewIs('admin.districts.edit');
  68. $response->assertSee($district->name);
  69. }
  70. public function test_manager_cannot_view_district_edit_form(): void
  71. {
  72. $district = District::factory()->create();
  73. $response = $this->actingAs($this->managerUser)
  74. ->get(route('admin.district.show', $district->id));
  75. $response->assertStatus(403);
  76. }
  77. // ==================== Store ====================
  78. public function test_admin_can_create_new_district(): void
  79. {
  80. $response = $this->actingAs($this->adminUser)
  81. ->post(route('admin.district.store'), [
  82. 'shortname' => 'ТСТ',
  83. 'name' => 'Тестовый округ',
  84. ]);
  85. $response->assertRedirect(route('admin.district.index'));
  86. $this->assertDatabaseHas('districts', [
  87. 'shortname' => 'ТСТ',
  88. 'name' => 'Тестовый округ',
  89. ]);
  90. }
  91. public function test_admin_can_update_existing_district(): void
  92. {
  93. $district = District::factory()->create([
  94. 'shortname' => 'СТР',
  95. 'name' => 'Старое название',
  96. ]);
  97. $response = $this->actingAs($this->adminUser)
  98. ->post(route('admin.district.store'), [
  99. 'id' => $district->id,
  100. 'shortname' => 'НВ',
  101. 'name' => 'Новое название',
  102. ]);
  103. $response->assertRedirect(route('admin.district.index'));
  104. $this->assertDatabaseHas('districts', [
  105. 'id' => $district->id,
  106. 'shortname' => 'НВ',
  107. 'name' => 'Новое название',
  108. ]);
  109. }
  110. public function test_store_district_requires_name(): void
  111. {
  112. $response = $this->actingAs($this->adminUser)
  113. ->post(route('admin.district.store'), [
  114. 'shortname' => 'ТСТ',
  115. ]);
  116. $response->assertSessionHasErrors('name');
  117. }
  118. public function test_store_district_requires_shortname(): void
  119. {
  120. $response = $this->actingAs($this->adminUser)
  121. ->post(route('admin.district.store'), [
  122. 'name' => 'Тестовый округ',
  123. ]);
  124. $response->assertSessionHasErrors('shortname');
  125. }
  126. // ==================== Destroy ====================
  127. public function test_admin_can_delete_district_without_areas(): void
  128. {
  129. $district = District::factory()->create();
  130. $response = $this->actingAs($this->adminUser)
  131. ->delete(route('admin.district.destroy', $district->id));
  132. $response->assertRedirect(route('admin.district.index'));
  133. $this->assertSoftDeleted('districts', ['id' => $district->id]);
  134. }
  135. public function test_admin_cannot_delete_district_with_areas(): void
  136. {
  137. $district = District::factory()->create();
  138. Area::factory()->create(['district_id' => $district->id]);
  139. $response = $this->actingAs($this->adminUser)
  140. ->delete(route('admin.district.destroy', $district->id));
  141. $response->assertRedirect(route('admin.district.index'));
  142. $response->assertSessionHas('error');
  143. $this->assertDatabaseHas('districts', ['id' => $district->id, 'deleted_at' => null]);
  144. }
  145. // ==================== Undelete ====================
  146. public function test_admin_can_restore_deleted_district(): void
  147. {
  148. $district = District::factory()->create();
  149. $district->delete();
  150. $response = $this->actingAs($this->adminUser)
  151. ->post(route('admin.district.undelete', $district->id));
  152. $response->assertRedirect(route('admin.district.index'));
  153. $this->assertDatabaseHas('districts', [
  154. 'id' => $district->id,
  155. 'deleted_at' => null,
  156. ]);
  157. }
  158. // ==================== Export ====================
  159. public function test_admin_can_export_districts(): void
  160. {
  161. District::factory()->count(3)->create();
  162. $response = $this->actingAs($this->adminUser)
  163. ->post(route('admin.district.export'));
  164. $response->assertRedirect();
  165. }
  166. // ==================== Import ====================
  167. public function test_admin_can_import_districts(): void
  168. {
  169. Storage::fake('upload');
  170. // Создаем тестовый XLSX файл
  171. $file = $this->createTestDistrictsXlsx();
  172. $response = $this->actingAs($this->adminUser)
  173. ->post(route('admin.district.import'), [
  174. 'import_file' => $file,
  175. ]);
  176. $response->assertRedirect(route('admin.district.index'));
  177. }
  178. public function test_import_requires_file(): void
  179. {
  180. $response = $this->actingAs($this->adminUser)
  181. ->post(route('admin.district.import'), []);
  182. $response->assertSessionHasErrors('import_file');
  183. }
  184. public function test_import_requires_xlsx_file(): void
  185. {
  186. $file = UploadedFile::fake()->create('test.txt', 100, 'text/plain');
  187. $response = $this->actingAs($this->adminUser)
  188. ->post(route('admin.district.import'), [
  189. 'import_file' => $file,
  190. ]);
  191. $response->assertSessionHasErrors('import_file');
  192. }
  193. // ==================== Helper Methods ====================
  194. private function createTestDistrictsXlsx(): UploadedFile
  195. {
  196. $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
  197. $sheet = $spreadsheet->getActiveSheet();
  198. $sheet->setCellValue('A1', 'ID');
  199. $sheet->setCellValue('B1', 'Сокращение');
  200. $sheet->setCellValue('C1', 'Название');
  201. $sheet->setCellValue('A2', '');
  202. $sheet->setCellValue('B2', 'ТСТ');
  203. $sheet->setCellValue('C2', 'Тестовый округ');
  204. $tempPath = sys_get_temp_dir() . '/test_districts_' . uniqid() . '.xlsx';
  205. $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
  206. $writer->save($tempPath);
  207. return new UploadedFile(
  208. $tempPath,
  209. 'test_districts.xlsx',
  210. 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  211. null,
  212. true
  213. );
  214. }
  215. }