create([ 'day_of_week' => $day, 'start_time' => '09:00', 'end_time' => '17:00', 'is_active' => true, ]); } }); it('displays current month by default', function () { $currentMonth = now()->translatedFormat('F Y'); Volt::test('availability-calendar') ->assertSee($currentMonth); }); it('navigates to next month', function () { $nextMonth = now()->addMonth()->translatedFormat('F Y'); Volt::test('availability-calendar') ->call('nextMonth') ->assertSee($nextMonth); }); it('prevents navigating to past months', function () { Volt::test('availability-calendar') ->assertSet('year', now()->year) ->assertSet('month', now()->month) ->call('previousMonth') ->assertSet('year', now()->year) ->assertSet('month', now()->month); }); it('handles year rollover when navigating months', function () { Carbon::setTestNow(Carbon::create(2024, 12, 15)); Volt::test('availability-calendar') ->assertSet('year', 2024) ->assertSet('month', 12) ->call('nextMonth') ->assertSet('year', 2025) ->assertSet('month', 1); Carbon::setTestNow(); }); it('loads available slots when date is selected', function () { $sunday = Carbon::now()->next(Carbon::SUNDAY)->format('Y-m-d'); Volt::test('availability-calendar') ->call('selectDate', $sunday) ->assertSet('selectedDate', $sunday) ->assertNotSet('availableSlots', []); }); it('does not select unavailable dates', function () { // Friday is a non-working day in our setup $friday = Carbon::now()->next(Carbon::FRIDAY)->format('Y-m-d'); Volt::test('availability-calendar') ->call('selectDate', $friday) ->assertSet('selectedDate', null) ->assertSet('availableSlots', []); }); it('clears selection when navigating months', function () { $sunday = Carbon::now()->next(Carbon::SUNDAY)->format('Y-m-d'); Volt::test('availability-calendar') ->call('selectDate', $sunday) ->assertSet('selectedDate', $sunday) ->call('nextMonth') ->assertSet('selectedDate', null) ->assertSet('availableSlots', []); }); it('displays RTL layout for Arabic locale', function () { app()->setLocale('ar'); Volt::test('availability-calendar') ->assertSeeHtml('dir="rtl"'); }); it('does not select blocked dates', function () { $sunday = Carbon::now()->next(Carbon::SUNDAY); BlockedTime::factory()->allDay()->create([ 'block_date' => $sunday->toDateString(), ]); Volt::test('availability-calendar') ->call('selectDate', $sunday->toDateString()) ->assertSet('selectedDate', null); }); it('does not select fully booked dates', function () { $sunday = Carbon::now()->next(Carbon::SUNDAY); $slots = ['09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00']; foreach ($slots as $slot) { Consultation::factory()->approved()->create([ 'booking_date' => $sunday->toDateString(), 'booking_time' => $slot, ]); } Volt::test('availability-calendar') ->call('selectDate', $sunday->toDateString()) ->assertSet('selectedDate', null); }); it('shows available legend items', function () { Volt::test('availability-calendar') ->assertSee(__('booking.available')) ->assertSee(__('booking.partial')) ->assertSee(__('booking.unavailable')); }); it('allows selecting partially booked dates', function () { $sunday = Carbon::now()->next(Carbon::SUNDAY); Consultation::factory()->approved()->create([ 'booking_date' => $sunday->toDateString(), 'booking_time' => '10:00', ]); Volt::test('availability-calendar') ->call('selectDate', $sunday->toDateString()) ->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')); });