mod common;
use assert_cmd::Command;
use common::TestRepo;
use predicates::prelude::*;
fn cw() -> Command {
Command::cargo_bin("gw").unwrap()
}
#[test]
fn test_global_list_no_repos() {
let repo = TestRepo::new();
let output = repo.cw(&["-g", "list"]);
let combined = format!(
"{}{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr),
);
assert!(
combined.contains("No repositor")
|| combined.contains("No repo")
|| combined.contains("no repositor")
|| combined.contains("worktree"),
"Expected message about no repos, got: {}",
combined
);
}
#[test]
fn test_global_list_with_worktree() {
let repo = TestRepo::new();
let _wt = repo.create_worktree("feature-one");
let output = repo.cw(&["-g", "list"]);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("feature-one") || stdout.contains("worktree"),
"Expected worktree info in global list, got: {}",
stdout
);
}
#[test]
fn test_global_list_multiple_repos() {
let repo1 = TestRepo::new();
let _wt1 = repo1.create_worktree("feat-alpha");
let repo2 = TestRepo::new();
let _wt2 = repo2.create_worktree("feat-beta");
let output = repo1.cw(&["-g", "list"]);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("feat-alpha") || stdout.contains("worktree"),
"Expected at least repo1's worktree in global list, got: {}",
stdout
);
}
#[test]
fn test_global_list_format_table() {
let repo = TestRepo::new();
let _wt = repo.create_worktree("table-test");
let output = repo.cw(&["-g", "list"]);
let stdout = String::from_utf8_lossy(&output.stdout);
if stdout.contains("REPO") {
assert!(stdout.contains("WORKTREE") || stdout.contains("BRANCH"));
assert!(stdout.contains("STATUS"));
}
assert!(output.status.success());
}
#[test]
fn test_global_list_shows_status() {
let repo = TestRepo::new();
let wt = repo.create_worktree("status-check");
std::fs::write(wt.join("dirty.txt"), "uncommitted change").unwrap();
let output = repo.cw(&["-g", "list"]);
let stdout = String::from_utf8_lossy(&output.stdout);
if stdout.contains("status-check") {
assert!(
stdout.contains("clean")
|| stdout.contains("modified")
|| stdout.contains("active")
|| stdout.contains("stale"),
"Expected a status indicator, got: {}",
stdout
);
}
}
#[test]
fn test_global_list_help() {
cw().args(["-g", "list", "--help"])
.assert()
.success()
.stdout(
predicate::str::contains("list")
.or(predicate::str::contains("List"))
.or(predicate::str::contains("worktree")),
);
}
#[test]
fn test_global_list_after_worktree_deleted() {
let repo = TestRepo::new();
let _wt = repo.create_worktree("to-delete");
let del_output = repo.cw(&["delete", "to-delete"]);
assert!(
del_output.status.success(),
"delete failed: {}",
String::from_utf8_lossy(&del_output.stderr)
);
let output = repo.cw(&["-g", "list"]);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
!stdout.contains("to-delete"),
"Deleted worktree should not appear in list"
);
}
#[test]
fn test_global_scan_succeeds() {
let repo = TestRepo::new();
let output = repo.cw(&["scan"]);
assert!(
output.status.success(),
"scan command should succeed: {}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("Scanning") || stdout.contains("repository") || stdout.contains("No repo"),
"Expected scan output, got: {}",
stdout
);
}
#[test]
fn test_global_scan_help() {
cw().args(["scan", "--help"]).assert().success().stdout(
predicate::str::contains("scan")
.or(predicate::str::contains("Scan"))
.or(predicate::str::contains("repositor")),
);
}
#[test]
fn test_global_prune_clean() {
let repo = TestRepo::new();
let output = repo.cw(&["prune"]);
assert!(output.status.success());
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("clean") || stdout.contains("nothing") || stdout.contains("Pruning"),
"Expected clean prune message, got: {}",
stdout
);
}
#[test]
fn test_global_prune_removes_stale() {
let repo = TestRepo::new();
let _wt = repo.create_worktree("prune-test");
let output1 = repo.cw(&["prune"]);
assert!(output1.status.success());
let output2 = repo.cw(&["prune"]);
assert!(output2.status.success());
}
#[test]
fn test_global_prune_help() {
cw().args(["prune", "--help"]).assert().success().stdout(
predicate::str::contains("prune")
.or(predicate::str::contains("Prune"))
.or(predicate::str::contains("registry"))
.or(predicate::str::contains("stale")),
);
}
#[test]
fn test_global_flag_accepted() {
let repo = TestRepo::new();
let output = repo.cw(&["-g", "list"]);
assert!(
output.status.success(),
"-g list should succeed: {}",
String::from_utf8_lossy(&output.stderr)
);
}
#[test]
fn test_global_long_flag_accepted() {
let repo = TestRepo::new();
let output = repo.cw(&["--global", "list"]);
assert!(
output.status.success(),
"--global list should succeed: {}",
String::from_utf8_lossy(&output.stderr)
);
}
#[test]
fn test_global_list_returns_zero() {
let repo = TestRepo::new();
let output = repo.cw(&["-g", "list"]);
assert_eq!(output.status.code(), Some(0));
}
#[test]
fn test_global_list_clean_worktree() {
let repo = TestRepo::new();
let _wt = repo.create_worktree("clean-wt");
let output = repo.cw(&["-g", "list"]);
let stdout = String::from_utf8_lossy(&output.stdout);
if stdout.contains("clean-wt") {
assert!(
stdout.contains("clean"),
"Expected 'clean' status for unmodified worktree"
);
}
}
#[test]
fn test_global_list_modified_worktree() {
let repo = TestRepo::new();
let wt = repo.create_worktree("mod-wt");
std::fs::write(wt.join("newfile.txt"), "new content").unwrap();
TestRepo::git_at(&wt, &["add", "newfile.txt"]);
let output = repo.cw(&["-g", "list"]);
let stdout = String::from_utf8_lossy(&output.stdout);
if stdout.contains("mod-wt") {
assert!(
stdout.contains("modified") || stdout.contains("active"),
"Expected modified/active status for dirty worktree, got: {}",
stdout
);
}
}
#[test]
fn test_global_list_multiple_worktrees_same_repo() {
let repo = TestRepo::new();
let _wt1 = repo.create_worktree("multi-a");
let _wt2 = repo.create_worktree("multi-b");
let output = repo.cw(&["-g", "list"]);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("multi-a"),
"Expected multi-a in list, got: {}",
stdout
);
assert!(
stdout.contains("multi-b"),
"Expected multi-b in list, got: {}",
stdout
);
}
#[test]
fn test_global_prune_output_format() {
let repo = TestRepo::new();
let output = repo.cw(&["prune"]);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("Pruning") || stdout.contains("pruning"),
"Expected pruning header, got: {}",
stdout
);
}
#[test]
fn test_global_scan_exit_code_zero() {
let repo = TestRepo::new();
let output = repo.cw(&["scan"]);
assert_eq!(output.status.code(), Some(0));
}
#[test]
fn test_global_prune_exit_code_zero() {
let repo = TestRepo::new();
let output = repo.cw(&["prune"]);
assert_eq!(output.status.code(), Some(0));
}