diff --git a/tests/table/mod.rs b/tests/table/mod.rs index c3c978a9..d93f61f0 100644 --- a/tests/table/mod.rs +++ b/tests/table/mod.rs @@ -1,6 +1,20 @@ //! Integration tests for table reflow and HTML table conversion. //! -//! Covers `reflow_table`, `convert_html_tables` and related `process_stream` behaviour. +//! This module provides comprehensive test coverage for the table processing +//! functionality in `mdtablefix`, including Markdown table reflowing and +//! HTML-to-Markdown conversion. +//! +//! The module is organised into focused submodules: +//! - `reflow`: Tests for `reflow_table` covering basic reflow, malformed tables, +//! header preservation, escaped pipes and indentation. +//! - `process_stream_tests`: Tests for `process_stream` verifying normalisation +//! of various HTML table variants and handling of multiple tables. +//! - `uniform`: Regression tests ensuring uniform column widths after reflowing. +//! - `convert_html`: Parameterised tests for HTML table conversion edge cases. +//! - `regressions`: Real-world data validation tests. +//! +//! Each test uses fixtures defined in this module to ensure consistent test data +//! across different scenarios whilst avoiding duplication. use mdtablefix::{convert_html_tables, process_stream, reflow_table}; @@ -10,8 +24,7 @@ use prelude::*; #[fixture] fn malformed_table() -> Vec { - let lines = lines_vec!["| A | |", "| 1 | 2 | 3 |"]; - lines + lines_vec!["| A | |", "| 1 | 2 | 3 |"] } #[fixture] @@ -26,8 +39,7 @@ fn escaped_pipe_table() -> Vec { #[fixture] fn indented_table() -> Vec { - let lines = lines_vec![" | I | J | |", " | 1 | 2 | | 3 | 4 |"]; - lines + lines_vec![" | I | J | |", " | 1 | 2 | | 3 | 4 |"] } #[fixture] @@ -102,14 +114,12 @@ fn html_table_inconsistent_first_row() -> Vec { #[fixture] fn html_table_empty() -> Vec { - let lines = lines_vec!["
"]; - lines + lines_vec!["
"] } #[fixture] fn html_table_unclosed() -> Vec { - let lines = lines_vec!["", ""]; - lines + lines_vec!["
1
", ""] } #[fixture] diff --git a/tests/table/uniform.rs b/tests/table/uniform.rs index 81a21e8a..f931f004 100644 --- a/tests/table/uniform.rs +++ b/tests/table/uniform.rs @@ -2,18 +2,7 @@ use super::*; -#[test] -fn test_uniform_example_one() { - let input = lines_vec![ - "| Logical type | PostgreSQL | SQLite notes |", - "|--------------|-------------------------|-------------------------------------------|", - "| strings | `TEXT` (or `VARCHAR`) | `TEXT` - SQLite ignores the length specifier anyway |", - "| booleans | `BOOLEAN DEFAULT FALSE` | declare as `BOOLEAN`; Diesel serialises to 0 / 1 so this is fine |", - "| integers | `INTEGER` / `BIGINT` | ditto |", - "| decimals | `NUMERIC` | stored as FLOAT in SQLite; Diesel `Numeric` round-trips, but beware precision |", - "| blobs / raw | `BYTEA` | `BLOB` |", - ]; - let output = reflow_table(&input); +fn assert_uniform_column_widths(output: &[String]) { assert!(!output.is_empty()); let widths: Vec = output[0] .trim_matches('|') @@ -28,6 +17,21 @@ fn test_uniform_example_one() { } } +#[test] +fn test_uniform_example_one() { + let input = lines_vec![ + "| Logical type | PostgreSQL | SQLite notes |", + "|--------------|-------------------------|-------------------------------------------|", + "| strings | `TEXT` (or `VARCHAR`) | `TEXT` - SQLite ignores the length specifier anyway |", + "| booleans | `BOOLEAN DEFAULT FALSE` | declare as `BOOLEAN`; Diesel serialises to 0 / 1 so this is fine |", + "| integers | `INTEGER` / `BIGINT` | ditto |", + "| decimals | `NUMERIC` | stored as FLOAT in SQLite; Diesel `Numeric` round-trips, but beware precision |", + "| blobs / raw | `BYTEA` | `BLOB` |", + ]; + let output = reflow_table(&input); + assert_uniform_column_widths(&output); +} + #[test] fn test_uniform_example_two() { let input = lines_vec![ @@ -38,16 +42,5 @@ fn test_uniform_example_two() { "| **D. Two separate migration trees** | Maintain `migrations/sqlite` and `migrations/postgres` directories with identical version numbers. Use `embed_migrations!(\"migrations/\")` to compile the right set. | You ship a single binary with migrations baked in. |", ]; let output = reflow_table(&input); - assert!(!output.is_empty()); - let widths: Vec = output[0] - .trim_matches('|') - .split('|') - .map(str::len) - .collect(); - for row in output { - let cols: Vec<&str> = row.trim_matches('|').split('|').collect(); - for (i, col) in cols.iter().enumerate() { - assert_eq!(col.len(), widths[i]); - } - } + assert_uniform_column_widths(&output); } diff --git a/tests/wrap/cli.rs b/tests/wrap/cli.rs index fd598f3d..9e1eea85 100644 --- a/tests/wrap/cli.rs +++ b/tests/wrap/cli.rs @@ -1,4 +1,8 @@ //! CLI wrapping option tests. +//! +//! Validates that the `--wrap` command-line flag correctly triggers text +//! wrapping behaviour when processing Markdown content through the `mdtablefix` +//! binary. use super::*; diff --git a/tests/wrap/footnotes.rs b/tests/wrap/footnotes.rs index 6042817f..c3d8e8e2 100644 --- a/tests/wrap/footnotes.rs +++ b/tests/wrap/footnotes.rs @@ -1,4 +1,8 @@ //! Footnote wrapping tests. +//! +//! Validates wrapping behaviour for Markdown footnotes, ensuring proper +//! indentation is maintained and inline code spans are not broken across lines. +//! Tests various footnote formats including those with URLs and code. use super::*; @@ -12,6 +16,19 @@ fn test_wrap_footnote_multiline() { assert_wrapped_list_item(&output, "[^note]: ", 2); } +#[test] +fn test_wrap_footnote_multiline_with_blank_lines() { + let input = lines_vec![ + "[^note]: This footnote begins with a paragraph long enough to trigger wrapping so that indentation can be checked.", + "", + " This second paragraph should also wrap correctly and remain indented.", + ]; + let output = process_stream(&input); + assert_eq!(output[1], ""); + assert!(output.iter().skip(2).all(|l| l.starts_with(" "))); + assert!(output.iter().all(|l| l.len() <= 80)); +} + #[test] fn test_wrap_footnote_with_inline_code() { let input = lines_vec![concat!( diff --git a/tests/wrap/links.rs b/tests/wrap/links.rs index 5c06c14a..40dcc28b 100644 --- a/tests/wrap/links.rs +++ b/tests/wrap/links.rs @@ -52,8 +52,7 @@ fn test_wrap_paragraph_with_nested_link() { #[test] fn test_wrap_link_with_trailing_punctuation() { let input = lines_vec![ - "[`rust-multithreaded-logging-framework-for-python-design.md`](./\\ - rust-multithreaded-logging-framework-for-python-design.md).", + "[`rust-multithreaded-logging-framework-for-python-design.md`](./rust-multithreaded-logging-framework-for-python-design.md).", ]; let output = process_stream(&input); assert_eq!(output, input); diff --git a/tests/wrap/paragraphs.rs b/tests/wrap/paragraphs.rs index eaf87052..45331761 100644 --- a/tests/wrap/paragraphs.rs +++ b/tests/wrap/paragraphs.rs @@ -1,5 +1,9 @@ //! Paragraph wrapping tests. +//! +//! Validates text wrapping behaviour for paragraph content, including handling +//! of long words that exceed the 80-column limit and cannot be broken. +use rstest::rstest; use super::*; #[test] @@ -14,8 +18,12 @@ fn test_wrap_paragraph() { } #[test] -fn test_wrap_paragraph_with_long_word() { - let long_word = "a".repeat(100); +#[rstest] +#[case(100)] +#[case(150)] +#[case(200)] +fn test_wrap_paragraph_with_long_word_parameterised(#[case] word_length: usize) { + let long_word = "a".repeat(word_length); let input = lines_vec![&long_word]; let output = process_stream(&input); assert_eq!(output.len(), 1);
1