390 lines
12 KiB
PHP
390 lines
12 KiB
PHP
<?php
|
|
|
|
use App\Enums\ConsultationStatus;
|
|
use App\Enums\ConsultationType;
|
|
use App\Enums\PaymentStatus;
|
|
use App\Models\Consultation;
|
|
use App\Models\User;
|
|
use Livewire\Volt\Volt;
|
|
|
|
// Access Control Tests
|
|
test('unauthenticated user is redirected to login', function () {
|
|
$this->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();
|
|
});
|