Repository: tweag/nickel
Pull request #1034 (2023-01-05 17:56:56)

Add snapshot testing infrastructure
This PR adds snapshot testing infrastructure using the `cargo-insta` crate & accompanying binary.

The README file added in https://github.com/tweag/nickel/pull/1034/commits/7251b20d1ceb9f220c49399a61b4779f1067a2a1 includes detailed instructions for interacting with the tool. 


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 304ee1b7..0c4eb180 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -319,6 +319,18 @@ dependencies = [
  "xdg",
 ]
 
+[[package]]
+name = "console"
+version = "0.15.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9b6515d269224923b26b5febea2ed42b2d5f2ce37284a4dd670fedd6cb8347a"
+dependencies = [
+ "encode_unicode",
+ "lazy_static",
+ "libc",
+ "windows-sys 0.42.0",
+]
+
 [[package]]
 name = "convert_case"
 version = "0.4.0"
@@ -651,6 +663,12 @@ dependencies = [
  "log",
 ]
 
+[[package]]
+name = "encode_unicode"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
+
 [[package]]
 name = "endian-type"
 version = "0.1.2"
@@ -894,6 +912,20 @@ dependencies = [
  "str_stack",
 ]
 
+[[package]]
+name = "insta"
+version = "1.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb5686bd8e9239eabe90bb30a0c341bffd6fdc177fb556708f2cb792bf00352d"
+dependencies = [
+ "console",
+ "lazy_static",
+ "linked-hash-map",
+ "regex",
+ "similar",
+ "yaml-rust",
+]
+
 [[package]]
 name = "instant"
 version = "0.1.12"
