Repository: mitsuhiko/insta
Pull request #760 (2025-04-05 20:54:52)

Add pre-commit hook for Rust code formatting
Co-authored-by: Claude <no-reply@anthropic.com>



Patch:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 2cf3a5b..9581bc1 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -24,6 +24,10 @@ repos:
       - id: markdown-link-check
         name: markdown-link-check-all
         stages: [manual]
+  - repo: https://github.com/doublify/pre-commit-rust
+    rev: v1.0
+    hooks:
+      - id: fmt
   - repo: local
     hooks:
       - id: no-dbg
diff --git a/.typos.toml b/.typos.toml
index f7dddbc..fa5e8be 100644
--- a/.typos.toml
+++ b/.typos.toml
@@ -1,2 +1,2 @@
 [default]
-extend-words = { "Foled" = "Foled" }
\ No newline at end of file
+extend-words = { "Foled" = "Foled" }
diff --git a/cargo-insta/src/cli.rs b/cargo-insta/src/cli.rs
index 0fc7277..bcea5e1 100644
--- a/cargo-insta/src/cli.rs
+++ b/cargo-insta/src/cli.rs
@@ -197,8 +197,8 @@ struct TestCommand {
     #[arg(long)]
     force_update_snapshots: bool,
     /// Handle unreferenced snapshots after a successful test run.
-    #[arg(long, default_value = "ignore")]
-    unreferenced: UnreferencedSnapshots,
+    #[arg(long)]
+    unreferenced: Option<UnreferencedSnapshots>,
     /// Filters to apply to the insta glob feature.
     #[arg(long)]
     glob_filter: Vec<String>,
@@ -742,9 +742,14 @@ fn test_run(mut cmd: TestCommand, color: ColorWhen) -> Result<(), Box<dyn Error>
     // Legacy command
     if cmd.delete_unreferenced_snapshots {
         eprintln!("Warning: `--delete-unreferenced-snapshots` is deprecated. Use `--unreferenced=delete` instead.");
-        cmd.unreferenced = UnreferencedSnapshots::Delete;
+        cmd.unreferenced = Some(UnreferencedSnapshots::Delete);
     }
 
+    // If unreferenced wasn't specified, use the config file setting
+    cmd.unreferenced = cmd
+        .unreferenced
+        .or_else(|| Some(loc.tool_config.test_unreferenced()));
+
     // Prioritize the command line over the tool config
     let test_runner = match cmd.test_runner {
         TestRunner::Auto => loc.tool_config.test_runner(),
@@ -797,7 +802,12 @@ fn test_run(mut cmd: TestCommand, color: ColorWhen) -> Result<(), Box<dyn Error>
     // tests ran successfully
     if success {
         if let Some(ref snapshot_ref_path) = snapshot_ref_file {
-            handle_unreferenced_snapshots(snapshot_ref_path.borrow(), &loc, cmd.unreferenced)?;
+            handle_unreferenced_snapshots(
+                snapshot_ref_path.borrow(),
+                &loc,
+                // we set this to `Some` above so can't be `None`
+                cmd.unreferenced.unwrap(),
+            )?;
         }
     }
 
@@ -996,7 +1006,7 @@ fn prepare_test_runner<'snapshot_ref>(
     proc.env("INSTA_CARGO_INSTA", "1");
     proc.env("INSTA_CARGO_INSTA_VERSION", cargo_insta_version());
 
-    let snapshot_ref_file = if cmd.unreferenced != UnreferencedSnapshots::Ignore {
+    let snapshot_ref_file = if cmd.unreferenced != Some(UnreferencedSnapshots::Ignore) {
         match snapshot_ref_file {
             Some(path) => Some(Cow::Borrowed(path)),
             None => {


Test patch:
diff --git a/cargo-insta/tests/functional/main.rs b/cargo-insta/tests/functional/main.rs
index d67f1dd..66f75fd 100644
--- a/cargo-insta/tests/functional/main.rs
+++ b/cargo-insta/tests/functional/main.rs
@@ -889,3 +889,137 @@ src/
         stderr
     );
 }
+
+#[test]
+fn test_unreferenced_config_reject() {
+    // This test verifies that the `test.unreferenced: reject` setting in insta.yaml
+    // is respected when no command-line argument is provided.
+    //
+    // Specifically, it tests the fix for issue #757, which ensures that:
+    // 1. Config file settings are properly applied when not overridden by command-line flags
+    // 2. Error handling for unreferenced snapshots properly updates the success flag
+    let test_project = TestFiles::new()
+        .add_cargo_toml("test_unreferenced_config_reject")
+        .add_file(
+            "src/lib.rs",
+            r#"
+#[test]
+fn test_snapshot() {
+    insta::assert_snapshot!("Hello, world!");
+}
+"#
+            .to_string(),
+        )
+        .create_project();
+
+    // Run tests to create snapshots first (without the config file)
+    let output = test_project
+        .insta_cmd()
+        .args(["test", "--accept"])
+        .output()
+        .unwrap();
+
+    assert!(output.status.success());
+
+    // Now add the config file after snapshot is created
+    test_project.update_file(
+        "insta.yaml",
+        r#"
+test:
+  unreferenced: reject
+"#
+        .to_string(),
+    );
+
+    // Manually add an unreferenced snapshot
+    let unreferenced_snapshot_path = test_project
+        .workspace_dir
+        .join("src/snapshots/test_unreferenced_config_reject__unused_snapshot.snap");
+    std::fs::create_dir_all(unreferenced_snapshot_path.parent().unwrap()).unwrap();
+    std::fs::write(
+        &unreferenced_snapshot_path,
+        r#"---
+source: src/lib.rs
+expression: "Unused snapshot"
+---
+Unused snapshot
+"#,
+    )
+    .unwrap();
+
+    // Verify files exist
+    let snapshot_path = test_project
+        .workspace_dir
+        .join("src/snapshots/test_unreferenced_config_reject__snapshot.snap");
+    let unreferenced_path = test_project
+        .workspace_dir
+        .join("src/snapshots/test_unreferenced_config_reject__unused_snapshot.snap");
+
+    assert!(snapshot_path.exists(), "Normal snapshot file should exist");
+    assert!(
+        unreferenced_path.exists(),
+        "Unreferenced snapshot file should exist"
+    );
+
+    // First verify explicitly passing --unreferenced=reject does fail correctly
+    let output = test_project
+        .insta_cmd()
+        .args(["test", "--unreferenced=reject", "--", "--nocapture"])
+        .stderr(Stdio::piped())
+        .output()
+        .unwrap();
+
+    // The test should fail with explicit flag
+    assert!(
+        !output.status.success(),
+        "Command should fail with explicit --unreferenced=reject flag"
+    );
+
+    let stderr = String::from_utf8_lossy(&output.stderr);
+    assert!(
+        stderr.contains("encountered unreferenced snapshots"),
+        "Expected error message about unreferenced snapshots, got: {}",
+        stderr
+    );
+
+    // Now run without flags - this should also fail due to the config file setting
+    let output = test_project
+        .insta_cmd()
+        .args(["test", "--", "--nocapture"])
+        .stderr(Stdio::piped())
+        .output()
+        .unwrap();
+
+    // The command should fail because of the config file setting
+    assert!(
+        !output.status.success(),
+        "Command should fail when config file has test.unreferenced: reject"
+    );
+
+    // Verify the error message mentions unreferenced snapshots
+    let stderr = String::from_utf8_lossy(&output.stderr);
+    assert!(
+        stderr.contains("encountered unreferenced snapshots"),
+        "Expected error message about unreferenced snapshots, got: {}",
+        stderr
+    );
+
+    // Run with --unreferenced=delete to clean up
+    let output = test_project
+        .insta_cmd()
+        .args(["test", "--unreferenced=delete", "--", "--nocapture"])
+        .output()
+        .unwrap();
+
+    assert!(output.status.success());
+
+    // Verify the unreferenced snapshot was deleted
+    assert!(
+        snapshot_path.exists(),
+        "Normal snapshot file should still exist"
+    );
+    assert!(
+        !unreferenced_path.exists(),
+        "Unreferenced snapshot file should have been deleted"
+    );
+}