use std::fs;
use std::process::Command;
use tempfile::TempDir;
fn git(dir: &std::path::Path, args: &[&str]) -> bool {
Command::new("git")
.current_dir(dir)
.args(args)
.status()
.map(|s| s.success())
.unwrap_or(false)
}
fn create_test_repo(dir: &std::path::Path) {
git(dir, &["init", "-b", "main"]);
git(dir, &["config", "user.email", "test@example.com"]);
git(dir, &["config", "user.name", "Test User"]);
fs::write(dir.join("README.md"), "# Test Repo\n").unwrap();
git(dir, &["add", "."]);
git(dir, &["commit", "-m", "Initial commit"]);
}
fn create_test_workspace(temp: &TempDir) -> std::path::PathBuf {
let workspace = temp.path().to_path_buf();
let manifest_dir = workspace.join(".gitgrip").join("manifests");
fs::create_dir_all(&manifest_dir).unwrap();
let repo1 = workspace.join("repo1");
fs::create_dir_all(&repo1).unwrap();
create_test_repo(&repo1);
let repo2 = workspace.join("repo2");
fs::create_dir_all(&repo2).unwrap();
create_test_repo(&repo2);
let manifest = format!(
r#"version: 1
repos:
repo1:
url: file://{}
path: repo1
default_branch: main
repo2:
url: file://{}
path: repo2
default_branch: main
"#,
repo1.display(),
repo2.display()
);
fs::write(manifest_dir.join("manifest.yaml"), manifest).unwrap();
workspace
}
#[test]
fn test_manifest_parsing() {
use gitgrip::core::manifest::Manifest;
let manifest = r#"
version: 1
repos:
app:
url: git@github.com:user/app.git
path: app
default_branch: main
lib:
url: git@github.com:user/lib.git
path: lib
"#;
let result = Manifest::parse(manifest);
assert!(result.is_ok(), "Manifest should parse successfully");
let manifest = result.unwrap();
assert_eq!(manifest.repos.len(), 2, "Should have 2 repos");
assert!(manifest.repos.contains_key("app"), "Should have app repo");
assert!(manifest.repos.contains_key("lib"), "Should have lib repo");
}
#[test]
fn test_state_parsing() {
use gitgrip::core::state::StateFile;
let state_json = r#"{
"currentManifestPr": 42,
"branchToPr": {
"feat/test": 42
},
"prLinks": {}
}"#;
let result = StateFile::parse(state_json);
assert!(result.is_ok(), "State should parse successfully");
let state = result.unwrap();
assert_eq!(state.current_manifest_pr, Some(42));
assert_eq!(state.get_pr_for_branch("feat/test"), Some(42));
}
#[test]
#[ignore = "Requires local file:// URL support"]
fn test_local_workspace_status() {
let temp = TempDir::new().unwrap();
let workspace = create_test_workspace(&temp);
let output = Command::new(env!("CARGO_BIN_EXE_gr"))
.current_dir(&workspace)
.arg("status")
.output()
.expect("Failed to execute gr status");
let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stdout.contains("repo1") || stderr.contains("repo"),
"Should show repos in output. stdout: {}, stderr: {}",
stdout,
stderr
);
}
#[test]
#[ignore = "Requires local file:// URL support"]
fn test_local_branch_creation() {
let temp = TempDir::new().unwrap();
let workspace = create_test_workspace(&temp);
let output = Command::new(env!("CARGO_BIN_EXE_gr"))
.current_dir(&workspace)
.args(["branch", "feat/test-branch"])
.output()
.expect("Failed to execute gr branch");
assert!(output.status.success(), "gr branch should succeed");
}
#[test]
#[ignore = "Requires local file:// URL support"]
fn test_local_add_commit() {
let temp = TempDir::new().unwrap();
let workspace = create_test_workspace(&temp);
let _ = Command::new(env!("CARGO_BIN_EXE_gr"))
.current_dir(&workspace)
.args(["branch", "feat/changes"])
.output();
fs::write(workspace.join("repo1").join("new.txt"), "new file").unwrap();
let _ = Command::new(env!("CARGO_BIN_EXE_gr"))
.current_dir(&workspace)
.args(["add", "."])
.output();
let output = Command::new(env!("CARGO_BIN_EXE_gr"))
.current_dir(&workspace)
.args(["commit", "-m", "Add new file"])
.output()
.expect("Failed to commit");
assert!(output.status.success(), "gr commit should succeed");
}