use std::fs;
use std::process::Command;
use callisto_cli::cli::{
AddArgs, GlobalArgs, InitArgs, OutputFormat, PlanPublishArgs, StatusArgs, VersionArgs,
};
use callisto_cli::commands;
use tempfile::tempdir;
fn setup_polyglot_git_repo() -> tempfile::TempDir {
let dir = tempdir().unwrap();
let root = dir.path();
let status = Command::new("git")
.args(["init"])
.current_dir(root)
.status()
.unwrap();
assert!(status.success());
Command::new("git")
.args(["config", "user.name", "Callisto Tester"])
.current_dir(root)
.status()
.unwrap();
Command::new("git")
.args(["config", "user.email", "tester@callisto.dev"])
.current_dir(root)
.status()
.unwrap();
let cargo_toml = r#"[workspace]
members = ["crates/core"]
resolver = "2"
"#;
fs::write(root.join("Cargo.toml"), cargo_toml).unwrap();
fs::create_dir_all(root.join("crates/core/src")).unwrap();
let crate_toml = r#"[package]
name = "core-crate"
version = "0.1.0"
edition = "2021"
"#;
fs::write(root.join("crates/core/Cargo.toml"), crate_toml).unwrap();
fs::write(root.join("crates/core/src/lib.rs"), "pub fn hello() {}\n").unwrap();
fs::create_dir_all(root.join("packages/web")).unwrap();
let pkg_json = r#"{
"name": "@myorg/web-app",
"version": "1.0.0"
}
"#;
fs::write(root.join("packages/web/package.json"), pkg_json).unwrap();
Command::new("git")
.args(["add", "."])
.current_dir(root)
.status()
.unwrap();
Command::new("git")
.args(["commit", "-m", "Initial commit"])
.current_dir(root)
.status()
.unwrap();
dir
}
#[test]
fn test_full_polyglot_workspace_release_lifecycle() {
let dir = setup_polyglot_git_repo();
let root = dir.path();
let global = GlobalArgs {
format: OutputFormat::Json,
cwd: root.to_path_buf(),
dry_run: false,
};
let init_res = commands::init::handle(InitArgs { yes: true }, &global);
assert!(init_res.is_ok());
assert!(root.join("callisto.toml").exists());
let add_res = commands::add::handle(
AddArgs {
packages: vec![
"core-crate:minor".to_string(),
"@myorg/web-app:patch".to_string(),
],
summary: Some("Polyglot release feature update".to_string()),
},
&global,
);
assert!(add_res.is_ok());
assert!(root.join(".changeset").exists());
let status_res = commands::status::handle(
StatusArgs {
strict: false,
strict_graph: false,
check: false,
},
&global,
);
assert!(status_res.is_ok());
let version_res = commands::version::handle(
VersionArgs {
refresh_lockfiles: false,
strict: false,
strict_graph: false,
allow_empty_changesets: false,
},
&global,
);
assert!(version_res.is_ok());
let updated_cargo = fs::read_to_string(root.join("crates/core/Cargo.toml")).unwrap();
assert!(updated_cargo.contains("version = \"0.2.0\""));
let updated_pkg = fs::read_to_string(root.join("packages/web/package.json")).unwrap();
assert!(updated_pkg.contains("\"version\": \"1.0.1\""));
let plan_res = commands::plan_publish::handle(PlanPublishArgs {}, &global);
assert!(plan_res.is_ok());
}
#[test]
fn test_pre_mode_blackbox_lifecycle() {
use callisto_cli::cli::PreArgs;
let dir = setup_polyglot_git_repo();
let root = dir.path();
let global = GlobalArgs {
format: OutputFormat::Json,
cwd: root.to_path_buf(),
dry_run: false,
};
let enter_res = commands::pre::handle(
PreArgs::Enter {
tag: "beta".to_string(),
},
&global,
);
assert!(enter_res.is_ok());
assert!(root.join(".changeset/pre.json").exists());
let add_res = commands::add::handle(
AddArgs {
packages: vec!["core-crate:minor".to_string()],
summary: Some("Beta feature".to_string()),
},
&global,
);
assert!(add_res.is_ok());
let version_res = commands::version::handle(
VersionArgs {
refresh_lockfiles: false,
strict: false,
strict_graph: false,
allow_empty_changesets: false,
},
&global,
);
assert!(version_res.is_ok());
let updated_cargo = fs::read_to_string(root.join("crates/core/Cargo.toml")).unwrap();
assert!(updated_cargo.contains("0.2.0-beta.0"));
let exit_res = commands::pre::handle(PreArgs::Exit, &global);
assert!(exit_res.is_ok());
let final_version_res = commands::version::handle(
VersionArgs {
refresh_lockfiles: false,
strict: false,
strict_graph: false,
allow_empty_changesets: true,
},
&global,
);
assert!(final_version_res.is_ok());
let final_cargo = fs::read_to_string(root.join("crates/core/Cargo.toml")).unwrap();
assert!(final_cargo.contains("0.2.0"));
assert!(!root.join(".changeset/pre.json").exists());
}
#[test]
fn test_cst_comment_preservation_on_version_bump() {
let dir = setup_polyglot_git_repo();
let root = dir.path();
let cargo_toml = r#"[package]
name = "core-crate"
version = "0.1.0" # Important inline comment
# Important section comment
edition = "2021"
"#;
fs::write(root.join("crates/core/Cargo.toml"), cargo_toml).unwrap();
let global = GlobalArgs {
format: OutputFormat::Json,
cwd: root.to_path_buf(),
dry_run: false,
};
commands::add::handle(
AddArgs {
packages: vec!["core-crate:patch".to_string()],
summary: Some("Patch update".to_string()),
},
&global,
)
.unwrap();
commands::version::handle(
VersionArgs {
refresh_lockfiles: false,
strict: false,
strict_graph: false,
allow_empty_changesets: false,
},
&global,
)
.unwrap();
let updated_cargo = fs::read_to_string(root.join("crates/core/Cargo.toml")).unwrap();
assert!(updated_cargo.contains("version = \"0.1.1\""));
assert!(updated_cargo.contains("# Important inline comment"));
assert!(updated_cargo.contains("# Important section comment"));
}
#[test]
fn test_compose_pr_body_before_version_and_subpkg_changelog() {
let dir = setup_polyglot_git_repo();
let root = dir.path();
let global = GlobalArgs {
format: OutputFormat::Text,
cwd: root.to_path_buf(),
dry_run: false,
};
commands::add::handle(
AddArgs {
packages: vec!["core-crate:minor".to_string()],
summary: Some("Add new core component API".to_string()),
},
&global,
)
.unwrap();
let compose_res = commands::compose_pr_body::handle(
callisto_cli::cli::ComposePrBodyArgs {
existing_body: None,
labels: Vec::new(),
branch: None,
},
&global,
);
assert!(compose_res.is_ok());
commands::version::handle(
VersionArgs {
refresh_lockfiles: false,
strict: false,
strict_graph: false,
allow_empty_changesets: false,
},
&global,
)
.unwrap();
let changelog_path = root.join("crates/core/CHANGELOG.md");
assert!(
changelog_path.exists(),
"crates/core/CHANGELOG.md must exist!"
);
let changelog_content = fs::read_to_string(&changelog_path).unwrap();
assert!(changelog_content.contains("0.2.0"));
}
#[test]
fn test_dry_run_flag_preserves_disk_state() {
let dir = setup_polyglot_git_repo();
let root = dir.path();
let global_dry = GlobalArgs {
format: OutputFormat::Text,
cwd: root.to_path_buf(),
dry_run: true,
};
commands::add::handle(
AddArgs {
packages: vec!["core-crate:patch".to_string()],
summary: Some("Dry run test patch".to_string()),
},
&global_dry,
)
.unwrap();
let version_res = commands::version::handle(
VersionArgs {
refresh_lockfiles: false,
strict: false,
strict_graph: false,
allow_empty_changesets: false,
},
&global_dry,
);
assert!(version_res.is_ok());
let cargo_content = fs::read_to_string(root.join("crates/core/Cargo.toml")).unwrap();
assert!(cargo_content.contains("version = \"0.1.0\""));
}