admin = User::factory()->admin()->create(); }); // =========================================== // Access Tests // =========================================== test('admin can access working hours configuration page', function () { $this->actingAs($this->admin) ->get(route('admin.settings.working-hours')) ->assertOk(); }); test('non-admin cannot access working hours configuration page', function () { $client = User::factory()->individual()->create(); $this->actingAs($client) ->get(route('admin.settings.working-hours')) ->assertForbidden(); }); test('unauthenticated user cannot access working hours configuration page', function () { $this->get(route('admin.settings.working-hours')) ->assertRedirect(route('login')); }); // =========================================== // Component Initialization Tests // =========================================== test('component initializes with empty schedule when no working hours exist', function () { $this->actingAs($this->admin); $component = Volt::test('admin.settings.working-hours'); foreach (range(0, 6) as $day) { expect($component->get("schedule.{$day}.is_active"))->toBeFalse(); expect($component->get("schedule.{$day}.start_time"))->toBe('09:00'); expect($component->get("schedule.{$day}.end_time"))->toBe('17:00'); } }); test('component initializes with existing working hours', function () { WorkingHour::factory()->create([ 'day_of_week' => 1, 'start_time' => '08:00:00', 'end_time' => '16:00:00', 'is_active' => true, ]); $this->actingAs($this->admin); $component = Volt::test('admin.settings.working-hours'); expect($component->get('schedule.1.is_active'))->toBeTrue(); expect($component->get('schedule.1.start_time'))->toBe('08:00'); expect($component->get('schedule.1.end_time'))->toBe('16:00'); }); // =========================================== // Save Working Hours Tests // =========================================== test('admin can save working hours configuration', function () { $this->actingAs($this->admin); Volt::test('admin.settings.working-hours') ->set('schedule.1.is_active', true) ->set('schedule.1.start_time', '09:00') ->set('schedule.1.end_time', '17:00') ->call('save') ->assertHasNoErrors(); $workingHour = WorkingHour::where('day_of_week', 1)->first(); expect($workingHour)->not->toBeNull() ->and($workingHour->is_active)->toBeTrue() ->and($workingHour->start_time)->toContain('09:00') ->and($workingHour->end_time)->toContain('17:00'); }); test('admin can enable multiple days with different hours', function () { $this->actingAs($this->admin); Volt::test('admin.settings.working-hours') ->set('schedule.0.is_active', true) ->set('schedule.0.start_time', '09:00') ->set('schedule.0.end_time', '17:00') ->set('schedule.1.is_active', true) ->set('schedule.1.start_time', '08:00') ->set('schedule.1.end_time', '16:00') ->set('schedule.2.is_active', true) ->set('schedule.2.start_time', '10:00') ->set('schedule.2.end_time', '18:00') ->call('save') ->assertHasNoErrors(); expect(WorkingHour::where('is_active', true)->count())->toBe(3); $monday = WorkingHour::where('day_of_week', 1)->first(); expect($monday->start_time)->toContain('08:00'); expect($monday->end_time)->toContain('16:00'); }); test('admin can disable a day', function () { WorkingHour::factory()->create([ 'day_of_week' => 1, 'is_active' => true, ]); $this->actingAs($this->admin); Volt::test('admin.settings.working-hours') ->set('schedule.1.is_active', false) ->call('save') ->assertHasNoErrors(); $workingHour = WorkingHour::where('day_of_week', 1)->first(); expect($workingHour->is_active)->toBeFalse(); }); test('existing working hours are updated not duplicated', function () { WorkingHour::factory()->create([ 'day_of_week' => 1, 'start_time' => '08:00:00', 'end_time' => '16:00:00', 'is_active' => true, ]); $this->actingAs($this->admin); Volt::test('admin.settings.working-hours') ->set('schedule.1.start_time', '09:00') ->set('schedule.1.end_time', '17:00') ->call('save') ->assertHasNoErrors(); expect(WorkingHour::where('day_of_week', 1)->count())->toBe(1); $workingHour = WorkingHour::where('day_of_week', 1)->first(); expect($workingHour->start_time)->toContain('09:00'); expect($workingHour->end_time)->toContain('17:00'); }); // =========================================== // Validation Tests // =========================================== test('validation fails when end time is before start time for active day', function () { $this->actingAs($this->admin); Volt::test('admin.settings.working-hours') ->set('schedule.1.is_active', true) ->set('schedule.1.start_time', '17:00') ->set('schedule.1.end_time', '09:00') ->call('save') ->assertHasErrors(['schedule.1.end_time']); }); test('validation fails when end time equals start time for active day', function () { $this->actingAs($this->admin); Volt::test('admin.settings.working-hours') ->set('schedule.1.is_active', true) ->set('schedule.1.start_time', '09:00') ->set('schedule.1.end_time', '09:00') ->call('save') ->assertHasErrors(['schedule.1.end_time']); }); test('inactive days do not require time validation', function () { $this->actingAs($this->admin); Volt::test('admin.settings.working-hours') ->set('schedule.1.is_active', false) ->set('schedule.1.start_time', '17:00') ->set('schedule.1.end_time', '09:00') ->call('save') ->assertHasNoErrors(); }); // =========================================== // Audit Log Tests // =========================================== test('audit log is created when working hours are saved', function () { $this->actingAs($this->admin); Volt::test('admin.settings.working-hours') ->set('schedule.0.is_active', true) ->set('schedule.0.start_time', '09:00') ->set('schedule.0.end_time', '17:00') ->call('save'); expect(AdminLog::where('target_type', 'working_hours')->count())->toBe(1); $log = AdminLog::where('target_type', 'working_hours')->first(); expect($log->admin_id)->toBe($this->admin->id); expect($log->action)->toBe('update'); }); test('audit log contains old and new values', function () { WorkingHour::factory()->create([ 'day_of_week' => 1, 'start_time' => '08:00:00', 'end_time' => '16:00:00', 'is_active' => true, ]); $this->actingAs($this->admin); Volt::test('admin.settings.working-hours') ->set('schedule.1.start_time', '09:00') ->set('schedule.1.end_time', '17:00') ->call('save'); $log = AdminLog::where('target_type', 'working_hours')->first(); expect($log->old_values)->toBeArray(); expect($log->new_values)->toBeArray(); }); // =========================================== // Slot Display Tests // =========================================== test('active day shows available slots badge', function () { $this->actingAs($this->admin); Volt::test('admin.settings.working-hours') ->set('schedule.1.is_active', true) ->set('schedule.1.start_time', '09:00') ->set('schedule.1.end_time', '12:00') ->assertSee(__('admin.slots_available', ['count' => 3])); }); test('inactive day does not show slots badge', function () { $this->actingAs($this->admin); Volt::test('admin.settings.working-hours') ->set('schedule.1.is_active', false) ->assertSee(__('admin.closed')); }); test('invalid time range shows no slots badge', function () { $this->actingAs($this->admin); Volt::test('admin.settings.working-hours') ->set('schedule.1.is_active', true) ->set('schedule.1.start_time', '17:00') ->set('schedule.1.end_time', '09:00') ->assertSee(__('admin.no_slots')); }); // =========================================== // Time Format Display Tests // =========================================== test('active day displays 12-hour time format', function () { $this->actingAs($this->admin); Volt::test('admin.settings.working-hours') ->set('schedule.1.is_active', true) ->set('schedule.1.start_time', '09:00') ->set('schedule.1.end_time', '17:00') ->assertSee('9:00 AM') ->assertSee('5:00 PM'); }); // =========================================== // Flash Message Tests // =========================================== test('save completes without errors and data is persisted', function () { $this->actingAs($this->admin); Volt::test('admin.settings.working-hours') ->set('schedule.1.is_active', true) ->set('schedule.1.start_time', '09:00') ->set('schedule.1.end_time', '17:00') ->call('save') ->assertHasNoErrors(); // Verify data was saved expect(WorkingHour::where('day_of_week', 1)->exists())->toBeTrue(); });