use rumdl_lib::lint_context::LintContext;
use rumdl_lib::rule::Rule;
use rumdl_lib::rules::MD029OrderedListPrefix;
#[test]
fn test_md029_nested_bullets_continue_list() {
let rule = MD029OrderedListPrefix::default();
let content = r#"1. First item
2. Second item:
- Nested bullet 1
- Nested bullet 2
3. Third item
4. Fourth item"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let warnings = rule.check(&ctx).unwrap();
assert_eq!(
warnings.len(),
0,
"Should not report MD029 errors when nested bullets are properly indented (3+ spaces)"
);
}
#[test]
fn test_md029_nested_bullets_with_code_block() {
let rule = MD029OrderedListPrefix::default();
let content = r#"1. Install WSL, reboot
2. Install distro:
- Install WSL, reboot
- Install distro (I use Debian)
- Configure distro (Create user account, etc.)
Get into the distro, then:
```bash
sudo apt-get update
```
3. Install cuda-toolkit
NOTE: Important note
4. Final step"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let warnings = rule.check(&ctx).unwrap();
assert_eq!(
warnings.len(),
0,
"Should not report MD029 errors for nested bullets and code blocks in list continuation"
);
}
#[test]
fn test_md029_under_indented_bullets_break_list() {
let rule = MD029OrderedListPrefix::default();
let content = r#"1. First item
2. Second item:
- Bullet with 2 spaces (starts new list)
3. Third item"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let warnings = rule.check(&ctx).unwrap();
assert!(
warnings.is_empty(),
"Item 3 is correctly numbered for its list (which starts at 3)"
);
}
#[test]
fn test_md029_nested_ordered_list_continues() {
let rule = MD029OrderedListPrefix::default();
let content = r#"1. First item
2. Second item with nested ordered list:
1. Nested item A
2. Nested item B
3. Third item"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let warnings = rule.check(&ctx).unwrap();
let parent_warnings: Vec<_> = warnings
.iter()
.filter(|w| w.line == 7) .collect();
assert_eq!(
parent_warnings.len(),
0,
"Parent list should continue correctly with nested ordered lists"
);
}
#[test]
fn test_md029_complex_continuation_content() {
let rule = MD029OrderedListPrefix::default();
let content = r#"1. First item
2. Second item with complex content:
Some paragraph text here.
- Bullet 1
- Bullet 2
More text.
```bash
echo "code block"
```
Final paragraph.
3. Third item
4. Fourth item"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let warnings = rule.check(&ctx).unwrap();
assert_eq!(
warnings.len(),
0,
"Should handle complex continuation content (text + bullets + code)"
);
}
#[test]
fn test_md029_unindented_text_breaks_list() {
let rule = MD029OrderedListPrefix::default();
let content = r#"1. First item
2. Second item
Unindented paragraph breaks the list.
3. Third item"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let warnings = rule.check(&ctx).unwrap();
assert!(
warnings.is_empty(),
"Item 3 is correctly numbered for its list (which starts at 3)"
);
}
#[test]
fn test_md029_wider_marker_with_nested_list() {
let rule = MD029OrderedListPrefix::default();
let content = r#"1. First item
10. Item with wide marker:
- Nested bullet (4 spaces)
11. This item continues"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let warnings = rule.check(&ctx).unwrap();
assert_eq!(warnings.len(), 2, "Should report numbering errors");
assert_eq!(warnings[0].line, 3);
assert!(warnings[0].message.contains("expected 2"));
assert_eq!(warnings[1].line, 6);
assert!(warnings[1].message.contains("expected 3"));
}
#[test]
fn test_md029_wider_marker_with_under_indented_bullet() {
let rule = MD029OrderedListPrefix::default();
let content = r#"1. First item
10. Item with wide marker:
- Bullet with 3 spaces (breaks the list)
11. This item continues"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let warnings = rule.check(&ctx).unwrap();
assert_eq!(warnings.len(), 1, "Should report numbering error for 10");
assert_eq!(warnings[0].line, 3); assert!(warnings[0].message.contains("expected 2"));
assert!(warnings[0].fix.is_some(), "Normal error should have fix");
}
#[test]
fn test_md029_multiple_nested_levels() {
let rule = MD029OrderedListPrefix::default();
let content = r#"1. First item
2. Second item with deep nesting:
- Level 1 bullet
- Level 2 bullet (6 spaces)
- Level 3 bullet (9 spaces)
Back to level 1 text
3. Third item"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let warnings = rule.check(&ctx).unwrap();
assert_eq!(
warnings.len(),
0,
"Should handle multiple nested levels within list item"
);
}
#[test]
fn test_md029_fix_renumbers_correctly_after_nested_content() {
let rule = MD029OrderedListPrefix::default();
let content = r#"1. First item
2. Second item:
- Nested bullet
1. Wrong number (should be 3)
2. Wrong number (should be 4)"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let warnings = rule.check(&ctx).unwrap();
assert_eq!(warnings.len(), 2, "Should detect 2 numbering errors");
assert_eq!(warnings[0].line, 6);
assert!(warnings[0].message.contains('1') && warnings[0].message.contains("expected 3"));
assert_eq!(warnings[1].line, 8);
assert!(warnings[1].message.contains('2') && warnings[1].message.contains("expected 4"));
let fixed = rule.fix(&ctx).unwrap();
assert!(fixed.contains("3. Wrong number"));
assert!(fixed.contains("4. Wrong number"));
}
#[test]
fn test_md029_commonmark_example_248() {
let rule = MD029OrderedListPrefix::default();
let content = r#"1. First item
2. Second item
indented code
3. Third item"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let warnings = rule.check(&ctx).unwrap();
assert_eq!(
warnings.len(),
0,
"Should follow CommonMark: indented code continues list"
);
}
#[test]
fn test_md029_lazy_continuation_is_valid_commonmark() {
let rule = MD029OrderedListPrefix::default();
let content = r#"1. Item one
2. Item two
Lazy continuation (not indented)
3. Item three"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let warnings = rule.check(&ctx).unwrap();
let numbering_errors: Vec<_> = warnings
.iter()
.filter(|w| w.rule_name.as_deref() == Some("MD029"))
.collect();
assert_eq!(
numbering_errors.len(),
0,
"Lazy continuation should not break list continuity - this is valid CommonMark"
);
}