#![allow(clippy::unwrap_used)] #![allow(deprecated)]
use assert_cmd::Command;
use predicates::prelude::*;
use std::io::Write;
use tempfile::NamedTempFile;
fn aprender_shell() -> Command {
Command::cargo_bin("aprender-shell").expect("Failed to find aprender-shell binary")
}
fn create_temp_history(commands: &[&str]) -> NamedTempFile {
let mut file = NamedTempFile::new().expect("Failed to create temp file");
for cmd in commands {
writeln!(file, "{}", cmd).expect("Failed to write command");
}
file
}
fn create_zsh_history(commands: &[&str]) -> NamedTempFile {
let mut file = NamedTempFile::new().expect("Failed to create temp file");
for (i, cmd) in commands.iter().enumerate() {
writeln!(file, ": {}:0;{}", 1700000000 + i, cmd).expect("Failed to write command");
}
file
}
#[test]
fn test_cli_001_help_flag() {
aprender_shell()
.arg("--help")
.assert()
.success()
.stdout(predicate::str::contains("aprender-shell"))
.stdout(predicate::str::contains("AI-powered shell completion"));
}
#[test]
fn test_cli_001_version_flag() {
aprender_shell()
.arg("--version")
.assert()
.success()
.stdout(predicate::str::contains("aprender-shell"));
}
#[test]
fn test_cli_001_subcommand_help() {
aprender_shell()
.args(["train", "--help"])
.assert()
.success()
.stdout(predicate::str::contains("Train a model"));
}
#[test]
fn test_cli_002_train_basic() {
let history = create_temp_history(&[
"git status",
"git commit -m test",
"git push",
"cargo build",
"cargo test",
]);
let output = NamedTempFile::new().unwrap();
aprender_shell()
.args([
"train",
"-f",
history.path().to_str().unwrap(),
"-o",
output.path().to_str().unwrap(),
])
.assert()
.success()
.stdout(predicate::str::contains("Training"))
.stdout(predicate::str::contains("Model saved"));
}
#[test]
fn test_cli_002_train_filters_corrupted() {
let history = create_temp_history(&[
"git status",
"git commit-m test", "git push",
"cargo build-r", "cargo test",
]);
let output = NamedTempFile::new().unwrap();
aprender_shell()
.args([
"train",
"-f",
history.path().to_str().unwrap(),
"-o",
output.path().to_str().unwrap(),
])
.assert()
.success()
.stdout(predicate::str::contains("Commands loaded: 3")); }
#[test]
fn test_cli_002_train_zsh_format() {
let history = create_zsh_history(&["git status", "git commit -m test", "ls -la"]);
let output = NamedTempFile::new().unwrap();
aprender_shell()
.args([
"train",
"-f",
history.path().to_str().unwrap(),
"-o",
output.path().to_str().unwrap(),
])
.assert()
.success()
.stdout(predicate::str::contains("Commands loaded: 3"));
}
#[test]
fn test_cli_003_suggest_basic() {
let history = create_temp_history(&[
"git status",
"git status",
"git commit -m test",
"git push origin main",
]);
let model = NamedTempFile::new().unwrap();
aprender_shell()
.args([
"train",
"-f",
history.path().to_str().unwrap(),
"-o",
model.path().to_str().unwrap(),
])
.assert()
.success();
aprender_shell()
.args(["suggest", "git ", "-m", model.path().to_str().unwrap()])
.assert()
.success()
.stdout(predicate::str::contains("git status")); }
#[test]
fn test_cli_003_suggest_partial_token() {
let history = create_temp_history(&[
"git commit -m test",
"git checkout main",
"git clone url",
"git status",
]);
let model = NamedTempFile::new().unwrap();
aprender_shell()
.args([
"train",
"-f",
history.path().to_str().unwrap(),
"-o",
model.path().to_str().unwrap(),
])
.assert()
.success();
aprender_shell()
.args(["suggest", "git c", "-m", model.path().to_str().unwrap()])
.assert()
.success()
.stdout(predicate::str::contains("git c")); }
#[test]
fn test_cli_003_suggest_no_corrupted() {
let history = create_temp_history(&[
"git commit -m test",
"git commit-m broken", "git checkout main",
]);
let model = NamedTempFile::new().unwrap();
aprender_shell()
.args([
"train",
"-f",
history.path().to_str().unwrap(),
"-o",
model.path().to_str().unwrap(),
])
.assert()
.success();
aprender_shell()
.args(["suggest", "git co", "-m", model.path().to_str().unwrap()])
.assert()
.success()
.stdout(predicate::str::contains("commit-m").not());
}
#[test]
fn test_cli_004_stats() {
let history = create_temp_history(&["git status", "git commit -m test", "cargo build"]);
let model = NamedTempFile::new().unwrap();
aprender_shell()
.args([
"train",
"-f",
history.path().to_str().unwrap(),
"-o",
model.path().to_str().unwrap(),
])
.assert()
.success();
aprender_shell()
.args(["stats", "-m", model.path().to_str().unwrap()])
.assert()
.success()
.stdout(predicate::str::contains("N-gram size"))
.stdout(predicate::str::contains("Vocabulary size"));
}
#[test]
fn test_cli_005_validate() {
let history = create_temp_history(&[
"git status",
"git status",
"git commit -m test",
"git push",
"cargo build",
"cargo test",
"cargo run",
"ls -la",
"cd src",
"cat file.txt",
]);
aprender_shell()
.args(["validate", "-f", history.path().to_str().unwrap()])
.assert()
.success()
.stdout(predicate::str::contains("VALIDATION RESULTS"))
.stdout(predicate::str::contains("Hit@"));
}
#[test]
fn test_cli_006_augment_basic() {
let history = create_temp_history(&[
"git status",
"git commit -m test",
"git push origin main",
"cargo build --release",
"cargo test --all",
]);
let model = NamedTempFile::new().unwrap();
aprender_shell()
.args([
"augment",
"-f",
history.path().to_str().unwrap(),
"-o",
model.path().to_str().unwrap(),
"-a",
"0.5", ])
.assert()
.success()
.stdout(predicate::str::contains("Data Augmentation"))
.stdout(predicate::str::contains("Coverage"));
}
#[test]
fn test_cli_006_augment_with_diversity() {
let history = create_temp_history(&[
"git status",
"git commit -m test",
"git push",
"cargo build",
"cargo test",
]);
let model = NamedTempFile::new().unwrap();
aprender_shell()
.args([
"augment",
"-f",
history.path().to_str().unwrap(),
"-o",
model.path().to_str().unwrap(),
"--monitor-diversity",
])
.assert()
.success()
.stdout(predicate::str::contains("Diversity"));
}
#[test]
fn test_cli_007_missing_history_file() {
aprender_shell()
.args(["train", "-f", "/nonexistent/path/history"])
.assert()
.failure();
}
#[test]
fn test_cli_007_invalid_ngram_size() {
let history = create_temp_history(&["git status"]);
aprender_shell()
.args([
"train",
"-f",
history.path().to_str().unwrap(),
"-n",
"99", ])
.assert()
.failure() .stderr(predicate::str::contains("N-gram size must be between 2 and 5"));
}
#[test]
fn test_cli_008_zsh_widget() {
aprender_shell()
.arg("zsh-widget")
.assert()
.success()
.stdout(predicate::str::contains("aprender-shell ZSH widget"))
.stdout(predicate::str::contains("_aprender_suggest"))
.stdout(predicate::str::contains("bindkey"));
}
#[test]
fn test_cli_009_export_import_roundtrip() {
let history = create_temp_history(&["git status", "git commit -m test", "cargo build"]);
let model = NamedTempFile::new().unwrap();
let export_file = NamedTempFile::new().unwrap();
let imported_model = NamedTempFile::new().unwrap();
aprender_shell()
.args([
"train",
"-f",
history.path().to_str().unwrap(),
"-o",
model.path().to_str().unwrap(),
])
.assert()
.success();
aprender_shell()
.args([
"export",
export_file.path().to_str().unwrap(),
"-m",
model.path().to_str().unwrap(),
])
.assert()
.success()
.stdout(predicate::str::contains("exported"));
aprender_shell()
.args([
"import",
export_file.path().to_str().unwrap(),
"-o",
imported_model.path().to_str().unwrap(),
])
.assert()
.success()
.stdout(predicate::str::contains("imported"));
}
include!("parts/cli_integration_010.rs");
include!("parts/cli_integration_017.rs");
include!("parts/cli_integration_021.rs");