Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mitsuhiko/insta
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1.5.3
Choose a base ref
...
head repository: mitsuhiko/insta
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1.6.0
Choose a head ref
  • 7 commits
  • 8 files changed
  • 1 contributor

Commits on Feb 3, 2021

  1. Verified

    This commit was signed with the committer’s verified signature.
    jacobtylerwalls Jacob Walls
    Copy the full SHA
    4c203c9 View commit details

Commits on Feb 7, 2021

  1. Bump similar to 1.1.0

    mitsuhiko committed Feb 7, 2021
    Copy the full SHA
    a885a7c View commit details
  2. Copy the full SHA
    450c7bb View commit details
  3. Copy the full SHA
    dc97e77 View commit details
  4. Changelog update

    mitsuhiko committed Feb 7, 2021
    Copy the full SHA
    ae83643 View commit details
  5. Copy the full SHA
    454bd66 View commit details
  6. 1.6.0

    mitsuhiko committed Feb 7, 2021
    Copy the full SHA
    41d254b View commit details
Showing with 168 additions and 51 deletions.
  1. +7 −0 CHANGELOG.md
  2. +2 −2 Cargo.toml
  3. +4 −4 cargo-insta/Cargo.lock
  4. +2 −2 cargo-insta/Cargo.toml
  5. +63 −42 src/runtime.rs
  6. +12 −1 src/serialization.rs
  7. +47 −0 tests/test_clash_detection.rs
  8. +31 −0 tests/test_inline.rs
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -2,6 +2,13 @@

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. (#156)
* Improvements to diff rendering.
* Detect some snapshot name clashes. (#159)

## 1.5.3

* Replace [difference](https://crates.io/crates/difference) with
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "insta"
version = "1.5.3"
version = "1.6.0"
license = "Apache-2.0"
authors = ["Armin Ronacher <armin.ronacher@active-4.com>"]
description = "A snapshot testing library for Rust"
@@ -47,4 +47,4 @@ toml = { version = "0.5.7", optional = true }
globset = { version = "0.4.6", optional = true }
walkdir = { version = "2.3.1", optional = true }
uuid = "0.8.1"
similar = "0.3.0"
similar = "1.1.0"
8 changes: 4 additions & 4 deletions cargo-insta/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions cargo-insta/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cargo-insta"
version = "1.5.3"
version = "1.6.0"
license = "Apache-2.0"
authors = ["Armin Ronacher <armin.ronacher@active-4.com>"]
description = "A review tool for the insta snapshot testing library for Rust"
@@ -12,7 +12,7 @@ edition = "2018"
readme = "README.md"

[dependencies]
insta = { version = "1.5.3", path = "..", features = ["redactions"] }
insta = { version = "1.6.0", path = "..", features = ["redactions"] }
console = "0.14.0"
clap = { version = "2.33.3", default-features = false }
difference = "2.0.0"
105 changes: 63 additions & 42 deletions src/runtime.rs
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ use std::sync::Mutex;
use std::thread;

use lazy_static::lazy_static;
use similar::text::{ChangeTag, TextDiff};
use similar::{ChangeTag, TextDiff};

use serde::Deserialize;

@@ -22,6 +22,8 @@ use crate::utils::{is_ci, style};
lazy_static! {
static ref WORKSPACES: Mutex<BTreeMap<String, &'static Path>> = Mutex::new(BTreeMap::new());
static ref TEST_NAME_COUNTERS: Mutex<BTreeMap<String, usize>> = Mutex::new(BTreeMap::new());
static ref TEST_NAME_CLASH_DETECTION: Mutex<BTreeMap<String, bool>> =
Mutex::new(BTreeMap::new());
}

// This macro is basically eprintln but without being captured and
@@ -204,54 +206,51 @@ pub fn get_cargo_workspace(manifest_dir: &str) -> &Path {
}
}

fn print_changeset(diff: &TextDiff, expr: Option<&str>) {
let mut lines = vec![];

for group in diff.grouped_ops(5) {
for op in group {
for change in diff.iter_changes(&op) {
lines.push(change);
}
}
}

fn print_changeset(diff: &TextDiff<str>, expr: Option<&str>) {
let width = term_width();

if let Some(expr) = expr {
println!("{:─^1$}", "", width,);
println!("{}", style(format_rust_expression(expr)));
}
println!("────────────┬{:─^1$}", "", width.saturating_sub(13),);
println!("────────────┬{:─^1$}", "", width.saturating_sub(13));
let mut has_changes = false;
for change in lines.iter() {
match change.tag() {
ChangeTag::Insert => {
has_changes = true;
println!(
"{:>5} {:>5} │{}{}",
"",
style(change.new_index().unwrap()).dim().bold(),
style("+").green(),
style(change.value().trim_end()).green()
);
}
ChangeTag::Delete => {
has_changes = true;
println!(
"{:>5} {:>5} │{}{}",
style(change.old_index().unwrap()).dim(),
"",
style("-").red(),
style(change.value().trim_end()).red()
);
}
ChangeTag::Equal => {
println!(
"{:>5} {:>5} │ {}",
style(change.old_index().unwrap()).dim(),
style(change.new_index().unwrap()).dim().bold(),
style(change.value().trim_end()).dim()
);
for (idx, group) in diff.grouped_ops(4).iter().enumerate() {
if idx > 0 {
println!("┈┈┈┈┈┈┈┈┈┈┈┈┼{:┈^1$}", "", width.saturating_sub(13));
}
for op in group {
for change in diff.iter_changes(&op) {
match change.tag() {
ChangeTag::Insert => {
has_changes = true;
println!(
"{:>5} {:>5} │{}{}",
"",
style(change.new_index().unwrap()).cyan().dim().bold(),
style("+").green(),
style(change.value().trim_end()).green()
);
}
ChangeTag::Delete => {
has_changes = true;
println!(
"{:>5} {:>5} │{}{}",
style(change.old_index().unwrap()).cyan().dim(),
"",
style("-").red(),
style(change.value().trim_end()).red()
);
}
ChangeTag::Equal => {
println!(
"{:>5} {:>5} │ {}",
style(change.old_index().unwrap()).cyan().dim(),
style(change.new_index().unwrap()).cyan().dim().bold(),
style(change.value().trim_end()).dim()
);
}
}
}
}
}
@@ -499,14 +498,36 @@ fn generate_snapshot_name_for_thread(module_path: &str) -> Result<String, &'stat

// clean test name first
let mut name = name.rsplit("::").next().unwrap();
let mut test_prefixed = false;
if name.starts_with("test_") {
name = &name[5..];
test_prefixed = true;
}

// next check if we need to add a suffix
let name = add_suffix_to_snapshot_name(Cow::Borrowed(name));
let key = format!("{}::{}", module_path.replace("::", "__"), name);

// because fn foo and fn test_foo end up with the same snapshot name we
// make sure we detect this here and raise an error.
let mut name_clash_detection = TEST_NAME_CLASH_DETECTION
.lock()
.unwrap_or_else(|x| x.into_inner());
match name_clash_detection.get(&key) {
None => {
name_clash_detection.insert(key.clone(), test_prefixed);
}
Some(&was_test_prefixed) => {
if was_test_prefixed != test_prefixed {
panic!(
"Insta snapshot name clash detected between '{}' \
and 'test_{}' in '{}'. Rename one function.",
name, name, module_path
);
}
}
}

// if the snapshot name clashes we need to increment a counter.
// we really do not care about poisoning here.
let mut counters = TEST_NAME_COUNTERS.lock().unwrap_or_else(|x| x.into_inner());
13 changes: 12 additions & 1 deletion src/serialization.rs
Original file line number Diff line number Diff line change
@@ -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")]
47 changes: 47 additions & 0 deletions tests/test_clash_detection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use std::env;
use std::thread;

#[test]
fn test_clash_detection() {
let old_update_value = env::var("INSTA_UPDATE");
let old_force_pass_value = env::var("INSTA_FORCE_PASS");
env::set_var("INSTA_UPDATE", "no");
env::set_var("INSTA_FORCE_PASS", "0");

let err1 = thread::Builder::new()
.name("test_foo_always_missing".into())
.spawn(|| {
insta::assert_debug_snapshot!(42);
})
.unwrap()
.join()
.unwrap_err();
let err2 = thread::Builder::new()
.name("foo_always_missing".into())
.spawn(|| {
insta::assert_debug_snapshot!(42);
})
.unwrap()
.join()
.unwrap_err();

if let Ok(value) = old_update_value {
env::set_var("INSTA_UPDATE", value);
} else {
env::remove_var("INSTA_UPDATE");
}
if let Ok(value) = old_force_pass_value {
env::set_var("INSTA_FORCE_PASS", value);
} else {
env::remove_var("INSTA_FORCE_PASS");
}

let s1 = err1.downcast_ref::<String>().unwrap();
let s2 = err2.downcast_ref::<String>().unwrap();
let mut values = vec![s1.as_str(), s2.as_str()];
values.sort();
assert_eq!(&values[..], vec![
"Insta snapshot name clash detected between \'foo_always_missing\' and \'test_foo_always_missing\' in \'test_clash_detection\'. Rename one function.",
"snapshot assertion for \'foo_always_missing\' failed in line 14",
]);
}
31 changes: 31 additions & 0 deletions tests/test_inline.rs
Original file line number Diff line number Diff line change
@@ -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() {