Skip to content

Commit

Permalink
Merge pull request #350 from epage/convert
Browse files Browse the repository at this point in the history
feat(assert): Allow comparing json to jsonlines
  • Loading branch information
epage authored Jul 23, 2024
2 parents 32b9b5a + 273025e commit 5211c64
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 8 deletions.
4 changes: 2 additions & 2 deletions crates/snapbox/src/assert/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ impl Assert {
}

// On `expected` being an error, make a best guess
let format = expected.intended_format();
actual = actual.coerce_to(format);
actual = actual.coerce_to(expected.against_format());
actual = actual.coerce_to(expected.intended_format());

if self.normalize_paths && expected.filters.is_paths_set() {
actual = FilterPaths.filter(actual);
Expand Down
17 changes: 16 additions & 1 deletion crates/snapbox/src/data/filters.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::data::DataFormat;

#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
pub(crate) struct FilterSet {
flags: usize,
against: Option<DataFormat>,
}

impl FilterSet {
Expand All @@ -9,7 +12,10 @@ impl FilterSet {
}

pub(crate) const fn empty() -> Self {
Self { flags: 0 }
Self {
flags: 0,
against: None,
}
}

pub(crate) fn redactions(mut self) -> Self {
Expand All @@ -32,6 +38,11 @@ impl FilterSet {
self
}

pub(crate) fn against(mut self, format: DataFormat) -> Self {
self.against = Some(format);
self
}

pub(crate) const fn is_redaction_set(&self) -> bool {
self.is_set(Self::REDACTIONS)
}
Expand All @@ -47,6 +58,10 @@ impl FilterSet {
pub(crate) const fn is_unordered_set(&self) -> bool {
self.is_set(Self::UNORDERED)
}

pub(crate) const fn get_against(&self) -> Option<DataFormat> {
self.against
}
}

impl FilterSet {
Expand Down
123 changes: 118 additions & 5 deletions crates/snapbox/src/data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ impl<S: serde::Serialize> IntoJson for S {
}

/// Convert to [`Data`] with modifiers for `expected` data
#[allow(clippy::wrong_self_convention)]
pub trait IntoData: Sized {
/// Remove default [`filters`][crate::filter] from this `expected` result
fn raw(self) -> Data {
Expand Down Expand Up @@ -135,15 +136,21 @@ pub trait IntoData: Sized {
/// use snapbox::str;
///
/// let expected = str![[r#"{"hello": "world"}"#]]
/// .json();
/// .is_json();
/// assert_eq!(expected.format(), snapbox::data::DataFormat::Json);
/// # }
/// ```
#[cfg(feature = "json")]
fn json(self) -> Data {
fn is_json(self) -> Data {
self.is(DataFormat::Json)
}

#[cfg(feature = "json")]
#[deprecated(since = "0.6.13", note = "Replaced with `IntoData::is_json`")]
fn json(self) -> Data {
self.is_json()
}

/// Initialize as json lines or [`Error`][DataFormat::Error]
///
/// This is generally used for `expected` data
Expand All @@ -156,23 +163,96 @@ pub trait IntoData: Sized {
/// use snapbox::str;
///
/// let expected = str![[r#"{"hello": "world"}"#]]
/// .json_lines();
/// .is_jsonlines();
/// assert_eq!(expected.format(), snapbox::data::DataFormat::JsonLines);
/// # }
/// ```
#[cfg(feature = "json")]
fn json_lines(self) -> Data {
fn is_jsonlines(self) -> Data {
self.is(DataFormat::JsonLines)
}

#[cfg(feature = "json")]
#[deprecated(since = "0.6.13", note = "Replaced with `IntoData::is_jsonlines`")]
fn json_lines(self) -> Data {
self.is_jsonlines()
}

/// Initialize as Term SVG
///
/// This is generally used for `expected` data
#[cfg(feature = "term-svg")]
fn term_svg(self) -> Data {
fn is_termsvg(self) -> Data {
self.is(DataFormat::TermSvg)
}

#[cfg(feature = "term-svg")]
#[deprecated(since = "0.6.13", note = "Replaced with `IntoData::is_termsvg`")]
fn term_svg(self) -> Data {
self.is_termsvg()
}

/// Override the type this snapshot will be compared against
///
/// Normally, the `actual` data is coerced to [`IntoData::is`].
/// This allows overriding that so you can store your snapshot in a more readable, diffable
/// format.
///
/// # Examples
///
/// ```rust
/// # #[cfg(feature = "json")] {
/// use snapbox::prelude::*;
/// use snapbox::str;
///
/// let expected = str![[r#"{"hello": "world"}"#]]
/// .against(snapbox::data::DataFormat::JsonLines);
/// # }
/// ```
fn against(self, format: DataFormat) -> Data {
self.into_data().against(format)
}

/// Initialize as json or [`Error`][DataFormat::Error]
///
/// This is generally used for `expected` data
///
/// # Examples
///
/// ```rust
/// # #[cfg(feature = "json")] {
/// use snapbox::prelude::*;
/// use snapbox::str;
///
/// let expected = str![[r#"{"hello": "world"}"#]]
/// .is_json();
/// # }
/// ```
#[cfg(feature = "json")]
fn against_json(self) -> Data {
self.against(DataFormat::Json)
}

/// Initialize as json lines or [`Error`][DataFormat::Error]
///
/// This is generally used for `expected` data
///
/// # Examples
///
/// ```rust
/// # #[cfg(feature = "json")] {
/// use snapbox::prelude::*;
/// use snapbox::str;
///
/// let expected = str![[r#"{"hello": "world"}"#]]
/// .against_jsonlines();
/// # }
/// ```
#[cfg(feature = "json")]
fn against_jsonlines(self) -> Data {
self.against(DataFormat::JsonLines)
}

/// Convert to [`Data`], applying defaults
fn into_data(self) -> Data;
}
Expand Down Expand Up @@ -558,6 +638,29 @@ impl Data {
})
}

/// Override the type this snapshot will be compared against
///
/// Normally, the `actual` data is coerced to [`Data::is`].
/// This allows overriding that so you can store your snapshot in a more readable, diffable
/// format.
///
/// # Examples
///
/// ```rust
/// # #[cfg(feature = "json")] {
/// use snapbox::prelude::*;
/// use snapbox::str;
///
/// let expected = str![[r#"{"hello": "world"}"#]]
/// .is(snapbox::data::DataFormat::Json)
/// .against(snapbox::data::DataFormat::JsonLines);
/// # }
/// ```
fn against(mut self, format: DataFormat) -> Data {
self.filters = self.filters.against(format);
self
}

/// Convert `Self` to [`format`][DataFormat] if possible
///
/// This is generally used on `actual` data to make it match `expected`
Expand All @@ -573,6 +676,10 @@ impl Data {
(DataInner::Json(inner), DataFormat::Json) => DataInner::Json(inner),
#[cfg(feature = "json")]
(DataInner::JsonLines(inner), DataFormat::JsonLines) => DataInner::JsonLines(inner),
#[cfg(feature = "json")]
(DataInner::JsonLines(inner), DataFormat::Json) => DataInner::Json(inner),
#[cfg(feature = "json")]
(DataInner::Json(inner), DataFormat::JsonLines) => DataInner::JsonLines(inner),
#[cfg(feature = "term-svg")]
(DataInner::TermSvg(inner), DataFormat::TermSvg) => DataInner::TermSvg(inner),
(DataInner::Binary(inner), _) => {
Expand Down Expand Up @@ -686,6 +793,12 @@ impl Data {
}
}

pub(crate) fn against_format(&self) -> DataFormat {
self.filters
.get_against()
.unwrap_or_else(|| self.intended_format())
}

pub(crate) fn relevant(&self) -> Option<&str> {
match &self.inner {
DataInner::Error(_) => None,
Expand Down
27 changes: 27 additions & 0 deletions crates/snapbox/tests/testsuite/assert.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use snapbox::assert_data_eq;
use snapbox::data::IntoData;
use snapbox::file;
use snapbox::str;

Expand Down Expand Up @@ -26,3 +27,29 @@ line1
fn test_expect_file() {
assert_data_eq!(include_str!("../../README.md"), file!["../../README.md"]);
}

#[test]
#[cfg(feature = "json")]
fn actual_expected_formats_differ() {
assert_data_eq!(
r#"{}
{"order": 1}
{"order": 2}
{"order": 3}
"#,
str![[r#"
[
{},
{
"order": 1
},
{
"order": 2
},
{
"order": 3
}
]
"#]].is_json().against_jsonlines(),
);
}

0 comments on commit 5211c64

Please sign in to comment.