Repository: mitsuhiko/insta
Pull request #528 (2024-07-15 06:23:02)

Unify handling of file & inline snapshots (compat)
This is a version of #468 that doesn't break compatibility — the change in snapshot (removing the leading `---` in inline snapshots) is optional, and snapshots still pass if they have it. Otherwise it has the same benefits of #468

(There is a tiny corner case that if a snapshot is intended to test whether there's a leading `---`, we could get a false match, but this is a very small possibility — much much smaller than removing the line endings we've done)

As part of that, this adds `as_str_exact` & `matches_fully` methods to `SnapshotContents`, which allows us to unify our normalization of snapshots contents, and allow detecting snapshots that pass but don't completely match; for example if we want to restore checking for line endings.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 402d64d..abc9f8a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,8 @@ All notable changes to insta and cargo-insta are documented here.
   themselves contain `###`. If there are no existing `#` characters in the
   snapshot value, a single `#` will be used.  #540
 
+- Inline snapshots can now be updated with `--force-update-snapshots`.  #569
+
 - `cargo insta test` accepts multiple `--exclude` flags.  #520
 
 - `test` `runner` in insta's yaml config works.  #544
@@ -35,6 +37,8 @@ All notable changes to insta and cargo-insta are documented here.
 
 - Add a new integration test approach for `cargo-insta` and a set of integration tests.  #537
 
+- Enable Filters to be created from `IntoIterator` types, rather than just `Vec`s.  #570
+
 ## 1.39.0
 
 - Fixed a bug in `require_full_match`.  #485
diff --git a/insta/Cargo.toml b/insta/Cargo.toml
index 0a22c2f..f8ff1c7 100644
--- a/insta/Cargo.toml
+++ b/insta/Cargo.toml
@@ -36,24 +36,22 @@ glob = ["walkdir", "globset"]
 colors = ["console"]
 
 # Serialization formats
-# TODO: This could be cleaner by using "dep:csv" without renaming the dep, but
-# this technique allows for a lower MSRV
-csv = ["dep_csv", "serde"]
+csv = ["dep:csv", "serde"]
 json = ["serde"]
-ron = ["dep_ron", "serde"]
-toml = ["dep_toml", "serde"]
+ron = ["dep:ron", "serde"]
+toml = ["dep:toml", "serde"]
 yaml = ["serde"]
 
 # internal feature exclusive to cargo-insta
 _cargo_insta_internal = ["clap"]
 
 [dependencies]
-dep_csv = { package = "csv", version = "1.1.6", optional = true }
+csv = { version = "1.1.6", optional = true }
 console = { version = "0.15.4", optional = true, default-features = false }
 pest = { version = "2.1.3", optional = true }
 pest_derive = { version = "2.1.0", optional = true }
-dep_ron = { package = "ron", version = "0.7.1", optional = true }
-dep_toml = { package = "toml", version = "0.5.7", optional = true }
+ron = { version = "0.7.1", optional = true }
+toml = { version = "0.5.7", optional = true }
 globset = { version = "0.4.6", optional = true }
 walkdir = { version = "2.3.1", optional = true }
 similar = { version = "2.1.0", features = ["inline"] }
diff --git a/insta/src/filters.rs b/insta/src/filters.rs
index be0485e..5c64d1a 100644
--- a/insta/src/filters.rs
+++ b/insta/src/filters.rs
@@ -1,5 +1,6 @@
 use std::borrow::Cow;
 use std::iter::FromIterator;
+use std::iter::IntoIterator;
 
 use regex::Regex;
 
@@ -10,9 +11,12 @@ pub struct Filters {
     rules: Vec<(Regex, String)>,
 }
 
