{"id":13413879,"url":"https://github.com/gkampitakis/go-snaps","last_synced_at":"2026-02-27T14:19:11.182Z","repository":{"id":38386894,"uuid":"432439598","full_name":"gkampitakis/go-snaps","owner":"gkampitakis","description":"Jest-like snapshot testing in Go 📸","archived":false,"fork":false,"pushed_at":"2026-02-27T12:16:39.000Z","size":1034,"stargazers_count":252,"open_issues_count":11,"forks_count":9,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-02-27T13:39:09.234Z","etag":null,"topics":["go","go-testing","jest","matchjson","matchsnapshot","snapshot","snapshot-testing","testing","unit-testing"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/gkampitakis/go-snaps","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gkampitakis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"contributing.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["gkampitakis"]}},"created_at":"2021-11-27T11:15:22.000Z","updated_at":"2026-02-27T11:56:14.000Z","dependencies_parsed_at":"2023-02-09T22:01:10.428Z","dependency_job_id":"a56eafb9-2274-4929-af2b-deb3ab6531bf","html_url":"https://github.com/gkampitakis/go-snaps","commit_stats":null,"previous_names":[],"tags_count":54,"template":false,"template_full_name":null,"purl":"pkg:github/gkampitakis/go-snaps","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkampitakis%2Fgo-snaps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkampitakis%2Fgo-snaps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkampitakis%2Fgo-snaps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkampitakis%2Fgo-snaps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gkampitakis","download_url":"https://codeload.github.com/gkampitakis/go-snaps/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkampitakis%2Fgo-snaps/sbom","scorecard":{"id":428879,"data":{"date":"2025-08-11","repo":{"name":"github.com/gkampitakis/go-snaps","commit":"e303e41fc4b99990d2f5064da78356a5042f7e69"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.8,"checks":[{"name":"Code-Review","score":2,"reason":"Found 6/30 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":7,"reason":"4 commit(s) and 5 issue activity found in the last 90 days -- score normalized to 7","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/go.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/gkampitakis/go-snaps/go.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/gkampitakis/go-snaps/go.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/go.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/gkampitakis/go-snaps/go.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/gkampitakis/go-snaps/go.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/gkampitakis/go-snaps/go.yml/main?enable=pin","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":1,"reason":"SAST tool is not run on all commits -- score normalized to 1","details":["Warn: 4 commits out of 29 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T02:51:40.131Z","repository_id":38386894,"created_at":"2025-08-19T02:51:40.132Z","updated_at":"2025-08-19T02:51:40.132Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29899486,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T12:09:13.686Z","status":"ssl_error","status_checked_at":"2026-02-27T12:09:13.282Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","go-testing","jest","matchjson","matchsnapshot","snapshot","snapshot-testing","testing","unit-testing"],"created_at":"2024-07-30T20:01:51.818Z","updated_at":"2026-02-27T14:19:11.173Z","avatar_url":"https://github.com/gkampitakis.png","language":"Go","funding_links":["https://github.com/sponsors/gkampitakis"],"categories":["Testing"],"sub_categories":["Testing Frameworks"],"readme":"# Go Snaps\n\n[![Go](https://github.com/gkampitakis/go-snaps/actions/workflows/go.yml/badge.svg?branch=main)](https://github.com/gkampitakis/go-snaps/actions/workflows/go.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/gkampitakis/go-snaps)](https://goreportcard.com/report/github.com/gkampitakis/go-snaps)\n[![Go Reference](https://pkg.go.dev/badge/github.com/gkampitakis/go-snaps.svg)](https://pkg.go.dev/github.com/gkampitakis/go-snaps)\n\n\u003cp align=\"center\"\u003e\n\u003cb\u003eJest-like snapshot testing in Go\u003c/b\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"./images/logo.svg\" alt=\"Logo\" width=\"400\"/\u003e\n\u003c/p\u003e\n\n## Contents\n\n- [Installation](#installation)\n- [MatchSnapshot](#matchsnapshot)\n- [MatchStandaloneSnapshot](#matchstandalonesnapshot)\n- [MatchJSON](#matchjson)\n- [MatchStandaloneJSON](#matchstandalonejson)\n- [MatchYAML](#matchyaml)\n- [MatchStandaloneYAML](#matchstandaloneyaml)\n- [MatchInlineSnapshot](#matchinlinesnapshot) `Experimental`\n- [Matchers](#matchers)\n  - [match.Any](#matchany)\n  - [match.Custom](#matchcustom)\n  - [match.Type\\[ExpectedType\\]](#matchtype)\n- [Configuration](#configuration)\n- [Update Snapshots](#update-snapshots)\n  - [Clean obsolete Snapshots](#clean-obsolete-snapshots)\n  - [Sort Snapshots](#sort-snapshots)\n  - [Skipping Tests](#skipping-tests)\n- [Running tests on CI](#running-tests-on-ci)\n- [No Color](#no-color)\n- [Snapshots Structure](#snapshots-structure)\n- [Known Limitations](#known-limitations)\n- [Acknowledgments](#acknowledgments)\n- [Contributing](./contributing.md)\n\n## Installation\n\nTo install `go-snaps`, use `go get`:\n\n```bash\ngo get github.com/gkampitakis/go-snaps\n```\n\nImport the `go-snaps/snaps` package into your code:\n\n```go\npackage example\n\nimport (\n  \"testing\"\n\n  \"github.com/gkampitakis/go-snaps/snaps\"\n)\n\nfunc TestExample(t *testing.T) {\n  snaps.MatchSnapshot(t, \"Hello World\")\n}\n```\n\n## MatchSnapshot\n\n`MatchSnapshot` can be used to capture any type of data structured or unstructured.\n\nYou can pass multiple parameters to `MatchSnapshot` or call `MatchSnapshot` multiple\ntimes inside the same test. The difference is in the latter, it will\ncreate multiple entries in the snapshot file.\n\n```go\n// test_simple.go\n\nfunc TestSimple(t *testing.T) {\n  t.Run(\"should make multiple entries in snapshot\", func(t *testing.T) {\n    snaps.MatchSnapshot(t, 5, 10, 20, 25)\n    snaps.MatchSnapshot(t, \"some value\")\n  })\n}\n```\n\n`go-snaps` saves the snapshots in `__snapshots__` directory and the file\nname is the test file name with extension `.snap`.\n\nSo for example if your test is called `test_simple.go` when you run your tests, a snapshot file\nwill be created at `./__snapshots__/test_simple.snaps`.\n\n## MatchStandaloneSnapshot\n\n`MatchStandaloneSnapshot` will create snapshots on separate files as opposed to `MatchSnapshot` which adds multiple snapshots inside the same file.\n\n_Combined with `snaps.Ext` you can have proper syntax highlighting and better readability_\n\n```go\n// test_simple.go\n\nfunc TestSimple(t *testing.T) {\n  snaps.MatchStandaloneSnapshot(t, \"Hello World\")\n  // or create an html snapshot file\n  snaps.WithConfig(snaps.Ext(\".html\")).\n    MatchStandaloneSnapshot(t, \"\u003chtml\u003e\u003cbody\u003e\u003ch1\u003eHello World\u003c/h1\u003e\u003c/body\u003e\u003c/html\u003e\")\n}\n```\n\n`go-snaps` saves the snapshots in `__snapshots__` directory and the file\nname is the `t.Name()` plus a number plus the extension `.snap`.\n\nSo for the above example the snapshot file name will be `./__snapshots__/TestSimple_1.snap` and `./__snapshots__/TestSimple_1.snap.html`.\n\n## MatchJSON\n\n`MatchJSON` can be used to capture data that can represent a valid json.\n\nYou can pass a valid json in form of `string` or `[]byte` or whatever value can be passed\nsuccessfully on `json.Marshal`.\n\n```go\nfunc TestJSON(t *testing.T) {\n  type User struct {\n    Age   int\n    Email string\n  }\n\n  snaps.MatchJSON(t, `{\"user\":\"mock-user\",\"age\":10,\"email\":\"mock@email.com\"}`)\n  snaps.MatchJSON(t, []byte(`{\"user\":\"mock-user\",\"age\":10,\"email\":\"mock@email.com\"}`))\n  snaps.MatchJSON(t, User{10, \"mock-email\"})\n}\n```\n\nJSON will be saved in snapshot in pretty format for more readability and deterministic diffs.\n\n## MatchStandaloneJSON\n\n`MatchStandaloneJSON` will create snapshots on separate files as opposed to `MatchJSON` which adds multiple snapshots inside the same file.\n\n```go\nfunc TestSimple(t *testing.T) {\n  snaps.MatchStandaloneJSON(t, `{\"user\":\"mock-user\",\"age\":10,\"email\":\"mock@email.com\"}`)\n  snaps.MatchStandaloneJSON(t, User{10, \"mock-email\"})\n}\n```\n\n`go-snaps` saves the snapshots in `__snapshots__` directory and the file\nname is the `t.Name()` plus a number plus the extension `.snap.json`.\n\nSo for the above example the snapshot file name will be `./__snapshots__/TestSimple_1.snap.json` and `./__snapshots__/TestSimple_2.snap.json`.\n\n## MatchYAML\n\n`MatchYAML` can be used to capture data that can represent a valid yaml.\n\nYou can pass a valid json in form of `string` or `[]byte` or whatever value can be passed\nsuccessfully on `yaml.Marshal`.\n\n```go\nfunc TestYAML(t *testing.T) {\n  type User struct {\n    Age   int\n    Email string\n  }\n\n  snaps.MatchYAML(t, \"user: \\\"mock-user\\\"\\nage: 10\\nemail: mock@email.com\")\n  snaps.MatchYAML(t, []byte(\"user: \\\"mock-user\\\"\\nage: 10\\nemail: mock@email.com\"))\n  snaps.MatchYAML(t, User{10, \"mock-email\"})\n}\n```\n\n## MatchStandaloneYAML\n\n`MatchStandaloneYAML` will create snapshots on separate files as opposed to `MatchYAML` which adds multiple snapshots inside the same file.\n\n```go\nfunc TestSimple(t *testing.T) {\n  snaps.MatchStandaloneYAML(t, \"user: \\\"mock-user\\\"\\nage: 10\\nemail: \\\"mock@email.com\\\"\")\n  snaps.MatchStandaloneYAML(t, User{10, \"mock-email\"})\n}\n```\n\n`go-snaps` saves the snapshots in `__snapshots__` directory and the file\nname is the `t.Name()` plus a number plus the extension `.snap.yaml`.\n\nSo for the above example the snapshot file name will be `./__snapshots__/TestSimple_1.snap.yaml` and `./__snapshots__/TestSimple_2.snap.yaml`.\n\n### Matchers\n\n`MatchJSON`'s and `MatchYAML`'s third argument can accept a list of matchers. Matchers are functions that can act\nas property matchers and test values.\n\nYou can pass the path of the property you want to match and test.\n\nCurrently `go-snaps` has three build in matchers\n\n- `match.Any`\n- `match.Custom`\n- `match.Type[ExpectedType]`\n\n_Open to feedback for building more matchers or you can build your own [example](./examples/matchJSON_test.go#L16)._\n\n#### Path Syntax\n\nFor JSON go-snaps utilises gjson.\n\n_More information about the supported path syntax from [gjson](https://github.com/tidwall/gjson/blob/v1.17.0/SYNTAX.md)._\n\nAs for YAML go-snaps utilises [github.com/goccy/go-yaml#5-use-yamlpath](https://github.com/goccy/go-yaml#5-use-yamlpath).\n\n_More information about the supported syntax [PathString](https://github.com/goccy/go-yaml/blob/9cbf5d4217830fd4ad1504e9ed117c183ade0994/path.go#L17-L26)._\n\n#### match.Any\n\nAny matcher acts as a placeholder for any value. It replaces any targeted path with a\nplaceholder string.\n\n```go\nAny(\"user.name\")\n// or with multiple paths\nAny(\"user.name\", \"user.email\")\n```\n\nAny matcher provides some methods for setting options\n\n```go\nmatch.Any(\"user.name\").\n  Placeholder(value). // allows to define a different placeholder value from the default \"\u003cAny Value\u003e\"\n  ErrOnMissingPath(bool) // determines whether the matcher will err in case of a missing, default true\n```\n\n#### match.Custom\n\nCustom matcher allows you to bring your own validation and placeholder value\n\n```go\nmatch.Custom(\"user.age\", func(val any) (any, error) {\n\t\tage, ok := val.(float64)\n\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"expected number but got %T\", val)\n\t\t}\n\n\t\treturn \"some number\", nil\n})\n```\n\nThe callback parameter value for JSON can be on of these types:\n\n```go\nbool // for JSON booleans\nfloat64 // for JSON numbers\nstring // for JSON string literals\nnil // for JSON null\nmap[string]any // for JSON objects\n[]any // for JSON arrays\n```\n\nIf Custom matcher returns an error the snapshot test will fail with that error.\n\nCustom matcher provides a method for setting an option\n\n```go\nmatch.Custom(\"path\",myFunc).\n  Placeholder(value). // allows to define a different placeholder value from the default \"\u003cAny Value\u003e\"\n  ErrOnMissingPath(bool) // determines whether the matcher will err in case of a missing path, default true\n```\n\n#### match.Type\n\nType matcher evaluates types that are passed in a snapshot and it replaces any targeted path with a placeholder in the form of `\u003cType:ExpectedType\u003e`.\n\n```go\nmatch.Type[string](\"user.info\")\n// or with multiple paths\nmatch.Type[float64](\"user.age\", \"data.items\")\n```\n\nType matcher provides a method for setting an option\n\n```go\nmatch.Type[string](\"user.info\").\n  ErrOnMissingPath(bool) // determines whether the matcher will err in case of a missing path, default true\n```\n\nYou can see more [examples](./examples/matchJSON_test.go#L96).\n\n## MatchInlineSnapshot\n\n`MatchInlineSnapshot` allows you to store expected snapshot values directly within your test source code, rather than in external snapshot files.\n\n**First run** - Create the snapshot by passing `nil` on the last argument:\n\n```go\nfunc TestInlineSnapshot(t *testing.T) {\n\tsnaps.MatchInlineSnapshot(t, \"Hello World\", nil)\n\tsnaps.MatchInlineSnapshot(t, 123, nil)\n\tsnaps.MatchInlineSnapshot(t, map[string]int{\"foo\": 1, \"bar\": 2}, nil)\n}\n```\n\nThen run your tests, and `go-snaps` will automatically insert the snapshot into your test code.\n\n```go\nfunc TestInlineSnapshot(t *testing.T) {\n\tsnaps.MatchInlineSnapshot(t, \"Hello World\", snaps.Inline(\"Hello World\"))\n\tsnaps.MatchInlineSnapshot(t, 123, snaps.Inline(\"int(123)\"))\n\tsnaps.MatchInlineSnapshot(t, map[string]int{\"foo\": 1, \"bar\": 2}, snaps.Inline(`map[string]int{\"bar\":2, \"foo\":1}`))\n}\n```\n\nEvery subsequent test run will compare the actual value against the inline snapshot, and if they differ, the test will fail and display a diff.\n\n\u003e [!NOTE]\n\u003e `MatchInlineSnapshot` is experimental and looking for feedback and thorough testing before being marked as stable.\n\n## Configuration\n\n`go-snaps` allows passing configuration for overriding\n\n- the directory where snapshots are stored, _relative or absolute path_ `snaps.Dir(\"my_dir\")`\n- the filename where snapshots are stored `snaps.Filename(\"my_file\")`\n- the snapshot file's extension (_regardless the extension the filename will include the `.snaps` inside the filename_) `snaps.Ext(\".json\")`\n- programmatically control whether to update snapshots. _You can find an example usage at [examples](/examples/examples_test.go#13)_ `snaps.Update(true)`\n- json config's json format configuration: `snaps.JSON(snaps.JSONConfig{...})`\n  - `Width`: The maximum width in characters before wrapping json output (default: 80)\n  - `Indent`: The indentation string to use for nested structures (default: 1 spaces)\n  - `SortKeys`: Whether to sort json object keys alphabetically (default: true)\n- a custom serializer function for non-structured snapshots `snaps.Serializer(func(any) string {...})`\n- a helper serializer function `snaps.Raw()` that uses `fmt.Sprint` to serialize the value as is without any formatting or indentation.\n\n```go\nt.Run(\"snapshot tests\", func(t *testing.T) {\n  snaps.WithConfig(snaps.Filename(\"my_custom_name\"), snaps.Dir(\"my_dir\")).MatchSnapshot(t, \"Hello Word\")\n\n  s := snaps.WithConfig(\n    snaps.Dir(\"my_dir\"),\n    snaps.Filename(\"json_file\"),\n    snaps.Ext(\".json\"),\n    snaps.Update(false),\n    snaps.Serializer(func(v any) string {\n      // custom serializer logic\n      return fmt.Sprintf(\"custom: %v\", v)\n    }),\n    // or snaps.Raw() for no formatting\n    snaps.JSON(snaps.JSONConfig{\n      Width:    80,\n      Indent:   \"    \",\n      SortKeys: false,\n    }),\n  )\n\n  s.MatchJSON(t, `{\"hello\":\"world\"}`)\n})\n```\n\nYou can see more on [examples](/examples/matchSnapshot_test.go#L67)\n\n## Update Snapshots\n\nYou can update your failing snapshots by setting `UPDATE_SNAPS` env variable to true.\n\n```bash\nUPDATE_SNAPS=true go test ./...\n```\n\nIf you don't want to update all failing snapshots, or you want to update only one of\nthem you can you use the `-run` flag to target the test(s) you want.\n\nFor more information on `go test` flags you can run\n\n```go\ngo help testflag\n```\n\n### Clean obsolete snapshots\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"./images/summary-obsolete.png\" alt=\"Summary Obsolete\" width=\"700\"/\u003e\n\u003cimg src=\"./images/summary-removed.png\" alt=\"Summary Removed\" width=\"700\"/\u003e\n\u003c/p\u003e\n\n`go-snaps` can identify obsolete snapshots.\n\nIn order to enable this functionality you need to use `TestMain(m *testing.M)` to\ncall `snaps.Clean(t)` after your tests have run. This will also print a **Snapshot Summary**. (if running tests\nwith verbose flag `-v`)\n\nIf you want to remove the obsolete snap files and snapshots you can run\ntests with `UPDATE_SNAPS=clean` env variable.\n\nThe reason for using `TestMain` is because `go-snaps` needs to be sure that all tests\nare finished so it can keep track of which snapshots were not called.\n\n**Example:**\n\n```go\nfunc TestMain(m *testing.M) {\n  v := m.Run()\n\n  // After all tests have run `go-snaps` can check for unused snapshots\n  snaps.Clean(m)\n\t// dirty, err := snaps.Clean(m)\n  // _ = err\n  // if dirty {\n  //   fmt.Println(\"Some snapshots were outdated.\")\n  //   os.Exit(1)\n  // }\n\n  os.Exit(v)\n}\n```\n\nFor more information around [TestMain](https://pkg.go.dev/testing#hdr-Main).\n\n### Sort Snapshots\n\nBy default `go-snaps` appends new snaps to the snapshot file and in case of parallel tests the order is random. If you want snaps to be sorted in deterministic order you need to use `TestMain` per package:\n\n```go\nfunc TestMain(m *testing.M) {\n  v := m.Run()\n\n  // After all tests have run `go-snaps` will sort snapshots\n  snaps.Clean(m, snaps.CleanOpts{Sort: true})\n\n  os.Exit(v)\n}\n```\n\n### Skipping Tests\n\nIf you want to skip one test using `t.Skip`, `go-snaps` can't keep track\nif the test was skipped or if it was removed. For that reason `go-snaps` exposes\na wrapper for `t.Skip`, `t.Skipf` and `t.SkipNow`, which keep tracks of skipped files.\n\nYou can skip, or only run specific tests by using the `-run` flag. `go-snaps`\ncan identify which tests are being skipped and parse only the relevant tests\nfor obsolete snapshots.\n\n## Running Tests on CI\n\nWhen `go-snaps` detects that it is running in CI it will automatically fail when snapshots are missing or there diffs. This is done to ensure new snapshots are committed alongside the tests and assertions are successful.\n\nYou can override this behavior by setting `UPDATE_SNAPS` to `always` when running your tests that will create or update snapshots.\n\n\u003e `go-snaps` uses [ciinfo](https://github.com/gkampitakis/ciinfo) for detecting if it runs on CI environment.\n\n## No Color\n\n`go-snaps` supports disabling color outputs by running your tests with the env variable\n`NO_COLOR` set to any value.\n\n```bash\nNO_COLOR=true go test ./...\n```\n\nFor more information around [NO_COLOR](https://no-color.org).\n\n## Snapshots Structure\n\nSnapshots have the form\n\n```text\n[TestName - Number]\n\u003cdata\u003e\n---\n```\n\n`TestID` is the test name plus an increasing number to allow multiple calls of `MatchSnapshot` in a single test.\n\n```txt\n[TestSimple/should_make_a_map_snapshot - 1]\nmap[string]any{\n    \"mock-0\": \"value\",\n    \"mock-1\": int(2),\n    \"mock-2\": func() {...},\n    \"mock-3\": float32(10.399999618530273),\n}\n---\n```\n\n\u003e [!NOTE]\n\u003e If your snapshot data contain characters `---` at the start of a line followed by a new line, `go-snaps` will \"escape\" them and save them as `/-/-/-/` to differentiate them from termination characters.\n\n## Known Limitations\n\n- When running a specific test file by specifying a path `go test ./my_test.go`, `go-snaps` can't track the path so it will mistakenly mark snapshots as obsolete.\n- go-snaps doesn't handle CRLF line endings. If you are using Windows, you may need to convert the line endings to LF.\n- go-snaps cannot determine the snapshot path automatically when running with `go test -trimpath ./...`. It then instead relies on the current working directory to define the snapshot directory. If this is a problem in your use case you can set an absolute path with `snaps.WithConfig(snaps.Dir(\"/some/absolute/path\"))`\n\n## Acknowledgments\n\nThis library used [Jest Snapshoting](https://jestjs.io/docs/snapshot-testing) and [Cupaloy](https://github.com/bradleyjkemp/cupaloy) as inspiration.\n\n- Jest is a full-fledged Javascript testing framework and has robust snapshoting features.\n- Cupaloy is a great and simple Golang snapshoting solution.\n- The [logo](https://github.com/MariaLetta/free-gophers-pack) was made by [MariaLetta](https://github.com/MariaLetta).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgkampitakis%2Fgo-snaps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgkampitakis%2Fgo-snaps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgkampitakis%2Fgo-snaps/lists"}