#![cfg(test)]
use assert_cmd::Command;
use std::fs;
use std::process::Command as StdCommand;
use tempfile::TempDir;
fn setup_git_repo_with_real_changes() -> TempDir {
let temp_dir = TempDir::new().unwrap();
let repo_path = temp_dir.path();
StdCommand::new("git")
.arg("init")
.current_dir(repo_path)
.status()
.expect("Failed to init git repo");
StdCommand::new("git")
.args(["config", "user.name", "Test User"])
.current_dir(repo_path)
.status()
.expect("Failed to configure git user name");
StdCommand::new("git")
.args(["config", "user.email", "test@example.com"])
.current_dir(repo_path)
.status()
.expect("Failed to configure git user email");
fs::write(
repo_path.join("main.rs"),
r#"fn main() {
println!("Hello, world!");
}
"#,
)
.unwrap();
fs::write(
repo_path.join("lib.rs"),
r#"pub fn add(a: i32, b: i32) -> i32 {
a + b
}
"#,
)
.unwrap();
StdCommand::new("git")
.args(["add", "."])
.current_dir(repo_path)
.status()
.expect("Failed to git add");
StdCommand::new("git")
.args(["commit", "-m", "Initial commit"])
.current_dir(repo_path)
.status()
.expect("Failed to create first commit");
fs::write(
repo_path.join("main.rs"),
r#"fn main() {
println!("Hello, Rust world!");
println!("This is a change!");
}
"#,
)
.unwrap();
fs::write(
repo_path.join("lib.rs"),
r#"pub fn add(a: i32, b: i32) -> i32 {
a + b
}
pub fn multiply(a: i32, b: i32) -> i32 {
a * b
}
"#,
)
.unwrap();
fs::write(
repo_path.join("new_file.rs"),
r#"pub struct NewStruct {
pub field: String,
}
"#,
)
.unwrap();
StdCommand::new("git")
.args(["add", "."])
.current_dir(repo_path)
.status()
.expect("Failed to git add second commit");
StdCommand::new("git")
.args(["commit", "-m", "Add new functionality"])
.current_dir(repo_path)
.status()
.expect("Failed to create second commit");
temp_dir
}
#[test]
fn test_diff_command_should_output_file_contents_not_placeholder() {
let repo = setup_git_repo_with_real_changes();
let mut cmd = Command::cargo_bin("context-creator").unwrap();
let output = cmd
.current_dir(repo.path())
.args(["diff", "HEAD~1", "HEAD"])
.output()
.unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("Hello, Rust world!"),
"Expected actual file contents from main.rs changes, got: {stdout}"
);
assert!(
stdout.contains("pub fn multiply"),
"Expected actual file contents from lib.rs changes, got: {stdout}"
);
assert!(
stdout.contains("pub struct NewStruct"),
"Expected actual file contents from new_file.rs, got: {stdout}"
);
assert!(
!stdout.contains("Diff command not yet implemented"),
"Should not contain placeholder message, but got: {stdout}"
);
}
#[test]
fn test_diff_command_should_respect_token_limits() {
let repo = setup_git_repo_with_real_changes();
let mut cmd = Command::cargo_bin("context-creator").unwrap();
let output = cmd
.current_dir(repo.path())
.args(["--max-tokens", "100", "diff", "HEAD~1", "HEAD"])
.output()
.unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("Context Statistics")
|| stdout.contains("Files processed")
|| stdout.contains("Estimated tokens"),
"Expected token management integration, got: {stdout}"
);
assert!(
!stdout.contains("Diff command not yet implemented"),
"Should have functional diff with token management, got: {stdout}"
);
}
#[test]
fn test_diff_command_should_generate_proper_markdown() {
let repo = setup_git_repo_with_real_changes();
let mut cmd = Command::cargo_bin("context-creator").unwrap();
let output = cmd
.current_dir(repo.path())
.args(["diff", "HEAD~1", "HEAD"])
.output()
.unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("# ") || stdout.contains("## "),
"Expected markdown headers, got: {stdout}"
);
assert!(
stdout.contains("```rust") || stdout.contains("```"),
"Expected code blocks for changed files, got: {stdout}"
);
assert!(
stdout.contains("main.rs") && stdout.contains("lib.rs") && stdout.contains("new_file.rs"),
"Expected all changed files to be listed, got: {stdout}"
);
}
#[test]
fn test_diff_command_should_include_semantic_analysis() {
let repo = setup_git_repo_with_real_changes();
let mut cmd = Command::cargo_bin("context-creator").unwrap();
let output = cmd
.current_dir(repo.path())
.args(["--trace-imports", "diff", "HEAD~1", "HEAD"])
.output()
.unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("Dependencies:")
|| stdout.contains("Imports:")
|| stdout.contains("# Semantic Analysis")
|| stdout.contains("## Semantic Analysis")
|| stdout.contains("*Semantic analysis integration is in development*"),
"Expected semantic analysis integration, got: {stdout}"
);
assert!(
!stdout.contains("Diff command not yet implemented"),
"Should have functional diff with semantic analysis, got: {stdout}"
);
}
#[test]
fn test_diff_command_should_save_to_output_file() {
let repo = setup_git_repo_with_real_changes();
let output_file = repo.path().join("diff_output.md");
let mut cmd = Command::cargo_bin("context-creator").unwrap();
let result = cmd
.current_dir(repo.path())
.args(["--output-file", "diff_output.md", "diff", "HEAD~1", "HEAD"])
.output()
.unwrap();
if !result.status.success() {
let stderr_msg = String::from_utf8_lossy(&result.stderr);
panic!("Command failed with stderr: {stderr_msg}");
}
assert!(
output_file.exists(),
"Expected output file to be created at: {output_file:?}"
);
let file_content = fs::read_to_string(&output_file).unwrap();
assert!(
file_content.contains("Hello, Rust world!") || file_content.contains("pub fn multiply"),
"Expected actual diff content in output file, got: {file_content}"
);
assert!(
!file_content.contains("Diff command not yet implemented"),
"Output file should contain actual diff, not placeholder: {file_content}"
);
}
#[test]
fn test_diff_command_should_show_change_statistics() {
let repo = setup_git_repo_with_real_changes();
let mut cmd = Command::cargo_bin("context-creator").unwrap();
let output = cmd
.current_dir(repo.path())
.args(["diff", "HEAD~1", "HEAD"])
.output()
.unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("files changed")
|| stdout.contains("insertions")
|| stdout.contains("deletions")
|| stdout.contains("Files changed")
|| stdout.contains("Lines added")
|| stdout.contains("Lines removed"),
"Expected change statistics, got: {stdout}"
);
assert!(
stdout.contains("3") && (stdout.contains("file") || stdout.contains("File")),
"Expected to show 3 files changed, got: {stdout}"
);
}