diff --git a/crates/snapbox/src/data/format.rs b/crates/snapbox/src/data/format.rs index 07e4a75d..7ab71014 100644 --- a/crates/snapbox/src/data/format.rs +++ b/crates/snapbox/src/data/format.rs @@ -1,19 +1,26 @@ +/// Describes the structure of [`Data`][crate::Data] #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Default)] #[non_exhaustive] pub enum DataFormat { + /// Processing of the [`Data`][crate::Data] failed Error, + /// Non-textual, opaque data Binary, #[default] Text, #[cfg(feature = "json")] Json, + /// Streamed JSON output according to #[cfg(feature = "json")] JsonLines, + /// [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#DOS_and_Windows) + /// rendered as [svg](https://docs.rs/anstyle-svg) #[cfg(feature = "term-svg")] TermSvg, } impl DataFormat { + /// Assumed file extension for the format pub fn ext(self) -> &'static str { match self { Self::Error => "txt", diff --git a/crates/snapbox/src/data/mod.rs b/crates/snapbox/src/data/mod.rs index b7b5a51d..8c63c051 100644 --- a/crates/snapbox/src/data/mod.rs +++ b/crates/snapbox/src/data/mod.rs @@ -1,3 +1,5 @@ +//! `actual` and `expected` [`Data`] for testing code + mod format; mod runtime; mod source; @@ -7,8 +9,26 @@ mod tests; pub use format::DataFormat; pub use source::DataSource; pub use source::Inline; +#[doc(hidden)] pub use source::Position; +/// Capture the pretty debug representation of a value +/// +/// Note: this is fairly brittle as debug representations are not generally subject to semver +/// guarantees. +/// +/// ```rust,no_run +/// use snapbox::ToDebug as _; +/// +/// fn some_function() -> usize { +/// // ... +/// # 5 +/// } +/// +/// let actual = some_function(); +/// let expected = snapbox::str![["5"]]; +/// snapbox::assert_eq(actual.to_debug(), expected); +/// ``` pub trait ToDebug { fn to_debug(&self) -> Data; } @@ -110,14 +130,13 @@ pub(crate) enum DataInner { TermSvg(String), } +/// # Constructors +/// +/// See also +/// - [`str!`] for inline snapshots +/// - [`file!`] for external snapshots +/// - [`ToDebug`] for verifying a debug representation impl Data { - pub(crate) fn with_inner(inner: DataInner) -> Self { - Self { - inner, - source: None, - } - } - /// Mark the data as binary (no post-processing) pub fn binary(raw: impl Into>) -> Self { Self::with_inner(DataInner::Binary(raw.into())) @@ -150,15 +169,6 @@ impl Data { Self::text("") } - fn with_source(mut self, source: impl Into) -> Self { - self.source = Some(source.into()); - self - } - - fn with_path(self, path: impl Into) -> Self { - self.with_source(path.into()) - } - /// Load `expected` data from a file pub fn read_from(path: &std::path::Path, data_format: Option) -> Self { match Self::try_read_from(path, data_format) { @@ -167,6 +177,27 @@ impl Data { .with_path(path), } } +} + +/// # Assertion frameworks operations +/// +/// For example, see [`OutputAssert`][crate::cmd::OutputAssert] +impl Data { + pub(crate) fn with_inner(inner: DataInner) -> Self { + Self { + inner, + source: None, + } + } + + fn with_source(mut self, source: impl Into) -> Self { + self.source = Some(source.into()); + self + } + + fn with_path(self, path: impl Into) -> Self { + self.with_source(path.into()) + } /// Load `expected` data from a file pub fn try_read_from( @@ -195,11 +226,6 @@ impl Data { Ok(data.with_path(path)) } - /// Location the data came from - pub fn source(&self) -> Option<&DataSource> { - self.source.as_ref() - } - /// Overwrite a snapshot pub fn write_to(&self, source: &DataSource) -> Result<(), crate::Error> { match &source.inner { @@ -400,6 +426,11 @@ impl Data { Self { inner, source } } + /// Location the data came from + pub fn source(&self) -> Option<&DataSource> { + self.source.as_ref() + } + /// Outputs the current `DataFormat` of the underlying data pub fn format(&self) -> DataFormat { match &self.inner { diff --git a/crates/snapbox/src/data/source.rs b/crates/snapbox/src/data/source.rs index d2f1c81d..066ec7d5 100644 --- a/crates/snapbox/src/data/source.rs +++ b/crates/snapbox/src/data/source.rs @@ -1,3 +1,4 @@ +/// Origin of a snapshot so it can be updated #[derive(Clone, Debug, PartialEq, Eq)] pub struct DataSource { pub(crate) inner: DataSourceInner, @@ -68,7 +69,7 @@ impl std::fmt::Display for DataSource { } } -/// Data from within Rust source code +/// Output of [`str!`][crate::str!] #[derive(Clone, Debug, PartialEq, Eq)] pub struct Inline { #[doc(hidden)] @@ -81,18 +82,21 @@ impl Inline { /// Initialize `Self` as [`format`][crate::data::DataFormat] or [`Error`][crate::data::DataFormat::Error] /// /// This is generally used for `expected` data + /// + /// ```rust + /// # #[cfg(feature = "json")] { + /// use snapbox::str; + /// + /// let expected = str![[r#"{"hello": "world"}"#]] + /// .is(snapbox::data::DataFormat::Json); + /// assert_eq!(expected.format(), snapbox::data::DataFormat::Json); + /// # } + /// ``` pub fn is(self, format: super::DataFormat) -> super::Data { let data: super::Data = self.into(); data.is(format) } - /// Deprecated, replaced with [`Inline::is`] - #[deprecated(since = "0.5.2", note = "Replaced with `Inline::is`")] - pub fn coerce_to(self, format: super::DataFormat) -> super::Data { - let data: super::Data = self.into(); - data.coerce_to(format) - } - fn trimmed(&self) -> String { let mut data = self.data; if data.contains('\n') { @@ -117,6 +121,7 @@ impl From for super::Data { } /// Position within Rust source code, see [`Inline`] +#[doc(hidden)] #[derive(Clone, Debug, PartialEq, Eq)] pub struct Position { #[doc(hidden)] diff --git a/crates/snapbox/src/filters/mod.rs b/crates/snapbox/src/filters/mod.rs index b62c87f5..f515f60a 100644 --- a/crates/snapbox/src/filters/mod.rs +++ b/crates/snapbox/src/filters/mod.rs @@ -1,4 +1,4 @@ -//! Normalize `actual` or `expected` data +//! Normalize `actual` or `expected` [`Data`] //! //! This can be done for //! - Making snapshots consistent across platforms or conditional compilation