mod common;
use common::*;
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("warning(s)"));
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("warning(s)"));
}
#[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("warning(s)"));
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
This file has no violations and contains enough content to pass all rules.
We need to write several sentences here to make sure we have at least fifty
words in total for the content quality checks to pass successfully.
Let me add some more text to ensure we definitely pass the minimum word
count threshold that is required by the linter for content validation.
```rust
# fn main() {
let x = 42;
# }
```
",
)
.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"));
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);
}