adminUser = User::factory()->create(['role' => Role::ADMIN]); $this->managerUser = User::factory()->create(['role' => Role::MANAGER]); } // ==================== Authentication & Authorization ==================== public function test_guest_cannot_access_districts_index(): void { $response = $this->get(route('admin.district.index')); $response->assertRedirect(route('login')); } public function test_manager_cannot_access_districts_index(): void { $response = $this->actingAs($this->managerUser) ->get(route('admin.district.index')); $response->assertStatus(403); } public function test_admin_can_access_districts_index(): void { $response = $this->actingAs($this->adminUser) ->get(route('admin.district.index')); $response->assertStatus(200); $response->assertViewIs('admin.districts.index'); } // ==================== Index ==================== public function test_districts_index_displays_districts(): void { $district = District::factory()->create(['name' => 'Тестовый округ']); $response = $this->actingAs($this->adminUser) ->get(route('admin.district.index')); $response->assertStatus(200); $response->assertSee('Тестовый округ'); } public function test_districts_index_displays_areas_count(): void { $district = District::factory()->create(); Area::factory()->count(3)->create(['district_id' => $district->id]); $response = $this->actingAs($this->adminUser) ->get(route('admin.district.index')); $response->assertStatus(200); $response->assertSee('3'); } // ==================== Show ==================== public function test_admin_can_view_district_edit_form(): void { $district = District::factory()->create(); $response = $this->actingAs($this->adminUser) ->get(route('admin.district.show', $district->id)); $response->assertStatus(200); $response->assertViewIs('admin.districts.edit'); $response->assertSee($district->name); } public function test_manager_cannot_view_district_edit_form(): void { $district = District::factory()->create(); $response = $this->actingAs($this->managerUser) ->get(route('admin.district.show', $district->id)); $response->assertStatus(403); } // ==================== Store ==================== public function test_admin_can_create_new_district(): void { $response = $this->actingAs($this->adminUser) ->post(route('admin.district.store'), [ 'shortname' => 'ТСТ', 'name' => 'Тестовый округ', ]); $response->assertRedirect(route('admin.district.index')); $this->assertDatabaseHas('districts', [ 'shortname' => 'ТСТ', 'name' => 'Тестовый округ', ]); } public function test_admin_can_update_existing_district(): void { $district = District::factory()->create([ 'shortname' => 'СТР', 'name' => 'Старое название', ]); $response = $this->actingAs($this->adminUser) ->post(route('admin.district.store'), [ 'id' => $district->id, 'shortname' => 'НВ', 'name' => 'Новое название', ]); $response->assertRedirect(route('admin.district.index')); $this->assertDatabaseHas('districts', [ 'id' => $district->id, 'shortname' => 'НВ', 'name' => 'Новое название', ]); } public function test_store_district_requires_name(): void { $response = $this->actingAs($this->adminUser) ->post(route('admin.district.store'), [ 'shortname' => 'ТСТ', ]); $response->assertSessionHasErrors('name'); } public function test_store_district_requires_shortname(): void { $response = $this->actingAs($this->adminUser) ->post(route('admin.district.store'), [ 'name' => 'Тестовый округ', ]); $response->assertSessionHasErrors('shortname'); } // ==================== Destroy ==================== public function test_admin_can_delete_district_without_areas(): void { $district = District::factory()->create(); $response = $this->actingAs($this->adminUser) ->delete(route('admin.district.destroy', $district->id)); $response->assertRedirect(route('admin.district.index')); $this->assertSoftDeleted('districts', ['id' => $district->id]); } public function test_admin_cannot_delete_district_with_areas(): void { $district = District::factory()->create(); Area::factory()->create(['district_id' => $district->id]); $response = $this->actingAs($this->adminUser) ->delete(route('admin.district.destroy', $district->id)); $response->assertRedirect(route('admin.district.index')); $response->assertSessionHas('error'); $this->assertDatabaseHas('districts', ['id' => $district->id, 'deleted_at' => null]); } // ==================== Undelete ==================== public function test_admin_can_restore_deleted_district(): void { $district = District::factory()->create(); $district->delete(); $response = $this->actingAs($this->adminUser) ->post(route('admin.district.undelete', $district->id)); $response->assertRedirect(route('admin.district.index')); $this->assertDatabaseHas('districts', [ 'id' => $district->id, 'deleted_at' => null, ]); } // ==================== Export ==================== public function test_admin_can_export_districts(): void { District::factory()->count(3)->create(); $response = $this->actingAs($this->adminUser) ->post(route('admin.district.export')); $response->assertRedirect(); } // ==================== Import ==================== public function test_admin_can_import_districts(): void { Storage::fake('upload'); // Создаем тестовый XLSX файл $file = $this->createTestDistrictsXlsx(); $response = $this->actingAs($this->adminUser) ->post(route('admin.district.import'), [ 'import_file' => $file, ]); $response->assertRedirect(route('admin.district.index')); } public function test_import_requires_file(): void { $response = $this->actingAs($this->adminUser) ->post(route('admin.district.import'), []); $response->assertSessionHasErrors('import_file'); } public function test_import_requires_xlsx_file(): void { $file = UploadedFile::fake()->create('test.txt', 100, 'text/plain'); $response = $this->actingAs($this->adminUser) ->post(route('admin.district.import'), [ 'import_file' => $file, ]); $response->assertSessionHasErrors('import_file'); } // ==================== Helper Methods ==================== private function createTestDistrictsXlsx(): UploadedFile { $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $sheet->setCellValue('A1', 'ID'); $sheet->setCellValue('B1', 'Сокращение'); $sheet->setCellValue('C1', 'Название'); $sheet->setCellValue('A2', ''); $sheet->setCellValue('B2', 'ТСТ'); $sheet->setCellValue('C2', 'Тестовый округ'); $tempPath = sys_get_temp_dir() . '/test_districts_' . uniqid() . '.xlsx'; $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet); $writer->save($tempPath); return new UploadedFile( $tempPath, 'test_districts.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', null, true ); } }