using ClaudeDo.Data.Models; using ClaudeDo.Worker.Lifecycle; using ClaudeDo.Worker.Tests.Infrastructure; using Microsoft.Extensions.Logging.Abstractions; namespace ClaudeDo.Worker.Tests.Lifecycle; public sealed class LegacyWorktreeFolderRecoveryTests : IDisposable { private readonly DbFixture _db = new(); private readonly List _tempDirs = new(); public void Dispose() { _db.Dispose(); foreach (var d in _tempDirs) { try { Directory.Delete(d, recursive: true); } catch { } } } private string MakeWorkingDir() { var dir = Path.Combine(Path.GetTempPath(), $"claudedo_legacy_wt_{Guid.NewGuid():N}"); Directory.CreateDirectory(dir); _tempDirs.Add(dir); return dir; } [Fact] public void FindAffectedListNames_FolderInsideWorkingDir_ReturnsListName() { var wd = MakeWorkingDir(); Directory.CreateDirectory(Path.Combine(wd, ".claudedo-worktrees")); var list = new ListEntity { Id = "1", Name = "Bandel.Hub", WorkingDir = wd, CreatedAt = DateTime.UtcNow }; var affected = LegacyWorktreeFolderRecovery.FindAffectedListNames(new[] { list }); Assert.Equal(new[] { "Bandel.Hub" }, affected); } [Fact] public void FindAffectedListNames_NoLegacyFolder_ReturnsEmpty() { var wd = MakeWorkingDir(); var list = new ListEntity { Id = "1", Name = "Clean", WorkingDir = wd, CreatedAt = DateTime.UtcNow }; var affected = LegacyWorktreeFolderRecovery.FindAffectedListNames(new[] { list }); Assert.Empty(affected); } [Fact] public void FindAffectedListNames_NullWorkingDir_IsSkipped() { var list = new ListEntity { Id = "1", Name = "NoRepo", WorkingDir = null, CreatedAt = DateTime.UtcNow }; var affected = LegacyWorktreeFolderRecovery.FindAffectedListNames(new[] { list }); Assert.Empty(affected); } [Fact] public async Task StartAsync_NoLists_DoesNotThrow() { var sut = new LegacyWorktreeFolderRecovery(_db.CreateFactory(), NullLogger.Instance); await sut.StartAsync(CancellationToken.None); await sut.StopAsync(CancellationToken.None); } }