using Data.SeaHavenIndustries; using Data.SeaHavenIndustries.Enums; using Microsoft.EntityFrameworkCore; using SeaHaven.DataServices.Helpers; using SeaHaven.DataServices.Implementation; namespace SeaHavenIndustries.Tests; public class WorkOrderBoardSearchFilterTests { private static ApplicationDbContext CreateContext() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .Options; return new ApplicationDbContext(options); } [Theory] [InlineData("BK5", 1)] [InlineData("10000000001", 1)] [InlineData("HVAC Tech", 1)] [InlineData("Acme HVAC", 1)] [InlineData("sched", 1)] public async Task Apply_MatchesExpectedField(string search, int expectedId) { await using var context = CreateContext(); await SeedSearchFixtures(context); var ids = await WorkOrderBoardSearchFilter .Apply(context.workOrders.AsQueryable(), search) .Select(w => w.Id) .ToListAsync(); Assert.Contains(expectedId, ids); } [Fact] public void NormalizeSearch_IgnoresSingleCharacter() { Assert.Null(WorkOrderBoardSearchFilter.NormalizeSearch("a")); Assert.Null(WorkOrderBoardSearchFilter.NormalizeSearch(" ")); Assert.Equal("ab", WorkOrderBoardSearchFilter.NormalizeSearch(" ab ")); } [Fact] public async Task Apply_LifecycleLabel_MatchesScheduled() { await using var context = CreateContext(); await SeedSearchFixtures(context); var ids = await WorkOrderBoardSearchFilter .Apply(context.workOrders.AsQueryable(), "scheduled") .Select(w => w.Id) .ToListAsync(); Assert.Single(ids); Assert.Equal(1, ids[0]); } private static async Task SeedSearchFixtures(ApplicationDbContext context) { context.Vendors.Add(new Vendor { Id = 1, CompanyName = "Acme HVAC", ContactName = "HVAC Tech", Phone = "555-0100" }); context.Dispatches.Add(new Dispatch { Id = 10, VendorId = 1 }); context.workOrders.Add(new WorkOrder { Id = 1, SiteCode = "BK5", InternalWONumber = "10000000001", LifecycleStatus = LifecycleStatus.Scheduled, PrimaryDispatchId = 10 }); await context.SaveChangesAsync(); } } public class WorkOrderBoardSearchCountsTests { private static ApplicationDbContext CreateContext() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .Options; return new ApplicationDbContext(options); } [Fact] public async Task GetBoardRows_SearchReducesScheduledAndKeepsTotal() { await using var context = CreateContext(); var weekStart = new DateOnly(2026, 6, 22); context.workOrders.AddRange( new WorkOrder { Id = 1, SiteCode = "BK5", ScheduledDate = new DateTime(2026, 6, 23), LifecycleStatus = LifecycleStatus.Scheduled }, new WorkOrder { Id = 2, SiteCode = "BK6", ScheduledDate = new DateTime(2026, 6, 24), LifecycleStatus = LifecycleStatus.Scheduled }, new WorkOrder { Id = 3, SiteCode = "BK5", ScheduledDate = null, LifecycleStatus = LifecycleStatus.Incomplete }); await context.SaveChangesAsync(); var service = new WorkOrderBoardDataService(context); var result = await service.GetBoardRowsAsync(new SeaHaven.DataServices.Interfaces.WorkOrderBoardQuery( weekStart, weekStart.AddDays(4), null, false, null, "BK5", null)); Assert.Equal(2, result.ScheduledTotalBeforeSearch); Assert.Single(result.ScheduledRows); Assert.Equal("BK5", result.ScheduledRows[0].SiteCode); Assert.Single(result.UnscheduledRows); Assert.Equal("BK5", result.UnscheduledRows[0].SiteCode); } } public class WorkOrderSearchDateRangeResolverTests { [Fact] public void Resolve_ThisWeek_UsesIsoMonday() { var reference = new DateOnly(2026, 6, 24); var range = SeaHaven.Services.Helpers.WorkOrderSearchDateRangeResolver.Resolve( SeaHaven.Services.Helpers.WorkOrderAdvancedSearchDatePreset.ThisWeek, null, null, reference); Assert.Equal(new DateOnly(2026, 6, 22), range.From); Assert.Equal(new DateOnly(2026, 6, 28), range.To); } [Fact] public void Resolve_Custom_RequiresDates() { var ex = Assert.Throws(() => SeaHaven.Services.Helpers.WorkOrderSearchDateRangeResolver.Resolve( SeaHaven.Services.Helpers.WorkOrderAdvancedSearchDatePreset.Custom, null, null)); Assert.Contains("dateFrom", ex.Message); } } public class WorkOrderAdvancedSearchServiceTests { private static ApplicationDbContext CreateContext() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .Options; return new ApplicationDbContext(options); } [Fact] public async Task SearchAsync_FiltersBySiteAndPaginates() { await using var context = CreateContext(); var weekStart = new DateOnly(2026, 6, 22); context.workOrders.AddRange( new WorkOrder { Id = 1, SiteCode = "BK5", ScheduledDate = new DateTime(2026, 6, 23), LifecycleStatus = LifecycleStatus.Scheduled, InternalWONumber = "10000000001" }, new WorkOrder { Id = 2, SiteCode = "BK6", ScheduledDate = new DateTime(2026, 6, 24), LifecycleStatus = LifecycleStatus.Scheduled, InternalWONumber = "10000000002" }); await context.SaveChangesAsync(); var dataService = new WorkOrderAdvancedSearchDataService(context); var service = new SeaHaven.Services.Implementation.WorkOrderAdvancedSearchService(dataService); var result = await service.SearchAsync(new SeaHaven.Services.DTOs.WorkOrderAdvancedSearchQueryDto { DatePreset = SeaHaven.Services.Helpers.WorkOrderAdvancedSearchDatePreset.Custom, DateFrom = weekStart, DateTo = weekStart.AddDays(6), Sites = new List { "BK5" }, Page = 1, PageSize = 50 }, null); Assert.Equal(1, result.TotalCount); Assert.Single(result.Items); Assert.Equal("BK5", result.Items.First().SiteCode); } [Fact] public async Task SearchAsync_ClampsPageSizeToMax() { await using var context = CreateContext(); var dataService = new WorkOrderAdvancedSearchDataService(context); var service = new SeaHaven.Services.Implementation.WorkOrderAdvancedSearchService(dataService); var result = await service.SearchAsync(new SeaHaven.Services.DTOs.WorkOrderAdvancedSearchQueryDto { DatePreset = SeaHaven.Services.Helpers.WorkOrderAdvancedSearchDatePreset.ThisWeek, PageSize = 500 }, null); Assert.Equal(100, result.PageSize); } }