shoc-backend/SeaHavenIndustries.Tests/WorkOrderServiceRegistryFilterRelationalTests.cs
2026-09-30 16:45:05 -03:00

159 lines
6.2 KiB
C#

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<ApplicationDbContext>()
.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<ApplicationDbContext> 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;
}
}
}
}