using Data.SeaHavenIndustries; using FluentAssertions; using Microsoft.EntityFrameworkCore; using SeaHaven.DataServices.Implementation; using SeaHaven.Services.DTOs; using SeaHaven.Services.Implementation; using Xunit; namespace Api.SeaHavenIndustries.Tests; public class TaskListTemplateServiceTests { private static ApplicationDbContext NewContext() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()) .Options; return new ApplicationDbContext(options); } private static TaskListTemplateService NewService(ApplicationDbContext ctx) => new(new TaskListTemplateDataService(ctx)); private static TaskListTemplate Template(string name, bool active, params (string text, int sort)[] items) { var t = new TaskListTemplate { Name = name, IsActive = active }; t.Items = items.Select(i => new TaskListTemplateItem { ItemText = i.text, SortOrder = i.sort }).ToList(); return t; } [Fact] public async Task GetAllAsync_ReturnsOnlyActiveOrderedByNameWithOrderedItems() { using var ctx = NewContext(); ctx.TaskListTemplates.AddRange( Template("Zeta", true, ("b", 2), ("a", 1)), Template("Alpha", true, ("first", 0)), Template("Hidden", false) ); ctx.SaveChanges(); var result = (await NewService(ctx).GetAllAsync(CancellationToken.None)).ToList(); result.Select(t => t.Name).Should().ContainInOrder("Alpha", "Zeta"); result.Single(t => t.Name == "Zeta").Items.Select(i => i.ItemText).Should().ContainInOrder("a", "b"); } [Fact] public async Task GetByIdAsync_WhenMissing_ReturnsNull() { using var ctx = NewContext(); var result = await NewService(ctx).GetByIdAsync(99, CancellationToken.None); result.Should().BeNull(); } [Fact] public async Task GetByIdAsync_ReturnsTemplateWithOrderedItems() { using var ctx = NewContext(); var t = Template("Alpha", true, ("b", 2), ("a", 1)); ctx.TaskListTemplates.Add(t); ctx.SaveChanges(); var result = await NewService(ctx).GetByIdAsync(t.Id, CancellationToken.None); result.Should().NotBeNull(); result!.Items.Select(i => i.ItemText).Should().ContainInOrder("a", "b"); } [Fact] public async Task CreateAsync_PersistsTemplateAndItemsAndReturnsId() { using var ctx = NewContext(); var input = new TaskListTemplateInput { Name = "New", Description = "desc", IsActive = true, Items = new() { new() { ItemText = "two", SortOrder = 0 }, new() { ItemText = "one", SortOrder = 0 } } }; var id = await NewService(ctx).CreateAsync(input, CancellationToken.None); id.Should().BeGreaterThan(0); var row = ctx.TaskListTemplates.Include(t => t.Items).Single(); row.Name.Should().Be("New"); row.Items.Should().HaveCount(2); row.Items!.Select(i => i.SortOrder).Should().ContainInOrder(0, 1); } [Fact] public async Task UpdateAsync_WhenNotFound_ReturnsFalse() { using var ctx = NewContext(); var result = await NewService(ctx).UpdateAsync(404, new TaskListTemplateInput { Name = "x" }, CancellationToken.None); result.Should().BeFalse(); } [Fact] public async Task UpdateAsync_ReplacesItems() { using var ctx = NewContext(); var t = Template("Alpha", true, ("old", 0)); ctx.TaskListTemplates.Add(t); ctx.SaveChanges(); var updated = await NewService(ctx).UpdateAsync(t.Id, new TaskListTemplateInput { Name = "Renamed", IsActive = false, Items = new() { new() { ItemText = "new1", SortOrder = 1 }, new() { ItemText = "new2", SortOrder = 2 } } }, CancellationToken.None); updated.Should().BeTrue(); var row = ctx.TaskListTemplates.Include(x => x.Items).Single(); row.Name.Should().Be("Renamed"); row.IsActive.Should().BeFalse(); row.Items!.Select(i => i.ItemText).Should().BeEquivalentTo(new[] { "new1", "new2" }); } [Fact] public async Task DeleteAsync_SoftDeletesByDeactivating() { using var ctx = NewContext(); var t = Template("Alpha", true); ctx.TaskListTemplates.Add(t); ctx.SaveChanges(); var result = await NewService(ctx).DeleteAsync(t.Id, CancellationToken.None); result.Should().BeTrue(); ctx.TaskListTemplates.Single().IsActive.Should().BeFalse(); } [Fact] public async Task DeleteAsync_WhenNotFound_ReturnsFalse() { using var ctx = NewContext(); var result = await NewService(ctx).DeleteAsync(404, CancellationToken.None); result.Should().BeFalse(); } }