use std::fmt;
use std::fmt::Formatter;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum SpecError {
Unnamed {
spec_violations: Vec<String>,
},
Named {
spec_violations: Vec<String>,
name: String,
}
}
impl SpecError {
pub fn unnamed(errors: Vec<String>) -> SpecError {
SpecError::Unnamed { spec_violations: errors }
}
pub fn errors(&self) -> &Vec<String> {
match self {
SpecError::Unnamed { spec_violations } => spec_violations,
SpecError::Named { spec_violations, .. } => spec_violations
}
}
#[cfg(test)]
pub fn contains(&self, error: &str) -> bool {
self.errors().contains(&error.to_string())
}
pub fn is_named(&self) -> bool {
match self {
SpecError::Named { .. } => true,
SpecError::Unnamed { .. } => false
}
}
pub fn named(self, spec_name: &str) -> SpecError {
match self {
SpecError::Unnamed { spec_violations } => {
SpecError::Named { name: spec_name.to_string(), spec_violations }
},
SpecError::Named { spec_violations, .. } => {
SpecError::Named { name: spec_name.to_string(), spec_violations }
}
}
}
}
impl fmt::Display for SpecError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
SpecError::Unnamed { spec_violations } => {
write!(f, "Spec failed: {}", spec_violations.join(", "))
},
SpecError::Named { name, spec_violations } => {
write!(f, "'{}' spec failed: {}", name, spec_violations.join(", "))
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn create_an_unnamed_spec_error() {
let error = SpecError::unnamed(vec!["some error".into()]);
assert!(!error.is_named());
assert_eq!("Spec failed: some error", error.to_string());
}
#[test]
fn create_a_named_spec_error() {
let error = SpecError::unnamed(vec!["some error".into()]).named("something");
assert!(error.is_named());
assert_eq!("'something' spec failed: some error", error.to_string());
}
}