admin = User::factory()->admin()->create(); }); // =========================================== // Access Tests // =========================================== test('admin can access consultation export page', function () { $this->actingAs($this->admin) ->get(route('admin.consultations.export')) ->assertOk(); }); test('non-admin cannot access consultation export page', function () { $client = User::factory()->individual()->create(); $this->actingAs($client) ->get(route('admin.consultations.export')) ->assertForbidden(); }); test('unauthenticated user cannot access consultation export page', function () { $this->get(route('admin.consultations.export')) ->assertRedirect(route('login')); }); // =========================================== // CSV Export Tests // =========================================== test('admin can export all consultations as CSV', function () { Consultation::factory()->count(5)->create(); $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('consultationType', 'all') ->call('exportCsv') ->assertFileDownloaded('consultations-export-'.now()->format('Y-m-d').'.csv'); }); test('admin can export consultations filtered by free type', function () { Consultation::factory()->count(3)->free()->create(); Consultation::factory()->count(2)->paid()->create(); $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('consultationType', 'free') ->call('exportCsv') ->assertFileDownloaded(); }); test('admin can export consultations filtered by paid type', function () { Consultation::factory()->count(3)->free()->create(); Consultation::factory()->count(2)->paid()->create(); $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('consultationType', 'paid') ->call('exportCsv') ->assertFileDownloaded(); }); test('admin can export consultations filtered by pending status', function () { Consultation::factory()->count(3)->pending()->create(); Consultation::factory()->count(2)->completed()->create(); $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('status', 'pending') ->call('exportCsv') ->assertFileDownloaded(); }); test('admin can export consultations filtered by completed status', function () { Consultation::factory()->count(3)->pending()->create(); Consultation::factory()->count(2)->completed()->create(); $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('status', 'completed') ->call('exportCsv') ->assertFileDownloaded(); }); test('admin can export consultations filtered by approved status', function () { Consultation::factory()->count(3)->approved()->create(); Consultation::factory()->count(2)->pending()->create(); $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('status', 'approved') ->call('exportCsv') ->assertFileDownloaded(); }); test('admin can export consultations filtered by cancelled status', function () { Consultation::factory()->count(2)->cancelled()->create(); Consultation::factory()->count(3)->completed()->create(); $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('status', 'cancelled') ->call('exportCsv') ->assertFileDownloaded(); }); test('admin can export consultations filtered by no-show status', function () { Consultation::factory()->count(2)->noShow()->create(); Consultation::factory()->count(3)->completed()->create(); $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('status', 'no_show') ->call('exportCsv') ->assertFileDownloaded(); }); test('admin can export consultations filtered by payment status pending', function () { Consultation::factory()->count(3)->paid()->create(['payment_status' => 'pending']); Consultation::factory()->count(2)->paid()->create(['payment_status' => 'received']); $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('paymentStatus', 'pending') ->call('exportCsv') ->assertFileDownloaded(); }); test('admin can export consultations filtered by payment status received', function () { Consultation::factory()->count(3)->paid()->create(['payment_status' => 'pending']); Consultation::factory()->count(2)->paid()->create(['payment_status' => 'received']); $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('paymentStatus', 'received') ->call('exportCsv') ->assertFileDownloaded(); }); test('admin can export consultations filtered by date range', function () { Consultation::factory()->create(['booking_date' => now()->subDays(10)]); Consultation::factory()->create(['booking_date' => now()->subDays(5)]); Consultation::factory()->create(['booking_date' => now()]); $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('dateFrom', now()->subDays(7)->format('Y-m-d')) ->set('dateTo', now()->format('Y-m-d')) ->call('exportCsv') ->assertFileDownloaded(); }); test('admin can export with combined filters', function () { Consultation::factory()->paid()->pending()->create(['booking_date' => now()->subDays(5)]); Consultation::factory()->free()->completed()->create(['booking_date' => now()->subDays(5)]); Consultation::factory()->paid()->completed()->create(['booking_date' => now()->subDays(5)]); $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('consultationType', 'paid') ->set('status', 'pending') ->set('dateFrom', now()->subDays(7)->format('Y-m-d')) ->set('dateTo', now()->format('Y-m-d')) ->call('exportCsv') ->assertFileDownloaded(); }); // =========================================== // PDF Export Tests // =========================================== test('admin can export consultations as PDF', function () { Consultation::factory()->count(5)->create(); $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->call('exportPdf') ->assertFileDownloaded('consultations-export-'.now()->format('Y-m-d').'.pdf'); }); test('admin can export PDF with filters', function () { Consultation::factory()->count(3)->free()->create(); Consultation::factory()->count(2)->paid()->create(); $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('consultationType', 'free') ->call('exportPdf') ->assertFileDownloaded(); }); // =========================================== // Empty Dataset Tests // =========================================== test('CSV export dispatches notification when no consultations match filters', function () { $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('consultationType', 'paid') ->set('status', 'completed') ->call('exportCsv') ->assertDispatched('notify'); }); test('PDF export dispatches notification when no consultations match filters', function () { $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('consultationType', 'paid') ->set('status', 'completed') ->call('exportPdf') ->assertDispatched('notify'); }); test('preview count shows zero when no consultations match filters', function () { $this->actingAs($this->admin); Volt::test('admin.consultations.export-consultations') ->set('consultationType', 'paid') ->set('status', 'completed') ->assertSee('0'); }); // =========================================== // Filter Tests // =========================================== test('preview count updates when filters change', function () { Consultation::factory()->count(3)->free()->create(); Consultation::factory()->count(2)->paid()->create(); $this->actingAs($this->admin); // All consultations - should show 5 Volt::test('admin.consultations.export-consultations') ->set('consultationType', 'all') ->assertSeeHtml('5'); // Filter to free only - should show 3 Volt::test('admin.consultations.export-consultations') ->set('consultationType', 'free') ->assertSeeHtml('3'); // Filter to paid only - should show 2 Volt::test('admin.consultations.export-consultations') ->set('consultationType', 'paid') ->assertSeeHtml('2'); }); test('clear filters resets all filter values', function () { $this->actingAs($this->admin); $component = Volt::test('admin.consultations.export-consultations') ->set('consultationType', 'paid') ->set('status', 'completed') ->set('paymentStatus', 'received') ->set('dateFrom', '2024-01-01') ->set('dateTo', '2024-12-31') ->call('clearFilters'); expect($component->get('consultationType'))->toBe('all'); expect($component->get('status'))->toBe('all'); expect($component->get('paymentStatus'))->toBe('all'); expect($component->get('dateFrom'))->toBe(''); expect($component->get('dateTo'))->toBe(''); }); // =========================================== // Language Tests // =========================================== test('export uses admin preferred language for headers', function () { $adminArabic = User::factory()->admin()->create(['preferred_language' => 'ar']); Consultation::factory()->create(); $this->actingAs($adminArabic); Volt::test('admin.consultations.export-consultations') ->call('exportCsv') ->assertFileDownloaded(); }); test('export uses English when admin prefers English', function () { $adminEnglish = User::factory()->admin()->create(['preferred_language' => 'en']); Consultation::factory()->create(); $this->actingAs($adminEnglish); Volt::test('admin.consultations.export-consultations') ->call('exportCsv') ->assertFileDownloaded(); });