diff --git a/src/MfGames.Nitride.Calendar/MfGames.Nitride.Calendar.csproj b/src/MfGames.Nitride.Calendar/MfGames.Nitride.Calendar.csproj index 12b4ffe..f2a7916 100644 --- a/src/MfGames.Nitride.Calendar/MfGames.Nitride.Calendar.csproj +++ b/src/MfGames.Nitride.Calendar/MfGames.Nitride.Calendar.csproj @@ -10,16 +10,16 @@ - - - + + + - - - - + + + + diff --git a/src/MfGames.Nitride.Feeds/MfGames.Nitride.Feeds.csproj b/src/MfGames.Nitride.Feeds/MfGames.Nitride.Feeds.csproj index 2e76f41..21b4f95 100644 --- a/src/MfGames.Nitride.Feeds/MfGames.Nitride.Feeds.csproj +++ b/src/MfGames.Nitride.Feeds/MfGames.Nitride.Feeds.csproj @@ -10,15 +10,15 @@ - - - + + + - - - + + + diff --git a/src/MfGames.Nitride.Generators/MfGames.Nitride.Generators.csproj b/src/MfGames.Nitride.Generators/MfGames.Nitride.Generators.csproj index a5f7424..c1dace6 100644 --- a/src/MfGames.Nitride.Generators/MfGames.Nitride.Generators.csproj +++ b/src/MfGames.Nitride.Generators/MfGames.Nitride.Generators.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/MfGames.Nitride.Handlebars/MfGames.Nitride.Handlebars.csproj b/src/MfGames.Nitride.Handlebars/MfGames.Nitride.Handlebars.csproj index c6d4e92..47c9801 100644 --- a/src/MfGames.Nitride.Handlebars/MfGames.Nitride.Handlebars.csproj +++ b/src/MfGames.Nitride.Handlebars/MfGames.Nitride.Handlebars.csproj @@ -10,15 +10,15 @@ - - - - - + + + + + - + diff --git a/src/MfGames.Nitride.Html/MfGames.Nitride.Html.csproj b/src/MfGames.Nitride.Html/MfGames.Nitride.Html.csproj index 91923b8..d9ed940 100644 --- a/src/MfGames.Nitride.Html/MfGames.Nitride.Html.csproj +++ b/src/MfGames.Nitride.Html/MfGames.Nitride.Html.csproj @@ -9,7 +9,7 @@ - + @@ -25,7 +25,7 @@ - + diff --git a/src/MfGames.Nitride.IO/MfGames.Nitride.IO.csproj b/src/MfGames.Nitride.IO/MfGames.Nitride.IO.csproj index 928fe60..41e802c 100644 --- a/src/MfGames.Nitride.IO/MfGames.Nitride.IO.csproj +++ b/src/MfGames.Nitride.IO/MfGames.Nitride.IO.csproj @@ -8,17 +8,17 @@ - - - - - - - + + + + + + + - + diff --git a/src/MfGames.Nitride.Json/MfGames.Nitride.Json.csproj b/src/MfGames.Nitride.Json/MfGames.Nitride.Json.csproj index b32b6c1..a630521 100644 --- a/src/MfGames.Nitride.Json/MfGames.Nitride.Json.csproj +++ b/src/MfGames.Nitride.Json/MfGames.Nitride.Json.csproj @@ -14,7 +14,7 @@ - + diff --git a/src/MfGames.Nitride.Markdown/MfGames.Nitride.Markdown.csproj b/src/MfGames.Nitride.Markdown/MfGames.Nitride.Markdown.csproj index cd5884b..d2e64f9 100644 --- a/src/MfGames.Nitride.Markdown/MfGames.Nitride.Markdown.csproj +++ b/src/MfGames.Nitride.Markdown/MfGames.Nitride.Markdown.csproj @@ -10,17 +10,17 @@ - - - - + + + + - - - - + + + + diff --git a/src/MfGames.Nitride.Temporal.Schedules/ApplySchedules.cs b/src/MfGames.Nitride.Temporal.Schedules/ApplySchedules.cs new file mode 100644 index 0000000..55378d3 --- /dev/null +++ b/src/MfGames.Nitride.Temporal.Schedules/ApplySchedules.cs @@ -0,0 +1,6 @@ +namespace MfGames.Nitride.Temporal.Schedules; + +public interface ApplySchedules +{ + +} diff --git a/src/MfGames.Nitride.Temporal.Schedules/ISchedule.cs b/src/MfGames.Nitride.Temporal.Schedules/ISchedule.cs new file mode 100644 index 0000000..3d556ec --- /dev/null +++ b/src/MfGames.Nitride.Temporal.Schedules/ISchedule.cs @@ -0,0 +1,24 @@ +using MfGames.Gallium; + +namespace MfGames.Nitride.Temporal.Schedules; + +/// +/// A schedule is a specific schedule that can be applied to an entity to make +/// changes based on components. +/// +public interface ISchedule +{ + /// + /// Determines if a schedule applies to a given entity. + /// + /// The entity to test. + /// True if the schedule applies to the given entity, otherwise false. + bool CanApply(Entity entity); + + /// + /// Applies the schedule changes to the entity and returns the results. + /// + /// The entity to update. + /// The modified entity, if the changes can be applied, otherwise the same entity. + Entity Apply(Entity entity); +} diff --git a/src/MfGames.Nitride.Temporal.Schedules/MfGames.Nitride.Temporal.Schedules.csproj b/src/MfGames.Nitride.Temporal.Schedules/MfGames.Nitride.Temporal.Schedules.csproj new file mode 100644 index 0000000..ee081a1 --- /dev/null +++ b/src/MfGames.Nitride.Temporal.Schedules/MfGames.Nitride.Temporal.Schedules.csproj @@ -0,0 +1,35 @@ + + + + net6.0 + enable + + + + An extension to Nitride static site generator to add a scheduling system for posts. + + + + + + + + + + + + + + + + True + + + + + Analyzer + False + + + + diff --git a/src/MfGames.Nitride.Temporal.Schedules/NumericalPathSchedule.cs b/src/MfGames.Nitride.Temporal.Schedules/NumericalPathSchedule.cs new file mode 100644 index 0000000..c964160 --- /dev/null +++ b/src/MfGames.Nitride.Temporal.Schedules/NumericalPathSchedule.cs @@ -0,0 +1,33 @@ +using System; +using System.Text.RegularExpressions; + +using MfGames.Gallium; +using MfGames.Nitride.Generators; + +namespace MfGames.Nitride.Temporal.Schedules; + +/// +/// A schedule that uses the `UPath` of the entity to determine an offset from +/// a starting point and calculates the information from there. +/// +[WithProperties] +public partial class NumericalPathSchedule +{ + public NumericalPathSchedule() + { + this.PathRegex = new Regex(@"^.*(\d+)"); + this.GetPath = (entity) => entity.Get().ToString(); + this.CaptureGroup = 1; + this.CaptureOffset = -1; + } + + public Regex? PathRegex { get; set; } + + public Func GetPath { get; set; } + public DateTime? ScheduleStart { get; set; } + public SchedulePeriod SchedulePeriod { get; set; } + + public int CaptureGroup { get; set; } + + public int CaptureOffset { get; set; } +} diff --git a/src/MfGames.Nitride.Temporal.Schedules/README.md b/src/MfGames.Nitride.Temporal.Schedules/README.md new file mode 100644 index 0000000..ee08cbc --- /dev/null +++ b/src/MfGames.Nitride.Temporal.Schedules/README.md @@ -0,0 +1,41 @@ +# Date Processing + +One of the common features of static websites are blogs which leads to having +some form of date-centric processing of pages to build archive pages, calendars, +and being able to write posts in the future. + +With the component system, the date of a given file is simply attached to +`Nodatime.Instant` component of the `Entity` object for the bulk of the +processing. + +## Supporting Time Zones + +The concept of time zones while date processing is one that is frequently +overlooked. A date is a date, right? However, most blogs and news sites have a +concept of when a new day starts but it isn't always the same time as the server +that is building the site. While a blog might be in America/Chicago time, a CI +server could be set to UTC (such as Azure build servers) and the +"day" may roll over fix or six hours before or after the blog's time. + +This is why Nitride uses `Instant` for when pages are implemented. These are +points in time that are independent of time zones, but we also provide tools for +converting a date model or one from the path into a proper instant based on the +blog's time zone. + +## Why NodaTime? + +We decided to use [NodaTime](https://nodatime.org/) instead of the built-in date +time functions for a number of reasons, mainly because it has a more intuitive +way of handling time zones + +## Configuring + +There are two callbacks on `NitrideBuilder` that can be used to define the date +and time processing for the blog. + +```csharp +NitrideBuilder builder; + +builder + .ConfigureDates((NitrideClock clock) => clock.SetTimeZone()) +``` diff --git a/src/MfGames.Nitride.Temporal.Schedules/Setup/NitrideTemporalSchedulesBuilderExtensions.cs b/src/MfGames.Nitride.Temporal.Schedules/Setup/NitrideTemporalSchedulesBuilderExtensions.cs new file mode 100644 index 0000000..7234447 --- /dev/null +++ b/src/MfGames.Nitride.Temporal.Schedules/Setup/NitrideTemporalSchedulesBuilderExtensions.cs @@ -0,0 +1,79 @@ +using System; + +using Autofac; + +using MfGames.Nitride.Commands; +using MfGames.Nitride.Temporal.Cli; + +using Serilog; + +namespace MfGames.Nitride.Temporal.Schedules.Setup; + +public static class NitrideTemporalSchedulesBuilderExtensions +{ + /// + /// Extends the builder to allow for configuring the temporal + /// settings for generation. + /// + public static NitrideBuilder UseTemporal( + this NitrideBuilder builder, + Action? configure = null) + { + // Get the configuration so we can set the various options. + var config = new NitrideTemporalConfiguration(); + + configure?.Invoke(config); + + // Add in the module registration. + builder.ConfigureContainer( + x => + { + // Register the module. + x.RegisterModule(); + + // Add in the CLI options. + if (config.AddDateOptionToCommandLine) + { + x.RegisterType() + .As(); + } + + if (config.AddExpireOptionToCommandLine + && config.Expiration != null) + { + x.Register( + context => + { + ILogger logger = context.Resolve(); + Timekeeper + clock = context.Resolve(); + + return new ExpiresPipelineCommandOption( + logger, + clock, + config.Expiration); + }) + .As(); + } + }); + + if (config.DateTimeZone != null) + { + builder.ConfigureSite( + ( + _, + scope) => + { + ILogger logger = scope.Resolve(); + Timekeeper timekeeper = scope.Resolve(); + + timekeeper.DateTimeZone = config.DateTimeZone; + logger.Verbose( + "Setting time zone to {Zone:l}", + timekeeper.DateTimeZone); + }); + } + + return builder; + } +} diff --git a/src/MfGames.Nitride.Temporal.Schedules/Setup/NitrideTemporalSchedulesModule.cs b/src/MfGames.Nitride.Temporal.Schedules/Setup/NitrideTemporalSchedulesModule.cs new file mode 100644 index 0000000..ab79259 --- /dev/null +++ b/src/MfGames.Nitride.Temporal.Schedules/Setup/NitrideTemporalSchedulesModule.cs @@ -0,0 +1,20 @@ +using Autofac; + +namespace MfGames.Nitride.Temporal.Schedules.Setup; + +public class NitrideTemporalSchedulesModule : Module +{ + /// + protected override void Load(ContainerBuilder builder) + { + builder.RegisterOperators(this); + builder.RegisterValidators(this); + + builder.RegisterType() + .AsSelf() + .SingleInstance(); + + builder.RegisterGeneric(typeof(SetInstantFromComponent<>)) + .As(typeof(SetInstantFromComponent<>)); + } +} diff --git a/src/MfGames.Nitride.Temporal.Schedules/Validators/ApplySchedulesValidator.cs b/src/MfGames.Nitride.Temporal.Schedules/Validators/ApplySchedulesValidator.cs new file mode 100644 index 0000000..b2a317c --- /dev/null +++ b/src/MfGames.Nitride.Temporal.Schedules/Validators/ApplySchedulesValidator.cs @@ -0,0 +1,18 @@ +using FluentValidation; + +namespace MfGames.Nitride.Temporal.Schedules.Validators; + +public class CreateDateIndexesValidator : AbstractValidator +{ + public CreateDateIndexesValidator() + { + this.RuleFor(a => a.Timekeeper) + .NotNull(); + + this.RuleFor(a => a.CreateIndex) + .NotNull(); + + this.RuleFor(a => a.Formats) + .NotNull(); + } +} diff --git a/src/MfGames.Nitride.Temporal/NitrideTemporalModule.cs b/src/MfGames.Nitride.Temporal/Setup/NitrideTemporalModule.cs similarity index 100% rename from src/MfGames.Nitride.Temporal/NitrideTemporalModule.cs rename to src/MfGames.Nitride.Temporal/Setup/NitrideTemporalModule.cs diff --git a/src/MfGames.Nitride.Yaml/MfGames.Nitride.Yaml.csproj b/src/MfGames.Nitride.Yaml/MfGames.Nitride.Yaml.csproj index 1093a94..9cc8072 100644 --- a/src/MfGames.Nitride.Yaml/MfGames.Nitride.Yaml.csproj +++ b/src/MfGames.Nitride.Yaml/MfGames.Nitride.Yaml.csproj @@ -14,7 +14,7 @@ - + diff --git a/src/MfGames.Nitride/MfGames.Nitride.csproj b/src/MfGames.Nitride/MfGames.Nitride.csproj index d3d2ff1..9206a33 100644 --- a/src/MfGames.Nitride/MfGames.Nitride.csproj +++ b/src/MfGames.Nitride/MfGames.Nitride.csproj @@ -18,7 +18,7 @@ - + diff --git a/tests/MfGames.Nitride.IO.Tests/MfGames.Nitride.IO.Tests.csproj b/tests/MfGames.Nitride.IO.Tests/MfGames.Nitride.IO.Tests.csproj index f1f4f20..00106dc 100644 --- a/tests/MfGames.Nitride.IO.Tests/MfGames.Nitride.IO.Tests.csproj +++ b/tests/MfGames.Nitride.IO.Tests/MfGames.Nitride.IO.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/tests/MfGames.Nitride.Json.Tests/MfGames.Nitride.Json.Tests.csproj b/tests/MfGames.Nitride.Json.Tests/MfGames.Nitride.Json.Tests.csproj index e250840..e4b5f6c 100644 --- a/tests/MfGames.Nitride.Json.Tests/MfGames.Nitride.Json.Tests.csproj +++ b/tests/MfGames.Nitride.Json.Tests/MfGames.Nitride.Json.Tests.csproj @@ -6,7 +6,7 @@ - + diff --git a/tests/MfGames.Nitride.Markdown.Tests/MfGames.Nitride.Markdown.Tests.csproj b/tests/MfGames.Nitride.Markdown.Tests/MfGames.Nitride.Markdown.Tests.csproj index ae576c0..c8214fc 100644 --- a/tests/MfGames.Nitride.Markdown.Tests/MfGames.Nitride.Markdown.Tests.csproj +++ b/tests/MfGames.Nitride.Markdown.Tests/MfGames.Nitride.Markdown.Tests.csproj @@ -6,18 +6,18 @@ - - + + - - - - - - - + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/MfGames.Nitride.Slugs.Tests/MfGames.Nitride.Slugs.Tests.csproj b/tests/MfGames.Nitride.Slugs.Tests/MfGames.Nitride.Slugs.Tests.csproj index d8a072d..5d0468e 100644 --- a/tests/MfGames.Nitride.Slugs.Tests/MfGames.Nitride.Slugs.Tests.csproj +++ b/tests/MfGames.Nitride.Slugs.Tests/MfGames.Nitride.Slugs.Tests.csproj @@ -6,21 +6,21 @@ - - - + + + - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/MfGames.Nitride.Temporal.Schedules.Tests/MfGames.Nitride.Temporal.Schedules.Tests.csproj b/tests/MfGames.Nitride.Temporal.Schedules.Tests/MfGames.Nitride.Temporal.Schedules.Tests.csproj new file mode 100644 index 0000000..da6250d --- /dev/null +++ b/tests/MfGames.Nitride.Temporal.Schedules.Tests/MfGames.Nitride.Temporal.Schedules.Tests.csproj @@ -0,0 +1,30 @@ + + + + net6.0 + enable + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git a/tests/MfGames.Nitride.Temporal.Schedules.Tests/NumericalPathScheduleTests.cs b/tests/MfGames.Nitride.Temporal.Schedules.Tests/NumericalPathScheduleTests.cs new file mode 100644 index 0000000..c161cce --- /dev/null +++ b/tests/MfGames.Nitride.Temporal.Schedules.Tests/NumericalPathScheduleTests.cs @@ -0,0 +1,324 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using MfGames.Gallium; +using MfGames.Nitride.Temporal.Tests; +using MfGames.Nitride.Tests; + +using Xunit; +using Xunit.Abstractions; + +namespace MfGames.Nitride.Temporal.Schedules.Tests; + +public class TestPageModel +{ + public string Access { get; set; } +} + +public class TestSchedule : NumericalPathSchedule +{ +} + +public class ApplySchedulesTests : TemporalSchedulesTestBase +{ + public ApplySchedulesTests(ITestOutputHelper output) + : base(output) + { + } + + [Fact] + public void MonthOnlyIndexes() + { + using TemporalSchedulesTestContext context = this.CreateContext(); + Timekeeper timekeeper = context.Resolve(); + + CreateDateIndexes op = context.Resolve() + .WithFormats("yyyy-MM") + .WithCreateIndex(this.CreateIndex); + + List input = new() + { + new Entity().Add("page1") + .Add(timekeeper.CreateInstant(2021, 1, 2)), + new Entity().Add("page2") + .Add(timekeeper.CreateInstant(2021, 2, 2)), + new Entity().Add("page3") + .Add(timekeeper.CreateInstant(2022, 1, 2)), + }; + + List?, List?>> actual = + this.GetActual(op, input); + + var expected = new List?, List?>> + { + new( + "index-2021-01", + new List { "page1" }, + new List()), + new( + "index-2021-02", + new List { "page2" }, + new List()), + new( + "index-2022-01", + new List { "page3" }, + new List()), + new("page1", null, null), + new("page2", null, null), + new("page3", null, null), + }; + + TestHelper.CompareObjects(expected, actual); + } + + [Fact] + public void YearMonthDayIndexes() + { + using TemporalSchedulesTestContext context = this.CreateContext(); + Timekeeper timekeeper = context.Resolve(); + + CreateDateIndexes op = context.Resolve() + .WithFormats("yyyy/MM/dd", "yyyy/MM", "yyyy") + .WithCreateIndex(this.CreateIndex); + + List input = new() + { + new Entity().Add("page1") + .Add(timekeeper.CreateInstant(2021, 1, 2)), + new Entity().Add("page2") + .Add(timekeeper.CreateInstant(2021, 2, 2)), + new Entity().Add("page3") + .Add(timekeeper.CreateInstant(2022, 1, 2)), + }; + + List?, List?>> actual = + this.GetActual(op, input); + + var expected = new List?, List?>> + { + new( + "index-2021", + new List(), + new List { "index-2021/01", "index-2021/02" }), + new( + "index-2021/01", + new List(), + new List { "index-2021/01/02" }), + new( + "index-2021/01/02", + new List { "page1" }, + new List()), + new( + "index-2021/02", + new List(), + new List { "index-2021/02/02" }), + new( + "index-2021/02/02", + new List { "page2" }, + new List()), + new( + "index-2022", + new List(), + new List { "index-2022/01" }), + new( + "index-2022/01", + new List(), + new List { "index-2022/01/02" }), + new( + "index-2022/01/02", + new List { "page3" }, + new List()), + new("page1", null, null), + new("page2", null, null), + new("page3", null, null), + }; + + TestHelper.CompareObjects(expected, actual); + } + + [Fact] + public void YearMonthDayIndexesThreshold1() + { + using TemporalSchedulesTestContext context = this.CreateContext(); + Timekeeper timekeeper = context.Resolve(); + + CreateDateIndexes op = context.Resolve() + .WithFormats("yyyy/MM/dd", "yyyy/MM", "yyyy") + .WithCreateIndex(this.CreateIndex) + .WithLessThanEqualCollapse(1); + + List input = new() + { + new Entity().Add("page1") + .Add(timekeeper.CreateInstant(2021, 1, 2)), + new Entity().Add("page2") + .Add(timekeeper.CreateInstant(2021, 2, 2)), + new Entity().Add("page3") + .Add(timekeeper.CreateInstant(2022, 1, 2)), + }; + + List?, List?>> actual = + this.GetActual(op, input); + + var expected = new List?, List?>> + { + new( + "index-2021", + new List(), + new List { "index-2021/01", "index-2021/02" }), + new( + "index-2021/01", + new List { "page1" }, + new List { "index-2021/01/02" }), + new( + "index-2021/01/02", + new List { "page1" }, + new List()), + new( + "index-2021/02", + new List { "page2" }, + new List { "index-2021/02/02" }), + new( + "index-2021/02/02", + new List { "page2" }, + new List()), + new( + "index-2022", + new List { "page3" }, + new List { "index-2022/01" }), + new( + "index-2022/01", + new List { "page3" }, + new List { "index-2022/01/02" }), + new( + "index-2022/01/02", + new List { "page3" }, + new List()), + new("page1", null, null), + new("page2", null, null), + new("page3", null, null), + }; + + TestHelper.CompareObjects(expected, actual); + } + + [Fact] + public void YearMonthIndexes() + { + using TemporalSchedulesTestContext context = this.CreateContext(); + Timekeeper timekeeper = context.Resolve(); + + CreateDateIndexes op = context.Resolve() + .WithFormats("yyyy-MM", "yyyy") + .WithCreateIndex(this.CreateIndex); + + List input = new() + { + new Entity().Add("page1") + .Add(timekeeper.CreateInstant(2021, 1, 2)), + new Entity().Add("page2") + .Add(timekeeper.CreateInstant(2021, 2, 2)), + new Entity().Add("page3") + .Add(timekeeper.CreateInstant(2022, 1, 2)), + }; + + List?, List?>> actual = + this.GetActual(op, input); + + var expected = new List?, List?>> + { + new( + "index-2021", + new List(), + new List { "index-2021-01", "index-2021-02" }), + new( + "index-2021-01", + new List { "page1" }, + new List()), + new( + "index-2021-02", + new List { "page2" }, + new List()), + new( + "index-2022", + new List(), + new List { "index-2022-01" }), + new( + "index-2022-01", + new List { "page3" }, + new List()), + new("page1", null, null), + new("page2", null, null), + new("page3", null, null), + }; + + TestHelper.CompareObjects(expected, actual); + } + + [Fact] + public void YearOnlyIndexes() + { + using TemporalSchedulesTestContext context = this.CreateContext(); + Timekeeper timekeeper = context.Resolve(); + + CreateDateIndexes op = context.Resolve() + .WithFormats("yyyy") + .WithCreateIndex(this.CreateIndex); + + List input = new() + { + new Entity().Add("page1") + .Add(timekeeper.CreateInstant(2021, 1, 2)), + new Entity().Add("page2") + .Add(timekeeper.CreateInstant(2021, 2, 2)), + new Entity().Add("page3") + .Add(timekeeper.CreateInstant(2022, 1, 2)), + }; + + List?, List?>> actual = + this.GetActual(op, input); + + var expected = new List?, List?>> + { + new( + "index-2021", + new List { "page1", "page2" }, + new List()), + new("index-2022", new List { "page3" }, new List()), + new("page1", null, null), + new("page2", null, null), + new("page3", null, null), + }; + + TestHelper.CompareObjects(expected, actual); + } + + private Entity CreateIndex(DateIndex a) + { + return new Entity().Add(a) + .Add($"index-{a.Key}"); + } + + private List?, List?>> GetActual( + CreateDateIndexes op, + List input) + { + var actual = op.Run(input) + .Select( + x => new Tuple?, List?>( + x.Get(), + x.GetOptional() + ?.Entries.Select(a => a.Get()) + .OrderBy(b => b) + .ToList(), + x.GetOptional() + ?.Indexes.Select(a => a.Get()) + .OrderBy(b => b) + .ToList())) + .OrderBy(x => x.Item1) + .ToList(); + + return actual; + } +} diff --git a/tests/MfGames.Nitride.Temporal.Schedules.Tests/TemporalSchedulesTestBase.cs b/tests/MfGames.Nitride.Temporal.Schedules.Tests/TemporalSchedulesTestBase.cs new file mode 100644 index 0000000..a332cb7 --- /dev/null +++ b/tests/MfGames.Nitride.Temporal.Schedules.Tests/TemporalSchedulesTestBase.cs @@ -0,0 +1,13 @@ +using MfGames.TestSetup; + +using Xunit.Abstractions; + +namespace MfGames.Nitride.Temporal.Schedules.Tests; + +public abstract class TemporalSchedulesTestBase : TestBase +{ + protected TemporalSchedulesTestBase(ITestOutputHelper output) + : base(output) + { + } +} diff --git a/tests/MfGames.Nitride.Temporal.Schedules.Tests/TemporalSchedulesTestContext.cs b/tests/MfGames.Nitride.Temporal.Schedules.Tests/TemporalSchedulesTestContext.cs new file mode 100644 index 0000000..3bc1770 --- /dev/null +++ b/tests/MfGames.Nitride.Temporal.Schedules.Tests/TemporalSchedulesTestContext.cs @@ -0,0 +1,16 @@ +using Autofac; + +using MfGames.Nitride.Temporal.Setup; +using MfGames.Nitride.Tests; + +namespace MfGames.Nitride.Temporal.Schedules.Tests; + +public class TemporalTestContext : NitrideTestContext +{ + /// + protected override void ConfigureContainer(ContainerBuilder builder) + { + base.ConfigureContainer(builder); + builder.RegisterModule(); + } +} diff --git a/tests/MfGames.Nitride.Tests/MfGames.Nitride.Tests.csproj b/tests/MfGames.Nitride.Tests/MfGames.Nitride.Tests.csproj index e040383..7e99b4e 100644 --- a/tests/MfGames.Nitride.Tests/MfGames.Nitride.Tests.csproj +++ b/tests/MfGames.Nitride.Tests/MfGames.Nitride.Tests.csproj @@ -8,13 +8,13 @@ - - - - - - - + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -26,7 +26,7 @@ - + diff --git a/tests/MfGames.Nitride.Yaml.Tests/MfGames.Nitride.Yaml.Tests.csproj b/tests/MfGames.Nitride.Yaml.Tests/MfGames.Nitride.Yaml.Tests.csproj index ec613c8..c6b094c 100644 --- a/tests/MfGames.Nitride.Yaml.Tests/MfGames.Nitride.Yaml.Tests.csproj +++ b/tests/MfGames.Nitride.Yaml.Tests/MfGames.Nitride.Yaml.Tests.csproj @@ -6,7 +6,7 @@ - +