mod common;
use common::*;
use predicates::prelude::*;
use predicates::str::contains;
use std::fs;
use tempfile::TempDir;
#[test]
fn test_fix_flag_applies_fixes() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("test.md");
fs::write(
&test_file,
"# Test Document \n\nThis has trailing spaces. \nMore content here.\n",
)
.unwrap();
let assert = cli_command()
.arg("lint")
.arg("--fix")
.arg(&test_file)
.assert();
assert
.success()
.stdout(contains("Fixed"))
.stdout(contains("Applied"));
let fixed_content = fs::read_to_string(&test_file).unwrap();
assert!(
!fixed_content.contains("spaces. "),
"Trailing spaces should be removed"
);
assert!(
fixed_content.contains("spaces."),
"Content should remain intact"
);
let backup_file = test_file.with_extension("md.bak");
assert!(backup_file.exists(), "Backup file should be created");
let backup_content = fs::read_to_string(&backup_file).unwrap();
assert!(
backup_content.contains("spaces. "),
"Backup should contain original content"
);
}
#[test]
fn test_fix_with_remaining_violations() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("test.md");
fs::write(
&test_file,
"# Test Document \n\n\n\nThis has trailing spaces. \n\n\n",
)
.unwrap();
let assert = cli_command()
.arg("lint")
.arg("--fix")
.arg(&test_file)
.assert();
assert
.success()
.stdout(contains("Fixed"))
.stdout(contains("Applied"))
.stdout(contains("Found"))
.stdout(contains("violation"));
let fixed_content = fs::read_to_string(&test_file).unwrap();
assert!(
!fixed_content.contains("spaces. "),
"Trailing spaces should be removed"
);
assert!(
fixed_content.contains("\n\n\n"),
"Multiple blank lines should remain (not fixable)"
);
}
#[test]
fn test_fix_with_fail_on_warnings() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("test.md");
fs::write(
&test_file,
"# Test Document \n\n\n\nThis has trailing spaces. \n",
)
.unwrap();
let assert = cli_command()
.arg("lint")
.arg("--fix")
.arg("--fail-on-warnings")
.arg(&test_file)
.assert();
assert
.code(1)
.stdout(contains("Fixed"))
.stdout(contains("Found"))
.stdout(contains("violation"));
}
#[test]
fn test_dry_run_flag() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("test.md");
let original_content = "# Test Document \n\nThis has trailing spaces. \n";
fs::write(&test_file, original_content).unwrap();
let assert = cli_command()
.arg("lint")
.arg("--fix")
.arg("--dry-run")
.arg(&test_file)
.assert();
assert.success().stdout(contains("Would fix"));
let content_after = fs::read_to_string(&test_file).unwrap();
assert_eq!(
content_after, original_content,
"File should not be modified in dry-run mode"
);
let backup_file = test_file.with_extension("md.bak");
assert!(
!backup_file.exists(),
"No backup should be created in dry-run mode"
);
}
#[test]
fn test_fix_unsafe_flag() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("test.md");
fs::write(
&test_file,
"# Test Document \n\nThis has trailing spaces. \nMore content.\n",
)
.unwrap();
let assert = cli_command()
.arg("lint")
.arg("--fix-unsafe")
.arg(&test_file)
.assert();
assert
.success()
.stdout(contains("Fixed"))
.stdout(contains("Applied"));
let fixed_content = fs::read_to_string(&test_file).unwrap();
assert!(
!fixed_content.contains("spaces. "),
"Trailing spaces should be removed"
);
}
#[test]
fn test_dry_run_with_fix_unsafe() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("test.md");
let original_content = "# Test Document \n\nThis has trailing spaces. \n";
fs::write(&test_file, original_content).unwrap();
let assert = cli_command()
.arg("lint")
.arg("--fix-unsafe")
.arg("--dry-run")
.arg(&test_file)
.assert();
assert.success().stdout(contains("Would fix"));
let content_after = fs::read_to_string(&test_file).unwrap();
assert_eq!(
content_after, original_content,
"File should not be modified in dry-run mode"
);
}
#[test]
fn test_backup_flag_disabled() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("test.md");
fs::write(
&test_file,
"# Test Document \n\nThis has trailing spaces. \n",
)
.unwrap();
let assert = cli_command()
.arg("lint")
.arg("--fix")
.arg("--no-backup")
.arg(&test_file)
.assert();
assert.success().stdout(contains("Fixed"));
let backup_file = test_file.with_extension("md.bak");
assert!(
!backup_file.exists(),
"No backup should be created when --no-backup"
);
let fixed_content = fs::read_to_string(&test_file).unwrap();
assert!(
!fixed_content.contains("spaces. "),
"Trailing spaces should be removed"
);
}
#[test]
fn test_fix_multiple_files() {
let temp_dir = TempDir::new().unwrap();
let file1 = temp_dir.path().join("file1.md");
let file2 = temp_dir.path().join("file2.md");
fs::write(&file1, "# File One \n\nTrailing spaces here. \n").unwrap();
fs::write(&file2, "# File Two \n\nMore trailing spaces. \n").unwrap();
let assert = cli_command()
.arg("lint")
.arg("--fix")
.arg(&file1)
.arg(&file2)
.assert();
assert
.success()
.stdout(contains("Fixed"))
.stdout(contains("Applied"))
.stdout(contains("2 file(s)"));
let content1 = fs::read_to_string(&file1).unwrap();
let content2 = fs::read_to_string(&file2).unwrap();
assert!(
!content1.contains("here. "),
"File 1 trailing spaces should be removed"
);
assert!(
!content2.contains("spaces. "),
"File 2 trailing spaces should be removed"
);
assert!(file1.with_extension("md.bak").exists());
assert!(file2.with_extension("md.bak").exists());
}
#[test]
fn test_fix_directory_recursively() {
let temp_dir = TempDir::new().unwrap();
let sub_dir = temp_dir.path().join("subdir");
fs::create_dir_all(&sub_dir).unwrap();
let file1 = temp_dir.path().join("file1.md");
let file2 = sub_dir.join("file2.md");
fs::write(&file1, "# File One \n\nTrailing spaces. \n").unwrap();
fs::write(&file2, "# File Two \n\nMore trailing spaces. \n").unwrap();
let assert = cli_command()
.arg("lint")
.arg("--fix")
.arg(temp_dir.path())
.assert();
assert
.success()
.stdout(contains("Fixed"))
.stdout(contains("Applied"));
let content1 = fs::read_to_string(&file1).unwrap();
let content2 = fs::read_to_string(&file2).unwrap();
assert!(!content1.contains("spaces. "));
assert!(!content2.contains("spaces. "));
}
#[test]
fn test_fix_no_fixable_violations() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("test.md");
fs::write(
&test_file,
"# Test Document\n\nThis has <b>inline HTML</b> which violates MD033.\n",
)
.unwrap();
let assert = cli_command()
.arg("lint")
.arg("--fix")
.arg(&test_file)
.assert();
let stdout = String::from_utf8(assert.get_output().stdout.clone()).unwrap();
assert
.success()
.stdout(contains("Found"))
.stdout(contains("violation"));
assert!(
!stdout.contains("Fixed"),
"Should not show 'Fixed' when no fixes applied"
);
assert!(
!stdout.contains("Applied"),
"Should not show 'Applied' when no fixes applied"
);
let content = fs::read_to_string(&test_file).unwrap();
assert!(
content.contains("<b>inline HTML</b>"),
"Content should be unchanged when no fixes applied"
);
let backup_file = test_file.with_extension("md.bak");
assert!(
!backup_file.exists(),
"No backup should be created when no fixes applied"
);
}
#[test]
fn test_fix_error_validation() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("test.md");
fs::write(&test_file, "# Test\nContent\n").unwrap();
let assert = cli_command()
.arg("lint")
.arg("--dry-run")
.arg(&test_file)
.assert();
assert
.code(1)
.stderr(contains("--dry-run requires either --fix or --fix-unsafe"));
}
#[test]
fn test_fix_clean_file() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("clean.md");
fs::write(
&test_file,
"# Clean Document\n\nThis file has no violations.\n\n```rust\nfn main() {}\n```\n",
)
.unwrap();
let assert = cli_command()
.arg("lint")
.arg("--fix")
.arg(&test_file)
.assert();
let stdout = String::from_utf8(assert.get_output().stdout.clone()).unwrap();
assert
.success()
.stdout(contains("✅ No issues found").or(contains("Found 0 violation")));
assert!(
!stdout.contains("Fixed"),
"Should not show 'Fixed' for clean files"
);
assert!(
!stdout.contains("Applied"),
"Should not show 'Applied' for clean files"
);
let backup_file = test_file.with_extension("md.bak");
assert!(
!backup_file.exists(),
"No backup should be created for clean files"
);
}
#[test]
fn test_fix_exit_codes() {
let temp_dir = TempDir::new().unwrap();
let test_file1 = temp_dir.path().join("all_fixable.md");
fs::write(
&test_file1,
"# Test\nTrailing spaces. \nMore trailing. \n",
)
.unwrap();
let assert = cli_command()
.arg("lint")
.arg("--fix")
.arg(&test_file1)
.assert();
assert.success();
let test_file2 = temp_dir.path().join("mixed.md");
fs::write(&test_file2, "# Test\n\n\n\nTrailing spaces. \n").unwrap();
let assert = cli_command()
.arg("lint")
.arg("--fix")
.arg(&test_file2)
.assert();
assert.success();
let test_file3 = temp_dir.path().join("mixed2.md");
fs::write(&test_file3, "# Test\n\n\n\nTrailing spaces. \n").unwrap();
let assert = cli_command()
.arg("lint")
.arg("--fix")
.arg("--fail-on-warnings")
.arg(&test_file3)
.assert();
assert.code(1);
}