diff --git a/Cargo.lock b/Cargo.lock index f9ce40d6..d29eff3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -810,6 +810,7 @@ dependencies = [ "libtest-mimic", "normalize-line-endings", "os_pipe", + "serde", "serde_json", "similar", "snapbox-macros", diff --git a/crates/snapbox/Cargo.toml b/crates/snapbox/Cargo.toml index 9e5760e8..37f7319f 100644 --- a/crates/snapbox/Cargo.toml +++ b/crates/snapbox/Cargo.toml @@ -46,7 +46,7 @@ cmd = ["dep:os_pipe", "dep:wait-timeout", "dep:libc", "dep:windows-sys"] examples = ["dep:escargot"] ## Snapshotting of json -json = ["structured-data", "dep:serde_json"] +json = ["structured-data", "dep:serde_json", "dep:serde"] ## Snapshotting of term styling term-svg = ["structured-data", "dep:anstyle-svg"] ## Snapshotting of structured data @@ -96,6 +96,7 @@ document-features = { version = "0.2.6", optional = true } serde_json = { version = "1.0.85", optional = true} anstyle-svg = { version = "0.1.3", optional = true } +serde = { version = "1.0.198", optional = true } [target.'cfg(windows)'.dependencies] windows-sys = { version = "0.52.0", features = ["Win32_Foundation"], optional = true } diff --git a/crates/snapbox/src/data/mod.rs b/crates/snapbox/src/data/mod.rs index 7d9485d6..a47a12e2 100644 --- a/crates/snapbox/src/data/mod.rs +++ b/crates/snapbox/src/data/mod.rs @@ -50,6 +50,37 @@ impl ToDebug for D { } } +/// Capture the serde representation of a value +/// +/// # Examples +/// +/// ```rust,no_run +/// use snapbox::IntoJson as _; +/// +/// fn some_function() -> usize { +/// // ... +/// # 5 +/// } +/// +/// let actual = some_function(); +/// let expected = snapbox::str![["5"]]; +/// snapbox::assert_eq(actual.into_json(), expected); +/// ``` +#[cfg(feature = "json")] +pub trait IntoJson { + fn into_json(self) -> Data; +} + +#[cfg(feature = "json")] +impl IntoJson for S { + fn into_json(self) -> Data { + match serde_json::to_value(self) { + Ok(value) => Data::json(value), + Err(err) => Data::error(err.to_string(), DataFormat::Json), + } + } +} + /// Convert to [`Data`] with modifiers for `expected` data pub trait IntoData: Sized { /// Remove default [`filters`][crate::filter] from this `expected` result @@ -189,6 +220,7 @@ pub(crate) enum DataInner { /// - [`file!`] for external snapshots /// - [`ToString`] for verifying a `Display` representation /// - [`ToDebug`] for verifying a debug representation +/// - [`IntoJson`] for verifying the serde representation /// - [`IntoData`] for modifying `expected` impl Data { /// Mark the data as binary (no post-processing) diff --git a/crates/snapbox/src/lib.rs b/crates/snapbox/src/lib.rs index 5f62ed24..44aa3ed2 100644 --- a/crates/snapbox/src/lib.rs +++ b/crates/snapbox/src/lib.rs @@ -114,6 +114,8 @@ pub use assert::Action; pub use assert::Assert; pub use data::Data; pub use data::IntoData; +#[cfg(feature = "json")] +pub use data::IntoJson; pub use data::ToDebug; pub use filter::RedactedValue; pub use filter::Redactions; @@ -134,6 +136,8 @@ pub type Error = assert::Error; /// Easier access to common traits pub mod prelude { pub use crate::IntoData; + #[cfg(feature = "json")] + pub use crate::IntoJson; pub use crate::ToDebug; }