use std::path::{Path, PathBuf};
use rskit_errors::{AppError, AppResult};
use rskit_fs::sync_io::file;
use rskit_util::env;
use super::matcher::Match;
pub const BLESS_ENV: &str = "RSKIT_BLESS";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GoldenMode {
Verify,
Bless,
}
impl GoldenMode {
#[must_use]
pub fn from_env() -> Self {
if env::get_non_empty(BLESS_ENV).is_some() {
Self::Bless
} else {
Self::Verify
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GoldenOutcome {
Verified,
Blessed,
}
#[derive(Debug, Clone)]
pub struct Golden {
path: PathBuf,
matcher: Match,
}
impl Golden {
#[must_use]
pub fn new(path: impl Into<PathBuf>, matcher: Match) -> Self {
Self {
path: path.into(),
matcher,
}
}
#[must_use]
pub fn path(&self) -> &Path {
&self.path
}
pub fn verify(&self, actual: &str) -> AppResult<GoldenOutcome> {
self.run(actual, GoldenMode::from_env())
}
pub fn run(&self, actual: &str, mode: GoldenMode) -> AppResult<GoldenOutcome> {
match mode {
GoldenMode::Bless => {
file::create_parent_dir(&self.path)?;
file::write(&self.path, self.matcher.normalize(actual))?;
Ok(GoldenOutcome::Blessed)
}
GoldenMode::Verify => {
if !file::exists(&self.path)? {
return Err(AppError::not_found(
"golden file",
Some(&self.path.display().to_string()),
)
.hint(format!("set {BLESS_ENV}=1 to generate it from live output")));
}
let expected = file::read_string(&self.path)?;
self.matcher
.verify(&expected, actual)
.map_err(|err| err.with_detail("golden", self.path.display().to_string()))?;
Ok(GoldenOutcome::Verified)
}
}
}
}