use super::common::{init_test_git_repo, init_test_jj_repo, run_aiw, write_test_fence_json};
use googletest::prelude::*;
use std::process::Command;
type TestResult = Result<(), Box<dyn std::error::Error>>;
#[googletest::test]
fn workspace_creation_and_dry_run_in_real_git_repo_succeeds() -> TestResult {
let temp_dir = tempfile::tempdir()?;
let repo_root = temp_dir.path();
init_test_git_repo(repo_root);
write_test_fence_json(repo_root);
let output = run_aiw(repo_root, &["agy", "test-git-workspace", "--dry-run"]);
expect_that!(output.status.success(), is_true());
let ws_path = repo_root.join(".workspaces").join("test-git-workspace");
expect_that!(ws_path.exists(), is_true());
expect_that!(ws_path.join(".git").exists(), is_true());
let stdout = String::from_utf8_lossy(&output.stdout);
expect_that!(stdout.as_ref(), starts_with("fence "));
expect_that!(stdout.as_ref(), contains_substring("--settings"));
expect_that!(stdout.as_ref(), contains_substring("agy"));
expect_that!(
stdout.as_ref(),
contains_substring("--dangerously-skip-permissions")
);
let wt_list = Command::new("git")
.args(["--no-pager", "worktree", "list", "--porcelain"])
.current_dir(repo_root)
.output()?;
expect_that!(wt_list.status.success(), is_true());
let list_stdout = String::from_utf8_lossy(&wt_list.stdout);
expect_that!(
list_stdout.as_ref(),
contains_substring("test-git-workspace")
);
Ok(())
}
#[googletest::test]
fn idempotent_workspace_reuse_in_real_git_repo_succeeds() -> TestResult {
let temp_dir = tempfile::tempdir()?;
let repo_root = temp_dir.path();
init_test_git_repo(repo_root);
write_test_fence_json(repo_root);
let first_output = run_aiw(repo_root, &["agy", "reused-git-workspace", "--dry-run"]);
expect_that!(first_output.status.success(), is_true());
let ws_path = repo_root.join(".workspaces").join("reused-git-workspace");
expect_that!(ws_path.exists(), is_true());
expect_that!(ws_path.join(".git").exists(), is_true());
let second_output = run_aiw(repo_root, &["agy", "reused-git-workspace", "--dry-run"]);
expect_that!(second_output.status.success(), is_true());
let wt_list = Command::new("git")
.args(["--no-pager", "worktree", "list", "--porcelain"])
.current_dir(repo_root)
.output()?;
expect_that!(wt_list.status.success(), is_true());
let list_stdout = String::from_utf8_lossy(&wt_list.stdout);
expect_that!(
list_stdout.as_ref(),
contains_substring("reused-git-workspace")
);
Ok(())
}
#[googletest::test]
fn forget_subcommand_removes_workspace_from_git_worktree_list() -> TestResult {
let temp_dir = tempfile::tempdir()?;
let repo_root = temp_dir.path();
init_test_git_repo(repo_root);
write_test_fence_json(repo_root);
let create_output = run_aiw(repo_root, &["agy", "ws-to-forget-git", "--dry-run"]);
expect_that!(create_output.status.success(), is_true());
let ws_path = repo_root.join(".workspaces").join("ws-to-forget-git");
expect_that!(ws_path.exists(), is_true());
let list_before = Command::new("git")
.args(["--no-pager", "worktree", "list", "--porcelain"])
.current_dir(repo_root)
.output()?;
expect_that!(
String::from_utf8_lossy(&list_before.stdout).as_ref(),
contains_substring("ws-to-forget-git")
);
let forget_output = run_aiw(repo_root, &["forget", "ws-to-forget-git"]);
expect_that!(forget_output.status.success(), is_true());
let list_after = Command::new("git")
.args(["--no-pager", "worktree", "list", "--porcelain"])
.current_dir(repo_root)
.output()?;
expect_that!(
String::from_utf8_lossy(&list_after.stdout).as_ref(),
not(contains_substring("ws-to-forget-git"))
);
expect_that!(ws_path.exists(), is_false());
Ok(())
}
#[googletest::test]
fn git_repo_in_subdirectory_discovers_root_and_creates_workspace() -> TestResult {
let temp_dir = tempfile::tempdir()?;
let repo_root = temp_dir.path();
init_test_git_repo(repo_root);
write_test_fence_json(repo_root);
let sub = repo_root.join("deep").join("nested");
std::fs::create_dir_all(&sub)?;
let output = run_aiw(&sub, &["agy", "from-sub-git", "--dry-run"]);
expect_that!(output.status.success(), is_true());
let ws_path = repo_root.join(".workspaces").join("from-sub-git");
expect_that!(ws_path.exists(), is_true());
expect_that!(ws_path.join(".git").exists(), is_true());
Ok(())
}
#[googletest::test]
fn git_repo_nested_inside_jj_repo_identifies_git_root_and_creates_git_workspace() -> TestResult {
let temp_dir = tempfile::tempdir()?;
let outer_jj = temp_dir.path();
init_test_jj_repo(outer_jj);
let nested_git = outer_jj.join("sub_git_project");
std::fs::create_dir_all(&nested_git)?;
init_test_git_repo(&nested_git);
write_test_fence_json(&nested_git);
let out = run_aiw(&nested_git, &["agy", "nested-git-ws", "--dry-run"]);
expect_that!(out.status.success(), is_true());
let nested_ws = nested_git.join(".workspaces").join("nested-git-ws");
expect_that!(nested_ws.exists(), is_true());
expect_that!(nested_ws.join(".git").exists(), is_true());
expect_that!(outer_jj.join(".workspaces").exists(), is_false());
let wt_list = Command::new("git")
.args(["--no-pager", "worktree", "list", "--porcelain"])
.current_dir(&nested_git)
.output()?;
expect_that!(wt_list.status.success(), is_true());
let list_stdout = String::from_utf8_lossy(&wt_list.stdout);
expect_that!(list_stdout.as_ref(), contains_substring("nested-git-ws"));
let deep_nested = nested_git.join("src").join("components");
std::fs::create_dir_all(&deep_nested)?;
let deep_out = run_aiw(&deep_nested, &["agy", "from-deep-sub", "--dry-run"]);
expect_that!(deep_out.status.success(), is_true());
let deep_ws = nested_git.join(".workspaces").join("from-deep-sub");
expect_that!(deep_ws.exists(), is_true());
expect_that!(deep_ws.join(".git").exists(), is_true());
expect_that!(outer_jj.join(".workspaces").exists(), is_false());
Ok(())
}
#[googletest::test]
fn list_subcommand_in_git_repo_lists_all_workspaces() -> TestResult {
let temp_dir = tempfile::tempdir()?;
let repo_root = temp_dir.path();
init_test_git_repo(repo_root);
write_test_fence_json(repo_root);
let out_empty = run_aiw(repo_root, &["list"]);
expect_that!(out_empty.status.success(), is_true());
expect_that!(String::from_utf8_lossy(&out_empty.stdout).as_ref(), eq(""));
let out1 = run_aiw(repo_root, &["agy", "git-one", "--dry-run"]);
expect_that!(out1.status.success(), is_true());
let out2 = run_aiw(repo_root, &["agy", "git-two", "--dry-run"]);
expect_that!(out2.status.success(), is_true());
let out_list = run_aiw(repo_root, &["list"]);
expect_that!(out_list.status.success(), is_true());
expect_that!(
String::from_utf8_lossy(&out_list.stdout).as_ref(),
eq("git-one\ngit-two\n")
);
let out_ls = run_aiw(repo_root, &["ls"]);
expect_that!(out_ls.status.success(), is_true());
expect_that!(
String::from_utf8_lossy(&out_ls.stdout).as_ref(),
eq("git-one\ngit-two\n")
);
let ws_path = repo_root.join(".workspaces").join("git-one");
let out_from_ws = run_aiw(&ws_path, &["list"]);
expect_that!(out_from_ws.status.success(), is_true());
expect_that!(
String::from_utf8_lossy(&out_from_ws.stdout).as_ref(),
eq("git-one\ngit-two\n")
);
let out_forget = run_aiw(repo_root, &["forget", "git-one"]);
expect_that!(out_forget.status.success(), is_true());
let out_after_forget = run_aiw(repo_root, &["list"]);
expect_that!(out_after_forget.status.success(), is_true());
expect_that!(
String::from_utf8_lossy(&out_after_forget.stdout).as_ref(),
eq("git-two\n")
);
Ok(())
}