use rusty_figlet::export::{ExportFormat, write_export};
use rusty_figlet::filter::{Cell, Color, NamedColor, RenderGrid};
#[cfg(feature = "output-html")]
#[test]
fn html_emits_valid_html5() {
let grid = RenderGrid::from_text_rows(&[String::from("HELLO")]);
let bytes = write_export(&grid, ExportFormat::Html).expect("html ok");
let s = String::from_utf8(bytes).expect("utf-8");
assert!(s.contains("<pre>"));
assert!(s.contains("</pre>"));
assert!(s.contains("HELLO"));
let open = s.find("<pre>").expect("opens with <pre>");
let close = s.find("</pre>").expect("closes with </pre>");
assert!(open < close);
}
#[cfg(feature = "output-html")]
#[test]
fn html_escapes_script_tags() {
let cells = vec![
Cell::new('<'),
Cell::new('s'),
Cell::new('c'),
Cell::new('r'),
Cell::new('i'),
Cell::new('p'),
Cell::new('t'),
Cell::new('>'),
];
let grid = RenderGrid::from_rows(vec![cells]);
let bytes = write_export(&grid, ExportFormat::Html).expect("html ok");
let s = String::from_utf8(bytes).expect("utf-8");
assert!(s.contains("<script>"));
assert!(!s.contains("<script>"));
}
#[cfg(feature = "output-html")]
#[test]
fn html_escapes_attribute_injection() {
let cells: Vec<Cell> = "\"><img onerror=alert(1)>".chars().map(Cell::new).collect();
let grid = RenderGrid::from_rows(vec![cells]);
let bytes = write_export(&grid, ExportFormat::Html).expect("html ok");
let s = String::from_utf8(bytes).expect("utf-8");
assert!(s.contains("""));
assert!(s.contains("<img"));
assert!(!s.contains("<img"));
}
#[cfg(feature = "output-irc")]
#[test]
fn irc_emits_mirc_codes() {
let cell = Cell {
ch: 'R',
fg: Color::Named(NamedColor::Red),
bg: None,
attrs: 0,
};
let grid = RenderGrid::from_rows(vec![vec![cell]]);
let bytes = write_export(&grid, ExportFormat::Irc).expect("irc ok");
assert!(bytes.contains(&0x03));
assert!(bytes.contains(&0x0F));
assert!(bytes.contains(&b'R'));
}
#[cfg(feature = "output-irc")]
#[test]
fn irc_strips_non_printable() {
let row = vec![
Cell::new('\x00'),
Cell::new('\x07'),
Cell::new('\t'),
Cell::new('A'),
Cell::new('\x7F'),
Cell::new('\u{0085}'),
];
let grid = RenderGrid::from_rows(vec![row]);
let bytes = write_export(&grid, ExportFormat::Irc).expect("irc ok");
assert!(!bytes.contains(&0x00));
assert!(!bytes.contains(&0x07));
assert!(bytes.contains(&b'\t'));
assert!(bytes.contains(&b'A'));
assert!(!bytes.contains(&0x7F));
assert!(!bytes.contains(&0x85));
}
#[cfg(feature = "output-svg")]
#[test]
fn svg_emits_valid_xml() {
let grid = RenderGrid::from_text_rows(&[String::from("AB")]);
let bytes = write_export(&grid, ExportFormat::Svg).expect("svg ok");
let s = String::from_utf8(bytes).expect("utf-8");
assert!(s.starts_with("<?xml"));
assert!(s.contains("<svg "));
assert!(s.contains("</svg>"));
assert!(s.contains("<text "));
assert!(s.contains("xmlns=\"http://www.w3.org/2000/svg\""));
assert!(!s.contains("='"));
}
#[cfg(feature = "output-svg")]
#[test]
fn svg_contains_no_external_resource_attrs() {
let grid = RenderGrid::from_text_rows(&[String::from("test")]);
let bytes = write_export(&grid, ExportFormat::Svg).expect("svg ok");
let s = String::from_utf8(bytes).expect("utf-8");
assert!(!s.contains("xlink:href"));
assert!(!s.contains("<image"));
assert!(!s.contains("<use "));
assert!(!s.contains("<script"));
assert!(!s.contains("<foreignObject"));
assert!(!s.contains("style=\""));
}
#[cfg(feature = "output-svg")]
#[test]
fn svg_escapes_javascript_uri() {
let cells: Vec<Cell> = "javascript:alert(1)".chars().map(Cell::new).collect();
let grid = RenderGrid::from_rows(vec![cells]);
let bytes = write_export(&grid, ExportFormat::Svg).expect("svg ok");
let s = String::from_utf8(bytes).expect("utf-8");
assert!(!s.contains("href="));
assert!(!s.contains("xlink:"));
}
#[test]
fn leaf_disabled_returns_unsupported_export_format() {
let grid = RenderGrid::blank(1, 1);
let err = write_export(&grid, ExportFormat::AnsiTrue).unwrap_err();
match err {
rusty_figlet::FigletError::UnsupportedExportFormat {
requested,
available: _,
} => {
assert_eq!(requested, "ansi-true");
}
other => panic!("expected UnsupportedExportFormat, got {other:?}"),
}
}
#[cfg(feature = "output-html")]
#[test]
fn html_handles_cjk() {
let grid = RenderGrid::from_text_rows(&[String::from("中文字符")]);
let bytes = write_export(&grid, ExportFormat::Html).expect("html ok");
let s = String::from_utf8(bytes).expect("utf-8");
assert!(s.contains("中"));
assert!(s.contains("文"));
assert!(s.contains("字"));
assert!(s.contains("符"));
}
#[cfg(feature = "output-html")]
#[test]
fn html_handles_emoji() {
let grid = RenderGrid::from_text_rows(&[String::from("🦀🚀✨")]);
let bytes = write_export(&grid, ExportFormat::Html).expect("html ok");
let s = String::from_utf8(bytes).expect("utf-8");
assert!(s.contains("🦀"));
assert!(s.contains("🚀"));
assert!(s.contains("✨"));
}
#[cfg(feature = "output-svg")]
#[test]
fn svg_handles_arabic_rtl() {
let grid = RenderGrid::from_text_rows(&[String::from("مرحبا")]);
let bytes = write_export(&grid, ExportFormat::Svg).expect("svg ok");
let s = String::from_utf8(bytes).expect("utf-8");
assert!(s.contains("مرحبا"));
}
#[cfg(feature = "output-irc")]
#[test]
fn irc_handles_hebrew_rtl() {
let grid = RenderGrid::from_text_rows(&[String::from("שלום")]);
let bytes = write_export(&grid, ExportFormat::Irc).expect("irc ok");
let s = String::from_utf8_lossy(&bytes);
assert!(s.contains("ש"));
assert!(s.contains("ל"));
assert!(s.contains("ו"));
assert!(s.contains("ם"));
}