Repository: mitsuhiko/insta (Rust)

Issue:
CSV with iterable of elements creates only 2 lines (header+content)
## Description

I believe [this playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=31c708fb85bc4d0a1e304d9583e9a7bb) explains the problem. When we `.serialize()` a `Vec` of objects that implements `Serialize` with the `Serializer` of the `csv` crate, it doesn't create a line for each object but flatten them together. There might be good reasons to do it in `csv` but it does make `assert_csv_snapshot!()` not really useful. I hope I did not miss an obvious solution to what I'm trying to do. And also, I was not sure to report this as a bug or as a feature so please forgive me if that's not the right category.

Additional helpful information:

- Version of insta: 1.5.2
- Version of rustc: 1.49.0
- Operating system and version: Linux Ubuntu 20.10

## What did you expect

I would expect to be able to send a `Vec` or any kind of iterator of objects implementing `Serialize`, to the macro `assert_csv_snapshot!()` and be able to have a multiline `*.snap` instead of a 2-lines (one header line + one content line).



Discussion:
Yep. I also ran into this and I think the current format is not particularly useful. Would accept a PR to modify this behavior but currently relatively low priority for myself to fix this.
I wanted to be sure that it could not be solved at a higher level, but I would say that BurntSushi/rust-csv#221 is a pretty clear answer about it.

I might take a look at how to improve the behavior of `assert_csv_snapshot!()`.
Thank you for the feature! That is just perfect! 



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9ac2062a..53241dcc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,11 @@
 
 All notable changes to insta and cargo-insta are documented here.
 
+## 1.6.0
+
+* Change CSV serialization format to format multiple structs as
+  multiple rows.   Fixes #156
+
 ## 1.5.3
 
 * Replace [difference](https://crates.io/crates/difference) with
diff --git a/src/serialization.rs b/src/serialization.rs
index 8a1e698b..d9251b03 100644
--- a/src/serialization.rs
+++ b/src/serialization.rs
@@ -52,9 +52,20 @@ pub fn serialize_content(
             let mut buf = Vec::with_capacity(128);
             {
                 let mut writer = csv::Writer::from_writer(&mut buf);
-                writer.serialize(&content).unwrap();
+                // 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() {
+                    for content in content_slice {
+                        writer.serialize(content).unwrap();
+                    }
+                } else {
+                    writer.serialize(&content).unwrap();
+                }
                 writer.flush().unwrap();
             }
+            if buf.ends_with(b"\n") {
+                buf.truncate(buf.len() - 1);
+            }
             String::from_utf8(buf).unwrap()
         }
         #[cfg(feature = "ron")]


Test patch:
diff --git a/tests/test_inline.rs b/tests/test_inline.rs
index 25980db8..da20dfc0 100644
--- a/tests/test_inline.rs
+++ b/tests/test_inline.rs
@@ -75,6 +75,37 @@ fn test_csv_inline() {
     "###);
 }
 
+#[cfg(feature = "csv")]
+#[test]
+fn test_csv_inline_multiple_values() {
+    #[derive(Serialize)]
+    pub struct Email(String);
+
+    #[derive(Serialize)]
+    pub struct User {
+        id: u32,
+        username: String,
+        email: Email,
+    }
+
+    let user1 = User {
+        id: 1453,
+        username: "mehmed-doe".into(),
+        email: Email("mehmed@doe.invalid".into()),
+    };
+    let user2 = User {
+        id: 1455,
+        username: "mehmed-doe-di".into(),
+        email: Email("mehmed@doe-di.invalid".into()),
+    };
+
+    assert_csv_snapshot!(vec![user1, user2], @r###"
+    id,username,email
+    1453,mehmed-doe,mehmed@doe.invalid
+    1455,mehmed-doe-di,mehmed@doe-di.invalid
+    "###);
+}
+
 #[cfg(feature = "ron")]
 #[test]
 fn test_ron_inline() {