using ClaudeDo.Worker.Git; namespace ClaudeDo.Worker.Tests.Git; public class WorktreeRootResolverTests { [Fact] public void ResolveSiblingRoot_NoTrailingSeparator_ReturnsParent() { var workingDir = Path.Combine(Path.GetTempPath(), "cd_repo_no_sep"); var root = WorktreeRootResolver.ResolveSiblingRoot(workingDir); Assert.Equal(Path.GetFullPath(Path.GetTempPath()).TrimEnd(Path.DirectorySeparatorChar), root); } [Fact] public void ResolveSiblingRoot_WithTrailingSeparator_StillReturnsParent() { var workingDir = Path.Combine(Path.GetTempPath(), "cd_repo_with_sep") + Path.DirectorySeparatorChar; var root = WorktreeRootResolver.ResolveSiblingRoot(workingDir); Assert.Equal(Path.GetFullPath(Path.GetTempPath()).TrimEnd(Path.DirectorySeparatorChar), root); } [Fact] public void ResolveSiblingRoot_WithTrailingAltSeparator_StillReturnsParent() { var workingDir = Path.Combine(Path.GetTempPath(), "cd_repo_with_alt_sep") + "/"; var root = WorktreeRootResolver.ResolveSiblingRoot(workingDir); Assert.Equal(Path.GetFullPath(Path.GetTempPath()).TrimEnd(Path.DirectorySeparatorChar), root); } [Fact] public void ResolveSiblingRoot_DriveRoot_Throws() { var driveRoot = Path.GetPathRoot(Path.GetTempPath())!; Assert.Throws(() => WorktreeRootResolver.ResolveSiblingRoot(driveRoot)); } [Fact] public void EnsureOutsideWorkingDir_PathOutside_DoesNotThrow() { var workingDir = Path.Combine(Path.GetTempPath(), "cd_repo"); var worktreePath = Path.Combine(Path.GetTempPath(), ".claudedo-worktrees", "slug", "task1"); WorktreeRootResolver.EnsureOutsideWorkingDir(worktreePath, workingDir); } [Fact] public void EnsureOutsideWorkingDir_PathInsideWorkingDir_Throws() { var workingDir = Path.Combine(Path.GetTempPath(), "cd_repo"); var worktreePath = Path.Combine(workingDir, ".claudedo-worktrees", "slug", "task1"); Assert.Throws( () => WorktreeRootResolver.EnsureOutsideWorkingDir(worktreePath, workingDir)); } [Fact] public void EnsureOutsideWorkingDir_PathEqualsWorkingDir_Throws() { var workingDir = Path.Combine(Path.GetTempPath(), "cd_repo"); Assert.Throws( () => WorktreeRootResolver.EnsureOutsideWorkingDir(workingDir, workingDir)); } [Fact] public void EnsureOutsideWorkingDir_SiblingWithSharedPrefix_DoesNotThrow() { // "cd_repo-other" is NOT under "cd_repo" even though it shares a string prefix; // a naive StartsWith(workingDir) check would incorrectly reject this. var workingDir = Path.Combine(Path.GetTempPath(), "cd_repo"); var worktreePath = Path.Combine(Path.GetTempPath(), "cd_repo-other", "task1"); WorktreeRootResolver.EnsureOutsideWorkingDir(worktreePath, workingDir); } }