totalScheduledTasks)->toBe(0); expect($state->dueTasks)->toBe(0); expect($state->upcomingTasks)->toBe([]); expect($state->nextExecution)->toBeNull(); expect($state->statistics)->toBe([]); expect($state->lastUpdated)->toBeString(); }); it('creates state from array', function () { $data = [ 'totalScheduledTasks' => 10, 'dueTasks' => 2, 'upcomingTasks' => [ [ 'id' => 'task-1', 'schedule_type' => 'cron', 'next_run' => '2024-01-15 13:00:00', ], ], 'nextExecution' => '2024-01-15 13:00:00', 'statistics' => [ 'total_executions_today' => 50, ], 'lastUpdated' => '2024-01-15 12:00:00', ]; $state = SchedulerState::fromArray($data); expect($state->totalScheduledTasks)->toBe(10); expect($state->dueTasks)->toBe(2); expect($state->upcomingTasks)->toHaveCount(1); expect($state->nextExecution)->toBe('2024-01-15 13:00:00'); }); it('converts state to array', function () { $upcomingTasks = [ [ 'id' => 'task-1', 'schedule_type' => 'interval', 'next_run' => '2024-01-15 13:00:00', 'next_run_relative' => 'in 1 hour', 'is_due' => false, ], ]; $statistics = [ 'successful_executions' => 45, 'failed_executions' => 5, ]; $state = new SchedulerState( totalScheduledTasks: 5, dueTasks: 1, upcomingTasks: $upcomingTasks, nextExecution: '2024-01-15 13:00:00', statistics: $statistics, lastUpdated: '2024-01-15 12:00:00' ); $array = $state->toArray(); expect($array)->toHaveKey('totalScheduledTasks'); expect($array)->toHaveKey('dueTasks'); expect($array)->toHaveKey('upcomingTasks'); expect($array)->toHaveKey('nextExecution'); expect($array)->toHaveKey('statistics'); expect($array['upcomingTasks'])->toHaveCount(1); }); it('creates new state with updated scheduler data', function () { $state = SchedulerState::empty(); $upcomingTasks = [ [ 'id' => 'backup-task', 'schedule_type' => 'cron', 'next_run' => '2024-01-15 02:00:00', 'is_due' => true, ], ]; $statistics = [ 'tasks_executed_today' => 20, 'average_execution_time' => 1.5, ]; $updatedState = $state->withSchedulerData( totalScheduledTasks: 3, dueTasks: 1, upcomingTasks: $upcomingTasks, nextExecution: '2024-01-15 02:00:00', statistics: $statistics ); // Original unchanged expect($state->totalScheduledTasks)->toBe(0); expect($state->upcomingTasks)->toBe([]); expect($state->nextExecution)->toBeNull(); // New state updated expect($updatedState->totalScheduledTasks)->toBe(3); expect($updatedState->dueTasks)->toBe(1); expect($updatedState->upcomingTasks)->toHaveCount(1); expect($updatedState->nextExecution)->toBe('2024-01-15 02:00:00'); expect($updatedState->statistics)->toHaveKey('tasks_executed_today'); expect($updatedState->lastUpdated)->not->toBe($state->lastUpdated); }); it('is immutable', function () { $state = new SchedulerState( totalScheduledTasks: 10, dueTasks: 2, upcomingTasks: [], nextExecution: '2024-01-15 12:00:00', statistics: [], lastUpdated: '2024-01-15 11:00:00' ); $newState = $state->withSchedulerData( totalScheduledTasks: 15, dueTasks: 3, upcomingTasks: [], nextExecution: '2024-01-15 13:00:00', statistics: [] ); // Original unchanged expect($state->totalScheduledTasks)->toBe(10); expect($state->dueTasks)->toBe(2); // New instance expect($newState)->not->toBe($state); expect($newState->totalScheduledTasks)->toBe(15); expect($newState->dueTasks)->toBe(3); }); it('handles null next execution', function () { $state = SchedulerState::empty()->withSchedulerData( totalScheduledTasks: 0, dueTasks: 0, upcomingTasks: [], nextExecution: null, statistics: [] ); expect($state->nextExecution)->toBeNull(); expect($state->totalScheduledTasks)->toBe(0); }); it('handles empty upcoming tasks', function () { $state = SchedulerState::empty()->withSchedulerData( totalScheduledTasks: 0, dueTasks: 0, upcomingTasks: [], nextExecution: null, statistics: [] ); expect($state->upcomingTasks)->toBe([]); expect($state->statistics)->toBe([]); }); });