ntu/tests/integration_tests.rs
dschlueter 2ec4d12d6c Implement sequences feature v1.1.0
- Add -s/--sequence option to select transformation sequences
- Add -L flag to list all available sequences
- Implement 5 hardcoded sequences: default, lower, upper, minimal, utf-8
- Refactor clean_filename() to support sequence-based transformations
- Update all tests to pass sequence parameter (25 tests passing)
- Add 8 new integration tests for sequence functionality
- Update documentation (README, CHANGELOG, manpage)
- Update shell completions (bash, zsh, fish)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 18:38:23 +01:00

391 lines
12 KiB
Rust

use assert_cmd::assert::OutputAssertExt;
use assert_cmd::cargo::cargo_bin;
use predicates::prelude::*;
use std::fs;
use std::process::Command;
use tempfile::TempDir;
#[test]
fn test_help_flag() {
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("--help");
cmd.assert()
.success()
.stdout(predicate::str::contains("Usage: ntu"));
}
#[test]
fn test_version_flag() {
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("--version");
cmd.assert()
.success()
.stdout(predicate::str::contains("NameToUnix"));
}
#[test]
fn test_dry_run_no_changes() {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join("test file.txt");
fs::write(&file_path, "test content").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("--dry-run").arg("-r").arg(temp_dir.path());
cmd.assert().success();
// File should still have spaces (not renamed)
assert!(file_path.exists());
assert!(!temp_dir.path().join("test_file.txt").exists());
}
#[test]
fn test_actual_rename() {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join("test file.txt");
fs::write(&file_path, "test content").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("-r").arg(temp_dir.path());
cmd.assert().success();
// File should be renamed
assert!(!file_path.exists());
assert!(temp_dir.path().join("test_file.txt").exists());
}
#[test]
fn test_hidden_files_preserved() {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join(".gitignore");
fs::write(&file_path, "*.tmp").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("-r").arg(temp_dir.path());
cmd.assert().success();
// Hidden file should not be renamed
assert!(file_path.exists());
}
#[test]
fn test_hidden_file_with_spaces() {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join(".my config");
fs::write(&file_path, "config content").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("-r").arg(temp_dir.path());
cmd.assert().success();
// Hidden file should be renamed but keep leading dot
assert!(!file_path.exists());
assert!(temp_dir.path().join(".my_config").exists());
}
#[test]
fn test_umlaut_conversion() {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join("Müller.txt");
fs::write(&file_path, "test").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("-r").arg(temp_dir.path());
cmd.assert().success();
// Umlaut should be converted
assert!(!file_path.exists());
assert!(temp_dir.path().join("Mueller.txt").exists());
}
#[test]
fn test_double_extension() {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join("my archive.tar.gz");
fs::write(&file_path, "archive").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("-r").arg(temp_dir.path());
cmd.assert().success();
// Should keep .tar.gz intact
assert!(!file_path.exists());
assert!(temp_dir.path().join("my_archive.tar.gz").exists());
}
#[test]
fn test_exclude_pattern() {
let temp_dir = TempDir::new().unwrap();
let file1 = temp_dir.path().join("test file.txt");
let file2 = temp_dir.path().join("test file.tmp");
fs::write(&file1, "test1").unwrap();
fs::write(&file2, "test2").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("--exclude")
.arg("*.tmp")
.arg("-r")
.arg(temp_dir.path());
cmd.assert().success();
// .txt should be renamed, .tmp should not
assert!(!file1.exists());
assert!(temp_dir.path().join("test_file.txt").exists());
assert!(file2.exists()); // Excluded
}
#[test]
fn test_quiet_mode() {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join("test file.txt");
fs::write(&file_path, "test").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("--quiet").arg("-r").arg(temp_dir.path());
cmd.assert()
.success()
.stdout(predicate::str::is_empty());
}
#[test]
fn test_multiple_paths() {
let temp_dir1 = TempDir::new().unwrap();
let temp_dir2 = TempDir::new().unwrap();
let file1 = temp_dir1.path().join("file 1.txt");
let file2 = temp_dir2.path().join("file 2.txt");
fs::write(&file1, "test1").unwrap();
fs::write(&file2, "test2").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("-r").arg(temp_dir1.path()).arg(temp_dir2.path());
cmd.assert().success();
// Both files should be renamed
assert!(temp_dir1.path().join("file_1.txt").exists());
assert!(temp_dir2.path().join("file_2.txt").exists());
}
#[test]
fn test_parentheses_removed() {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join("Document (1).txt");
fs::write(&file_path, "test").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("-r").arg(temp_dir.path());
cmd.assert().success();
// Parentheses should be replaced with underscores
assert!(!file_path.exists());
assert!(temp_dir.path().join("Document_1.txt").exists());
}
#[test]
fn test_special_identifiers_preserved() {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join("C++ Guide.pdf");
fs::write(&file_path, "test").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("-r").arg(temp_dir.path());
cmd.assert().success();
// C++ should be preserved
assert!(!file_path.exists());
assert!(temp_dir.path().join("C++_Guide.pdf").exists());
}
#[test]
fn test_non_recursive_default() {
let temp_dir = TempDir::new().unwrap();
fs::create_dir(temp_dir.path().join("subdir")).unwrap();
let file1 = temp_dir.path().join("top file.txt");
let file2 = temp_dir.path().join("subdir").join("nested file.txt");
fs::write(&file1, "test1").unwrap();
fs::write(&file2, "test2").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg(temp_dir.path());
cmd.assert().success();
// Top-Level umbenannt
assert!(temp_dir.path().join("top_file.txt").exists());
// Nested NICHT umbenannt (non-recursive)
assert!(file2.exists());
}
#[test]
fn test_recursive_flag() {
let temp_dir = TempDir::new().unwrap();
fs::create_dir(temp_dir.path().join("subdir")).unwrap();
let file1 = temp_dir.path().join("top file.txt");
let file2 = temp_dir.path().join("subdir").join("nested file.txt");
fs::write(&file1, "test1").unwrap();
fs::write(&file2, "test2").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("-r").arg(temp_dir.path());
cmd.assert().success();
// Beide umbenannt
assert!(temp_dir.path().join("top_file.txt").exists());
assert!(temp_dir.path().join("subdir").join("nested_file.txt").exists());
}
#[test]
fn test_conf_option_valid_file() {
let temp_dir = TempDir::new().unwrap();
let config_file = temp_dir.path().join("custom.toml");
fs::write(&config_file, "[replacements]\n\"test\" = \"xyz\"").unwrap();
let file_path = temp_dir.path().join("test_file.txt");
fs::write(&file_path, "content").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("--conf").arg(&config_file).arg(temp_dir.path());
cmd.assert().success();
assert!(temp_dir.path().join("xyz_file.txt").exists());
}
#[test]
fn test_conf_option_missing_file() {
let temp_dir = TempDir::new().unwrap();
let nonexistent = temp_dir.path().join("nonexistent.toml");
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("--conf").arg(&nonexistent).arg(temp_dir.path());
cmd.assert()
.failure()
.stderr(predicate::str::contains("nicht gefunden"));
}
#[test]
fn test_sequence_lower() {
let temp_dir = TempDir::new().unwrap();
let config_file = temp_dir.path().join("empty.toml");
fs::write(&config_file, "[replacements]\n").unwrap();
let file_path = temp_dir.path().join("Test File.txt");
fs::write(&file_path, "content").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("--conf")
.arg(&config_file)
.arg("-s")
.arg("lower")
.arg(temp_dir.path());
cmd.assert().success();
assert!(temp_dir.path().join("test_file.txt").exists());
}
#[test]
fn test_sequence_upper() {
let temp_dir = TempDir::new().unwrap();
let config_file = temp_dir.path().join("empty.toml");
fs::write(&config_file, "[replacements]\n").unwrap();
let file_path = temp_dir.path().join("test file.txt");
fs::write(&file_path, "content").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("--conf")
.arg(&config_file)
.arg("-s")
.arg("upper")
.arg(temp_dir.path());
cmd.assert().success();
assert!(temp_dir.path().join("TEST_FILE.TXT").exists());
}
#[test]
fn test_sequence_minimal() {
let temp_dir = TempDir::new().unwrap();
let config_file = temp_dir.path().join("empty.toml");
fs::write(&config_file, "[replacements]\n").unwrap();
let file_path = temp_dir.path().join("Müller Datei.txt");
fs::write(&file_path, "content").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("--conf")
.arg(&config_file)
.arg("-s")
.arg("minimal")
.arg(temp_dir.path());
cmd.assert().success();
// Umlaute bleiben erhalten, nur Leerzeichen ersetzt
assert!(temp_dir.path().join("Müller_Datei.txt").exists());
}
#[test]
fn test_sequence_utf8() {
let temp_dir = TempDir::new().unwrap();
let config_file = temp_dir.path().join("empty.toml");
fs::write(&config_file, "[replacements]\n").unwrap();
let file_path = temp_dir.path().join("schön (1).txt");
fs::write(&file_path, "content").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("--conf")
.arg(&config_file)
.arg("-s")
.arg("utf-8")
.arg(temp_dir.path());
cmd.assert().success();
// Umlaut bleibt, Klammern entfernt
assert!(temp_dir.path().join("schön_1.txt").exists());
}
#[test]
fn test_list_sequences() {
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("-L");
cmd.assert()
.success()
.stdout(predicate::str::contains("default"))
.stdout(predicate::str::contains("lower"))
.stdout(predicate::str::contains("upper"))
.stdout(predicate::str::contains("minimal"))
.stdout(predicate::str::contains("utf-8"));
}
#[test]
fn test_list_sequences_verbose() {
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("-L").arg("-v");
cmd.assert()
.success()
.stdout(predicate::str::contains("Umlauts → ASCII"))
.stdout(predicate::str::contains("Case transform"));
}
#[test]
fn test_invalid_sequence() {
let temp_dir = TempDir::new().unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("-s").arg("invalid_seq").arg(temp_dir.path());
cmd.assert()
.failure()
.stderr(predicate::str::contains("Unbekannte Sequence"));
}
#[test]
fn test_sequence_default_explicit() {
let temp_dir = TempDir::new().unwrap();
let config_file = temp_dir.path().join("empty.toml");
fs::write(&config_file, "[replacements]\n").unwrap();
let file_path = temp_dir.path().join("Müller File.txt");
fs::write(&file_path, "content").unwrap();
let mut cmd = Command::new(cargo_bin!("ntu"));
cmd.arg("--conf")
.arg(&config_file)
.arg("-s")
.arg("default")
.arg(temp_dir.path());
cmd.assert().success();
// Default: Umlaut → ASCII
assert!(temp_dir.path().join("Mueller_File.txt").exists());
}