using ClaudeDo.Ui.Services; namespace ClaudeDo.Ui.Tests; public sealed class RepoScannerTests : IDisposable { private readonly string _root = Path.Combine(Path.GetTempPath(), "repo-scan-" + Guid.NewGuid().ToString("N")); public RepoScannerTests() => Directory.CreateDirectory(_root); public void Dispose() { try { Directory.Delete(_root, recursive: true); } catch { } } private string MakeDir(string name) { var p = Path.Combine(_root, name); Directory.CreateDirectory(p); return p; } [Fact] public void Scan_ReturnsSubfoldersWithGitDirectory() { var repo = MakeDir("repo-a"); Directory.CreateDirectory(Path.Combine(repo, ".git")); var result = RepoScanner.Scan(_root); Assert.Single(result); Assert.Equal("repo-a", result[0].Name); Assert.Equal(repo, result[0].FullPath); } [Fact] public void Scan_TreatsDotGitFileAsRepo() { var repo = MakeDir("worktree-repo"); File.WriteAllText(Path.Combine(repo, ".git"), "gitdir: ../somewhere"); var result = RepoScanner.Scan(_root); Assert.Single(result); Assert.Equal("worktree-repo", result[0].Name); } [Fact] public void Scan_IgnoresPlainFolders() { MakeDir("not-a-repo"); var result = RepoScanner.Scan(_root); Assert.Empty(result); } [Fact] public void Scan_IsNotRecursive() { var nested = MakeDir(Path.Combine("outer", "inner")); Directory.CreateDirectory(Path.Combine(nested, ".git")); // outer itself has no .git var result = RepoScanner.Scan(_root); Assert.Empty(result); } [Fact] public void Scan_ReturnsEmptyForMissingFolder() { var result = RepoScanner.Scan(Path.Combine(_root, "does-not-exist")); Assert.Empty(result); } }