using ClaudeDo.Data.Models; using ClaudeDo.Data.Repositories; using ClaudeDo.Worker.Findings; using ClaudeDo.Worker.Tests.Infrastructure; namespace ClaudeDo.Worker.Tests.Findings; public sealed class FindingsStoreLocatorTests : IDisposable { private readonly DbFixture _fx = new(); public void Dispose() => _fx.Dispose(); [Fact] public async Task ResolveForTask_UsesTheTasksListWorkingDir() { using var db = _fx.CreateContext(); db.Lists.Add(new ListEntity { Id = "l1", Name = "A", CreatedAt = DateTime.UtcNow, WorkingDir = @"C:\repo-a", FindingsTracked = true }); db.Tasks.Add(new TaskEntity { Id = "t1", ListId = "l1", Title = "x", CreatedAt = DateTime.UtcNow }); await db.SaveChangesAsync(); var locator = new FindingsStoreLocator(new TaskRepository(db), new ListRepository(db)); var target = await locator.ResolveForTaskAsync("t1", CancellationToken.None); Assert.Equal(@"C:\repo-a", target.WorkingDir); Assert.True(target.Tracked); } [Fact] public async Task ResolveForList_MatchesByIdOrName() { using var db = _fx.CreateContext(); db.Lists.Add(new ListEntity { Id = "l1", Name = "Alpha", CreatedAt = DateTime.UtcNow, WorkingDir = @"C:\repo-a" }); db.Lists.Add(new ListEntity { Id = "l2", Name = "Beta", CreatedAt = DateTime.UtcNow, WorkingDir = @"C:\repo-b" }); await db.SaveChangesAsync(); var locator = new FindingsStoreLocator(new TaskRepository(db), new ListRepository(db)); Assert.Equal(@"C:\repo-b", (await locator.ResolveForListAsync("l2", CancellationToken.None)).WorkingDir); Assert.Equal(@"C:\repo-a", (await locator.ResolveForListAsync("Alpha", CancellationToken.None)).WorkingDir); } [Fact] public async Task ResolveForList_WithoutArgument_UsesTheOnlyListWithAWorkingDir() { using var db = _fx.CreateContext(); db.Lists.Add(new ListEntity { Id = "l1", Name = "Alpha", CreatedAt = DateTime.UtcNow, WorkingDir = @"C:\repo-a" }); db.Lists.Add(new ListEntity { Id = "l2", Name = "NoDir", CreatedAt = DateTime.UtcNow, WorkingDir = null }); await db.SaveChangesAsync(); var locator = new FindingsStoreLocator(new TaskRepository(db), new ListRepository(db)); var target = await locator.ResolveForListAsync("", CancellationToken.None); Assert.Equal(@"C:\repo-a", target.WorkingDir); } [Fact] public async Task ResolveForList_WithoutArgument_ThrowsAndNamesCandidatesWhenAmbiguous() { using var db = _fx.CreateContext(); db.Lists.Add(new ListEntity { Id = "l1", Name = "Alpha", CreatedAt = DateTime.UtcNow, WorkingDir = @"C:\repo-a" }); db.Lists.Add(new ListEntity { Id = "l2", Name = "Beta", CreatedAt = DateTime.UtcNow, WorkingDir = @"C:\repo-b" }); await db.SaveChangesAsync(); var locator = new FindingsStoreLocator(new TaskRepository(db), new ListRepository(db)); var ex = await Assert.ThrowsAsync( () => locator.ResolveForListAsync("", CancellationToken.None)); Assert.Contains("Alpha", ex.Message); Assert.Contains("Beta", ex.Message); } [Fact] public async Task ResolveForList_ThrowsWhenTheListHasNoWorkingDir() { using var db = _fx.CreateContext(); db.Lists.Add(new ListEntity { Id = "l1", Name = "Alpha", CreatedAt = DateTime.UtcNow, WorkingDir = null }); await db.SaveChangesAsync(); var locator = new FindingsStoreLocator(new TaskRepository(db), new ListRepository(db)); await Assert.ThrowsAsync( () => locator.ResolveForListAsync("Alpha", CancellationToken.None)); } }