use term_maths::render;
fn render_lines(latex: &str) -> Vec<String> {
let block = render(latex);
let output = format!("{}", block);
output.lines().map(|l| l.trim_end().to_string()).collect()
}
#[test]
fn test_simple_fraction() {
let lines = render_lines(r"\frac{a}{b}");
assert_eq!(lines, vec![" a", "───", " b"]);
}
#[test]
fn test_nested_fraction() {
let lines = render_lines(r"\frac{1}{1+\frac{1}{x}}");
assert_eq!(lines.len(), 5);
assert!(lines[0].contains('1'));
assert!(lines[1].chars().all(|c| c == '─'));
assert!(lines[3].contains('+'));
}
#[test]
fn test_superscript() {
let lines = render_lines(r"x^2");
assert_eq!(lines.len(), 1);
assert_eq!(lines[0], "x²");
}
#[test]
fn test_subscript() {
let lines = render_lines(r"a_n");
assert_eq!(lines.len(), 1);
assert_eq!(lines[0], "aₙ");
}
#[test]
fn test_supsub() {
let lines = render_lines(r"x_i^2");
assert_eq!(lines.len(), 1);
assert_eq!(lines[0], "x²ᵢ");
}
#[test]
fn test_superscript_fallback() {
let lines = render_lines(r"e^{i\pi}");
assert!(lines.len() >= 2);
let joined = lines.join("\n");
assert!(joined.contains('π'));
assert!(joined.contains('e'));
}
#[test]
fn test_horizontal_sequence() {
let block = render(r"a + b");
assert_eq!(block.height(), 1);
let output = format!("{}", block);
assert!(output.contains("a"));
assert!(output.contains("+"));
assert!(output.contains("b"));
}
#[test]
fn test_sqrt() {
let lines = render_lines(r"\sqrt{x}");
assert!(lines[0].contains('─'));
assert!(lines.iter().any(|l| l.contains('√')));
assert!(lines.iter().any(|l| l.contains('x')));
}
#[test]
fn test_euler_identity() {
let lines = render_lines(r"e^{i\pi} + 1 = 0");
assert!(lines.len() >= 2);
let joined = lines.join("\n");
assert!(joined.contains('π'));
assert!(joined.contains('0'));
}
#[test]
fn test_quadratic_formula() {
let lines = render_lines(r"\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}");
assert!(lines.len() >= 3); assert!(lines.iter().any(|l| l.contains('─') && !l.contains('√')));
let joined = lines.join("\n");
assert!(joined.contains('√'));
assert!(joined.contains("2a"));
}
#[test]
fn test_empty_input() {
let block = render("");
assert!(block.is_empty() || block.height() <= 1);
}
#[test]
fn test_single_symbol() {
let block = render(r"\alpha");
assert_eq!(block.height(), 1);
let output = format!("{}", block);
assert!(output.contains('α'));
}
#[test]
fn test_fraction_baseline_alignment() {
let lines = render_lines(r"x + \frac{a}{b}");
let bar_row = lines.iter().position(|l| l.contains('─')).unwrap();
assert!(lines[bar_row].contains('x') || lines[bar_row].contains('+'));
}
#[test]
fn test_dft_summation() {
let lines = render_lines(r"X[k] = \sum_{n=0}^{N-1} x[n] \cdot e^{-j \frac{2\pi}{N} kn}");
let joined = lines.join("\n");
assert!(joined.contains('∑'), "missing Σ");
assert!(
joined.contains("N - 1") || joined.contains("N-1"),
"missing upper limit"
);
assert!(
joined.contains("n = 0") || joined.contains("n=0"),
"missing lower limit"
);
assert!(joined.contains('π'), "missing π in exponent");
assert!(lines.len() >= 3, "DFT should be at least 3 lines tall");
}
#[test]
fn test_convolution_integral() {
let lines = render_lines(r"(f * g)(t) = \int_{-\infty}^{\infty} f(\tau) g(t - \tau) \, d\tau");
let joined = lines.join("\n");
assert!(
joined.contains('⌠') || joined.contains('∫'),
"missing integral symbol"
);
assert!(joined.contains('∞'), "missing infinity");
assert!(joined.contains("-∞"), "missing negative infinity");
assert!(joined.contains('τ'), "missing tau");
assert!(
lines.len() >= 3,
"convolution integral should be at least 3 lines"
);
}
#[test]
fn test_transfer_function() {
let lines =
render_lines(r"H(z) = \frac{b_0 + b_1 z^{-1} + b_2 z^{-2}}{1 + a_1 z^{-1} + a_2 z^{-2}}");
let joined = lines.join("\n");
assert!(
lines.iter().any(|l| l.contains('─')),
"missing fraction bar"
);
assert!(joined.contains('₀') || joined.contains("b_0"), "missing b₀");
assert!(joined.contains('₁') || joined.contains("b_1"), "missing b₁");
assert!(joined.contains("z⁻¹"), "missing z⁻¹");
assert!(
lines.len() >= 3,
"transfer function should be at least 3 lines"
);
}
#[test]
fn test_hann_window() {
let lines = render_lines(r"w(n) = 0.5 \left(1 - \cos\left(\frac{2\pi n}{N - 1}\right)\right)");
let joined = lines.join("\n");
assert!(joined.contains("cos"), "missing cos");
assert!(joined.contains('π'), "missing π");
assert!(
joined.contains('⎛') || joined.contains('('),
"missing delimiter"
);
assert!(joined.contains("N - 1"), "missing N - 1 denominator");
assert!(lines.len() >= 2, "Hann window should be at least 2 lines");
}
#[test]
fn test_integral_multirow() {
let lines = render_lines(r"\int_{0}^{1}");
let joined = lines.join("\n");
assert!(joined.contains('⌠'), "missing ⌠ top piece");
assert!(joined.contains('⌡'), "missing ⌡ bottom piece");
}
#[test]
fn test_sum_with_limits() {
let lines = render_lines(r"\sum_{i=1}^{n}");
let joined = lines.join("\n");
assert!(joined.contains('∑'), "missing Σ");
assert!(
lines.len() >= 3,
"sum with limits should be at least 3 lines"
);
}
#[test]
fn test_scaled_delimiters() {
let lines = render_lines(r"\left(\frac{a}{b}\right)");
let joined = lines.join("\n");
assert!(
joined.contains('⎛') && joined.contains('⎝'),
"missing scaled parentheses"
);
assert!(joined.contains('─'), "missing fraction bar");
}
#[test]
fn test_overline() {
let lines = render_lines(r"\overline{abc}");
assert_eq!(lines.len(), 2);
assert!(lines[0].contains('‾'), "missing overline character");
assert!(lines[1].contains("abc"), "missing body");
}
#[test]
fn test_accent_hat() {
let lines = render_lines(r"\hat{x}");
assert_eq!(lines.len(), 2);
assert!(lines[0].contains('^'), "missing hat");
assert!(lines[1].contains('x'), "missing body");
}
#[test]
fn test_accent_vec() {
let lines = render_lines(r"\vec{v}");
assert_eq!(lines.len(), 2);
assert!(lines[0].contains('→'), "missing arrow");
assert!(lines[1].contains('v'), "missing body");
}
#[test]
fn test_sqrt_of_fraction() {
let lines = render_lines(r"\sqrt{\frac{a}{b}}");
let joined = lines.join("\n");
assert!(joined.contains('√'), "missing radical");
assert!(joined.contains('─'), "missing overline or fraction bar");
assert!(lines.len() >= 3, "sqrt of fraction should be multi-line");
}
#[test]
fn test_pmatrix_2x2() {
let lines = render_lines(r"\begin{pmatrix} a & b \\ c & d \end{pmatrix}");
let joined = lines.join("\n");
assert!(
joined.contains('⎛') || joined.contains('('),
"missing left paren"
);
assert!(
joined.contains('⎞') || joined.contains(')'),
"missing right paren"
);
for ch in ['a', 'b', 'c', 'd'] {
assert!(joined.contains(ch), "missing entry {}", ch);
}
}
#[test]
fn test_bmatrix_identity() {
let lines = render_lines(r"\begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}");
let joined = lines.join("\n");
assert!(
joined.contains('⎡') || joined.contains('['),
"missing left bracket"
);
assert!(
joined.contains('⎤') || joined.contains(']'),
"missing right bracket"
);
}
#[test]
fn test_vmatrix_determinant() {
let lines = render_lines(r"\begin{vmatrix} a & b \\ c & d \end{vmatrix}");
let joined = lines.join("\n");
assert!(joined.contains('│'), "missing vertical bar delimiter");
}
#[test]
fn test_matrix_with_fractions() {
let lines = render_lines(r"\begin{pmatrix} \frac{1}{2} & 0 \\ 0 & \frac{3}{4} \end{pmatrix}");
let joined = lines.join("\n");
assert!(joined.contains('─'), "missing fraction bar");
assert!(joined.contains('1') && joined.contains('2'), "missing 1/2");
assert!(joined.contains('3') && joined.contains('4'), "missing 3/4");
assert!(
lines.len() >= 4,
"matrix with fractions should be at least 4 lines"
);
}
#[test]
fn test_3x3_matrix() {
let lines = render_lines(r"\begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix}");
let joined = lines.join("\n");
for d in '1'..='9' {
assert!(joined.contains(d), "missing digit {}", d);
}
assert!(lines.len() >= 3, "3x3 matrix should be at least 3 lines");
}
#[test]
fn test_mathbb_double_struck() {
let block = render(r"\mathbb{R}");
let output = format!("{}", block);
assert_eq!(output.trim(), "ℝ");
}
#[test]
fn test_mathbb_integers() {
let block = render(r"\mathbb{Z}");
let output = format!("{}", block);
assert_eq!(output.trim(), "ℤ");
}
#[test]
fn test_mathcal_script() {
let block = render(r"\mathcal{L}");
let output = format!("{}", block);
assert_eq!(output.trim(), "ℒ");
}
#[test]
fn test_mathbf_bold() {
let block = render(r"\mathbf{x}");
let output = format!("{}", block);
assert_eq!(output.trim(), "𝐱");
}
#[test]
fn test_mathfrak_fraktur() {
let block = render(r"\mathfrak{g}");
let output = format!("{}", block);
assert_eq!(output.trim(), "𝔤");
}
#[test]
fn test_mathbb_with_superscript() {
let lines = render_lines(r"\mathbb{R}^n");
assert_eq!(lines.len(), 1);
let output = &lines[0];
assert!(output.contains('ℝ'), "missing double-struck R");
assert!(output.contains('ⁿ'), "missing superscript n");
}
#[test]
fn test_mathsf_sans_serif() {
let block = render(r"\mathsf{ABC}");
let output = format!("{}", block);
assert!(output.contains('𝖠'), "missing sans-serif A");
assert!(output.contains('𝖡'), "missing sans-serif B");
assert!(output.contains('𝖢'), "missing sans-serif C");
}
#[test]
fn test_mathtt_monospace() {
let block = render(r"\mathtt{code}");
let output = format!("{}", block);
assert!(output.contains('𝚌'), "missing monospace c");
}