Skip to content

Commit

Permalink
feat(snapbox)!: Support custom panic messages
Browse files Browse the repository at this point in the history
Resolves assert-rs#223.
  • Loading branch information
not-my-profile committed Aug 18, 2023
1 parent 1231dd9 commit f4e924c
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 19 deletions.
44 changes: 37 additions & 7 deletions crates/snapbox/src/assert.rs
Expand Up @@ -21,17 +21,18 @@ use crate::Action;
/// .matches_path(actual, "tests/fixtures/help_output_is_clean.txt");
/// ```
#[derive(Clone, Debug)]
pub struct Assert {
pub struct Assert<'a> {
action: Action,
action_var: Option<String>,
normalize_paths: bool,
substitutions: crate::Substitutions,
pub(crate) palette: crate::report::Palette,
pub(crate) data_format: Option<DataFormat>,
message: Option<std::fmt::Arguments<'a>>,
}

/// # Assertions
impl Assert {
impl<'a> Assert<'a> {
pub fn new() -> Self {
Default::default()
}
Expand Down Expand Up @@ -288,14 +289,34 @@ impl Assert {
}
}

fn error_message(&self, message: &'static str) -> crate::report::Styled<&str> {
self.palette.error(message)
fn error_message(
&self,
default_message: &'static str,
) -> crate::report::Styled<ErrorMessage<'a>> {
self.palette.error(match self.message {
Some(custom_message) => ErrorMessage::Custom(custom_message),
None => ErrorMessage::Default(default_message),
})
}
}

enum ErrorMessage<'a> {
Default(&'static str),
Custom(std::fmt::Arguments<'a>),
}

impl std::fmt::Display for ErrorMessage<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ErrorMessage::Default(err) => write!(f, "{err}"),
ErrorMessage::Custom(err) => write!(f, "{err}"),
}
}
}

/// # Directory Assertions
#[cfg(feature = "path")]
impl Assert {
impl Assert<'_> {
#[track_caller]
pub fn subset_eq(
&self,
Expand Down Expand Up @@ -456,7 +477,7 @@ impl Assert {
}

/// # Customize Behavior
impl Assert {
impl<'a> Assert<'a> {
/// Override the color palette
pub fn palette(mut self, palette: crate::report::Palette) -> Self {
self.palette = palette;
Expand All @@ -478,6 +499,14 @@ impl Assert {
self
}

/// Override the panic message.
///
/// Currently only supported by `eq`, `eq_path`, `matches` and `matches_path`.
pub fn message(mut self, args: std::fmt::Arguments<'a>) -> Self {
self.message = Some(args);
self
}

/// Override the default [`Substitutions`][crate::Substitutions]
pub fn substitutions(mut self, substitutions: crate::Substitutions) -> Self {
self.substitutions = substitutions;
Expand Down Expand Up @@ -509,7 +538,7 @@ impl Assert {
}
}

impl Default for Assert {
impl Default for Assert<'_> {
fn default() -> Self {
Self {
action: Default::default(),
Expand All @@ -518,6 +547,7 @@ impl Default for Assert {
substitutions: Default::default(),
palette: crate::report::Palette::color(),
data_format: Default::default(),
message: Default::default(),
}
.substitutions(crate::Substitutions::with_exe())
}
Expand Down
22 changes: 11 additions & 11 deletions crates/snapbox/src/cmd.rs
Expand Up @@ -5,16 +5,16 @@ use anstream::panic;

/// Process spawning for testing of non-interactive commands
#[derive(Debug)]
pub struct Command {
pub struct Command<'a> {
cmd: std::process::Command,
stdin: Option<crate::Data>,
timeout: Option<std::time::Duration>,
_stderr_to_stdout: bool,
config: crate::Assert,
config: crate::Assert<'a>,
}

/// # Builder API
impl Command {
impl<'a> Command<'a> {
pub fn new(program: impl AsRef<std::ffi::OsStr>) -> Self {
Self {
cmd: std::process::Command::new(program),
Expand All @@ -37,7 +37,7 @@ impl Command {
}

/// Customize the assertion behavior
pub fn with_assert(mut self, config: crate::Assert) -> Self {
pub fn with_assert(mut self, config: crate::Assert<'a>) -> Self {
self.config = config;
self
}
Expand Down Expand Up @@ -275,7 +275,7 @@ impl Command {
}

/// # Run Command
impl Command {
impl<'a> Command<'a> {
/// Run the command and assert on the results
///
/// ```rust
Expand All @@ -288,7 +288,7 @@ impl Command {
/// .stdout_eq("42");
/// ```
#[track_caller]
pub fn assert(self) -> OutputAssert {
pub fn assert(self) -> OutputAssert<'a> {
let config = self.config.clone();
match self.output() {
Ok(output) => OutputAssert::new(output).with_assert(config),
Expand Down Expand Up @@ -424,7 +424,7 @@ where
})
}

impl From<std::process::Command> for Command {
impl From<std::process::Command> for Command<'_> {
fn from(cmd: std::process::Command) -> Self {
Self::from_std(cmd)
}
Expand All @@ -435,12 +435,12 @@ impl From<std::process::Command> for Command {
/// Create an `OutputAssert` through the [`Command::assert`].
///
/// [`Output`]: std::process::Output
pub struct OutputAssert {
pub struct OutputAssert<'a> {
output: std::process::Output,
config: crate::Assert,
config: crate::Assert<'a>,
}

impl OutputAssert {
impl<'a> OutputAssert<'a> {
/// Create an `Assert` for a given [`Output`].
///
/// [`Output`]: std::process::Output
Expand All @@ -452,7 +452,7 @@ impl OutputAssert {
}

/// Customize the assertion behavior
pub fn with_assert(mut self, config: crate::Assert) -> Self {
pub fn with_assert(mut self, config: crate::Assert<'a>) -> Self {
self.config = config;
self
}
Expand Down
5 changes: 4 additions & 1 deletion src/schema.rs
Expand Up @@ -806,7 +806,10 @@ impl Env {
self.remove.extend(other.remove.iter().cloned());
}

pub(crate) fn apply(&self, mut command: snapbox::cmd::Command) -> snapbox::cmd::Command {
pub(crate) fn apply<'a>(
&self,
mut command: snapbox::cmd::Command<'a>,
) -> snapbox::cmd::Command<'a> {
if !self.inherit() {
command = command.env_clear();
}
Expand Down

0 comments on commit f4e924c

Please sign in to comment.