"""Tests for the branch-worktree helper scripts (#38/#39). Exercises path generation and refuse-to-overwrite via the scripts' ``--dry-run`` mode, so no real worktrees, branches, network, or deletions are involved. """ import os import subprocess import unittest from pathlib import Path REPO = Path(__file__).resolve().parent.parent SCRIPTS = REPO / "scripts" BRANCHES = REPO / "branches" def run(script, *args): proc = subprocess.run( ["bash", str(SCRIPTS / script), *args], capture_output=True, text=True, cwd=str(REPO), ) return proc.returncode, proc.stdout, proc.stderr class TestWorktreeStart(unittest.TestCase): def test_dry_run_path_generation(self): rc, out, _ = run("worktree-start", "--dry-run", "fix/issue-123-example") self.assertEqual(rc, 0) self.assertIn("branches/fix-issue-123-example", out) self.assertIn("fix/issue-123-example", out) self.assertIn("prgs/master", out) # default start-ref def test_bad_args_exit_2(self): rc, _, _ = run("worktree-start") self.assertEqual(rc, 2) def test_refuses_existing_worktree(self): slug = f"zz-refuse-start-{os.getpid()}" target = BRANCHES / slug target.mkdir(parents=True, exist_ok=True) try: rc, _, err = run("worktree-start", "--dry-run", slug) self.assertEqual(rc, 1) self.assertIn("Refusing to reuse", err) finally: target.rmdir() class TestWorktreeReview(unittest.TestCase): def test_dry_run_detached_review_path(self): rc, out, _ = run("worktree-review", "--dry-run", "fix/issue-9-x") self.assertEqual(rc, 0) self.assertIn("branches/review-fix-issue-9-x", out) self.assertIn("--detach", out) self.assertIn("prgs/fix/issue-9-x", out) # default start-ref def test_refuses_existing_review_worktree(self): slug = f"review-zz-refuse-rev-{os.getpid()}" target = BRANCHES / slug target.mkdir(parents=True, exist_ok=True) try: # branch name maps to the same slug: review- rc, _, err = run("worktree-review", "--dry-run", f"zz-refuse-rev-{os.getpid()}") self.assertEqual(rc, 1) self.assertIn("Refusing to reuse", err) finally: target.rmdir() class TestWorktreeClean(unittest.TestCase): def test_missing_worktree_errors(self): rc, _, err = run("worktree-clean", "--dry-run", "does-not-exist-xyz") self.assertEqual(rc, 1) self.assertIn("No such worktree", err) def test_dry_run_does_not_delete(self): slug = f"zz-clean-{os.getpid()}" target = BRANCHES / slug target.mkdir(parents=True, exist_ok=True) try: rc, out, _ = run("worktree-clean", "--dry-run", slug) self.assertEqual(rc, 0) self.assertIn("worktree remove", out) self.assertTrue(target.is_dir()) # nothing removed in dry-run finally: target.rmdir() def test_dry_run_delete_branch_lists_branch_command(self): slug = f"zz-clean-b-{os.getpid()}" target = BRANCHES / slug target.mkdir(parents=True, exist_ok=True) try: rc, out, _ = run("worktree-clean", "--dry-run", "--delete-branch", slug) self.assertEqual(rc, 0) self.assertIn("branch -d", out) finally: target.rmdir() if __name__ == "__main__": unittest.main()