using System; using System.Collections.Generic; using System.Linq; using MfGames.Gallium; using MfGames.Nitride.Tests; using NodaTime; using NodaTime.Testing; using Xunit; using Xunit.Abstractions; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; using Zio; namespace MfGames.Nitride.Temporal.Schedules.Tests; public class PeriodicPathRegexScheduleTest : TemporalSchedulesTestBase { public PeriodicPathRegexScheduleTest(ITestOutputHelper output) : base(output) { } [Fact] public void DeserializedSetupWorks() { using TemporalSchedulesTestContext context = this.CreateContext(); // Create a numerical series of entities. var input = new List { new Entity().SetAll((UPath)"/chapter-01.md", new TestModel()), new Entity().SetAll((UPath)"/chapter-02.md", new TestModel()), new Entity().SetAll((UPath)"/chapter-03.md", new TestModel()), }; TestModel model = new DeserializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .Build() .Deserialize( string.Join( "\n", "---", "access: custom", "schedules:", " - pathRegex: chapter-(\\d+)", " scheduleStart: 2023-01-01", " schedulePeriod: 1 week", " access: public", "")); List? schedules = model.Schedules!; // Create the operation and run it, but treat it as being set after the // second but before the third item. TimeService time = context.Resolve(); ApplySchedules op = context.Resolve() .WithGetSchedules(_ => schedules); var now = Instant.FromUtc(2023, 1, 9, 0, 0); time.Clock = new FakeClock(now); var actual = op .Run(input) .Select( a => string.Format( "{0} -- {1} -- {2}", a.Get().ToString(), a.Has() ? time .ToDateTime(a.Get()) .ToString("yyyy-MM-dd") : "none", a.Get().Access)) .ToList(); var expected = new List { "/chapter-01.md -- 2023-01-01 -- public", "/chapter-02.md -- 2023-01-08 -- public", "/chapter-03.md -- none -- private", }; TestHelper.CompareObjects(expected, actual); } [Fact] public void ManualSetupWorks() { using TemporalSchedulesTestContext context = this.CreateContext(); // Create a numerical series of entities. var input = new List { new Entity().SetAll((UPath)"/chapter-01.md", new TestModel()), new Entity().SetAll((UPath)"/chapter-02.md", new TestModel()), new Entity().SetAll((UPath)"/chapter-03.md", new TestModel()), }; var schedules = new List { new() { ScheduleStart = DateTime.Parse("2023-01-01"), Access = "public", }, }; // Create the operation and run it, but treat it as being set after the // second but before the third item. TimeService time = context.Resolve(); ApplySchedules op = context.Resolve() .WithGetSchedules(_ => schedules); var now = Instant.FromUtc(2023, 1, 9, 0, 0); time.Clock = new FakeClock(now); var actual = op .Run(input) .Select( a => string.Format( "{0} -- {1} -- {2}", a.Get().ToString(), a.Has() ? time .ToDateTime(a.Get()) .ToString("yyyy-MM-dd") : "none", a.Get().Access)) .ToList(); var expected = new List { "/chapter-01.md -- 2023-01-01 -- public", "/chapter-02.md -- 2023-01-08 -- public", "/chapter-03.md -- none -- private", }; TestHelper.CompareObjects(expected, actual); } [Fact] public void ScheduleOffsetWorks() { using TemporalSchedulesTestContext context = this.CreateContext(); // Create a numerical series of entities. var input = new List { new Entity().SetAll((UPath)"/chapter-11.md", new TestModel()), new Entity().SetAll((UPath)"/chapter-12.md", new TestModel()), new Entity().SetAll((UPath)"/chapter-13.md", new TestModel()), }; var schedules = new List { new() { ScheduleStart = DateTime.Parse("2023-01-01"), CaptureOffset = -11, Access = "public", }, }; // Create the operation and run it, but treat it as being set after the // second but before the third item. TimeService time = context.Resolve(); ApplySchedules op = context.Resolve() .WithGetSchedules(_ => schedules); var now = Instant.FromUtc(2023, 1, 9, 0, 0); time.Clock = new FakeClock(now); var actual = op .Run(input) .Select( a => string.Format( "{0} -- {1} -- {2}", a.Get().ToString(), a.Has() ? time .ToDateTime(a.Get()) .ToString("yyyy-MM-dd") : "none", a.Get().Access)) .ToList(); var expected = new List { "/chapter-11.md -- 2023-01-01 -- public", "/chapter-12.md -- 2023-01-08 -- public", "/chapter-13.md -- none -- private", }; TestHelper.CompareObjects(expected, actual); } [Fact] public void SequencedScheduleWorks() { using TemporalSchedulesTestContext context = this.CreateContext(); // Create a numerical series of entities. var input = new List { new Entity().SetAll((UPath)"/chapter-01.md", new TestModel()), new Entity().SetAll((UPath)"/chapter-02.md", new TestModel()), new Entity().SetAll((UPath)"/chapter-03.md", new TestModel()), }; var schedules = new List { new() { ScheduleStart = DateTime.Parse("2023-01-01"), Access = "subscriber", }, new() { ScheduleStart = DateTime.Parse("2023-01-07"), Access = "public", }, }; // Create the operation and run it, but treat it as being set after the // second but before the third item. TimeService time = context.Resolve(); ApplySchedules op = context.Resolve() .WithGetSchedules(_ => schedules); var now = Instant.FromUtc(2023, 1, 9, 0, 0); time.Clock = new FakeClock(now); var actual = op .Run(input) .Select( a => string.Format( "{0} -- {1} -- {2}", a.Get().ToString(), a.Has() ? time .ToDateTime(a.Get()) .ToString("yyyy-MM-dd") : "none", a.Get().Access)) .ToList(); var expected = new List { "/chapter-01.md -- 2023-01-07 -- public", "/chapter-02.md -- 2023-01-08 -- subscriber", "/chapter-03.md -- none -- private", }; TestHelper.CompareObjects(expected, actual); } public class TestModel { public string? Access { get; set; } = "private"; public List? Schedules { get; set; } } public class TestRegexSchedule : PeriodicPathRegexSchedule { public TestRegexSchedule() { this.SchedulePeriod = "1 week"; } public string? Access { get; set; } /// protected override Entity Apply( Entity entity, int number, Instant instant) { TestModel model = entity.Get(); model.Access = this.Access; return entity.SetAll(instant, model); } } }