complete story 7.6 with qa tests
This commit is contained in:
@@ -0,0 +1,254 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Consultation;
|
||||
use App\Models\User;
|
||||
use App\Models\WorkingHour;
|
||||
use Livewire\Volt\Volt;
|
||||
|
||||
beforeEach(function () {
|
||||
// Setup working hours for Monday (day 1)
|
||||
WorkingHour::factory()->create([
|
||||
'day_of_week' => 1,
|
||||
'start_time' => '09:00',
|
||||
'end_time' => '17:00',
|
||||
'is_active' => true,
|
||||
]);
|
||||
});
|
||||
|
||||
// Booking Page Status Banner Tests
|
||||
test('booking page shows can book today message for new users', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
Volt::test('client.consultations.book')
|
||||
->assertSee(__('booking.can_book_today'));
|
||||
});
|
||||
|
||||
test('booking page shows already booked message when user has pending booking today', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
Consultation::factory()->pending()->create([
|
||||
'user_id' => $client->id,
|
||||
'booking_date' => today(),
|
||||
]);
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
Volt::test('client.consultations.book')
|
||||
->assertSee(__('booking.already_booked_today'));
|
||||
});
|
||||
|
||||
test('booking page shows already booked message when user has approved booking today', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
Consultation::factory()->approved()->create([
|
||||
'user_id' => $client->id,
|
||||
'booking_date' => today(),
|
||||
]);
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
Volt::test('client.consultations.book')
|
||||
->assertSee(__('booking.already_booked_today'));
|
||||
});
|
||||
|
||||
test('booking page shows can book when user has only cancelled booking today', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
Consultation::factory()->cancelled()->create([
|
||||
'user_id' => $client->id,
|
||||
'booking_date' => today(),
|
||||
]);
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
Volt::test('client.consultations.book')
|
||||
->assertSee(__('booking.can_book_today'));
|
||||
});
|
||||
|
||||
test('booking page shows can book when user has only rejected booking today', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
Consultation::factory()->rejected()->create([
|
||||
'user_id' => $client->id,
|
||||
'booking_date' => today(),
|
||||
]);
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
Volt::test('client.consultations.book')
|
||||
->assertSee(__('booking.can_book_today'));
|
||||
});
|
||||
|
||||
// Pending Requests Display Tests
|
||||
test('booking page shows single pending request date', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
$pendingDate = today()->addDays(3);
|
||||
Consultation::factory()->pending()->create([
|
||||
'user_id' => $client->id,
|
||||
'booking_date' => $pendingDate,
|
||||
]);
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
Volt::test('client.consultations.book')
|
||||
->assertSee($pendingDate->format('d/m/Y'));
|
||||
});
|
||||
|
||||
test('booking page shows pending request count for multiple requests', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
Consultation::factory()->pending()->count(3)->create([
|
||||
'user_id' => $client->id,
|
||||
'booking_date' => today()->addDays(5),
|
||||
]);
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
Volt::test('client.consultations.book')
|
||||
->assertSee(__('booking.pending_count', ['count' => 3]));
|
||||
});
|
||||
|
||||
test('booking page shows limit message', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
Volt::test('client.consultations.book')
|
||||
->assertSee(__('booking.limit_message'));
|
||||
});
|
||||
|
||||
// getBookingStatus Method Tests
|
||||
test('getBookingStatus returns correct structure', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
$component = Volt::test('client.consultations.book');
|
||||
|
||||
// The component should have these view properties via with() method
|
||||
$component->assertViewHas('canBookToday', true)
|
||||
->assertViewHas('todayBooking', null)
|
||||
->assertViewHas('pendingRequests')
|
||||
->assertViewHas('bookedDates');
|
||||
});
|
||||
|
||||
test('bookedDates only includes pending and approved bookings', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
|
||||
// Create bookings with different statuses
|
||||
$pendingDate = today()->addDays(1)->format('Y-m-d');
|
||||
$approvedDate = today()->addDays(2)->format('Y-m-d');
|
||||
$cancelledDate = today()->addDays(3)->format('Y-m-d');
|
||||
$rejectedDate = today()->addDays(4)->format('Y-m-d');
|
||||
|
||||
Consultation::factory()->pending()->create([
|
||||
'user_id' => $client->id,
|
||||
'booking_date' => $pendingDate,
|
||||
]);
|
||||
Consultation::factory()->approved()->create([
|
||||
'user_id' => $client->id,
|
||||
'booking_date' => $approvedDate,
|
||||
]);
|
||||
Consultation::factory()->cancelled()->create([
|
||||
'user_id' => $client->id,
|
||||
'booking_date' => $cancelledDate,
|
||||
]);
|
||||
Consultation::factory()->rejected()->create([
|
||||
'user_id' => $client->id,
|
||||
'booking_date' => $rejectedDate,
|
||||
]);
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
$component = Volt::test('client.consultations.book');
|
||||
|
||||
$bookedDates = $component->viewData('bookedDates');
|
||||
|
||||
expect($bookedDates)->toContain($pendingDate)
|
||||
->toContain($approvedDate)
|
||||
->not->toContain($cancelledDate)
|
||||
->not->toContain($rejectedDate);
|
||||
});
|
||||
|
||||
test('bookedDates does not include past bookings', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
|
||||
$pastDate = today()->subDays(3)->format('Y-m-d');
|
||||
$futureDate = today()->addDays(3)->format('Y-m-d');
|
||||
|
||||
Consultation::factory()->approved()->create([
|
||||
'user_id' => $client->id,
|
||||
'booking_date' => $pastDate,
|
||||
]);
|
||||
Consultation::factory()->approved()->create([
|
||||
'user_id' => $client->id,
|
||||
'booking_date' => $futureDate,
|
||||
]);
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
$component = Volt::test('client.consultations.book');
|
||||
|
||||
$bookedDates = $component->viewData('bookedDates');
|
||||
|
||||
expect($bookedDates)->not->toContain($pastDate)
|
||||
->toContain($futureDate);
|
||||
});
|
||||
|
||||
// Bilingual Support Tests
|
||||
test('booking status messages display correctly in English', function () {
|
||||
app()->setLocale('en');
|
||||
$client = User::factory()->individual()->create();
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
Volt::test('client.consultations.book')
|
||||
->assertSee('You can book a consultation today');
|
||||
});
|
||||
|
||||
test('booking status messages display correctly in Arabic', function () {
|
||||
app()->setLocale('ar');
|
||||
$client = User::factory()->individual()->create();
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
Volt::test('client.consultations.book')
|
||||
->assertSee('يمكنك حجز استشارة اليوم');
|
||||
});
|
||||
|
||||
test('limit message displays correctly in English', function () {
|
||||
app()->setLocale('en');
|
||||
$client = User::factory()->individual()->create();
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
Volt::test('client.consultations.book')
|
||||
->assertSee('Note: You can book a maximum of 1 consultation per day.');
|
||||
});
|
||||
|
||||
test('limit message displays correctly in Arabic', function () {
|
||||
app()->setLocale('ar');
|
||||
$client = User::factory()->individual()->create();
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
Volt::test('client.consultations.book')
|
||||
->assertSee('ملاحظة: يمكنك حجز استشارة واحدة كحد أقصى في اليوم.');
|
||||
});
|
||||
|
||||
// Data Isolation Tests
|
||||
test('booking status does not include other users bookings', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
$otherClient = User::factory()->individual()->create();
|
||||
|
||||
$otherClientDate = today()->addDays(2)->format('Y-m-d');
|
||||
Consultation::factory()->pending()->create([
|
||||
'user_id' => $otherClient->id,
|
||||
'booking_date' => $otherClientDate,
|
||||
]);
|
||||
|
||||
$this->actingAs($client);
|
||||
|
||||
$component = Volt::test('client.consultations.book');
|
||||
|
||||
$bookedDates = $component->viewData('bookedDates');
|
||||
|
||||
expect($bookedDates)->not->toContain($otherClientDate);
|
||||
});
|
||||
@@ -138,3 +138,83 @@ it('allows selecting partially booked dates', function () {
|
||||
->assertSet('selectedDate', $sunday->toDateString())
|
||||
->assertNotSet('availableSlots', []);
|
||||
});
|
||||
|
||||
// User Booked Dates Tests
|
||||
it('accepts bookedDates prop on mount', function () {
|
||||
// Use a date in the current month to avoid navigating
|
||||
$bookedDate = Carbon::now()->startOfMonth()->addDays(10)->format('Y-m-d');
|
||||
|
||||
Volt::test('availability-calendar', ['bookedDates' => [$bookedDate]])
|
||||
->assertSet('bookedDates', [$bookedDate]);
|
||||
});
|
||||
|
||||
it('prevents selecting user booked dates', function () {
|
||||
$sunday = Carbon::now()->next(Carbon::SUNDAY);
|
||||
$component = Volt::test('availability-calendar', ['bookedDates' => [$sunday->format('Y-m-d')]]);
|
||||
|
||||
// Navigate to the month containing the Sunday if necessary
|
||||
if ($sunday->month !== now()->month || $sunday->year !== now()->year) {
|
||||
$component->call('nextMonth');
|
||||
}
|
||||
|
||||
$component->call('selectDate', $sunday->format('Y-m-d'))
|
||||
->assertSet('selectedDate', null);
|
||||
});
|
||||
|
||||
it('marks user booked dates with user_booked status in calendar', function () {
|
||||
$sunday = Carbon::now()->next(Carbon::SUNDAY);
|
||||
$component = Volt::test('availability-calendar', ['bookedDates' => [$sunday->format('Y-m-d')]]);
|
||||
|
||||
// Navigate to the month containing the Sunday if necessary
|
||||
if ($sunday->month !== now()->month || $sunday->year !== now()->year) {
|
||||
$component->call('nextMonth');
|
||||
}
|
||||
|
||||
$calendarDays = $component->viewData('calendarDays');
|
||||
$bookedDay = collect($calendarDays)->firstWhere('date', $sunday->format('Y-m-d'));
|
||||
|
||||
expect($bookedDay)->not->toBeNull();
|
||||
expect($bookedDay['status'])->toBe('user_booked');
|
||||
});
|
||||
|
||||
it('shows user booked legend when bookedDates is not empty', function () {
|
||||
$bookedDate = Carbon::now()->startOfMonth()->addDays(10)->format('Y-m-d');
|
||||
|
||||
Volt::test('availability-calendar', ['bookedDates' => [$bookedDate]])
|
||||
->assertSee(__('booking.user_booked'));
|
||||
});
|
||||
|
||||
it('does not show user booked legend when bookedDates is empty', function () {
|
||||
Volt::test('availability-calendar', ['bookedDates' => []])
|
||||
->assertDontSee(__('booking.user_booked'));
|
||||
});
|
||||
|
||||
it('user booked status takes precedence over available status', function () {
|
||||
$sunday = Carbon::now()->next(Carbon::SUNDAY);
|
||||
$component = Volt::test('availability-calendar', ['bookedDates' => [$sunday->format('Y-m-d')]]);
|
||||
|
||||
// Navigate to the month containing the Sunday if necessary
|
||||
if ($sunday->month !== now()->month || $sunday->year !== now()->year) {
|
||||
$component->call('nextMonth');
|
||||
}
|
||||
|
||||
$calendarDays = $component->viewData('calendarDays');
|
||||
$bookedDay = collect($calendarDays)->firstWhere('date', $sunday->format('Y-m-d'));
|
||||
|
||||
expect($bookedDay)->not->toBeNull();
|
||||
expect($bookedDay['status'])->toBe('user_booked');
|
||||
});
|
||||
|
||||
it('allows selecting dates not in bookedDates array', function () {
|
||||
$sunday = Carbon::now()->next(Carbon::SUNDAY);
|
||||
$monday = Carbon::now()->next(Carbon::MONDAY);
|
||||
$component = Volt::test('availability-calendar', ['bookedDates' => [$sunday->format('Y-m-d')]]);
|
||||
|
||||
// Navigate to the month containing the Monday if necessary
|
||||
if ($monday->month !== now()->month || $monday->year !== now()->year) {
|
||||
$component->call('nextMonth');
|
||||
}
|
||||
|
||||
$component->call('selectDate', $monday->format('Y-m-d'))
|
||||
->assertSet('selectedDate', $monday->format('Y-m-d'));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user