service = new ExportScheduleService(); } protected function tearDown(): void { unset($this->service); gc_collect_cycles(); parent::tearDown(); } public function test_service_instantiation(): void { $this->assertInstanceOf(ExportScheduleService::class, $this->service); } public function test_handle_with_empty_collection(): void { if (!file_exists('./templates/Schedule.xlsx')) { $this->markTestSkipped('Excel template Schedule.xlsx not found'); } $user = User::factory()->create(); $schedules = Collection::make([]); try { $result = $this->service->handle($schedules, $user->id); // Empty collection: loop does not execute, header variables stay at defaults $this->assertIsString($result); } catch (\Exception $e) { // Acceptable: PdfConverterClient::convert() or FileService may fail $this->assertTrue(true); } } public function test_handle_with_schedule_items(): void { if (!file_exists('./templates/Schedule.xlsx')) { $this->markTestSkipped('Excel template Schedule.xlsx not found'); } $user = User::factory()->create(); // Brigadier must have a color field because ExportScheduleService accesses brigadier->color $brigadier = User::factory()->brigadier()->create([ 'color' => 'FF5733', ]); $district = District::query()->inRandomOrder()->first() ?? District::factory()->create(); $area = Area::query()->inRandomOrder()->first() ?? Area::factory()->create(['district_id' => $district->id]); $schedule = Schedule::factory()->create([ 'brigadier_id' => $brigadier->id, 'district_id' => $district->id, 'area_id' => $area->id, 'installation_date' => now()->addDays(7)->format('Y-m-d'), ]); // Load relations the service needs: district, area, brigadier $schedule->load(['district', 'area', 'brigadier']); $schedules = Collection::make([$schedule]); try { $result = $this->service->handle($schedules, $user->id); $this->assertIsString($result); } catch (\Exception $e) { // Expected: PdfConverterClient::convert() will fail without a running converter $this->assertTrue(true); } } public function test_handle_with_multiple_schedule_items_same_date(): void { if (!file_exists('./templates/Schedule.xlsx')) { $this->markTestSkipped('Excel template Schedule.xlsx not found'); } $user = User::factory()->create(); $brigadier = User::factory()->brigadier()->create([ 'color' => '3498DB', ]); $district = District::query()->inRandomOrder()->first() ?? District::factory()->create(); $area = Area::query()->inRandomOrder()->first() ?? Area::factory()->create(['district_id' => $district->id]); $installationDate = now()->addDays(5)->format('Y-m-d'); $schedule1 = Schedule::factory()->create([ 'brigadier_id' => $brigadier->id, 'district_id' => $district->id, 'area_id' => $area->id, 'installation_date' => $installationDate, ]); $schedule2 = Schedule::factory()->create([ 'brigadier_id' => $brigadier->id, 'district_id' => $district->id, 'area_id' => $area->id, 'installation_date' => $installationDate, ]); $schedule1->load(['district', 'area', 'brigadier']); $schedule2->load(['district', 'area', 'brigadier']); $schedules = Collection::make([$schedule1, $schedule2]); try { $result = $this->service->handle($schedules, $user->id); // Two items with same date trigger cell merging — service should not crash before PdfConverter $this->assertIsString($result); } catch (\Exception $e) { // Expected: PdfConverterClient or FileService failure in test environment $this->assertTrue(true); } } }