using Data.SeaHavenIndustries; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using SeaHaven.DataServices.Helpers; using SeaHaven.Services.Implementation; namespace SeaHavenIndustries.Tests; public sealed class WorkOrderServiceRegistryFilterRelationalTests { [Fact] public async Task ServiceDisplayAndFilter_UseCurrentActiveNameAndKeepHistoricalAndLegacyLabels() { await using var connection = new SqliteConnection("Data Source=:memory:;Foreign Keys=True"); await connection.OpenAsync(); var options = new DbContextOptionsBuilder() .UseSqlite(connection) .Options; await using var context = new SqliteServiceRegistryTestDbContext(options); await context.Database.EnsureCreatedAsync(); context.Services.AddRange( new Service { Id = 10, Name = "Current Active Name", NormalizedName = "CURRENT ACTIVE NAME", Trade = "Electrical", IconKey = "electrical", IsActive = true }, new Service { Id = 20, Name = "Current Inactive Name", NormalizedName = "CURRENT INACTIVE NAME", Trade = "Electrical", IconKey = "electrical", IsActive = false }); context.workOrders.AddRange( new WorkOrder { Id = 1, ServiceId = 10, ServiceNameSnapshot = "Original Active Name", Trade = "Original Active Name" }, new WorkOrder { Id = 2, ServiceId = 20, ServiceNameSnapshot = "Historical Inactive Name", Trade = "Historical Inactive Name" }, new WorkOrder { Id = 3, Trade = "Legacy Cooling", Problem = "Legacy Leak" }); await context.SaveChangesAsync(); var activeRows = await WorkOrderBoardProjection.ProjectRowsAsync( context, context.workOrders.AsNoTracking().Where(w => w.Id == 1), isUnscheduled: true); var activeDisplay = WorkOrderBoardService.MapRawRow(Assert.Single(activeRows), DateTime.UtcNow); var inactiveRows = await WorkOrderBoardProjection.ProjectRowsAsync( context, context.workOrders.AsNoTracking().Where(w => w.Id == 2), isUnscheduled: true); var inactiveDisplay = WorkOrderBoardService.MapRawRow(Assert.Single(inactiveRows), DateTime.UtcNow); var legacyRows = await WorkOrderBoardProjection.ProjectRowsAsync( context, context.workOrders.AsNoTracking().Where(w => w.Id == 3), isUnscheduled: true); var legacyDisplay = WorkOrderBoardService.MapRawRow(Assert.Single(legacyRows), DateTime.UtcNow); var currentActiveNameMatches = await WorkOrderBoardQueryFilters .ApplyPmTypeFilter(context.workOrders.AsNoTracking(), new[] { "Current Active Name" }) .Select(w => w.Id) .ToListAsync(); var historicalInactiveNameMatches = await WorkOrderBoardQueryFilters .ApplyPmTypeFilter(context.workOrders.AsNoTracking(), new[] { "Historical Inactive Name" }) .Select(w => w.Id) .ToListAsync(); var inactiveRegistryNameMatches = await WorkOrderBoardQueryFilters .ApplyPmTypeFilter(context.workOrders.AsNoTracking(), new[] { "Current Inactive Name" }) .Select(w => w.Id) .ToListAsync(); var legacyTradeMatches = await WorkOrderBoardQueryFilters .ApplyPmTypeFilter(context.workOrders.AsNoTracking(), new[] { "Legacy Cooling" }) .Select(w => w.Id) .ToListAsync(); var legacyProblemMatches = await WorkOrderBoardQueryFilters .ApplyPmTypeFilter(context.workOrders.AsNoTracking(), new[] { "Legacy Leak" }) .Select(w => w.Id) .ToListAsync(); var actual = string.Join("\n", new[] { $"active-display={activeDisplay.Pm}", $"inactive-display={inactiveDisplay.Pm}", $"legacy-display={legacyDisplay.Pm}", $"active-filter={string.Join(',', currentActiveNameMatches)}", $"inactive-snapshot-filter={string.Join(',', historicalInactiveNameMatches)}", $"inactive-current-name-filter={string.Join(',', inactiveRegistryNameMatches)}", $"legacy-trade-filter={string.Join(',', legacyTradeMatches)}", $"legacy-problem-filter={string.Join(',', legacyProblemMatches)}" }); var expected = string.Join("\n", new[] { "active-display=Current Active Name", "inactive-display=Historical Inactive Name", "legacy-display=Legacy Cooling", "active-filter=1", "inactive-snapshot-filter=2", "inactive-current-name-filter=", "legacy-trade-filter=3", "legacy-problem-filter=3" }); Assert.True(expected == actual, $"Expected:\n{expected}\nActual:\n{actual}"); } private sealed class SqliteServiceRegistryTestDbContext : ApplicationDbContext { public SqliteServiceRegistryTestDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); // SQL Server filtered indexes and rowversion semantics are not supported by SQLite. foreach (var index in builder.Model.GetEntityTypes().SelectMany(entity => entity.GetIndexes())) { if (index.GetFilter() != null) index.SetFilter(null); } foreach (var entityType in new[] { typeof(WorkOrder), typeof(Dispatch) }) { var property = builder.Entity(entityType).Property("RowVersion").Metadata; property.ValueGenerated = Microsoft.EntityFrameworkCore.Metadata.ValueGenerated.Never; property.IsConcurrencyToken = false; } } } }