using Microsoft.EntityFrameworkCore; using Novelly.Api.Chapters; using Novelly.Api.Novels; using Novelly.Api.Trash; namespace Novelly.Api.Tests; [TestFixture] public class TrashPurgeScheduleTests { [Test] public void Before_the_run_time_the_next_run_is_today() => Assert.That( TrashPurgeSchedule.NextRunAfter(new DateTimeOffset(2026, 8, 20, 1, 0, 0, TimeSpan.Zero), new TimeOnly(2, 0)), Is.EqualTo(new DateTimeOffset(2026, 8, 20, 2, 0, 0, TimeSpan.Zero))); [Test] public void After_the_run_time_the_next_run_is_tomorrow() => Assert.That( TrashPurgeSchedule.NextRunAfter(new DateTimeOffset(2026, 8, 20, 3, 0, 0, TimeSpan.Zero), new TimeOnly(2, 0)), Is.EqualTo(new DateTimeOffset(2026, 8, 21, 2, 0, 0, TimeSpan.Zero))); [Test] public void Exactly_at_the_run_time_the_next_run_is_tomorrow() => Assert.That( TrashPurgeSchedule.NextRunAfter(new DateTimeOffset(2026, 8, 20, 2, 0, 0, TimeSpan.Zero), new TimeOnly(2, 0)), Is.EqualTo(new DateTimeOffset(2026, 8, 21, 2, 0, 0, TimeSpan.Zero))); } [TestFixture] public class TrashPurgeSweepTests : ServiceTestFixture { private Guid _novelId; protected override void OnSetUp() => _novelId = Novels.CreateAsync(new CreateNovelRequest("The Salt Road")).Result.Id; [Test] public async Task A_sweep_removes_only_items_older_than_the_retention_window() { var old = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("Old News")); var recent = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("Fresh Off The Press")); await Chapters.DeleteAsync(old!.Id); await Chapters.DeleteAsync(recent!.Id); using (var context = Db.CreateContext()) { var oldRow = await context.Chapters.IgnoreQueryFilters().SingleAsync(c => c.Id == old.Id); oldRow.DeletedAt = DateTimeOffset.UtcNow.AddDays(-31); await context.SaveChangesAsync(); } var cutoff = DateTimeOffset.UtcNow.AddDays(-30); var (characters, chapters, locations) = await TrashPurgeRunner.SweepAsync(Db.Context, cutoff, CancellationToken.None); Assert.Multiple(() => { Assert.That((characters, chapters, locations), Is.EqualTo((0, 1, 0))); }); using var verification = Db.CreateContext(); Assert.Multiple(async () => { Assert.That(await verification.Chapters.IgnoreQueryFilters().AnyAsync(c => c.Id == old.Id), Is.False); Assert.That(await verification.Chapters.IgnoreQueryFilters().AnyAsync(c => c.Id == recent.Id), Is.True); }); } }