use crate::ast::*;
use crate::latex_printer::{config::*, render_latex};
#[test]
fn test_all_table_styles() {
let doc = Document {
blocks: vec![Block::Table(Table {
rows: vec![
vec![
vec![Inline::Text("H1".to_string())],
vec![Inline::Text("H2".to_string())],
],
vec![
vec![Inline::Text("R1C1".to_string())],
vec![Inline::Text("R1C2".to_string())],
],
],
alignments: vec![Alignment::Left, Alignment::Center],
})],
};
let config_tabular = Config::default().with_table_style(TableStyle::Tabular);
let result_tabular = render_latex(&doc, config_tabular);
assert!(result_tabular.contains(r"\begin{tabular}[lc]"));
assert!(result_tabular.contains(r"\hline"));
assert!(!result_tabular.contains(r"\toprule"));
let config_longtabu = Config::default().with_table_style(TableStyle::Longtabu);
let result_longtabu = render_latex(&doc, config_longtabu);
assert!(result_longtabu.contains(r"\begin{longtabu}"));
assert!(result_longtabu.contains("X[l] to \\textwidth"));
let config_booktabs = Config::default().with_table_style(TableStyle::Booktabs);
let result_booktabs = render_latex(&doc, config_booktabs);
assert!(result_booktabs.contains(r"\toprule"));
assert!(result_booktabs.contains(r"\midrule"));
assert!(result_booktabs.contains(r"\bottomrule"));
assert!(!result_booktabs.contains(r"\hline"));
}
#[test]
fn test_all_code_block_styles() {
let doc = Document {
blocks: vec![Block::CodeBlock(CodeBlock {
kind: CodeBlockKind::Fenced {
info: Some("python".to_string()),
},
literal: "print('hello world')".to_string(),
})],
};
let config_verbatim = Config::default().with_code_block_style(CodeBlockStyle::Verbatim);
let result_verbatim = render_latex(&doc, config_verbatim);
assert!(result_verbatim.contains(r"\begin{verbatim}"));
assert!(!result_verbatim.contains("language="));
assert!(!result_verbatim.contains(r"\begin{minted}"));
let config_listings = Config::default().with_code_block_style(CodeBlockStyle::Listings);
let result_listings = render_latex(&doc, config_listings);
assert!(result_listings.contains(r"\begin{lstlisting}[language=python]"));
assert!(!result_listings.contains(r"\begin{verbatim}"));
assert!(!result_listings.contains(r"\begin{minted}"));
let config_minted = Config::default().with_code_block_style(CodeBlockStyle::Minted);
let result_minted = render_latex(&doc, config_minted);
assert!(result_minted.contains(r"\begin{minted}{python}"));
assert!(!result_minted.contains(r"\begin{verbatim}"));
assert!(!result_minted.contains(r"\begin{lstlisting}"));
}
#[test]
fn test_code_block_without_language() {
let doc = Document {
blocks: vec![Block::CodeBlock(CodeBlock {
kind: CodeBlockKind::Fenced { info: None },
literal: "echo 'no language'".to_string(),
})],
};
let config_verbatim = Config::default().with_code_block_style(CodeBlockStyle::Verbatim);
let result_verbatim = render_latex(&doc, config_verbatim);
assert!(result_verbatim.contains(r"\begin{verbatim}"));
let config_listings = Config::default().with_code_block_style(CodeBlockStyle::Listings);
let result_listings = render_latex(&doc, config_listings);
assert!(result_listings.contains(r"\begin{lstlisting}"));
assert!(!result_listings.contains("language="));
let config_minted = Config::default().with_code_block_style(CodeBlockStyle::Minted);
let result_minted = render_latex(&doc, config_minted);
assert!(result_minted.contains(r"\begin{minted}{text}"));
}
#[test]
fn test_width_configuration() {
let long_text = "This is a very long line of text that should be wrapped at different widths depending on the configuration settings.";
let doc = Document {
blocks: vec![Block::Paragraph(vec![Inline::Text(long_text.to_string())])],
};
let widths = vec![40, 80, 120];
let mut results = Vec::new();
for width in widths {
let config = Config::default().with_width(width);
let result = render_latex(&doc, config);
results.push(result);
}
let line_counts: Vec<usize> = results.iter().map(|r| r.lines().count()).collect();
assert!(line_counts[0] >= line_counts[1]); assert!(line_counts[1] >= line_counts[2]); }
#[test]
fn test_config_combinations() {
let doc = Document {
blocks: vec![
Block::Table(Table {
rows: vec![
vec![vec![Inline::Text("Table".to_string())]],
vec![vec![Inline::Text("Data".to_string())]],
],
alignments: vec![Alignment::Center],
}),
Block::CodeBlock(CodeBlock {
kind: CodeBlockKind::Fenced {
info: Some("rust".to_string()),
},
literal: "fn main() {}".to_string(),
}),
],
};
let table_styles = vec![
TableStyle::Tabular,
TableStyle::Longtabu,
TableStyle::Booktabs,
];
let code_styles = vec![
CodeBlockStyle::Verbatim,
CodeBlockStyle::Listings,
CodeBlockStyle::Minted,
];
for table_style in &table_styles {
for code_style in &code_styles {
let config = Config::default()
.with_table_style(table_style.clone())
.with_code_block_style(code_style.clone())
.with_width(100);
let result = render_latex(&doc, config);
match table_style {
TableStyle::Tabular => assert!(result.contains(r"\begin{tabular}")),
TableStyle::Longtabu => assert!(result.contains(r"\begin{longtabu}")),
TableStyle::Booktabs => assert!(result.contains(r"\toprule")),
}
match code_style {
CodeBlockStyle::Verbatim => assert!(result.contains(r"\begin{verbatim}")),
CodeBlockStyle::Listings => assert!(result.contains(r"\begin{lstlisting}")),
CodeBlockStyle::Minted => assert!(result.contains(r"\begin{minted}")),
}
}
}
}
#[test]
fn test_config_builder_pattern() {
let doc = Document {
blocks: vec![Block::Paragraph(vec![Inline::Text("Test".to_string())])],
};
let config = Config::default()
.with_width(60)
.with_table_style(TableStyle::Booktabs)
.with_code_block_style(CodeBlockStyle::Minted);
let result = render_latex(&doc, config);
assert!(result.contains("Test"));
let complex_doc = Document {
blocks: vec![
Block::Table(Table {
rows: vec![vec![vec![Inline::Text("H".to_string())]]],
alignments: vec![Alignment::Left],
}),
Block::CodeBlock(CodeBlock {
kind: CodeBlockKind::Fenced {
info: Some("python".to_string()),
},
literal: "pass".to_string(),
}),
],
};
let config = Config::default()
.with_table_style(TableStyle::Booktabs)
.with_code_block_style(CodeBlockStyle::Minted);
let result = render_latex(&complex_doc, config);
assert!(result.contains(r"\toprule"));
assert!(result.contains(r"\begin{minted}{python}"));
}
#[test]
fn test_default_config() {
let doc = Document {
blocks: vec![
Block::Table(Table {
rows: vec![vec![vec![Inline::Text("Test".to_string())]]],
alignments: vec![Alignment::Left],
}),
Block::CodeBlock(CodeBlock {
kind: CodeBlockKind::Fenced {
info: Some("rust".to_string()),
},
literal: "test".to_string(),
}),
],
};
let result = render_latex(&doc, Config::default());
assert!(result.contains(r"\begin{tabular}"));
assert!(result.contains(r"\begin{verbatim}"));
assert!(!result.contains(r"\toprule"));
assert!(!result.contains(r"\begin{lstlisting}"));
assert!(!result.contains(r"\begin{minted}"));
}
#[test]
fn test_config_equality() {
let config1 = Config::default()
.with_width(80)
.with_table_style(TableStyle::Tabular)
.with_code_block_style(CodeBlockStyle::Verbatim);
let _config2 = Config::default()
.with_width(80)
.with_table_style(TableStyle::Tabular)
.with_code_block_style(CodeBlockStyle::Verbatim);
let config3 = Config::default()
.with_width(100)
.with_table_style(TableStyle::Tabular)
.with_code_block_style(CodeBlockStyle::Verbatim);
assert_ne!(config1.width, config3.width);
}
#[test]
fn test_mixed_content_with_different_configs() {
let doc = Document {
blocks: vec![
Block::Heading(Heading {
kind: HeadingKind::Atx(1),
content: vec![Inline::Text("Document Title".to_string())],
}),
Block::Paragraph(vec![
Inline::Text("This document contains a ".to_string()),
Inline::Strong(vec![Inline::Text("table".to_string())]),
Inline::Text(" and a ".to_string()),
Inline::Emphasis(vec![Inline::Text("code block".to_string())]),
Inline::Text(".".to_string()),
]),
Block::Table(Table {
rows: vec![
vec![
vec![Inline::Text("Feature".to_string())],
vec![Inline::Text("Status".to_string())],
],
vec![
vec![Inline::Text("Tables".to_string())],
vec![Inline::Text("✓".to_string())],
],
],
alignments: vec![Alignment::Left, Alignment::Center],
}),
Block::CodeBlock(CodeBlock {
kind: CodeBlockKind::Fenced {
info: Some("rust".to_string()),
},
literal: "fn render_latex() -> String {\n // Implementation\n}".to_string(),
}),
Block::List(List {
kind: ListKind::Bullet(ListBulletKind::Star),
items: vec![
ListItem {
task: Some(TaskState::Complete),
blocks: vec![Block::Paragraph(vec![Inline::Text(
"LaTeX printer implemented".to_string(),
)])],
},
ListItem {
task: Some(TaskState::Incomplete),
blocks: vec![Block::Paragraph(vec![Inline::Text(
"Documentation updated".to_string(),
)])],
},
],
}),
],
};
let configs = vec![
Config::default(),
Config::default()
.with_table_style(TableStyle::Booktabs)
.with_code_block_style(CodeBlockStyle::Listings),
Config::default()
.with_table_style(TableStyle::Longtabu)
.with_code_block_style(CodeBlockStyle::Minted)
.with_width(60),
];
for config in configs {
let result = render_latex(&doc, config);
assert!(result.contains(r"\section{Document Title}"));
assert!(result.contains(r"\textbf{table}"));
assert!(result.contains(r"\textit{code") && result.contains(r"block}"));
assert!(result.contains(r"\begin{itemize}"));
assert!(result.contains(r"$\boxtimes$"));
assert!(result.contains(r"$\square$"));
assert!(!result.trim().is_empty());
assert!(result.lines().count() > 10);
}
}