@@ -1000,9 +1032,9 @@ dependencies = [
 
 [[package]]
 name = "linked-hash-map"
-version = "0.5.4"
+version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
 
 [[package]]
 name = "linux-raw-sys"
@@ -1189,6 +1221,7 @@ dependencies = [
  "comrak",
  "criterion",
  "directories",
+ "insta",
  "js-sys",
  "lalrpop",
  "lalrpop-util",
@@ -1745,9 +1778,9 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "1.5.6"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
+checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -1762,9 +1795,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.26"
+version = "0.6.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
 
 [[package]]
 name = "remove_dir_all"
@@ -2606,6 +2639,27 @@ dependencies = [
  "windows_x86_64_msvc 0.36.1",
 ]
 
+[[package]]
+name = "windows-sys"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc 0.42.0",
+ "windows_i686_gnu 0.42.0",
+ "windows_i686_msvc 0.42.0",
+ "windows_x86_64_gnu 0.42.0",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc 0.42.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
+
 [[package]]
 name = "windows_aarch64_msvc"
 version = "0.30.0"
@@ -2618,6 +2672,12 @@ version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
 
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
+
 [[package]]
 name = "windows_i686_gnu"
 version = "0.30.0"
@@ -2630,6 +2690,12 @@ version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
 
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
+
 [[package]]
 name = "windows_i686_msvc"
 version = "0.30.0"
@@ -2642,6 +2708,12 @@ version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
 
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
+
 [[package]]
 name = "windows_x86_64_gnu"
 version = "0.30.0"
@@ -2654,6 +2726,18 @@ version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
 
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
+
 [[package]]
 name = "windows_x86_64_msvc"
 version = "0.30.0"
@@ -2666,6 +2750,12 @@ version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
 
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
+
 [[package]]
 name = "xdg"
 version = "2.4.1"
diff --git a/Cargo.toml b/Cargo.toml
index 3d3ed2eb..c46f0e03 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -30,7 +30,7 @@ lalrpop = "0.19.6"
 
 [dependencies]
 lalrpop-util = "0.19.6"
-regex = "1.5"
+regex = "1.7"
 simple-counter = "0.1.0"
 codespan = "0.11"
 codespan-reporting = "0.11"
@@ -72,6 +72,7 @@ pprof = { version = "0.9.1", features = ["criterion", "flamegraph"] }
 nickel-lang-utilities = {path = "utilities", version = "0.3.1"}
 similar = "2.1.0"
 test-generator = "0.3.1"
+insta = { version = "1.24.1", features = ["filters"] }
 
 [workspace]
 members = [
diff --git a/HACKING.md b/HACKING.md
index 32842ad3..e63995d2 100644
--- a/HACKING.md
+++ b/HACKING.md
@@ -137,9 +137,9 @@ than the ones we get by default from `cargo test`.
 
 ### Testing failures
 
-Tests which are expected to fail are currently written in Rust, because that makes
-it possible to additionally check which particular error was raised. For example,
-([`tests/integration/records_fail.rs`](./tests/integration/records_fail.rs)):
+Tests which are expected to fail are predominantly written in Rust, because that
+makes it possible to additionally check which particular error was raised. For
+example, ([`tests/integration/records_fail.rs`](./tests/integration/records_fail.rs)):
 
 ```rust
 #[test]
@@ -179,6 +179,20 @@ let DivBy3 = fun label value =>
    | DivBy3)
 ```
 
+### Snapshot testing
+
+The project also contains a suite of snapshot tests in the `tests/snapshot`
+directory. Here, `.ncl` files written in the subdirectories of the `input`
+directory are run against the last-built Nickel binary, and their output is
+compared to the last-known output.
+
+Failures of these tests do not necessarily mean that anything is wrong. Rather
+it should be seen as an opportunity to review the diffs and either accept
+any changes, or fix any issues introduced.
+
+See the [README] in the snapshot testing crate for more detailed guides on
+working with snapshot tests.
+
 ## Benchmarking
 
 If your change is likely to impact performance, it is recommended to run the
diff --git a/flake.lock b/flake.lock
index bb70c0ed..d6522b41 100644
--- a/flake.lock
+++ b/flake.lock
@@ -10,11 +10,11 @@
         "rust-overlay": "rust-overlay"
       },
       "locked": {
-        "lastModified": 1672095661,
-        "narHash": "sha256-7NTsdCn3qsvU7A+1/7tY8pxbq0DYy1pFYNpzN6he9lI=",
+        "lastModified": 1673056065,
+        "narHash": "sha256-a68tMDTDqdAauxq377ALl4Uwm6oh9MeoY2WbTYRWZoo=",
         "owner": "ipetkov",
         "repo": "crane",
-        "rev": "98894bb39b03bfb379c5e10523cd61160e1ac782",
+        "rev": "0144134311767fcee80213321f079a8ffa0b9cc1",
         "type": "github"
       },
       "original": {
@@ -108,11 +108,11 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1672350804,
-        "narHash": "sha256-jo6zkiCabUBn3ObuKXHGqqORUMH27gYDIFFfLq5P4wg=",
+        "lastModified": 1672953546,
+        "narHash": "sha256-oz757DnJ1ITvwyTovuwG3l9cX6j9j6/DH9eH+cXFJmc=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "677ed08a50931e38382dbef01cba08a8f7eac8f6",
+        "rev": "a518c77148585023ff56022f09c4b2c418a51ef5",
         "type": "github"
       },
       "original": {
@@ -150,11 +150,11 @@
         "nixpkgs-stable": "nixpkgs-stable"
       },
       "locked": {
-        "lastModified": 1672050129,
-        "narHash": "sha256-GBQMcvJUSwAVOpDjVKzB6D5mmHI7Y4nFw+04bnS9QrM=",
+        "lastModified": 1672912243,
+        "narHash": "sha256-QnQeKUjco2kO9J4rBqIBPp5XcOMblIMnmyhpjeaJBYc=",
         "owner": "cachix",
         "repo": "pre-commit-hooks.nix",
-        "rev": "67d98f02443b9928bc77f1267741dcfdd3d7b65c",
+        "rev": "a4548c09eac4afb592ab2614f4a150120b29584c",
         "type": "github"
       },
       "original": {
@@ -184,11 +184,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1670034122,
-        "narHash": "sha256-EqmuOKucPWtMvCZtHraHr3Q3bgVszq1x2PoZtQkUuEk=",
+        "lastModified": 1672712534,
+        "narHash": "sha256-8S0DdMPcbITnlOu0uA81mTo3hgX84wK8S9wS34HEFY4=",
         "owner": "oxalica",
         "repo": "rust-overlay",
-        "rev": "a0d5773275ecd4f141d792d3a0376277c0fc0b65",
+        "rev": "69fb7bf0a8c40e6c4c197fa1816773774c8ac59f",
         "type": "github"
       },
       "original": {
@@ -207,11 +207,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1672453260,
-        "narHash": "sha256-ruR2xo30Vn7kY2hAgg2Z2xrCvNePxck6mgR5a8u+zow=",
+        "lastModified": 1673058265,
+        "narHash": "sha256-FFigGHIO9BQeIIKjH5dcpB+ey5CSgfy47wHPGeOhCps=",
         "owner": "oxalica",
         "repo": "rust-overlay",
-        "rev": "176b6fd3dd3d7cea8d22ab1131364a050228d94c",
+        "rev": "802ff3314663ec7114f29a6e8b200dfc892023f8",
         "type": "github"
       },
       "original": {
diff --git a/flake.nix b/flake.nix
index d73509d7..c27c587a 100644
--- a/flake.nix
+++ b/flake.nix
@@ -163,6 +163,7 @@
           lalrpopFilter = mkFilter ".*lalrpop$";
           nclFilter = mkFilter ".*ncl$";
           txtFilter = mkFilter ".*txt$";
+          snapFilter = mkFilter ".*snap$";
         in
         pkgs.lib.cleanSourceWith {
           src = pkgs.lib.cleanSource ./.;
@@ -174,6 +175,7 @@
               lalrpopFilter
               nclFilter
               txtFilter
+              snapFilter
               filterCargoSources
             ];
         };
@@ -234,6 +236,8 @@
 
         buildInputs = [
           pkgs.rust-analyzer
+          pkgs.cargo-insta
+          pkgs.nixpkgs-fmt
           pkgs.nodejs
           pkgs.node2nix
           pkgs.nodePackages.markdownlint-cli


Test patch:
diff --git a/tests/snapshot/README.md b/tests/snapshot/README.md
new file mode 100644
index 00000000..b8e53d03
--- /dev/null
+++ b/tests/snapshot/README.md
@@ -0,0 +1,47 @@
+# Snapshot testing
+
+Nickel snapshot tests are run by invoking the most recently built Nickel binary
+(located via the `CARGO_BIN_EXE_nickel` environment variable) with the Nickel
+files located in subdirectories of the `inputs` directory.
+
+Each subdirectory corresponds to the type of output we're snapshotting.
+Currently we have `errors`, which tests error descriptions written to STDERR,
+`export`, which tests the output when exporting JSON, and `pretty` which tests
+pretty-printed output.
+
+The actual test code is defined in `main.rs`, and uses the
+[`insta`](https://github.com/mitsuhiko/insta) crate to assert against snapshots
+stored in the `snapshots` directory. While it is possible to edit snapshot
+files manually to update them, it is significantly simpler to use the
+[`cargo-insta`](https://crates.io/crates/cargo-insta) tool. If you're using the
+nix dev shell, `cargo-insta` is already on your path. Most of this guide will
+assume you have `cargo-insta` installed. If you'd prefer not to install it,
+please read [this section](#without-cargo-insta).
+
+## What to do if a snapshot test fails
+
+1. Run `cargo insta review`.
+2. Check the output to see what changed
+  
+## How to add a new snapshot test
+
+1. Add the Nickel file whose output you want to test into one of the
+  `inputs` subdirectories. Give it a descriptive name, as the name of the file
+  is used when printing test failures, and is also used to name the snapshot
+  file.
+2. Run the snapshot tests with `cargo test --test snapshot`.
+3. You'll see a failure message, noting that the test was a new snapshot.
+4. Run `cargo insta review`.
+5. If you're happy with the output, accept it.
+6. Commit the input file and the generated snapshot. You're done!
+
+## Without `cargo-insta`
+
+1. Failing snapshot tests will cause a new snapshot file to be generated in the
+  snapshots directory. The naming scheme for these new files is
+  `${failing_snapshot_file_name}.new`. So if the snapshot file which failed
+  was called `snapshot__error_type_mismatch.ncl.snap`, the new file will be
+  called `snapshot__error_type_mismatch.ncl.snap.new`.
+2. Diff the old and new files, using your favourite diffing tool (or eyeballs).
+3. If you want to accept the new file, simply delete the old snapshot, and
+  remove the `.new` extension from the new one. To reject it, simply delete it.
diff --git a/tests/snapshot/inputs/errors/simple_contract_fail.ncl b/tests/snapshot/inputs/errors/simple_contract_fail.ncl
new file mode 100644
index 00000000..13c3b9c1
--- /dev/null
+++ b/tests/snapshot/inputs/errors/simple_contract_fail.ncl
@@ -0,0 +1,1 @@
+1 | Str
\ No newline at end of file
diff --git a/tests/snapshot/inputs/export/nested_record.ncl b/tests/snapshot/inputs/export/nested_record.ncl
new file mode 100644
index 00000000..6154d4e4
--- /dev/null
+++ b/tests/snapshot/inputs/export/nested_record.ncl
@@ -0,0 +1,13 @@
+{ 
+  a_num = 1,
+  some_str = "this is a string",
+  booooool = false,
+  an_array = [ 2, "other string", true, ["nested", "array"], { nested = "record" }],
+  a_record = {
+    even = {
+      more = {
+        nested = "record"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/tests/snapshot/inputs/pretty/simple_record.ncl b/tests/snapshot/inputs/pretty/simple_record.ncl
new file mode 100644
index 00000000..23f59862
--- /dev/null
+++ b/tests/snapshot/inputs/pretty/simple_record.ncl
@@ -0,0 +1,6 @@
+{ 
+  a | Num | default = 1, 
+  b : Str | force = "some long string that goes past the 80 character line limit for pretty printing", 
+  c : { x : Num, y: Num } = { x = 999.8979, y = 500 },
+  d | Array string.NonEmpty = ["a", "list", "of", "non", "empty", "strings"],
+}
\ No newline at end of file
diff --git a/tests/snapshot/main.rs b/tests/snapshot/main.rs
new file mode 100644
index 00000000..b56608aa
--- /dev/null
+++ b/tests/snapshot/main.rs
@@ -0,0 +1,110 @@
+use std::{
+    ffi::OsStr,
+    path::PathBuf,
+    process::{Command, Output},
+};
+use test_generator::test_resources;
+
+#[test_resources("tests/snapshot/inputs/pretty/*.ncl")]
+fn check_pretty_print_snapshots(file: &str) {
+    let file = TestFile::from_project_path(file);
+
+    let snapshot = NickelInvocation::new()
+        .subcommand("pprint-ast")
+        .file(&file)
+        .snapshot_stdout();
+
+    insta::assert_snapshot!(file.prefixed_test_name("pretty"), snapshot)
+}
+
+#[test_resources("tests/snapshot/inputs/export/*.ncl")]
+fn check_export_snapshots(file: &str) {
+    let file = TestFile::from_project_path(file);
+
+    let snapshot = NickelInvocation::new()
+        .subcommand("export")
+        .file(&file)
+        .snapshot_stdout();
+
+    insta::assert_snapshot!(file.prefixed_test_name("export"), snapshot)
+}
+
+#[test_resources("tests/snapshot/inputs/errors/*.ncl")]
+fn check_error_snapshots(file: &str) {
+    let file = TestFile::from_project_path(file);
+
+    let snapshot = NickelInvocation::new().file(&file).snapshot_stderr();
+
+    insta::with_settings!({filters => vec![
+        // Since error output includes fully-qualified paths to the source file
+        // we need to replace those with something static to avoid snapshots
+        // differing across machines.
+        (r"(?:/.+/tests/snapshot/inputs)", "[INPUTS_PATH]")
+    ]},
+    {
+        insta::assert_snapshot!(file.prefixed_test_name("error"), snapshot)
+    });
+}
+
+struct TestFile {
+    path_buf: PathBuf,
+}
+
+impl TestFile {
+    fn from_project_path(file: &str) -> Self {
+        let mut path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+        path_buf.push(file);
+        Self { path_buf }
+    }
+
+    fn prefixed_test_name(&self, prefix: &str) -> String {
+        let file_name = self
+            .path_buf
+            .as_path()
+            .file_name()
+            .and_then(|f| f.to_str())
+            .expect("Could not extract file name");
+        format!("{}_{}", prefix, file_name)
+    }
+
+    fn as_nickel_argument(&self) -> &str {
+        self.path_buf
+            .to_str()
+            .expect("Could not convert path arg to str")
+    }
+}
+
+struct NickelInvocation {
+    cmd: Command,
+}
+
+impl NickelInvocation {
+    fn new() -> Self {
+        let nickel_loc = env!("CARGO_BIN_EXE_nickel");
+        let mut cmd = Command::new(nickel_loc);
+        cmd.args(["--color", "never"]);
+        Self { cmd }
+    }
+
+    fn subcommand<S: AsRef<OsStr>>(&mut self, s: S) -> &mut Self {
+        self.cmd.arg(s);
+        self
+    }
+
+    fn file(&mut self, f: &TestFile) -> &mut Self {
+        self.cmd.args(["-f", f.as_nickel_argument()]);
+        self
+    }
+
+    fn run(&mut self) -> Output {
+        self.cmd.output().expect("Should be able to capture output")
+    }
+
+    fn snapshot_stderr(&mut self) -> String {
+        String::from_utf8(self.run().stderr).expect("Output should be utf8")
+    }
+
+    fn snapshot_stdout(&mut self) -> String {
+        String::from_utf8(self.run().stdout).expect("Output should be utf8")
+    }
+}
diff --git a/tests/snapshot/snapshots/snapshot__error_simple_contract_fail.ncl.snap b/tests/snapshot/snapshots/snapshot__error_simple_contract_fail.ncl.snap
new file mode 100644
index 00000000..6a082aaf
--- /dev/null
+++ b/tests/snapshot/snapshots/snapshot__error_simple_contract_fail.ncl.snap
@@ -0,0 +1,22 @@
+---
+source: tests/snapshot/main.rs
+expression: snapshot
+---
+error: contract broken by a value
+  ┌─ :1:1
+  │
+1 │ Str
+  │ --- expected type
+  │
+  ┌─ [INPUTS_PATH]/errors/simple_contract_fail.ncl:1:1
+  │
+1 │ 1 | Str
+  │ ^ applied to this expression
+
+note: 
+  ┌─ [INPUTS_PATH]/errors/simple_contract_fail.ncl:1:5
+  │
+1 │ 1 | Str
+  │     ^^^ bound here
+
+
diff --git a/tests/snapshot/snapshots/snapshot__export_nested_record.ncl.snap b/tests/snapshot/snapshots/snapshot__export_nested_record.ncl.snap
new file mode 100644
index 00000000..9d686f59
--- /dev/null
+++ b/tests/snapshot/snapshots/snapshot__export_nested_record.ncl.snap
@@ -0,0 +1,28 @@
+---
+source: tests/snapshot/main.rs
+expression: snapshot
+---
+{
+  "a_num": 1,
+  "a_record": {
+    "even": {
+      "more": {
+        "nested": "record"
+      }
+    }
+  },
+  "an_array": [
+    2,
+    "other string",
+    true,
+    [
+      "nested",
+      "array"
+    ],
+    {
+      "nested": "record"
+    }
+  ],
+  "booooool": false,
+  "some_str": "this is a string"
+}
diff --git a/tests/snapshot/snapshots/snapshot__pretty_simple_record.ncl.snap b/tests/snapshot/snapshots/snapshot__pretty_simple_record.ncl.snap
new file mode 100644
index 00000000..b6aac533
--- /dev/null
+++ b/tests/snapshot/snapshots/snapshot__pretty_simple_record.ncl.snap
@@ -0,0 +1,19 @@
+---
+source: tests/snapshot/main.rs
+expression: snapshot
+---
+{
+  a | Num | default = 1,
+  b : Str
+    
+    | force = "some long string that goes past the 80 character line limit for pretty printing",
+  c : {x: Num, y: Num}  = { x = 999.8979, y = 500, },
+  d | Array (string.NonEmpty) = [
+    "a",
+    "list",
+    "of",
+    "non",
+    "empty",
+    "strings"
+  ],
+}