'/dev/null' 2>&1"); $listener->onFinished(new ScheduledTaskFinished($task, 1.23)); $run = ScheduledTaskRun::query()->where('command', 'projectsend:purge-expired-files')->sole(); expect($run->status)->toBe(TaskRunStatus::Success) ->and($run->message)->toBeNull() ->and($run->duration_ms)->toBe(1230); }); test('a failed task is recorded as failed, overwriting a prior success', function () { $listener = app(RecordsScheduledTaskRuns::class); $task = fakeScheduledEvent("'/usr/bin/php' 'artisan' projectsend:fetch-news > '/dev/null' 2>&1"); // ScheduleRunCommand always dispatches Finished first, then Failed // only if the exit code was non-zero — replicate that exact order. $listener->onFinished(new ScheduledTaskFinished($task, 0.5)); $listener->onFailed(new ScheduledTaskFailed($task, new RuntimeException('Scheduled command [...] failed with exit code [1].'))); $run = ScheduledTaskRun::query()->where('command', 'projectsend:fetch-news')->sole(); expect($run->status)->toBe(TaskRunStatus::Failed) ->and($run->message)->toContain('exit code [1]') ->and($run->duration_ms)->toBeNull(); }); test('a non-projectsend command is not tracked', function () { $listener = app(RecordsScheduledTaskRuns::class); $task = fakeScheduledEvent("'/usr/bin/php' 'artisan' some:other-command"); $listener->onFinished(new ScheduledTaskFinished($task, 0.1)); expect(ScheduledTaskRun::query()->count())->toBe(0); });