From 6a856f428ecce9f6cfdc7b08e36736ea7e44f444 Mon Sep 17 00:00:00 2001 From: Adam Curtis Date: Thu, 9 Nov 2023 15:10:10 -0500 Subject: [PATCH] add tests for syntax highlighting --- Cargo.toml | 1 + tests/graphical.rs | 97 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 3e4d9ab..36e3236 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ regex = "1.5" lazy_static = "1.4" serde_json = "1.0.64" +strip-ansi-escapes = "0.2.0" [features] default = ["derive"] diff --git a/tests/graphical.rs b/tests/graphical.rs index 24bfbc2..e2f2f8c 100644 --- a/tests/graphical.rs +++ b/tests/graphical.rs @@ -1715,3 +1715,100 @@ fn single_line_with_wide_char_unaligned_span_empty() -> Result<(), MietteError> assert_eq!(expected, out); Ok(()) } + +#[test] +#[cfg(feature = "syntect-highlighter")] +fn syntax_highlighter() { + std::env::set_var("REPLACE_TABS", "4"); + #[derive(Debug, Error, Diagnostic)] + #[error("This is an error")] + #[diagnostic()] + pub struct Test { + #[source_code] + src: NamedSource, + #[label("this is a label")] + src_span: SourceSpan, + } + let src = NamedSource::new( + "hello_world", //NOTE: intentionally missing file extension + "fn main() {\n println!(\"Hello, World!\");\n}\n".to_string(), + ) + .with_language("Rust"); + let err = Test { + src, + src_span: (16, 26).into(), + }; + let mut out = String::new(); + GraphicalReportHandler::new_themed(GraphicalTheme::unicode()) + .render_report(&mut out, &err) + .unwrap(); + let expected = r#" × This is an error + ╭─[hello_world:2:5] + 1 │ fn main() { + 2 │ println!("Hello, World!"); + · ─────────────┬──────────── + · ╰── this is a label + 3 │ } + ╰──── +"#; + assert!(out.contains("\u{1b}[38;2;180;142;173m")); + assert_eq!(expected, strip_ansi_escapes::strip_str(out)) +} + +// This test reads a line from the current source file and renders it with Rust +// syntax highlighting. The goal is to test syntax highlighting on a non-trivial +// source code example. However, if tests are running in an environment where +// source files are missing, this will cause problems. In that case, it would +// be better to use include_str!() on a sufficiently complex example file. +#[test] +#[cfg(feature = "syntect-highlighter")] +fn syntax_highlighter_on_real_file() { + std::env::set_var("REPLACE_TABS", "4"); + + #[derive(Debug, Error, Diagnostic)] + #[error("This is an error")] + #[diagnostic()] + pub struct Test { + #[source_code] + src: NamedSource, + #[label("this is a label")] + src_span: SourceSpan, + } + // BEGIN SOURCE SNIPPET + + let (filename, line) = (file!(), line!() as usize); + + // END SOURCE SNIPPET + // SourceSpan constants for column and length + const CO: usize = 28; + const LEN: usize = 27; + let file_src = std::fs::read_to_string(&filename).unwrap(); + let offset = miette::SourceOffset::from_location(&file_src, line, CO); + let err = Test { + src: NamedSource::new(&filename, file_src.clone()), + src_span: SourceSpan::new(offset, LEN.into()), + }; + + let mut out = String::new(); + GraphicalReportHandler::new_themed(GraphicalTheme::unicode()) + .with_context_lines(1) + .render_report(&mut out, &err) + .unwrap(); + + let expected = format!( + r#" × This is an error + ╭─[{filename}:{l2}:{CO}] + {l1} │ + {l2} │ let (filename, line) = (file!(), line!() as usize); + · ─────────────┬───────────── + · ╰── this is a label + {l3} │ + ╰──── +"#, + l1 = line - 1, + l2 = line, + l3 = line + 1 + ); + assert!(out.contains("\u{1b}[38;2;180;142;173m")); + assert_eq!(expected, strip_ansi_escapes::strip_str(out)); +}