use rumdl_lib::lint_context::LintContext;
use rumdl_lib::rule::Rule;
use rumdl_lib::rules::MD056TableColumnCount;
#[test]
fn test_name() {
let rule = MD056TableColumnCount;
assert_eq!(rule.name(), "MD056");
}
#[test]
fn test_consistent_column_count() {
let rule = MD056TableColumnCount;
let content = r#"
| Header 1 | Header 2 | Header 3 |
| -------- | -------- | -------- |
| Cell 1.1 | Cell 1.2 | Cell 1.3 |
| Cell 2.1 | Cell 2.2 | Cell 2.3 |
"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let result = rule.check(&ctx).unwrap();
assert_eq!(result.len(), 0);
let content = r#"
Header 1 | Header 2 | Header 3
-------- | -------- | --------
Cell 1.1 | Cell 1.2 | Cell 1.3
Cell 2.1 | Cell 2.2 | Cell 2.3
"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let result = rule.check(&ctx).unwrap();
assert_eq!(result.len(), 0);
}
#[test]
fn test_inconsistent_column_count() {
let rule = MD056TableColumnCount;
let content = r#"
| Header 1 | Header 2 | Header 3 |
| -------- | -------- | -------- |
| Cell 1.1 | Cell 1.2 |
| Cell 2.1 | Cell 2.2 | Cell 2.3 | Extra |
"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let result = rule.check(&ctx).unwrap();
assert_eq!(result.len(), 2);
assert_eq!(result[0].line, 4); assert_eq!(result[1].line, 5); assert!(result[0].message.contains("2 cells, but expected 3"));
assert!(result[1].message.contains("4 cells, but expected 3"));
}
#[test]
fn test_complex_tables() {
let rule = MD056TableColumnCount;
let content = r#"
| Header 1 | Header 2 | Header 3 |
| -------- | -------- | -------- |
| Cell 1.1 | | Cell 1.3 |
| | Cell 2.2 | |
"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let result = rule.check(&ctx).unwrap();
assert_eq!(result.len(), 0);
let content = r#"
| Left | Center | Right |
|:-----|:------:|------:|
| 1 | 2 | 3 |
| 4 | 5 | 6 |
"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let result = rule.check(&ctx).unwrap();
assert_eq!(result.len(), 0);
}
#[test]
fn test_code_blocks_ignored() {
let rule = MD056TableColumnCount;
let content = r#"
| Header 1 | Header 2 | Header 3 |
| -------- | -------- | -------- |
| Cell 1.1 | Cell 1.2 | Cell 1.3 |
```markdown
| Bad table | with | inconsistent | columns |
| --- | --- |
| Too few | columns |
```
"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let result = rule.check(&ctx).unwrap();
assert_eq!(result.len(), 0);
}
#[test]
fn test_fix_too_few_columns() {
let rule = MD056TableColumnCount;
let content = r#"
| Header 1 | Header 2 | Header 3 |
| -------- | -------- | -------- |
| Cell 1.1 | Cell 1.2 |
"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let result = rule.fix(&ctx).unwrap();
assert!(result.contains("| Cell 1.1 | Cell 1.2 | |"));
}
#[test]
fn test_fix_too_many_columns() {
let rule = MD056TableColumnCount;
let content = r#"
| Header 1 | Header 2 | Header 3 |
| -------- | -------- | -------- |
| Cell 1.1 | Cell 1.2 | Cell 1.3 | Extra |
"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let result = rule.fix(&ctx).unwrap();
assert!(result.contains("| Cell 1.1 | Cell 1.2 | Cell 1.3 |"));
assert!(!result.contains("Extra"));
}
#[test]
fn test_table_row_detection() {
let rule = MD056TableColumnCount;
let content = r#"
This is a paragraph that happens to have | pipe characters
but isn't actually a table row.
| Header 1 | Header 2 |
| -------- | -------- |
| Cell 1.1 | Cell 1.2 |
"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let result = rule.check(&ctx).unwrap();
assert_eq!(result.len(), 0);
}
#[test]
fn test_pipes_in_code_spans_not_delimiters() {
let rule = MD056TableColumnCount;
let content = r#"
| Python type | Example |
| ----------- | -------- |
| Union | `x | y` |
| Dict | `dict[str, int]` |
"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::MkDocs, None);
let result = rule.check(&ctx).unwrap();
assert_eq!(
result.len(),
0,
"MkDocs flavor should treat pipes in backticks as content, not delimiters"
);
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let result = rule.check(&ctx).unwrap();
assert_eq!(
result.len(),
0,
"Standard flavor should treat pipes in code spans as content, not delimiters"
);
}
#[test]
fn test_mkdocs_flavor_various_code_spans_with_pipes() {
let rule = MD056TableColumnCount;
let content = r#"
| Type | Syntax |
| ---- | ------ |
| OR | `a | b` |
| Pipe | `|` |
| Multi | `a | b | c` |
"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::MkDocs, None);
let result = rule.check(&ctx).unwrap();
assert_eq!(result.len(), 0, "MkDocs should handle multiple pipes in code spans");
}
#[test]
fn test_escaped_pipes_both_flavors() {
let rule = MD056TableColumnCount;
let content = r#"
| Col1 | Col2 |
| ---- | ---- |
| a \| b | c |
"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let result = rule.check(&ctx).unwrap();
assert_eq!(result.len(), 0, "Escaped pipes should work in Standard flavor");
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::MkDocs, None);
let result = rule.check(&ctx).unwrap();
assert_eq!(result.len(), 0, "Escaped pipes should work in MkDocs flavor");
}
#[test]
fn test_mkdocs_flavor_fix_preserves_inline_code_pipes() {
let rule = MD056TableColumnCount;
let content = r#"
| Type | Syntax | Description |
| ---- | ------ | ----------- |
| OR | `a | b` |
"#;
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::MkDocs, None);
let result = rule.fix(&ctx).unwrap();
assert!(result.contains("`a | b`"), "Fix should preserve inline code with pipe");
}
#[test]
fn test_issue_479_pipe_in_code_span_table() {
let content = "| Operator | Dunder Method |\n|----------|-----------------|\n| `&` | `__and__` |\n| `|` | `__or__` |\n| `^` | `__xor__` |\n";
let ctx = LintContext::new(content, rumdl_lib::config::MarkdownFlavor::Standard, None);
let rule = MD056TableColumnCount;
let result = rule.check(&ctx).unwrap();
assert!(
result.is_empty(),
"Pipe in code span should not cause column count mismatch, got: {result:?}"
);
}