Skip to content

Commit bf1cf2a

Browse files
committed
tests/cmd(test[GitWorktree]): add tests for worktree operations
why: Verify GitWorktreeManager/GitWorktreeCmd functionality what: - Add WorktreeAddFixture with parametrized add() tests - Add WorktreeLockUnlockFixture with parametrized lock/unlock tests - Add tests for ls(), get(), filter(), remove(), prune() - All tests use NamedTuple + test_id pattern
1 parent c2a7fbd commit bf1cf2a

1 file changed

Lines changed: 181 additions & 0 deletions

File tree

tests/cmd/test_git.py

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,3 +1097,184 @@ def test_stash_entry_create_branch(git_repo: GitSync) -> None:
10971097
branch_names = [b.branch_name for b in branches]
10981098
# Either branch was created or we're on it
10991099
assert "stash-branch" in branch_names or "master" in branch_names
1100+
1101+
1102+
# =============================================================================
1103+
# GitWorktreeManager / GitWorktreeCmd Tests
1104+
# =============================================================================
1105+
1106+
1107+
class WorktreeAddFixture(t.NamedTuple):
1108+
"""Test fixture for GitWorktreeManager.add() operations."""
1109+
1110+
test_id: str
1111+
new_branch: str | None
1112+
detach: bool | None
1113+
1114+
1115+
WORKTREE_ADD_FIXTURES: list[WorktreeAddFixture] = [
1116+
WorktreeAddFixture(
1117+
test_id="add-worktree-with-new-branch",
1118+
new_branch="worktree-branch",
1119+
detach=None,
1120+
),
1121+
WorktreeAddFixture(
1122+
test_id="add-worktree-detached",
1123+
new_branch=None,
1124+
detach=True,
1125+
),
1126+
]
1127+
1128+
1129+
@pytest.mark.parametrize(
1130+
list(WorktreeAddFixture._fields),
1131+
WORKTREE_ADD_FIXTURES,
1132+
ids=[test.test_id for test in WORKTREE_ADD_FIXTURES],
1133+
)
1134+
def test_worktree_add(
1135+
git_repo: GitSync,
1136+
tmp_path: pathlib.Path,
1137+
test_id: str,
1138+
new_branch: str | None,
1139+
detach: bool | None,
1140+
) -> None:
1141+
"""Test GitWorktreeManager.add() with various scenarios."""
1142+
worktree_path = tmp_path / f"worktree-{test_id}"
1143+
1144+
result = git_repo.cmd.worktrees.add(
1145+
path=worktree_path,
1146+
new_branch=new_branch,
1147+
detach=detach,
1148+
)
1149+
1150+
# Should succeed (output contains "Preparing worktree" or similar)
1151+
assert "preparing worktree" in result.lower() or worktree_path.exists()
1152+
1153+
# Verify worktree was created
1154+
worktrees = git_repo.cmd.worktrees.ls()
1155+
worktree_paths = [wt.worktree_path for wt in worktrees]
1156+
assert str(worktree_path) in worktree_paths
1157+
1158+
1159+
def test_worktree_list(git_repo: GitSync, tmp_path: pathlib.Path) -> None:
1160+
"""Test GitWorktreeManager.ls() returns main worktree."""
1161+
worktrees = git_repo.cmd.worktrees.ls()
1162+
1163+
# Should have at least the main worktree
1164+
assert len(worktrees) >= 1
1165+
1166+
# Each worktree should have a path
1167+
for wt in worktrees:
1168+
assert wt.worktree_path is not None
1169+
1170+
1171+
def test_worktree_get(git_repo: GitSync, tmp_path: pathlib.Path) -> None:
1172+
"""Test GitWorktreeManager.get() retrieves specific worktree."""
1173+
# Create a worktree first
1174+
worktree_path = tmp_path / "get-test-worktree"
1175+
git_repo.cmd.worktrees.add(path=worktree_path, new_branch="get-test-branch")
1176+
1177+
# Get the worktree
1178+
worktree = git_repo.cmd.worktrees.get(worktree_path=str(worktree_path))
1179+
assert worktree is not None
1180+
assert worktree.worktree_path == str(worktree_path)
1181+
1182+
1183+
def test_worktree_filter(git_repo: GitSync, tmp_path: pathlib.Path) -> None:
1184+
"""Test GitWorktreeManager.filter() with QueryList filtering."""
1185+
# Create a worktree
1186+
worktree_path = tmp_path / "filter-test-worktree"
1187+
git_repo.cmd.worktrees.add(path=worktree_path, new_branch="filter-test-branch")
1188+
1189+
# Filter by branch
1190+
worktrees = git_repo.cmd.worktrees.filter(branch__contains="filter-test")
1191+
assert len(worktrees) >= 1
1192+
1193+
1194+
class WorktreeLockUnlockFixture(t.NamedTuple):
1195+
"""Test fixture for GitWorktreeCmd lock/unlock operations."""
1196+
1197+
test_id: str
1198+
reason: str | None
1199+
1200+
1201+
WORKTREE_LOCK_UNLOCK_FIXTURES: list[WorktreeLockUnlockFixture] = [
1202+
WorktreeLockUnlockFixture(
1203+
test_id="lock-without-reason",
1204+
reason=None,
1205+
),
1206+
WorktreeLockUnlockFixture(
1207+
test_id="lock-with-reason",
1208+
reason="Testing lock functionality",
1209+
),
1210+
]
1211+
1212+
1213+
@pytest.mark.parametrize(
1214+
list(WorktreeLockUnlockFixture._fields),
1215+
WORKTREE_LOCK_UNLOCK_FIXTURES,
1216+
ids=[test.test_id for test in WORKTREE_LOCK_UNLOCK_FIXTURES],
1217+
)
1218+
def test_worktree_lock_unlock(
1219+
git_repo: GitSync,
1220+
tmp_path: pathlib.Path,
1221+
test_id: str,
1222+
reason: str | None,
1223+
) -> None:
1224+
"""Test GitWorktreeCmd.lock() and unlock() operations."""
1225+
# Create a worktree first
1226+
worktree_path = tmp_path / f"lock-{test_id}-worktree"
1227+
git_repo.cmd.worktrees.add(path=worktree_path, new_branch=f"lock-{test_id}-branch")
1228+
1229+
# Get the worktree
1230+
worktree = git_repo.cmd.worktrees.get(worktree_path=str(worktree_path))
1231+
assert worktree is not None
1232+
1233+
# Lock the worktree
1234+
lock_result = worktree.lock(reason=reason)
1235+
assert lock_result == "" or "locked" not in lock_result.lower()
1236+
1237+
# Verify it's locked
1238+
worktree_after_lock = git_repo.cmd.worktrees.get(worktree_path=str(worktree_path))
1239+
assert worktree_after_lock is not None
1240+
assert worktree_after_lock.locked is True
1241+
1242+
# Unlock the worktree
1243+
unlock_result = worktree.unlock()
1244+
assert unlock_result == ""
1245+
1246+
# Verify it's unlocked
1247+
worktree_after_unlock = git_repo.cmd.worktrees.get(worktree_path=str(worktree_path))
1248+
assert worktree_after_unlock is not None
1249+
assert worktree_after_unlock.locked is False
1250+
1251+
1252+
def test_worktree_remove(git_repo: GitSync, tmp_path: pathlib.Path) -> None:
1253+
"""Test GitWorktreeCmd.remove()."""
1254+
# Create a worktree first
1255+
worktree_path = tmp_path / "remove-test-worktree"
1256+
git_repo.cmd.worktrees.add(path=worktree_path, new_branch="remove-test-branch")
1257+
1258+
# Get the worktree
1259+
worktree = git_repo.cmd.worktrees.get(worktree_path=str(worktree_path))
1260+
assert worktree is not None
1261+
1262+
# Remove the worktree
1263+
result = worktree.remove()
1264+
assert result == "" or "error" not in result.lower()
1265+
1266+
# Verify it's removed
1267+
worktrees_after = git_repo.cmd.worktrees.ls()
1268+
worktree_paths = [wt.worktree_path for wt in worktrees_after]
1269+
assert str(worktree_path) not in worktree_paths
1270+
1271+
1272+
def test_worktree_prune(git_repo: GitSync, tmp_path: pathlib.Path) -> None:
1273+
"""Test GitWorktreeManager.prune()."""
1274+
# Prune should succeed even if nothing to prune
1275+
result = git_repo.cmd.worktrees.prune()
1276+
assert result == "" or "prune" not in result.lower()
1277+
1278+
# Dry run should also succeed
1279+
result_dry = git_repo.cmd.worktrees.prune(dry_run=True)
1280+
assert "error" not in result_dry.lower() or result_dry == ""

0 commit comments

Comments
 (0)