use assert_cmd::cargo::cargo_bin_cmd;
use predicates::prelude::*;
use std::fs;
use tempfile::TempDir;
#[test]
fn test_unfixable_rules_not_fixed() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let test_file = temp_dir.path().join("test.md");
fs::write(
&test_file,
"# Main heading\n\n##Heading without space\n- List item with extra spaces \n> Blockquote with trailing spaces \n",
)
.expect("Failed to write test file");
let config_file = temp_dir.path().join("rumdl.toml");
fs::write(&config_file, "[global]\nunfixable = [\"MD018\", \"MD009\"]\n").expect("Failed to write config file");
let mut cmd = cargo_bin_cmd!("rumdl");
cmd.current_dir(&temp_dir)
.args(["check", "--fix", "--config", "rumdl.toml", "test.md"]);
let _output = cmd.output().expect("Failed to execute command");
let fixed_content = fs::read_to_string(&test_file).expect("Failed to read fixed file");
assert!(
fixed_content.contains("##Heading without space"),
"MD018 should not be fixed when marked as unfixable, but content is: {fixed_content}"
);
assert!(
fixed_content.contains(" \n"),
"MD009 should not be fixed when marked as unfixable, but content is: {fixed_content}"
);
assert!(
fixed_content.contains("- List item"),
"MD030 should be fixed when not in unfixable list, but content is: {fixed_content}"
);
}
#[test]
fn test_only_fixable_rules_are_fixed() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let test_file = temp_dir.path().join("test.md");
fs::write(
&test_file,
"# Main heading\n\n##Heading without space\n- List item with extra spaces \n> Blockquote with trailing spaces \nTrailing line without newline",
)
.expect("Failed to write test file");
let config_file = temp_dir.path().join("rumdl.toml");
fs::write(&config_file, "[global]\nfixable = [\"MD030\", \"MD047\"]\n").expect("Failed to write config file");
let mut cmd = cargo_bin_cmd!("rumdl");
cmd.current_dir(&temp_dir)
.args(["check", "--fix", "--config", "rumdl.toml", "test.md"]);
let _output = cmd.output().expect("Failed to execute command");
let fixed_content = fs::read_to_string(&test_file).expect("Failed to read fixed file");
assert!(
fixed_content.contains("##Heading without space"),
"MD018 should not be fixed when not in fixable list, but content is: {fixed_content}"
);
assert!(
fixed_content.contains(" \n"),
"MD009 should not be fixed when not in fixable list, but content is: {fixed_content}"
);
assert!(
fixed_content.contains("- List item"),
"MD030 should be fixed when in fixable list, but content is: {fixed_content}"
);
assert!(
fixed_content.ends_with('\n'),
"MD047 should be fixed when in fixable list, but content is: {fixed_content}"
);
}
#[test]
fn test_unfixable_takes_precedence_over_fixable() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let test_file = temp_dir.path().join("test.md");
fs::write(
&test_file,
"# Main heading\n\n##Heading without space\n- List item with extra spaces \n",
)
.expect("Failed to write test file");
let config_file = temp_dir.path().join("rumdl.toml");
fs::write(
&config_file,
"[global]\nfixable = [\"MD018\", \"MD030\"]\nunfixable = [\"MD018\"]\n",
)
.expect("Failed to write config file");
let mut cmd = cargo_bin_cmd!("rumdl");
cmd.current_dir(&temp_dir)
.args(["check", "--fix", "--config", "rumdl.toml", "test.md"]);
let _output = cmd.output().expect("Failed to execute command");
let fixed_content = fs::read_to_string(&test_file).expect("Failed to read fixed file");
assert!(
fixed_content.contains("##Heading without space"),
"MD018 should not be fixed when in unfixable list (precedence), but content is: {fixed_content}"
);
assert!(
fixed_content.contains("- List item"),
"MD030 should be fixed when in fixable list and not unfixable, but content is: {fixed_content}"
);
}
#[test]
fn test_pyproject_toml_fixable_unfixable() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let test_file = temp_dir.path().join("test.md");
fs::write(
&test_file,
"# Main heading\n\n##Heading without space\n- List item with extra spaces \n",
)
.expect("Failed to write test file");
let config_file = temp_dir.path().join(".rumdl.toml");
fs::write(&config_file, "[global]\nunfixable = [\"MD018\"]\n").expect("Failed to write config file");
let mut cmd = cargo_bin_cmd!("rumdl");
cmd.current_dir(&temp_dir).args(["check", "--fix", "test.md"]);
let _output = cmd.output().expect("Failed to execute command");
let fixed_content = fs::read_to_string(&test_file).expect("Failed to read fixed file");
assert!(
fixed_content.contains("##Heading without space"),
"MD018 should not be fixed when marked unfixable in .rumdl.toml, but content is: {fixed_content}"
);
assert!(
fixed_content.contains("- List item"),
"MD030 should be fixed when not in unfixable list, but content is: {fixed_content}"
);
}
#[test]
fn test_default_behavior_fixes_all_rules() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let test_file = temp_dir.path().join("test.md");
fs::write(
&test_file,
"# Main heading\n\n##Heading without space\n- List item with extra spaces \nTrailing line without newline",
)
.expect("Failed to write test file");
let mut cmd = cargo_bin_cmd!("rumdl");
cmd.current_dir(&temp_dir).args(["check", "--fix", "test.md"]);
let _output = cmd.output().expect("Failed to execute command");
let fixed_content = fs::read_to_string(&test_file).expect("Failed to read fixed file");
assert!(
fixed_content.contains("## Heading without space"),
"MD018 should be fixed by default, but content is: {fixed_content}"
);
assert!(
fixed_content.contains("- List item"),
"MD030 should be fixed by default, but content is: {fixed_content}"
);
assert!(
fixed_content.ends_with('\n'),
"MD047 should be fixed by default, but content is: {fixed_content}"
);
}
#[test]
fn test_check_fix_exits_nonzero_for_unfixable_warnings() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let test_file = temp_dir.path().join("test.md");
fs::write(&test_file, "# Heading\n\n[Broken Link](./totally_bogus)\n").expect("Failed to write test file");
let mut cmd = cargo_bin_cmd!("rumdl");
cmd.arg("check")
.arg("--fix")
.arg("--no-cache")
.arg(test_file.to_str().unwrap());
cmd.assert()
.failure()
.stdout(predicate::str::contains("MD057"))
.stdout(predicate::str::contains("does not exist"));
}
#[test]
fn test_check_fix_exits_zero_when_all_fixed() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let test_file = temp_dir.path().join("test.md");
fs::write(&test_file, "# Heading\n\nContent with trailing spaces \n").expect("Failed to write test file");
let mut cmd = cargo_bin_cmd!("rumdl");
cmd.arg("check")
.arg("--fix")
.arg("--no-cache")
.arg(test_file.to_str().unwrap());
cmd.assert().success();
}
#[test]
fn test_check_fix_exits_nonzero_when_unfixable_warnings_remain_after_partial_fix() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let test_file = temp_dir.path().join("test.md");
fs::write(
&test_file,
"# Heading\n\nContent with trailing spaces \n\n[Broken Link](./totally_bogus)\n",
)
.expect("Failed to write test file");
let mut cmd = cargo_bin_cmd!("rumdl");
cmd.arg("check")
.arg("--fix")
.arg("--no-cache")
.arg(test_file.to_str().unwrap());
cmd.assert().failure().stdout(predicate::str::contains("MD057"));
let fixed_content = fs::read_to_string(&test_file).expect("Failed to read fixed file");
assert!(
!fixed_content.contains("spaces \n"),
"MD009 trailing spaces should have been fixed, content: {fixed_content}"
);
}