Skip to content

Commit

Permalink
Merge pull request #309 from epage/docs
Browse files Browse the repository at this point in the history
docs(data): Clarify how to use the API
  • Loading branch information
epage committed May 15, 2024
2 parents 92bf621 + e46c53d commit f4ce057
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 22 deletions.
6 changes: 6 additions & 0 deletions crates/snapbox/src/data/format.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
/// Describes the structure of [`Data`][crate::Data]
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Default)]
pub enum DataFormat {
/// Processing of the [`Data`][crate::Data] failed
Error,
/// Non-textual, opaque data
Binary,
#[default]
Text,
#[cfg(feature = "json")]
Json,
/// [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",
Expand Down
73 changes: 52 additions & 21 deletions crates/snapbox/src/data/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! `actual` and `expected` [`Data`] for testing code

mod format;
mod normalize;
mod runtime;
Expand All @@ -12,8 +14,26 @@ pub use normalize::NormalizeNewlines;
pub use normalize::NormalizePaths;
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;
}
Expand Down Expand Up @@ -113,14 +133,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<Vec<u8>>) -> Self {
Self::with_inner(DataInner::Binary(raw.into()))
Expand Down Expand Up @@ -148,15 +167,6 @@ impl Data {
Self::text("")
}

fn with_source(mut self, source: impl Into<DataSource>) -> Self {
self.source = Some(source.into());
self
}

fn with_path(self, path: impl Into<std::path::PathBuf>) -> Self {
self.with_source(path.into())
}

/// Load `expected` data from a file
pub fn read_from(path: &std::path::Path, data_format: Option<DataFormat>) -> Self {
match Self::try_read_from(path, data_format) {
Expand All @@ -165,6 +175,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<DataSource>) -> Self {
self.source = Some(source.into());
self
}

fn with_path(self, path: impl Into<std::path::PathBuf>) -> Self {
self.with_source(path.into())
}

/// Load `expected` data from a file
pub fn try_read_from(
Expand Down Expand Up @@ -193,11 +224,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 {
Expand Down Expand Up @@ -382,6 +408,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 {
Expand Down
6 changes: 6 additions & 0 deletions crates/snapbox/src/data/normalize.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
//! Normalize `actual` or `expected` [`Data`]
//!
//! This can be done for
//! - Making snapshots consistent across platforms or conditional compilation
//! - Focusing snapshots on the characteristics of the data being tested

use super::Data;
use super::DataInner;

Expand Down
14 changes: 13 additions & 1 deletion crates/snapbox/src/data/source.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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)]
Expand All @@ -89,6 +90,16 @@ 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)
Expand Down Expand Up @@ -148,6 +159,7 @@ impl From<Inline> for super::Data {
}

/// Position within Rust source code, see [`Inline`]
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Position {
#[doc(hidden)]
Expand Down

0 comments on commit f4ce057

Please sign in to comment.