get(route('client.consultations.index')) ->assertRedirect(route('login')); }); test('client can view their consultations page', function () { $user = User::factory()->individual()->create(); $this->actingAs($user) ->get(route('client.consultations.index')) ->assertOk(); }); test('admin cannot access client consultations page', function () { $admin = User::factory()->admin()->create(); $this->actingAs($admin) ->get(route('client.consultations.index')) ->assertForbidden(); }); test('user sees only their own consultations', function () { $user = User::factory()->individual()->create(); $otherUser = User::factory()->individual()->create(); Consultation::factory()->approved()->create([ 'user_id' => $user->id, 'booking_date' => today()->addDays(3), 'booking_time' => '09:00:00', ]); Consultation::factory()->approved()->create([ 'user_id' => $otherUser->id, 'booking_date' => today()->addDays(2), 'booking_time' => '14:00:00', ]); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee('9:00 AM') ->assertDontSee('2:00 PM'); }); // Upcoming Section Tests test('upcoming section shows approved consultations with future date', function () { $user = User::factory()->individual()->create(); $consultation = Consultation::factory()->approved()->free()->create([ 'user_id' => $user->id, 'booking_date' => today()->addDays(3), 'booking_time' => '10:00:00', ]); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee('10:00 AM') ->assertSee(__('booking.type_free')); }); test('upcoming section is sorted by date ascending', function () { $user = User::factory()->individual()->create(); Consultation::factory()->approved()->create([ 'user_id' => $user->id, 'booking_date' => today()->addDays(5), 'booking_time' => '11:00:00', ]); Consultation::factory()->approved()->create([ 'user_id' => $user->id, 'booking_date' => today()->addDays(2), 'booking_time' => '09:00:00', ]); $this->actingAs($user); $component = Volt::test('client.consultations.index'); // The earlier date should appear first in upcoming $html = $component->html(); $pos1 = strpos($html, '9:00 AM'); $pos2 = strpos($html, '11:00 AM'); expect($pos1)->toBeLessThan($pos2); }); test('upcoming section displays consultation type correctly', function () { $user = User::factory()->individual()->create(); Consultation::factory()->approved()->free()->create([ 'user_id' => $user->id, 'booking_date' => today()->addDays(2), ]); Consultation::factory()->approved()->paid()->create([ 'user_id' => $user->id, 'booking_date' => today()->addDays(3), ]); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee(__('booking.type_free')) ->assertSee(__('booking.type_paid')); }); test('upcoming section shows payment status for paid consultations', function () { $user = User::factory()->individual()->create(); Consultation::factory()->approved()->create([ 'user_id' => $user->id, 'booking_date' => today()->addDays(2), 'consultation_type' => ConsultationType::Paid, 'payment_status' => PaymentStatus::Pending, ]); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee(__('booking.payment_pending')); }); test('upcoming section shows payment received badge when payment is received', function () { $user = User::factory()->individual()->create(); Consultation::factory()->approved()->create([ 'user_id' => $user->id, 'booking_date' => today()->addDays(2), 'consultation_type' => ConsultationType::Paid, 'payment_status' => PaymentStatus::Received, ]); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee(__('booking.payment_received')); }); test('calendar download button is available for upcoming approved consultations', function () { $user = User::factory()->individual()->create(); Consultation::factory()->approved()->create([ 'user_id' => $user->id, 'booking_date' => today()->addDays(2), ]); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee(__('booking.add_to_calendar')); }); // Pending Section Tests test('pending section shows consultations with pending status', function () { $user = User::factory()->individual()->create(); Consultation::factory()->pending()->create([ 'user_id' => $user->id, 'booking_date' => today()->addDays(5), 'problem_summary' => 'This is my pending consultation request', ]); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee('This is my pending consultation') ->assertSee(__('booking.pending_review')); }); test('pending section shows submission date', function () { $user = User::factory()->individual()->create(); Consultation::factory()->pending()->create([ 'user_id' => $user->id, 'booking_date' => today()->addDays(5), 'created_at' => now(), ]); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee(__('booking.submitted_on')); }); test('pending section truncates long problem summary', function () { $user = User::factory()->individual()->create(); $longSummary = str_repeat('This is a very long problem summary. ', 20); Consultation::factory()->pending()->create([ 'user_id' => $user->id, 'booking_date' => today()->addDays(5), 'problem_summary' => $longSummary, ]); $this->actingAs($user); // The summary should be truncated (not show full text) Volt::test('client.consultations.index') ->assertDontSee($longSummary); }); // Past Section Tests test('past section shows completed consultations', function () { $user = User::factory()->individual()->create(); Consultation::factory()->completed()->create([ 'user_id' => $user->id, 'booking_date' => today()->subDays(5), 'booking_time' => '14:00:00', ]); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee('2:00 PM'); }); test('past section shows cancelled consultations', function () { $user = User::factory()->individual()->create(); Consultation::factory()->cancelled()->create([ 'user_id' => $user->id, 'booking_date' => today()->subDays(3), ]); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee(ConsultationStatus::Cancelled->label()); }); test('past section shows no-show consultations', function () { $user = User::factory()->individual()->create(); Consultation::factory()->noShow()->create([ 'user_id' => $user->id, 'booking_date' => today()->subDays(3), ]); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee(ConsultationStatus::NoShow->label()); }); test('past section shows approved consultations with past date', function () { $user = User::factory()->individual()->create(); Consultation::factory()->approved()->create([ 'user_id' => $user->id, 'booking_date' => today()->subDays(2), 'booking_time' => '16:00:00', ]); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee('4:00 PM'); }); test('past section is sorted by date descending', function () { $user = User::factory()->individual()->create(); Consultation::factory()->completed()->create([ 'user_id' => $user->id, 'booking_date' => today()->subDays(10), 'booking_time' => '09:00:00', ]); Consultation::factory()->completed()->create([ 'user_id' => $user->id, 'booking_date' => today()->subDays(2), 'booking_time' => '15:00:00', ]); $this->actingAs($user); $component = Volt::test('client.consultations.index'); $html = $component->html(); // The more recent date should appear first in past section $pos1 = strpos($html, '3:00 PM'); $pos2 = strpos($html, '9:00 AM'); expect($pos1)->toBeLessThan($pos2); }); test('past section paginates correctly', function () { $user = User::factory()->individual()->create(); // Create 15 completed consultations with unique times for identification for ($i = 1; $i <= 15; $i++) { Consultation::factory()->completed()->create([ 'user_id' => $user->id, 'booking_date' => today()->subDays($i), 'booking_time' => sprintf('%02d:00:00', $i), ]); } $this->actingAs($user); // First page should show 10 items, ordered by booking_date desc // So items with booking_date subDays(1) through subDays(10) should appear // Items with subDays(11) through subDays(15) should NOT appear on first page $component = Volt::test('client.consultations.index'); // The 11th, 12th, 13th, 14th, 15th items (oldest) should NOT be on the first page // booking_time 11:00, 12:00, 13:00, 14:00, 15:00 correspond to the oldest items $component->assertDontSee('11:00 AM') ->assertDontSee('12:00 PM') ->assertDontSee('1:00 PM') ->assertDontSee('2:00 PM') ->assertDontSee('3:00 PM'); }); // Empty States Tests test('empty upcoming shows appropriate message with link to book', function () { $user = User::factory()->individual()->create(); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee(__('booking.no_upcoming_consultations')) ->assertSee(__('booking.book_consultation')); }); test('empty pending shows appropriate message', function () { $user = User::factory()->individual()->create(); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee(__('booking.no_pending_requests')); }); test('empty past shows appropriate message', function () { $user = User::factory()->individual()->create(); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee(__('booking.no_past_consultations')); }); // Read-only Tests test('consultations page is read only with no edit capabilities', function () { $user = User::factory()->individual()->create(); Consultation::factory()->approved()->create([ 'user_id' => $user->id, 'booking_date' => today()->addDays(3), ]); $this->actingAs($user); Volt::test('client.consultations.index') ->assertDontSee('Edit') ->assertDontSee('Cancel') ->assertDontSee('Delete'); }); // Section Heading Tests test('page displays all section headings', function () { $user = User::factory()->individual()->create(); $this->actingAs($user); Volt::test('client.consultations.index') ->assertSee(__('booking.my_consultations')) ->assertSee(__('booking.upcoming_consultations')) ->assertSee(__('booking.pending_requests')) ->assertSee(__('booking.past_consultations')); }); // Company Client Tests test('company client can view consultations page', function () { $user = User::factory()->company()->create(); $this->actingAs($user) ->get(route('client.consultations.index')) ->assertOk(); });