Skip to content

Commit

Permalink
feat(assert): Allow comparing json to jsonlines
Browse files Browse the repository at this point in the history
  • Loading branch information
epage committed Jul 23, 2024
1 parent 1d01d1b commit a7f8e4a
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 9 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
94 changes: 94 additions & 0 deletions crates/snapbox/src/data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,67 @@ pub trait IntoData: Sized {
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 @@ -576,6 +637,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 @@ -591,6 +675,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 @@ -704,6 +792,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
19 changes: 13 additions & 6 deletions crates/snapbox/tests/testsuite/assert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,18 @@ fn actual_expected_formats_differ() {
{"order": 3}
"#,
str![[r#"
{}
{"order":1}
{"order":2}
{"order":3}
"#]].is_jsonlines(),
[
{},
{
"order": 1
},
{
"order": 2
},
{
"order": 3
}
]
"#]].is_json().against_jsonlines(),
);
}

0 comments on commit a7f8e4a

Please sign in to comment.