Files
Playa/tests/Volcanic.AgenticCore.Extensions.Tests/Scheduler/JobFormatTests.cs
EugeneTes fd6b9027b6 fix(scheduler): address review findings
- JobScheduler: a stored job whose zone lookup throws no longer fails StartAsync; timer re-armed under the lock;
  a delivery cut off by shutdown isn't recorded (one-offs fire again after restart); CancelJobAsync in one step
- Schedules.ParseAt: ISO 8601 with a date only (no machine-clock date for a bare 09:00)
- core: a FollowUp prompt that loses the race to a starting run joins it as a follow-up, not steering
- Telegram: TimeZoneFor tolerates non-numeric targets; RunPromptAsync waits only when queued; one agent dir
- ScriptRunner: bad workspace paths are Failed, not exceptions; zone id helpers share TimeZoneIds.ToIana's rule
- tests: no wall-clock sleeps in scheduler tests; transcript-entry, disabled-scheduler and failing-prompt coverage
- docs: spec notes for the above; README row for the scheduler
2026-09-27 10:56:45 +02:00

40 lines
2.3 KiB
C#

using Volcanic.AgenticCore.Extensions.Scheduler;
using Volcanic.AgenticCore.Extensions.Tests.Scheduler.Support;
namespace Volcanic.AgenticCore.Extensions.Tests.Scheduler;
public sealed class JobFormatTests
{
private static readonly DateTimeOffset Now = SchedulerHarness.Start; // Sat 26 Sep 14:03 Berlin
private static readonly TimeZoneInfo Berlin = SchedulerHarness.Berlin;
private static ScheduledJob Job(string id, string name, JobKind kind, JobSchedule schedule) => new()
{
Id = id, Target = "111", Name = name, Kind = kind, Schedule = schedule, CreatedAt = Now,
Text = kind == JobKind.Watcher ? null : name, Command = kind == JobKind.Watcher ? "check" : null,
};
[Fact]
public void Job_lines_show_kind_schedule_next_and_last_failure()
{
var once = new DateTimeOffset(2026, 9, 27, 7, 0, 0, TimeSpan.Zero);
Assert.Equal("`k7m2q` ⏰ Call the dentist · once 27 Sep 09:00",
JobFormat.Line(new JobView(Job("k7m2q", "Call the dentist", JobKind.Reminder, new JobSchedule(once, null)), once), Berlin, Now));
Assert.Equal("`p3xz9` 💬 Inbox summary · `0 8 * * 1-5` · next 28 Sep 08:00",
JobFormat.Line(new JobView(Job("p3xz9", "Inbox summary", JobKind.Prompt, new JobSchedule(null, "0 8 * * 1-5")), new DateTimeOffset(2026, 9, 28, 6, 0, 0, TimeSpan.Zero)), Berlin, Now));
var failing = Job("w8r4t", "Price check", JobKind.Watcher, new JobSchedule(null, "*/10 * * * *")) with { LastResult = new JobResult(false, 1, false, "x", Now) };
Assert.Equal("`w8r4t` 🔍 Price check · `*/10 * * * *` · next 14:10 · last: failed (exit 1)",
JobFormat.Line(new JobView(failing, new DateTimeOffset(2026, 9, 26, 12, 10, 0, TimeSpan.Zero)), Berlin, Now));
}
[Fact]
public void When_omits_the_date_today()
{
Assert.Equal("14:10", JobFormat.When(new DateTimeOffset(2026, 9, 26, 12, 10, 0, TimeSpan.Zero), Berlin, Now));
Assert.Equal("27 Sep 00:10", JobFormat.When(new DateTimeOffset(2026, 9, 26, 22, 10, 0, TimeSpan.Zero), Berlin, Now));
Assert.Equal("Sat 2026-09-26 14:03", JobFormat.Stamp(Now, Berlin));
Assert.Equal("exit 1, timed out", JobFormat.FailureReason(new JobResult(false, 1, true, null, Now)));
Assert.Equal("did not start", JobFormat.FailureReason(new JobResult(false, null, false, "failed to start", Now)));
}
}