-impl<'a> From<Vec<(&'a str, &'a str)>> for Filters {
-    fn from(value: Vec<(&'a str, &'a str)>) -> Self {
-        Self::from_iter(value)
+impl<'a, I> From<I> for Filters
+where
+    I: IntoIterator<Item = (&'a str, &'a str)>,
+{
+    fn from(value: I) -> Self {
+        Self::from_iter(value.into_iter())
     }
 }
 
diff --git a/insta/src/macros.rs b/insta/src/macros.rs
index 7ffdb06..ba837e4 100644
--- a/insta/src/macros.rs
+++ b/insta/src/macros.rs
@@ -223,49 +223,31 @@ macro_rules! assert_compact_json_snapshot {
 #[doc(hidden)]
 #[macro_export]
 macro_rules! _assert_serialized_snapshot {
-    // If there are redaction expressions and an inline snapshot, capture
-    // the redactions expressions and pass to `_assert_snapshot_base`
-    //
-    // Note that if we could unify the Inline & File representations of snapshots
-    // redactions we could unify some of these branches.
-    (format=$format:ident, $value:expr, $(match ..)? {$($k:expr => $v:expr),* $(,)?}, @$snapshot:literal $(,)?) => {{
+    // If there are redaction expressions, capture the redactions expressions
+    // and pass to `_assert_snapshot_base`
+    (format=$format:ident, $value:expr, $(match ..)? {$($k:expr => $v:expr),* $(,)?} $($arg:tt)*) => {{
         let transform = |value| {
-            let (_, value) = $crate::_prepare_snapshot_for_redaction!(value, {$($k => $v),*}, $format, Inline);
+            let (_, value) = $crate::_prepare_snapshot_for_redaction!(value, {$($k => $v),*}, $format);
             value
         };
-        $crate::_assert_snapshot_base!(transform=transform, $value, @$snapshot);
-    }};
-    // If there are redaction expressions and no name, add a auto-generated name, call self
-    (format=$format:ident, $value:expr, $(match ..)? {$($k:expr => $v:expr),* $(,)?} $(,)?) => {{
-        $crate::_assert_serialized_snapshot!(format=$format, $crate::_macro_support::AutoName, $value, {$($k => $v),*});
+        $crate::_assert_snapshot_base!(transform=transform, $value $($arg)*);
     }};
-    // If there are redaction expressions, capture and pass to `_assert_snapshot_base`
+    // If there's a name and redaction expressions, capture and pass to `_assert_snapshot_base`
     (format=$format:ident, $name:expr, $value:expr, $(match ..)? {$($k:expr => $v:expr),* $(,)?} $(,)?) => {{
         let transform = |value| {
-            let (_, value) = $crate::_prepare_snapshot_for_redaction!(value, {$($k => $v),*}, $format, File);
+            let (_, value) = $crate::_prepare_snapshot_for_redaction!(value, {$($k => $v),*}, $format);
             value
         };
         $crate::_assert_snapshot_base!(transform=transform, $name, $value);
     }};
-    // If there's an inline snapshot, capture serialization function and pass to
-    // `_assert_snapshot_base`, specifying `Inline`
-    (format=$format:ident, $($arg:expr),*, @$snapshot:literal $(,)?) => {{
-        let transform = |value| {$crate::_macro_support::serialize_value(
-            &value,
-            $crate::_macro_support::SerializationFormat::$format,
-            $crate::_macro_support::SnapshotLocation::Inline
-        )};
-        $crate::_assert_snapshot_base!(transform = transform, $($arg),*, @$snapshot);
-    }};
-    // Capture serialization function and pass to `_assert_snapshot_base`,
-    // specifying `File`
-    (format=$format:ident, $($arg:expr),* $(,)?) => {{
+    // Capture serialization function and pass to `_assert_snapshot_base`
+    //
+    (format=$format:ident, $($arg:tt)*) => {{
         let transform = |value| {$crate::_macro_support::serialize_value(
             &value,
             $crate::_macro_support::SerializationFormat::$format,
-            $crate::_macro_support::SnapshotLocation::File
         )};
-        $crate::_assert_snapshot_base!(transform = transform, $($arg),*);
+        $crate::_assert_snapshot_base!(transform = transform, $($arg)*);
     }};
 }
 
@@ -273,7 +255,7 @@ macro_rules! _assert_serialized_snapshot {
 #[doc(hidden)]
 #[macro_export]
 macro_rules! _prepare_snapshot_for_redaction {
-    ($value:expr, {$($k:expr => $v:expr),*}, $format:ident, $location:ident) => {
+    ($value:expr, {$($k:expr => $v:expr),*}, $format:ident) => {
         {
             let vec = std::vec![
                 $((
@@ -285,7 +267,6 @@ macro_rules! _prepare_snapshot_for_redaction {
                 &$value,
                 &vec,
                 $crate::_macro_support::SerializationFormat::$format,
-                $crate::_macro_support::SnapshotLocation::$location
             );
             (vec, value)
         }
@@ -296,10 +277,10 @@ macro_rules! _prepare_snapshot_for_redaction {
 #[doc(hidden)]
 #[macro_export]
 macro_rules! _prepare_snapshot_for_redaction {
-    ($value:expr, {$($k:expr => $v:expr),*}, $format:ident, $location:ident) => {
+    ($value:expr, {$($k:expr => $v:expr),*}, $format:ident) => {
         compile_error!(
             "insta was compiled without redactions support. Enable the `redactions` feature."
-        );
+        )
     };
 }
 
diff --git a/insta/src/runtime.rs b/insta/src/runtime.rs
index 245157e..90c9639 100644
--- a/insta/src/runtime.rs
+++ b/insta/src/runtime.rs
@@ -397,6 +397,7 @@ impl<'a> SnapshotAssertionContext<'a> {
             }
             SnapshotUpdateBehavior::NewFile => {
                 if let Some(ref snapshot_file) = self.snapshot_file {
+                    // File snapshot
                     if let Some(new_path) = new_snapshot.save_new(snapshot_file)? {
                         if should_print {
                             elog!(
@@ -415,19 +416,7 @@ impl<'a> SnapshotAssertionContext<'a> {
                                 .bold(),
                         );
                     }
-
-                // special case for pending inline snapshots.  Here we really only want
-                // to write the contents if the snapshot contents changed as the metadata
-                // is not retained for inline snapshots.  This used to have different
-                // behavior in the past where we did indeed want to rewrite the snapshots
-                // entirely since we used to change the canonical snapshot format, but now
-                // this is significantly less likely to happen and seeing hundreds of unchanged
-                // inline snapshots in the review screen is not a lot of fun.
-                } else if self
-                    .old_snapshot
-                    .as_ref()
-                    .map_or(true, |x| x.contents() != new_snapshot.contents())
-                {
+                } else {
                     PendingInlineSnapshot::new(
                         Some(new_snapshot),
                         self.old_snapshot.clone(),
diff --git a/insta/src/serialization.rs b/insta/src/serialization.rs
index 6e39e81..fd137b5 100644
--- a/insta/src/serialization.rs
+++ b/insta/src/serialization.rs
@@ -22,11 +22,7 @@ pub enum SnapshotLocation {
     File,
 }
 
-pub fn serialize_content(
-    mut content: Content,
-    format: SerializationFormat,
-    location: SnapshotLocation,
-) -> String {
+pub fn serialize_content(mut content: Content, format: SerializationFormat) -> String {
     content = Settings::with(|settings| {
         if settings.sort_maps() {
             content.sort_maps();
@@ -41,20 +37,14 @@ pub fn serialize_content(
     });
 
     match format {
-        SerializationFormat::Yaml => {
-            let serialized = yaml::to_string(&content);
-            match location {
-                SnapshotLocation::Inline => serialized,
-                SnapshotLocation::File => serialized[4..].to_string(),
-            }
-        }
+        SerializationFormat::Yaml => yaml::to_string(&content)[4..].to_string(),
         SerializationFormat::Json => json::to_string_pretty(&content),
         SerializationFormat::JsonCompact => json::to_string_compact(&content),
         #[cfg(feature = "csv")]
         SerializationFormat::Csv => {
             let mut buf = Vec::with_capacity(128);
             {
-                let mut writer = dep_csv::Writer::from_writer(&mut buf);
+                let mut writer = csv::Writer::from_writer(&mut buf);
                 // if the top-level content we're serializing is a vector we
                 // want to serialize it multiple times once for each item.
                 if let Some(content_slice) = content.as_slice() {
@@ -74,14 +64,14 @@ pub fn serialize_content(
         #[cfg(feature = "ron")]
         SerializationFormat::Ron => {
             let mut buf = Vec::new();
-            let mut config = dep_ron::ser::PrettyConfig::new();
+            let mut config = ron::ser::PrettyConfig::new();
             config.new_line = "\n".to_string();
             config.indentor = "  ".to_string();
             config.struct_names = true;
-            let mut serializer = dep_ron::ser::Serializer::with_options(
+            let mut serializer = ron::ser::Serializer::with_options(
                 &mut buf,
                 Some(config),
-                dep_ron::options::Options::default(),
+                ron::options::Options::default(),
             )
             .unwrap();
             content.serialize(&mut serializer).unwrap();
@@ -89,7 +79,7 @@ pub fn serialize_content(
         }
         #[cfg(feature = "toml")]
         SerializationFormat::Toml => {
-            let mut rv = dep_toml::to_string_pretty(&content).unwrap();
+            let mut rv = toml::to_string_pretty(&content).unwrap();
             if rv.ends_with('\n') {
                 rv.truncate(rv.len() - 1);
             }
@@ -98,14 +88,10 @@ pub fn serialize_content(
     }
 }
 
-pub fn serialize_value<S: Serialize>(
-    s: &S,
-    format: SerializationFormat,
-    location: SnapshotLocation,
-) -> String {
+pub fn serialize_value<S: Serialize>(s: &S, format: SerializationFormat) -> String {
     let serializer = ContentSerializer::<ValueError>::new();
     let content = Serialize::serialize(s, serializer).unwrap();
-    serialize_content(content, format, location)
+    serialize_content(content, format)
 }
 
 #[cfg(feature = "redactions")]
@@ -113,14 +99,13 @@ pub fn serialize_value_redacted<S: Serialize>(
     s: &S,
     redactions: &[(crate::redaction::Selector, crate::redaction::Redaction)],
     format: SerializationFormat,
-    location: SnapshotLocation,
 ) -> String {
     let serializer = ContentSerializer::<ValueError>::new();
     let mut content = Serialize::serialize(s, serializer).unwrap();
     for (selector, redaction) in redactions {
         content = selector.redact(content, redaction);
     }
-    serialize_content(content, format, location)
+    serialize_content(content, format)
 }
 
 #[test]
@@ -140,7 +125,6 @@ fn test_yaml_serialization() {
             ),
         ]),
         SerializationFormat::Yaml,
-        SnapshotLocation::File,
     );
     crate::assert_snapshot!(&yaml, @r###"
     env:
@@ -166,9 +150,18 @@ fn test_yaml_serialization() {
             ),
         ]),
         SerializationFormat::Yaml,
-        SnapshotLocation::Inline,
     );
     crate::assert_snapshot!(&inline_yaml, @r###"
+    env:
+      - ENVIRONMENT
+      - production
+    cmdline:
+      - my-tool
+      - run
+    "###);
+
+    // Old approach with leading `---`:
+    crate::assert_snapshot!(&inline_yaml, @r###"
     ---
     env:
       - ENVIRONMENT
diff --git a/insta/src/snapshot.rs b/insta/src/snapshot.rs
index eccbda4..46de427 100644
--- a/insta/src/snapshot.rs
+++ b/insta/src/snapshot.rs
@@ -431,7 +431,7 @@ impl Snapshot {
 
     /// Snapshot contents _and_ metadata match another snapshot's.
     pub fn matches_fully(&self, other: &Snapshot) -> bool {
-        self.matches(other)
+        self.snapshot.matches_fully(&other.snapshot)
             && self.metadata.trim_for_persistence() == other.metadata.trim_for_persistence()
     }
 
@@ -520,16 +520,33 @@ impl SnapshotContents {
 
     /// Returns the snapshot contents as string with surrounding whitespace removed.
     pub fn as_str(&self) -> &str {
-        self.0.trim_start_matches(['\r', '\n']).trim_end()
+        let out = self.0.trim_start_matches(['\r', '\n']).trim_end();
+        // Old inline snapshots have `---` at the start, so this strips that if
+        // it exists. Soon we can start printing a warning and then eventually
+        // remove it in the next version.
+        match out.strip_prefix("---\n") {
+            Some(s) => s,
+            None => out,
+        }
+    }
+
+    /// Returns the snapshot contents as string without any trimming.
+    pub fn as_str_exact(&self) -> &str {
+        self.0.as_str()
+    }
+
+    pub fn matches_fully(&self, other: &SnapshotContents) -> bool {
+        self.as_str_exact() == other.as_str_exact()
     }
 
     pub fn to_inline(&self, indentation: usize) -> String {
         let contents = &self.0;
         let mut out = String::new();
 
+        // We don't technically need to escape on newlines, but it reduces diffs
+        let is_escape = contents.contains(['\\', '"', '\n']);
         // Escape the string if needed, with `r#`, using with 1 more `#` than
         // the maximum number of existing contiguous `#`.
-        let is_escape = contents.contains(&['\n', '\\', '"'][..]);
         let delimiter = if is_escape {
             let max_contiguous_hash = contents
                 .split(|c| c != '#')
@@ -754,21 +771,23 @@ a
 b"[1..];
     assert_eq!(
         SnapshotContents(t.to_string()).to_inline(0),
-        "r#\"
+        r##"r#"
 a
 b
-\"#"
+"#"##
     );
 
-    let t = &"
-a
-b"[1..];
     assert_eq!(
-        SnapshotContents(t.to_string()).to_inline(4),
-        "r#\"
+        SnapshotContents(
+            "a
+b"
+            .to_string()
+        )
+        .to_inline(4),
+        r##"r#"
     a
     b
-    \"#"
+    "#"##
     );
 
     let t = &"
@@ -776,10 +795,10 @@ b"[1..];
     b"[1..];
     assert_eq!(
         SnapshotContents(t.to_string()).to_inline(0),
-        "r#\"
+        r##"r#"
     a
     b
-\"#"
+"#"##
     );
 
     let t = &"
@@ -788,11 +807,11 @@ a
 b"[1..];
     assert_eq!(
         SnapshotContents(t.to_string()).to_inline(4),
-        "r#\"
+        r##"r#"
     a
 
     b
-    \"#"
+    "#"##
     );
 
     let t = &"
@@ -800,9 +819,9 @@ b"[1..];
 "[1..];
     assert_eq!(
         SnapshotContents(t.to_string()).to_inline(0),
-        "r#\"
+        r##"r#"
     ab
-\"#"
+"#"##
     );
 
     let t = "ab";
@@ -814,12 +833,12 @@ fn test_snapshot_contents_hashes() {
     let t = "a###b";
     assert_eq!(SnapshotContents(t.to_string()).to_inline(0), r#""a###b""#);
 
-    let t = "a\n###b";
+    let t = "a\n\\###b";
     assert_eq!(
         SnapshotContents(t.to_string()).to_inline(0),
         r#####"r####"
 a
-###b
+\###b
 "####"#####
     );
 }


Test patch:
diff --git a/cargo-insta/tests/main.rs b/cargo-insta/tests/main.rs
index a8c7e2f..71f4a7f 100644
--- a/cargo-insta/tests/main.rs
+++ b/cargo-insta/tests/main.rs
@@ -71,6 +71,7 @@ fn assert_success(output: &std::process::Output) {
     // we would otherwise lose any output from the command such as `dbg!`
     // statements.
     eprint!("{}", String::from_utf8_lossy(&output.stderr));
+    eprint!("{}", String::from_utf8_lossy(&output.stdout));
     assert!(
         output.status.success(),
         "Tests failed: {}\n{}",
@@ -289,21 +290,20 @@ fn test_yaml_snapshot() {
 
     assert_success(&output);
 
-    assert_snapshot!(test_project.diff("src/main.rs"), @r##"
+    assert_snapshot!(test_project.diff("src/main.rs"), @r###"
     --- Original: src/main.rs
     +++ Updated: src/main.rs
-    @@ -15,5 +15,9 @@
+    @@ -15,5 +15,8 @@
          };
          insta::assert_yaml_snapshot!(&user, {
              ".id" => "[user_id]",
     -    }, @"");
     +    }, @r#"
-    +    ---
     +    id: "[user_id]"
     +    email: john.doe@example.com
     +    "#);
      }
-    "##);
+    "###);
 }
 
 #[test]
@@ -715,3 +715,110 @@ fn test_virtual_manifest_single_crate() {
          member-2/src
     "###     );
 }
+
+#[test]
+fn test_force_update_inline_snapshot() {
+    let test_project = TestFiles::new()
+        .add_file(
+            "Cargo.toml",
+            r#"
+[package]
+name = "force-update-inline"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+insta = { path = '$PROJECT_PATH' }
+"#
+            .to_string(),
+        )
+        .add_file(
+            "src/lib.rs",
+            r#####"
+#[test]
+fn test_excessive_hashes() {
+    insta::assert_snapshot!("foo", @r####"foo"####);
+}
+"#####
+                .to_string(),
+        )
+        .create_project();
+
+    // Run the test with --force-update-snapshots and --accept
+    let output = test_project
+        .cmd()
+        .args([
+            "test",
+            "--force-update-snapshots",
+            "--accept",
+            "--",
+            "--nocapture",
+        ])
+        .output()
+        .unwrap();
+
+    assert_success(&output);
+
+    assert_snapshot!(test_project.diff("src/lib.rs"), @r#####"
+    --- Original: src/lib.rs
+    +++ Updated: src/lib.rs
+    @@ -1,5 +1,5 @@
+     
+     #[test]
+     fn test_excessive_hashes() {
+    -    insta::assert_snapshot!("foo", @r####"foo"####);
+    +    insta::assert_snapshot!("foo", @"foo");
+     }
+    "#####);
+}
+
+#[test]
+fn test_hashtag_escape_in_inline_snapshot() {
+    let test_project = TestFiles::new()
+        .add_file(
+            "Cargo.toml",
+            r#"
+[package]
+name = "test_hashtag_escape"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+insta = { path = '$PROJECT_PATH' }
+"#
+            .to_string(),
+        )
+        .add_file(
+            "src/main.rs",
+            r#"
+#[test]
+fn test_hashtag_escape() {
+    insta::assert_snapshot!("Value with #### hashtags\n", @"");
+}
+"#
+            .to_string(),
+        )
+        .create_project();
+
+    let output = test_project
+        .cmd()
+        .args(["test", "--accept"])
+        .output()
+        .unwrap();
+
+    assert_success(&output);
+
+    assert_snapshot!(test_project.diff("src/main.rs"), @r######"
+    --- Original: src/main.rs
+    +++ Updated: src/main.rs
+    @@ -1,5 +1,7 @@
+     
+     #[test]
+     fn test_hashtag_escape() {
+    -    insta::assert_snapshot!("Value with #### hashtags\n", @"");
+    +    insta::assert_snapshot!("Value with #### hashtags\n", @r#####"
+    +    Value with #### hashtags
+    +    "#####);
+     }
+    "######);
+}
diff --git a/insta/tests/test_inline.rs b/insta/tests/test_inline.rs
index 240ca46..93f7012 100644
--- a/insta/tests/test_inline.rs
+++ b/insta/tests/test_inline.rs
@@ -191,7 +191,6 @@ fn test_yaml_inline() {
         username: "peter-pan".into(),
         email: "peterpan@wonderland.invalid".into()
     }, @r###"
-    ---
     id: 42
     username: peter-pan
     email: peterpan@wonderland.invalid
@@ -215,7 +214,6 @@ fn test_yaml_inline_redacted() {
     }, {
         ".id" => "[user-id]"
     }, @r###"
-    ---
     id: "[user-id]"
     username: peter-pan
     email: peterpan@wonderland.invalid
diff --git a/insta/tests/test_redaction.rs b/insta/tests/test_redaction.rs
index 8d75e71..fbe95a4 100644
--- a/insta/tests/test_redaction.rs
+++ b/insta/tests/test_redaction.rs
@@ -122,12 +122,11 @@ fn test_with_random_value_and_match_comma() {
             ".id" => "[id]",
         },
         @r###"
-        ---
-        id: "[id]"
-        username: john_doe
-        email: john@example.com
-        extra: ""
-        "###, // comma here
+    id: "[id]"
+    username: john_doe
+    email: john@example.com
+    extra: ""
+    "###, // comma here
     );
 }
 
@@ -349,7 +348,6 @@ fn test_redact_newtype_enum() {
     assert_yaml_snapshot!(visitor, {
         r#".id"# => "[id]",
     }, @r###"
-    ---
     Visitor:
       id: "[id]"
       name: my-name
@@ -364,7 +362,6 @@ fn test_redact_newtype_enum() {
     assert_yaml_snapshot!(admin, {
         r#".id"# => "[id]",
     }, @r###"
-    ---
     Admin:
       id: "[id]"
       username: john_doe
diff --git a/insta/tests/test_settings.rs b/insta/tests/test_settings.rs
index db67e1d..da0c6ce 100644
--- a/insta/tests/test_settings.rs
+++ b/insta/tests/test_settings.rs
@@ -17,7 +17,6 @@ fn test_simple() {
     settings.set_sort_maps(true);
     settings.bind(|| {
         assert_yaml_snapshot!(&map, @r###"
-        ---
         a: first value
         b: second value
         c: third value
@@ -40,7 +39,6 @@ fn test_bound_to_scope() {
         settings.set_sort_maps(true);
         let _guard = settings.bind_to_scope();
         assert_yaml_snapshot!(&map, @r###"
-        ---
         a: first value
         b: second value
         c: third value
@@ -62,7 +60,6 @@ fn test_settings_macro() {
 
     with_settings!({sort_maps => true}, {
         insta::assert_yaml_snapshot!(&map, @r###"
-        ---
         a: first value
         b: second value
         c: third value