package scheduler import ( "strings" "testing" "time" "gitea.mixdep.ru/mix/gosentry/src/domain" ) func TestPrepareNextRunSetsDisplayString(t *testing.T) { jobs := []domain.Job{{Schedule: "*/5 * * * *", Enabled: true}} s := &Scheduler{jobs: &jobs, runtimes: domain.NewRuntimes(jobs), schedules: make(map[int]domain.Schedule)} s.parseJobSchedule(&jobs[0]) runtime := s.runtimeFor(&jobs[0]) from := time.Date(2026, 6, 14, 12, 3, 0, 0, time.UTC) s.prepareNextRun(&jobs[0], runtime, from) want := "2026-06-14 12:05:00" if runtime.NextRun != want { t.Errorf("NextRun: got %q, want %q", runtime.NextRun, want) } wantDue := time.Date(2026, 6, 14, 12, 5, 0, 0, time.UTC) if !runtime.NextDue.Equal(wantDue) { t.Errorf("NextDue: got %v, want %v", runtime.NextDue, wantDue) } } func TestPrepareNextRunSetsInvalidScheduleLabel(t *testing.T) { jobs := []domain.Job{{Schedule: "not-a-cron", Enabled: true}} s := &Scheduler{jobs: &jobs, runtimes: domain.NewRuntimes(jobs), schedules: make(map[int]domain.Schedule)} // parseJobSchedule will drop the invalid spec, so schedules map stays empty. s.parseJobSchedule(&jobs[0]) runtime := s.runtimeFor(&jobs[0]) s.prepareNextRun(&jobs[0], runtime, time.Now()) if runtime.NextRun != "Invalid schedule" { t.Errorf("NextRun: got %q, want 'Invalid schedule'", runtime.NextRun) } if !runtime.NextDue.IsZero() { t.Errorf("NextDue should be zero for invalid schedule, got %v", runtime.NextDue) } } func TestRunningOutputIncludesInvocation(t *testing.T) { started := time.Date(2026, 6, 17, 23, 40, 0, 0, time.Local) job := domain.Job{ Name: "Backup", Command: `C:\Program Files\FreeFileSync\FreeFileSync.exe`, Arguments: `D:\Local\Jobs\Auto.ffs_batch`, SuccessExitCodes: "0,1", } output := runningOutput(job, "Manual", started) for _, want := range []string{ "Running since 2026-06-17 23:40:00", "Manual", job.Command, job.Arguments, "0,1", "start_only", } { if !strings.Contains(output, want) { t.Fatalf("expected running output to contain %q, got:\n%s", want, output) } } }