use error_engine::{Catalog, EngineError, UNKNOWN_CODE};
fn write_temp_toml(contents: &str) -> tempfile_path::TempPath {
tempfile_path::TempPath::new(contents)
}
mod tempfile_path {
use std::path::{Path, PathBuf};
pub struct TempPath {
path: PathBuf,
}
impl TempPath {
pub fn new(contents: &str) -> Self {
let mut path = std::env::temp_dir();
let unique = format!(
"error-engine-test-{}-{}.toml",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
);
path.push(unique);
std::fs::write(&path, contents).unwrap();
Self { path }
}
pub fn as_str(&self) -> &str {
self.path.to_str().unwrap()
}
}
impl Drop for TempPath {
fn drop(&mut self) {
let _ = std::fs::remove_file(&self.path);
}
}
impl AsRef<Path> for TempPath {
fn as_ref(&self) -> &Path {
&self.path
}
}
}
const VALID_CATALOG: &str = r#"
[CONFIG_NOT_FOUND]
template = "Could not find the configuration file at {path}"
hint = "Check that the path is correct"
[DB_CONN_FAILED]
template = "Could not connect to the database: {reason}"
"#;
#[test]
fn load_valid_toml_and_render_existing_code() {
let file = write_temp_toml(VALID_CATALOG);
let catalog = Catalog::load(file.as_str()).expect("valid catalog should load");
let rendered = catalog.render("CONFIG_NOT_FOUND", &[("path", "/etc/app.toml".to_string())]);
assert_eq!(rendered, "Could not find the configuration file at /etc/app.toml");
}
#[test]
fn load_missing_path_returns_catalog_read_error() {
let result = Catalog::load("/definitely/does/not/exist/errors.toml");
assert!(matches!(result, Err(EngineError::CatalogRead { .. })));
}
#[test]
fn load_malformed_toml_returns_catalog_parse_error() {
let file = write_temp_toml("this is not valid = = toml [[[");
let result = Catalog::load(file.as_str());
assert!(matches!(result, Err(EngineError::CatalogParse { .. })));
}
#[test]
fn load_or_fallback_never_panics_on_missing_file() {
let catalog = Catalog::load_or_fallback("/definitely/does/not/exist/errors.toml");
let rendered = catalog.render("ANY_CODE", &[]);
assert!(rendered.contains(UNKNOWN_CODE));
}
#[test]
fn render_with_load_error_returns_unk_000_for_any_code() {
let catalog = Catalog::load_or_fallback("/definitely/does/not/exist/errors.toml");
let rendered = catalog.render("CONFIG_NOT_FOUND", &[]);
assert!(rendered.contains(UNKNOWN_CODE));
assert!(rendered.contains("catalog failed to load"));
}
#[test]
fn render_unknown_code_on_valid_catalog_returns_unk_000() {
let file = write_temp_toml(VALID_CATALOG);
let catalog = Catalog::load(file.as_str()).expect("valid catalog should load");
let rendered = catalog.render("NOT_A_REAL_CODE", &[]);
assert!(rendered.contains(UNKNOWN_CODE));
assert!(rendered.contains("NOT_A_REAL_CODE"));
}
#[test]
fn placeholder_with_no_context_value_stays_literal() {
let file = write_temp_toml(VALID_CATALOG);
let catalog = Catalog::load(file.as_str()).expect("valid catalog should load");
let rendered = catalog.render("DB_CONN_FAILED", &[]);
assert_eq!(rendered, "Could not connect to the database: {reason}");
}
#[test]
fn hint_returns_none_on_load_failure() {
let catalog = Catalog::load_or_fallback("/definitely/does/not/exist/errors.toml");
assert_eq!(catalog.hint("CONFIG_NOT_FOUND"), None);
}
#[test]
fn hint_returns_none_on_missing_code() {
let file = write_temp_toml(VALID_CATALOG);
let catalog = Catalog::load(file.as_str()).expect("valid catalog should load");
assert_eq!(catalog.hint("NOT_A_REAL_CODE"), None);
}
#[test]
fn hint_returns_value_when_present() {
let file = write_temp_toml(VALID_CATALOG);
let catalog = Catalog::load(file.as_str()).expect("valid catalog should load");
assert_eq!(catalog.hint("CONFIG_NOT_FOUND"), Some("Check that the path is correct"));
}