#![allow(missing_docs)]
use noyalib::{Value, from_str};
fn force_parse_error(source: &str) -> noyalib::Error {
from_str::<Value>(source).unwrap_err()
}
const INDENT_ERROR_SOURCE: &str = "\
header: ok
service:
nested: x
bad: y
trailer: ok
";
#[test]
fn radius_zero_renders_only_the_offending_line() {
let err = force_parse_error(INDENT_ERROR_SOURCE);
let formatted = err.format_with_source_radius(INDENT_ERROR_SOURCE, 0);
assert!(formatted.contains("error: "));
assert!(formatted.contains("line 4"));
assert!(formatted.contains("bad: y"));
assert!(formatted.contains("^"));
assert!(!formatted.contains("nested: x"));
assert!(!formatted.contains("trailer: ok"));
}
#[test]
fn radius_one_includes_one_line_above_and_below() {
let err = force_parse_error(INDENT_ERROR_SOURCE);
let formatted = err.format_with_source_radius(INDENT_ERROR_SOURCE, 1);
assert!(formatted.contains("nested: x"));
assert!(formatted.contains("trailer: ok"));
assert!(formatted.contains("bad: y"));
assert!(formatted.contains("^"));
}
#[test]
fn radius_clamped_at_file_boundaries() {
let err = force_parse_error(INDENT_ERROR_SOURCE);
let formatted = err.format_with_source_radius(INDENT_ERROR_SOURCE, 100);
assert!(formatted.contains("bad: y"));
assert!(formatted.contains("header: ok"));
assert!(formatted.contains("trailer: ok"));
}
#[test]
fn gutter_alignment_uses_widest_line_number() {
let mut source = String::new();
for i in 1..=20 {
source.push_str(&format!("line_{i}: ok\n"));
}
source.push_str("service:\n nested: x\n bad: y\n");
let err = force_parse_error(&source);
let formatted = err.format_with_source_radius(&source, 2);
assert!(formatted.contains("|"));
assert!(formatted.contains("bad: y"));
}
#[test]
fn caret_aligns_to_offending_column() {
let err = force_parse_error(INDENT_ERROR_SOURCE);
let formatted = err.format_with_source_radius(INDENT_ERROR_SOURCE, 0);
assert!(formatted.contains("|"));
assert!(formatted.contains("^"));
}
#[test]
fn no_location_falls_back_to_plain_display() {
use noyalib::Error;
let err = Error::EndOfStream;
let formatted = err.format_with_source_radius("anything", 5);
assert_eq!(formatted, format!("{err}"));
}
#[test]
fn empty_source_falls_back_to_plain_display() {
let err = force_parse_error(INDENT_ERROR_SOURCE);
let formatted = err.format_with_source_radius("", 0);
assert_eq!(formatted, format!("{err}"));
}
#[test]
fn format_with_source_unchanged_for_back_compat() {
let err = force_parse_error(INDENT_ERROR_SOURCE);
let formatted = err.format_with_source(INDENT_ERROR_SOURCE);
assert!(formatted.starts_with("error: "));
assert!(formatted.contains("--> line"));
let radial = err.format_with_source_radius(INDENT_ERROR_SOURCE, 0);
assert_ne!(formatted, radial);
}
#[test]
fn radius_two_includes_full_window() {
let source = "\
a: 1
b: 2
c: 3
service:
nested: x
bad: y
e: 5
f: 6
g: 7
";
let err = force_parse_error(source);
let formatted = err.format_with_source_radius(source, 2);
assert!(formatted.contains("bad: y"));
assert!(formatted.contains("nested: x"));
assert!(formatted.contains("service:"));
assert!(formatted.contains("e: 5"));
assert!(formatted.contains("f: 6"));
assert!(!formatted.contains("a: 1"));
}