use rumdl_lib::config::Config;
use rumdl_lib::rule::{FixCapability, Rule};
use rumdl_lib::rules::MD018NoMissingSpaceAtx;
use rumdl_lib::rules::MD033NoInlineHtml;
use rumdl_lib::rules::MD045NoAltText;
use rumdl_lib::rules::MD054LinkImageStyle;
#[test]
fn test_inherently_unfixable_rules_declare_capability() {
let rule = MD033NoInlineHtml::new();
assert_eq!(rule.fix_capability(), FixCapability::Unfixable);
let rule = MD045NoAltText::new();
assert_eq!(rule.fix_capability(), FixCapability::Unfixable);
}
#[test]
fn test_md054_is_conditionally_fixable() {
let rule = MD054LinkImageStyle::new(true, true, true, true, true, true);
assert_eq!(rule.fix_capability(), FixCapability::ConditionallyFixable);
}
#[test]
fn test_fixable_rules_declare_capability() {
let rule = MD018NoMissingSpaceAtx::new();
assert_eq!(rule.fix_capability(), FixCapability::FullyFixable);
}
#[test]
fn test_unfixable_config_prevents_fixing() {
let _content = "##Heading without space\n[empty link]()\n";
let mut config = Config::default();
config.global.unfixable = vec!["MD018".to_string()];
assert!(!is_rule_actually_fixable(&config, "MD018"));
assert!(is_rule_actually_fixable(&config, "MD042"));
}
#[test]
fn test_fixable_list_restricts_fixing() {
let _content = "##Heading without space\n[empty link]()\n";
let mut config = Config::default();
config.global.fixable = vec!["MD042".to_string()];
assert!(!is_rule_actually_fixable(&config, "MD018"));
assert!(is_rule_actually_fixable(&config, "MD042"));
assert!(!is_rule_actually_fixable(&config, "MD047"));
}
#[test]
fn test_unfixable_takes_precedence_over_fixable() {
let mut config = Config::default();
config.global.unfixable = vec!["MD018".to_string()];
config.global.fixable = vec!["MD018".to_string(), "MD042".to_string()];
assert!(!is_rule_actually_fixable(&config, "MD018"));
assert!(is_rule_actually_fixable(&config, "MD042"));
}
#[test]
fn test_case_insensitive_rule_names() {
let mut config = Config::default();
config.global.unfixable = vec!["md018".to_string()];
assert!(!is_rule_actually_fixable(&config, "MD018"));
assert!(!is_rule_actually_fixable(&config, "md018"));
assert!(!is_rule_actually_fixable(&config, "Md018"));
}
#[test]
fn test_empty_config_allows_all_fixes() {
let config = Config::default();
assert!(is_rule_actually_fixable(&config, "MD018"));
assert!(is_rule_actually_fixable(&config, "MD042"));
assert!(is_rule_actually_fixable(&config, "MD047"));
}
fn is_rule_actually_fixable(config: &Config, rule_name: &str) -> bool {
if config
.global
.unfixable
.iter()
.any(|r| r.eq_ignore_ascii_case(rule_name))
{
return false;
}
if !config.global.fixable.is_empty() {
return config.global.fixable.iter().any(|r| r.eq_ignore_ascii_case(rule_name));
}
true
}
#[test]
fn test_fix_count_excludes_unfixable() {
let mut config = Config::default();
config.global.unfixable = vec!["MD042".to_string()];
let warnings = [
("MD018", true), ("MD012", true), ("MD042", true), ("MD047", true), ];
let fixable_count = warnings
.iter()
.filter(|(rule, has_fix)| *has_fix && is_rule_actually_fixable(&config, rule))
.count();
assert_eq!(fixable_count, 3); }