mod common;
use tempfile::TempDir;
use gitgrip::core::griptree::GriptreeConfig;
use common::fixtures::WorkspaceBuilder;
#[test]
fn test_invalid_yaml_manifest() {
let result = gitgrip::core::manifest::Manifest::parse("{{{{not yaml");
assert!(result.is_err(), "should fail on invalid YAML");
}
#[test]
fn test_empty_repos_manifest() {
let yaml = "version: 1\nrepos:\n";
let result = gitgrip::core::manifest::Manifest::parse(yaml);
assert!(result.is_err(), "should fail with empty repos");
}
#[test]
fn test_manifest_missing_url() {
let yaml = r#"
version: 1
repos:
myrepo:
path: myrepo
default_branch: main
"#;
let result = gitgrip::core::manifest::Manifest::parse(yaml);
assert!(
result.is_err(),
"should fail when repo is missing URL field"
);
}
#[test]
fn test_manifest_path_traversal() {
let yaml = r#"
version: 1
repos:
evil:
url: https://github.com/test/repo.git
path: ../../etc/passwd
default_branch: main
"#;
let result = gitgrip::core::manifest::Manifest::parse(yaml);
assert!(result.is_err(), "should reject path traversal");
let err = result.unwrap_err().to_string();
assert!(
err.contains("Path escapes") || err.contains("traversal") || err.contains("boundary"),
"error should mention path escaping: {}",
err
);
}
#[test]
fn test_invalid_griptree_config() {
let temp = TempDir::new().unwrap();
let workspace_root = temp.path().join("workspace");
std::fs::create_dir_all(workspace_root.join(".gitgrip")).unwrap();
std::fs::write(
workspace_root.join(".gitgrip").join("griptree.json"),
"{invalid json",
)
.unwrap();
let result = gitgrip::core::griptree::GriptreeConfig::load_from_workspace(&workspace_root);
assert!(result.is_err(), "invalid griptree config should error");
}
#[test]
fn test_invalid_griptree_upstream_format() {
let temp = TempDir::new().unwrap();
let workspace_root = temp.path().join("workspace");
std::fs::create_dir_all(workspace_root.join(".gitgrip")).unwrap();
let mut config = GriptreeConfig::new("feat/griptree", "/workspace");
config
.repo_upstreams
.insert("app".to_string(), "main".to_string());
config
.save(&workspace_root.join(".gitgrip").join("griptree.json"))
.unwrap();
let config = GriptreeConfig::load_from_workspace(&workspace_root)
.unwrap()
.unwrap();
let result = config.upstream_for_repo("app", "main");
assert!(result.is_err(), "invalid upstream should return an error");
}
#[test]
fn test_status_with_missing_repo() {
let ws = WorkspaceBuilder::new()
.add_repo("app")
.add_repo("broken")
.build();
std::fs::remove_dir_all(ws.repo_path("broken")).unwrap();
let manifest = ws.load_manifest();
let result = gitgrip::cli::commands::status::run_status(
&ws.workspace_root,
&manifest,
false,
false,
None,
None,
false,
);
assert!(
result.is_ok(),
"status should handle missing repos gracefully: {:?}",
result.err()
);
}
#[test]
fn test_commit_with_no_staged_changes() {
let ws = WorkspaceBuilder::new().add_repo("app").build();
let manifest = ws.load_manifest();
let result = gitgrip::cli::commands::commit::run_commit(
&ws.workspace_root,
&manifest,
"should not commit",
false,
false,
None,
None,
);
assert!(
result.is_ok(),
"commit with no changes should not error: {:?}",
result.err()
);
}
#[test]
fn test_checkout_nonexistent_branch() {
let ws = WorkspaceBuilder::new().add_repo("app").build();
let manifest = ws.load_manifest();
let result = gitgrip::cli::commands::checkout::run_checkout(
&ws.workspace_root,
&manifest,
"nonexistent-branch",
false,
None,
None,
);
assert!(
result.is_ok(),
"checkout nonexistent branch should not crash: {:?}",
result.err()
);
}
#[test]
fn test_branch_already_exists() {
let ws = WorkspaceBuilder::new().add_repo("app").build();
let manifest = ws.load_manifest();
gitgrip::cli::commands::branch::run_branch(gitgrip::cli::commands::branch::BranchOptions {
workspace_root: &ws.workspace_root,
manifest: &manifest,
name: Some("feat/exists"),
delete: false,
move_commits: false,
repos_filter: None,
group_filter: None,
json: false,
})
.unwrap();
gitgrip::cli::commands::checkout::run_checkout(
&ws.workspace_root,
&manifest,
"main",
false,
None,
None,
)
.unwrap();
let result =
gitgrip::cli::commands::branch::run_branch(gitgrip::cli::commands::branch::BranchOptions {
workspace_root: &ws.workspace_root,
manifest: &manifest,
name: Some("feat/exists"),
delete: false,
move_commits: false,
repos_filter: None,
group_filter: None,
json: false,
});
assert!(
result.is_ok(),
"creating existing branch should not crash: {:?}",
result.err()
);
}
#[tokio::test]
async fn test_sync_with_deleted_remote() {
let ws = WorkspaceBuilder::new().add_repo("app").build();
std::fs::remove_dir_all(ws.remote_path("app")).unwrap();
let manifest = ws.load_manifest();
let result = gitgrip::cli::commands::sync::run_sync(
&ws.workspace_root,
&manifest,
false,
false,
None,
None,
false,
false,
false,
false,
)
.await;
match &result {
Ok(_) => {} Err(e) => {
let msg = e.to_string();
assert!(
!msg.is_empty(),
"sync error should have a descriptive message"
);
}
}
}
#[test]
fn test_push_on_main_nothing_to_push() {
let ws = WorkspaceBuilder::new().add_repo("app").build();
let manifest = ws.load_manifest();
let result = gitgrip::cli::commands::push::run_push(
&ws.workspace_root,
&manifest,
false,
false,
false,
false,
None,
None,
);
assert!(
result.is_ok(),
"push with nothing should succeed: {:?}",
result.err()
);
}
#[test]
fn test_forall_with_nonexistent_command() {
let ws = WorkspaceBuilder::new()
.add_repo("app")
.add_repo("lib")
.build();
let manifest = ws.load_manifest();
let result = gitgrip::cli::commands::forall::run_forall(
&ws.workspace_root,
&manifest,
"nonexistent-command-that-doesnt-exist-12345",
false, false, false, None,
None,
);
match &result {
Ok(_) => {} Err(e) => {
let msg = e.to_string();
assert!(
!msg.is_empty(),
"forall error should have a descriptive message"
);
}
}
}
#[test]
fn test_add_with_no_changes() {
let ws = WorkspaceBuilder::new().add_repo("app").build();
let manifest = ws.load_manifest();
let files = vec![".".to_string()];
let result =
gitgrip::cli::commands::add::run_add(&ws.workspace_root, &manifest, &files, None, None);
assert!(
result.is_ok(),
"add with no changes should succeed: {:?}",
result.err()
);
}
#[test]
fn test_detect_platform_unknown_url() {
let platform = gitgrip::platform::detect_platform("https://unknown-host.example.com/repo.git");
assert_eq!(platform, gitgrip::core::manifest::PlatformType::GitHub);
}
#[test]
fn test_detect_platform_file_url() {
let platform = gitgrip::platform::detect_platform("file:///tmp/repo.git");
assert_eq!(platform, gitgrip::core::manifest::PlatformType::GitHub);
}