use std::process::Command;
#[test]
fn test_help_command() {
let output = Command::new("cargo")
.args(&["run", "--", "--help"])
.output()
.expect("Failed to execute help command");
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(stdout.contains("For devs who code like ninjas but commit like toddlers"));
assert!(stdout.contains("🤡"));
assert!(stdout.contains("nc"));
assert!(stdout.contains("setup-alias"));
assert!(stdout.contains("YOLO mode"));
assert!(stdout.contains("-b, --br-huehuehue"));
}
#[test]
fn test_version_command() {
let output = Command::new("cargo")
.args(&["run", "--", "--version"])
.output()
.expect("Failed to execute version command");
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(stdout.contains("Noob Commit"));
assert!(stdout.contains("0.6.1"));
}
#[test]
fn test_dry_run_without_openai_key() {
let output = Command::new("cargo")
.args(&["run", "--", "--dry-run"])
.env_remove("OPENAI_API_KEY")
.output()
.expect("Failed to execute dry-run command");
let stderr = String::from_utf8(output.stderr).unwrap();
assert!(stderr.contains("forgot to set OPENAI_API_KEY"));
assert!(stderr.contains("🔑"));
assert!(stderr.contains("platform.openai.com"));
}
#[test]
fn test_non_git_directory() {
let temp_dir = std::env::temp_dir().join(format!("noob-commit-test-{}", std::process::id()));
std::fs::create_dir_all(&temp_dir).unwrap();
if temp_dir.join(".git").exists() {
std::fs::remove_dir_all(temp_dir.join(".git")).ok();
}
let binary_path = std::env::current_dir()
.unwrap()
.join("target")
.join("debug")
.join("noob-commit");
let output = Command::new(&binary_path)
.args(&["--dry-run"])
.current_dir(&temp_dir)
.env("OPENAI_API_KEY", "test-key")
.output()
.expect("Failed to execute command");
let stderr = String::from_utf8(output.stderr).unwrap();
let valid_errors = stderr.contains("isn't a git repo")
|| stderr.contains("Nothing to commit")
|| stderr.contains("🙈")
|| stderr.contains("🤷")
|| stderr.contains("API key")
|| stderr.contains("invalid_api_key")
|| stderr.contains("Trimming git diff");
assert!(
valid_errors,
"Expected git repo error, no files error, or API error, got: {}",
stderr
);
std::fs::remove_dir_all(&temp_dir).ok();
}
#[cfg(test)]
mod cli_tests {
use std::process::Command;
fn run_noob_commit(args: &[&str]) -> std::process::Output {
Command::new("cargo")
.arg("run")
.arg("--")
.args(args)
.output()
.expect("Failed to execute noob-commit")
}
#[test]
fn test_all_flags_present() {
let output = run_noob_commit(&["--help"]);
let stdout = String::from_utf8(output.stdout).unwrap();
let expected_flags = [
"-d, --dry-run",
"-r, --review",
"-f, --force",
"-e, --ok-to-send-env",
"-p, --no-push",
"-t, --max-tokens",
"-i, --max-input-chars",
"-m, --model",
"-s, --setup-alias",
"-M, --yes-to-modules",
"-c, --yes-to-crap",
"-b, --br-huehuehue",
"-a, --no-f-ads",
"-u, --update",
];
for flag in &expected_flags {
assert!(stdout.contains(flag), "Missing flag: {}", flag);
}
}
#[test]
fn test_emoji_usage() {
let output = run_noob_commit(&["--help"]);
let stdout = String::from_utf8(output.stdout).unwrap();
let expected_emojis = ["🤡", "🔍", "✏️", "⚡", "🔓", "📦", "🤖", "🧠", "🛠️", "🗑️"];
for emoji in &expected_emojis {
assert!(stdout.contains(emoji), "Missing emoji: {}", emoji);
}
}
#[test]
fn test_default_values() {
let output = run_noob_commit(&["--help"]);
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(stdout.contains("gpt-4.1-nano"));
assert!(stdout.contains("2000"));
assert!(stdout.contains("50000")); }
#[test]
fn test_max_input_chars_flag() {
let output = run_noob_commit(&["--help"]);
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(stdout.contains("-i, --max-input-chars"));
assert!(stdout.contains("Maximum characters of git diff to send to AI"));
}
}
#[test]
fn test_max_input_chars_truncation() {
use std::fs::{self, File};
use std::io::Write;
let temp_dir = std::env::temp_dir().join(format!("noob-commit-test-{}", std::process::id()));
fs::create_dir_all(&temp_dir).unwrap();
Command::new("git")
.args(&["init"])
.current_dir(&temp_dir)
.output()
.expect("Failed to init git repo");
Command::new("git")
.args(&["config", "user.email", "test@example.com"])
.current_dir(&temp_dir)
.output()
.expect("Failed to set git email");
Command::new("git")
.args(&["config", "user.name", "Test User"])
.current_dir(&temp_dir)
.output()
.expect("Failed to set git name");
let large_content = "a".repeat(100000); let file_path = temp_dir.join("large_file.txt");
let mut file = File::create(&file_path).unwrap();
writeln!(file, "{}", large_content).unwrap();
Command::new("git")
.args(&["add", "."])
.current_dir(&temp_dir)
.output()
.expect("Failed to add files");
Command::new("git")
.args(&["commit", "-m", "Initial commit"])
.current_dir(&temp_dir)
.output()
.expect("Failed to commit");
let mut file = File::create(&file_path).unwrap();
writeln!(file, "{}", "b".repeat(100000)).unwrap();
Command::new("git")
.args(&["add", "."])
.current_dir(&temp_dir)
.output()
.expect("Failed to add files");
let diff_output = Command::new("git")
.args(&["diff", "--staged"])
.current_dir(&temp_dir)
.output()
.expect("Failed to get diff");
let diff_size = diff_output.stdout.len();
println!("Diff size: {} bytes", diff_size);
let binary_path = std::env::current_dir()
.unwrap()
.join("target")
.join("debug")
.join("noob-commit");
let output = Command::new(&binary_path)
.args(&["--dry-run", "--max-input-chars", "0"])
.current_dir(&temp_dir)
.env("OPENAI_API_KEY", "test-key")
.output()
.expect("Failed to execute command");
let stderr = String::from_utf8(output.stderr).unwrap();
assert!(!stderr.contains("unexpected argument"));
let output = Command::new(&binary_path)
.args(&["--dry-run", "--max-input-chars", "100"])
.current_dir(&temp_dir)
.env("OPENAI_API_KEY", "test-key")
.output()
.expect("Failed to execute command");
let stderr = String::from_utf8(output.stderr).unwrap();
assert!(!stderr.contains("unexpected argument"));
fs::remove_dir_all(&temp_dir).ok();
}