w4c-workflows-api/w4c-workflows-api.Tests/TriggerDueTests.cs

67 lines
2.1 KiB
C#

using w4c_workflows.Models;
using w4c_workflows.Services.Triggers;
using Xunit;
namespace w4c_workflows.Tests;
public class TriggerDueTests
{
private static readonly DateTimeOffset Now = new(2026, 8, 28, 14, 30, 0, TimeSpan.Zero);
private static TriggerSpec Interval(string interval) =>
TriggerSpec.Parse($"{{\"type\":\"interval\",\"interval\":\"{interval}\"}}", out _)!;
private static TriggerSpec Cron(string expr) =>
TriggerSpec.Parse($"{{\"type\":\"cron\",\"cron\":\"{expr}\"}}", out _)!;
[Fact]
public void Fires_on_first_discovery_when_no_last_fire()
{
Assert.True(TriggerDue.IsDue(Interval("30m"), null, Now));
Assert.True(TriggerDue.IsDue(Cron("0 9 * * *"), null, Now));
}
[Fact]
public void Interval_not_due_before_elapse()
{
var lastFire = Now.AddMinutes(-10);
Assert.False(TriggerDue.IsDue(Interval("30m"), lastFire, Now));
}
[Fact]
public void Interval_due_once_elapsed()
{
var lastFire = Now.AddMinutes(-31);
Assert.True(TriggerDue.IsDue(Interval("30m"), lastFire, Now));
}
[Fact]
public void Interval_zero_is_never_due()
{
var spec = new TriggerSpec(TriggerType.Interval, null, TimeSpan.Zero, null, null);
Assert.False(TriggerDue.IsDue(spec, Now.AddHours(-1), Now));
}
[Fact]
public void Cron_due_when_next_occurrence_has_passed()
{
// 9:00 daily; last fired yesterday 09:00, now past today's 09:00.
var lastFire = new DateTimeOffset(2026, 8, 27, 9, 0, 0, TimeSpan.Zero);
Assert.True(TriggerDue.IsDue(Cron("0 9 * * *"), lastFire, Now));
}
[Fact]
public void Cron_not_due_when_next_occurrence_in_future()
{
var lastFire = Now.AddMinutes(-1); // fired 1 minute ago; next daily 09:00 is future
Assert.False(TriggerDue.IsDue(Cron("0 9 * * *"), lastFire, Now));
}
[Fact]
public void Unknown_type_is_never_due()
{
var spec = new TriggerSpec("webhook", null, null, "/h/x", null);
Assert.False(TriggerDue.IsDue(spec, Now.AddHours(-1), Now));
}
}