using JSMR.Application.Scanning.Contracts; using JSMR.Infrastructure.Scanning.Extensions; using Shouldly; namespace JSMR.Tests.Unit; public class DLSiteWorkExpectedDateInferenceTests { [Fact] public void Infers_From_Sandwich_Expected_Dates() { DLSiteWork[] works = [ Work(expected: new DateOnly(2026, 5, 1)), Work(), Work(expected: new DateOnly(2026, 5, 1)), ]; DateOnly?[] expectedExpectedDates = [ new DateOnly(2026, 5, 1), new DateOnly(2026, 5, 1), new DateOnly(2026, 5, 1) ]; AttemptInferAndVerify(works, expectedExpectedDates); } [Fact] public void Infers_From_Sandwich_Sales_Dates_Early() { DLSiteWork[] works = [ Work(sales: new DateOnly(2026, 5, 2)), Work(), Work(sales: new DateOnly(2026, 5, 7)), ]; DateOnly?[] expectedExpectedDates = [ null, // Sales date will not have expected date new DateOnly(2026, 5, 1), null // Sales date will not have expected date ]; AttemptInferAndVerify(works, expectedExpectedDates); } [Fact] public void Infers_From_Sandwich_Sales_Dates_Middle() { DLSiteWork[] works = [ Work(sales: new DateOnly(2026, 5, 12)), Work(), Work(sales: new DateOnly(2026, 5, 13)), ]; DateOnly?[] expectedExpectedDates = [ null, // Sales date will not have expected date new DateOnly(2026, 5, 11), null // Sales date will not have expected date ]; AttemptInferAndVerify(works, expectedExpectedDates); } [Fact] public void Infers_From_Sandwich_Sales_Dates_Late() { DLSiteWork[] works = [ Work(sales: new DateOnly(2026, 5, 25)), Work(), Work(sales: new DateOnly(2026, 5, 27)), ]; DateOnly?[] expectedExpectedDates = [ null, // Sales date will not have expected date new DateOnly(2026, 5, 21), null // Sales date will not have expected date ]; AttemptInferAndVerify(works, expectedExpectedDates); } [Fact] public void Infers_From_Sandwich_Mixed_Dates() { DLSiteWork[] works = [ Work(expected: new DateOnly(2026, 5, 1)), Work(), Work(sales: new DateOnly(2026, 5, 7)), ]; DateOnly?[] expectedExpectedDates = [ new DateOnly(2026, 5, 1), new DateOnly(2026, 5, 1), null // Sales date will not have expected date ]; AttemptInferAndVerify(works, expectedExpectedDates); } [Fact] public void Infers_A_Run_Of_Missing_Items_When_Bounded_By_Same_Date() { DLSiteWork[] works = [ Work(expected: new DateOnly(2026, 5, 1)), Work(), Work(), Work(), Work(expected: new DateOnly(2026, 5, 1)), ]; DateOnly?[] expected = [ new DateOnly(2026, 5, 1), new DateOnly(2026, 5, 1), new DateOnly(2026, 5, 1), new DateOnly(2026, 5, 1), new DateOnly(2026, 5, 1), ]; AttemptInferAndVerify(works, expected); } [Fact] public void DoesNotInfer_When_Expected_Sandwich_Difference() { DLSiteWork[] works = [ Work(expected: new DateOnly(2026, 5, 1)), Work(), Work(expected: new DateOnly(2026, 5, 11)), ]; DateOnly?[] expectedExpectedDates = [ new DateOnly(2026, 5, 1), null, new DateOnly(2026, 5, 11) ]; AttemptInferAndVerify(works, expectedExpectedDates); } [Fact] public void DoesNotInfer_When_Sales_Sandwich_Difference_Early_Middle() { DLSiteWork[] works = [ Work(sales: new DateOnly(2026, 5, 1)), Work(), Work(sales: new DateOnly(2026, 5, 12)), ]; DateOnly?[] expectedExpectedDates = [ null, // Sales date will not have expected date null, null // Sales date will not have expected date ]; AttemptInferAndVerify(works, expectedExpectedDates); } [Fact] public void DoesNotInfer_When_Sales_Sandwich_Difference_Early_Late() { DLSiteWork[] works = [ Work(sales: new DateOnly(2026, 5, 1)), Work(), Work(sales: new DateOnly(2026, 5, 22)), ]; DateOnly?[] expectedExpectedDates = [ null, // Sales date will not have expected date null, null // Sales date will not have expected date ]; AttemptInferAndVerify(works, expectedExpectedDates); } [Fact] public void DoesNotInfer_When_Sales_Sandwich_Difference_Middle_Late() { DLSiteWork[] works = [ Work(sales: new DateOnly(2026, 5, 14)), Work(), Work(sales: new DateOnly(2026, 5, 22)), ]; DateOnly?[] expectedExpectedDates = [ null, // Sales date will not have expected date null, null // Sales date will not have expected date ]; AttemptInferAndVerify(works, expectedExpectedDates); } [Fact] public void DoesNotInfer_When_No_Left() { DLSiteWork[] works = [ Work(), Work(expected: new DateOnly(2026, 5, 1)), ]; DateOnly?[] expectedExpectedDates = [ null, new DateOnly(2026, 5, 1) ]; AttemptInferAndVerify(works, expectedExpectedDates); } [Fact] public void DoesNotInfer_When_No_Right() { DLSiteWork[] works = [ Work(expected: new DateOnly(2026, 5, 1)), Work() ]; DateOnly?[] expectedExpectedDates = [ new DateOnly(2026, 5, 1), null ]; AttemptInferAndVerify(works, expectedExpectedDates); } [Fact] public void DoesNot_Overwrite_Existing_ExpectedDate() { DLSiteWork[] works = [ Work(expected: new DateOnly(2026, 5, 1)), Work(expected: new DateOnly(2026, 4, 11)), // already set Work(expected: new DateOnly(2026, 5, 21)), ]; DateOnly?[] expected = [ new DateOnly(2026, 5, 1), new DateOnly(2026, 4, 11), new DateOnly(2026, 5, 21), ]; AttemptInferAndVerify(works, expected); } private static void AttemptInferAndVerify(DLSiteWork[] works, DateOnly?[] expectedExpectedDates) { // Act works.InferAndUpdateExpectedDates(); // Assert works.Length.ShouldBe(expectedExpectedDates.Length); for (int i = 0; i < works.Length; i++) works[i].ExpectedDate.ShouldBe(expectedExpectedDates[i]); } private static DLSiteWork Work(DateOnly? expected = null, DateOnly? sales = null) => DLSiteWorkTestFactory.Create(expectedDate: expected, salesDate: sales); }