adminUser = User::factory()->create(['role' => Role::ADMIN]); $this->managerUser = User::factory()->create(['role' => Role::MANAGER]); $this->district = District::factory()->create(['shortname' => 'ЦАО', 'name' => 'Центральный']); } // ==================== Authentication & Authorization ==================== public function test_guest_cannot_access_areas_index(): void { $response = $this->get(route('admin.area.index')); $response->assertRedirect(route('login')); } public function test_manager_cannot_access_areas_index(): void { $response = $this->actingAs($this->managerUser) ->get(route('admin.area.index')); $response->assertStatus(403); } public function test_admin_can_access_areas_index(): void { $response = $this->actingAs($this->adminUser) ->get(route('admin.area.index')); $response->assertStatus(200); $response->assertViewIs('admin.areas.index'); } // ==================== Index ==================== public function test_areas_index_displays_areas(): void { $area = Area::factory()->create([ 'name' => 'Тестовый район', 'district_id' => $this->district->id, ]); $response = $this->actingAs($this->adminUser) ->get(route('admin.area.index')); $response->assertStatus(200); $response->assertSee('Тестовый район'); } public function test_areas_index_can_filter_by_district(): void { $area1 = Area::factory()->create([ 'name' => 'Район ЦАО', 'district_id' => $this->district->id, ]); $otherDistrict = District::factory()->create(['shortname' => 'САО']); $area2 = Area::factory()->create([ 'name' => 'Район САО', 'district_id' => $otherDistrict->id, ]); $response = $this->actingAs($this->adminUser) ->get(route('admin.area.index', ['district_id' => $this->district->id])); $response->assertStatus(200); $response->assertSee('Район ЦАО'); $response->assertDontSee('Район САО'); } // ==================== Show ==================== public function test_admin_can_view_area_edit_form(): void { $area = Area::factory()->create(['district_id' => $this->district->id]); $response = $this->actingAs($this->adminUser) ->get(route('admin.area.show', $area->id)); $response->assertStatus(200); $response->assertViewIs('admin.areas.edit'); $response->assertSee($area->name); } public function test_manager_cannot_view_area_edit_form(): void { $area = Area::factory()->create(['district_id' => $this->district->id]); $response = $this->actingAs($this->managerUser) ->get(route('admin.area.show', $area->id)); $response->assertStatus(403); } // ==================== Store ==================== public function test_admin_can_create_new_area(): void { $response = $this->actingAs($this->adminUser) ->post(route('admin.area.store'), [ 'name' => 'Тестовый район', 'district_id' => $this->district->id, ]); $response->assertRedirect(route('admin.area.index')); $this->assertDatabaseHas('areas', [ 'name' => 'Тестовый район', 'district_id' => $this->district->id, ]); } public function test_admin_can_update_existing_area(): void { $area = Area::factory()->create([ 'name' => 'Старое название', 'district_id' => $this->district->id, ]); $newDistrict = District::factory()->create(); $response = $this->actingAs($this->adminUser) ->post(route('admin.area.store'), [ 'id' => $area->id, 'name' => 'Новое название', 'district_id' => $newDistrict->id, ]); $response->assertRedirect(route('admin.area.index')); $this->assertDatabaseHas('areas', [ 'id' => $area->id, 'name' => 'Новое название', 'district_id' => $newDistrict->id, ]); } public function test_store_area_requires_name(): void { $response = $this->actingAs($this->adminUser) ->post(route('admin.area.store'), [ 'district_id' => $this->district->id, ]); $response->assertSessionHasErrors('name'); } public function test_store_area_requires_district_id(): void { $response = $this->actingAs($this->adminUser) ->post(route('admin.area.store'), [ 'name' => 'Тестовый район', ]); $response->assertSessionHasErrors('district_id'); } public function test_store_area_validates_district_exists(): void { $response = $this->actingAs($this->adminUser) ->post(route('admin.area.store'), [ 'name' => 'Тестовый район', 'district_id' => 99999, ]); $response->assertSessionHasErrors('district_id'); } // ==================== Destroy ==================== public function test_admin_can_delete_area(): void { $area = Area::factory()->create(['district_id' => $this->district->id]); $response = $this->actingAs($this->adminUser) ->delete(route('admin.area.destroy', $area->id)); $response->assertRedirect(route('admin.area.index')); $this->assertSoftDeleted('areas', ['id' => $area->id]); } // ==================== Undelete ==================== public function test_admin_can_restore_deleted_area(): void { $area = Area::factory()->create(['district_id' => $this->district->id]); $area->delete(); $response = $this->actingAs($this->adminUser) ->post(route('admin.area.undelete', $area->id)); $response->assertRedirect(route('admin.area.index')); $this->assertDatabaseHas('areas', [ 'id' => $area->id, 'deleted_at' => null, ]); } // ==================== Export ==================== public function test_admin_can_export_areas(): void { Area::factory()->count(3)->create(['district_id' => $this->district->id]); $response = $this->actingAs($this->adminUser) ->post(route('admin.area.export')); $response->assertRedirect(); } // ==================== Import ==================== public function test_admin_can_import_areas(): void { Storage::fake('upload'); $file = $this->createTestAreasXlsx(); $response = $this->actingAs($this->adminUser) ->post(route('admin.area.import'), [ 'import_file' => $file, ]); $response->assertRedirect(route('admin.area.index')); } public function test_import_requires_file(): void { $response = $this->actingAs($this->adminUser) ->post(route('admin.area.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.area.import'), [ 'import_file' => $file, ]); $response->assertSessionHasErrors('import_file'); } // ==================== Helper Methods ==================== private function createTestAreasXlsx(): UploadedFile { $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $sheet->setCellValue('A1', 'ID'); $sheet->setCellValue('B1', 'Название'); $sheet->setCellValue('C1', 'Округ (сокращение)'); $sheet->setCellValue('D1', 'ID округа'); $sheet->setCellValue('A2', ''); $sheet->setCellValue('B2', 'Тестовый район'); $sheet->setCellValue('C2', 'ЦАО'); $sheet->setCellValue('D2', $this->district->id); $tempPath = sys_get_temp_dir() . '/test_areas_' . uniqid() . '.xlsx'; $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet); $writer->save($tempPath); return new UploadedFile( $tempPath, 'test_areas.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', null, true ); } }