Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add json format config #121

Merged
merged 4 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,10 @@ You can see more [examples](./examples/matchJSON_test.go#L96).
- the filename where snapshots are stored
- the snapshot file's extension (_regardless the extension the filename will include the `.snaps` inside the filename_)
- programmatically control whether to update snapshots. _You can find an example usage at [examples](/examples/examples_test.go#13)_
- json config's json format configuration:
- `Width`: The maximum width in characters before wrapping json output (default: 80)
- `Indent`: The indentation string to use for nested structures (default: 1 spaces)
- `SortKeys`: Whether to sort json object keys alphabetically (default: true)

```go
t.Run("snapshot tests", func(t *testing.T) {
Expand All @@ -283,7 +287,12 @@ t.Run("snapshot tests", func(t *testing.T) {
snaps.Dir("my_dir"),
snaps.Filename("json_file"),
snaps.Ext(".json"),
snaps.Update(false)
snaps.Update(false),
snaps.JSON(snaps.JSONConfig{
Width: 80,
Indent: " ",
SortKeys: false,
}),
)

s.MatchJSON(t, `{"hello":"world"}`)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"user": "mock-user",
"age": 10,
"email": "mock@email.com"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"user": "mock-user",
"age": 10,
"email": "mock@email.com"
}
16 changes: 16 additions & 0 deletions examples/__snapshots__/matchJSON_test.snap
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,19 @@
"metadata": "<Type:map[string]interface {}>"
}
---

[TestMatchJSON/should_create_a_prettyJSON_snap_following_by_config - 1]
{
"user": "mock-user",
"age": 10,
"email": "mock@email.com"
}
---

[TestMatchJSON/should_create_a_prettyJSON_snap_following_by_config - 2]
{
"user": "mock-user",
"age": 10,
"email": "mock@email.com"
}
---
10 changes: 10 additions & 0 deletions examples/matchJSON_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ func TestMatchJSON(t *testing.T) {

snaps.MatchJSON(t, u)
})

t.Run("should create a prettyJSON snap following by config", func(t *testing.T) {
value := `{"user":"mock-user","age":10,"email":"mock@email.com"}`
s := snaps.WithConfig(snaps.JSON(snaps.JSONConfig{
Indent: " ",
SortKeys: false,
}))
s.MatchJSON(t, value)
s.MatchJSON(t, []byte(value))
})
}

func TestMatchers(t *testing.T) {
Expand Down
10 changes: 10 additions & 0 deletions examples/matchStandaloneJSON_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ func TestMatchStandaloneJSON(t *testing.T) {
snaps.MatchStandaloneJSON(t, u)
})

t.Run("should create a prettyJSON snap following by config", func(t *testing.T) {
value := `{"user":"mock-user","age":10,"email":"mock@email.com"}`
s := snaps.WithConfig(snaps.JSON(snaps.JSONConfig{
Indent: " ",
SortKeys: false,
}))
s.MatchStandaloneJSON(t, value)
s.MatchStandaloneJSON(t, []byte(value))
})

t.Run("matchers", func(t *testing.T) {
t.Run("Custom matcher", func(t *testing.T) {
t.Run("struct marshalling", func(t *testing.T) {
Expand Down
8 changes: 4 additions & 4 deletions snaps/matchJSON.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
)

var (
jsonOptions = &pretty.Options{
defaultPrettyJSONOptions = &pretty.Options{
SortKeys: true,
Indent: " ",
}
Expand Down Expand Up @@ -97,7 +97,7 @@ func matchJSON(c *Config, t testingT, input any, matchers ...match.JSONMatcher)
return
}

snapshot := takeJSONSnapshot(j)
snapshot := takeJSONSnapshot(c, j)
prevSnapshot, line, err := getPrevSnapshot(testID, snapPath)
if errors.Is(err, errSnapNotFound) {
if !shouldCreate(c.update) {
Expand Down Expand Up @@ -159,8 +159,8 @@ func validateJSON(input any) ([]byte, error) {
}
}

func takeJSONSnapshot(b []byte) string {
return strings.TrimSuffix(string(pretty.PrettyOptions(b, jsonOptions)), "\n")
func takeJSONSnapshot(c *Config, b []byte) string {
return strings.TrimSuffix(string(pretty.PrettyOptions(b, c.json.getPrettyJSONOptions())), "\n")
}

func applyJSONMatchers(b []byte, matchers ...match.JSONMatcher) ([]byte, []match.MatcherError) {
Expand Down
2 changes: 1 addition & 1 deletion snaps/matchStandaloneJSON.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func matchStandaloneJSON(c *Config, t testingT, input any, matchers ...match.JSO
return
}

snapshot := takeJSONSnapshot(j)
snapshot := takeJSONSnapshot(c, j)
prevSnapshot, err := getPrevStandaloneSnapshot(snapPath)
if errors.Is(err, errSnapNotFound) {
if !shouldCreate(c.update) {
Expand Down
34 changes: 34 additions & 0 deletions snaps/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"sync"

"github.com/gkampitakis/go-snaps/internal/colors"
"github.com/tidwall/pretty"
)

var (
Expand All @@ -30,6 +31,30 @@ type Config struct {
snapsDir string
extension string
update *bool
json *JSONConfig
}

type JSONConfig struct {
// Width is a max column width for single line arrays
// Default: see defaultPrettyJSONOptions.Width for detail
Width int
// Indent is the nested indentation
// Default: see defaultPrettyJSONOptions.Indent for detail
Indent string
// SortKeys will sort the keys alphabetically
// Default: see defaultPrettyJSONOptions.SortKeys for detail
SortKeys bool
}

func (j *JSONConfig) getPrettyJSONOptions() *pretty.Options {
if j == nil {
return defaultPrettyJSONOptions
}
return &pretty.Options{
Width: j.Width,
Indent: j.Indent,
SortKeys: j.SortKeys,
}
}

// Update determines whether to update snapshots or not
Expand Down Expand Up @@ -75,6 +100,15 @@ func Ext(ext string) func(*Config) {
}
}

// Specify json format configuration
//
// default: see defaultPrettyJSONOptions for default json config
func JSON(json JSONConfig) func(*Config) {
return func(c *Config) {
c.json = &json
}
}

// Create snaps with configuration
//
// e.g snaps.WithConfig(snaps.Filename("my_test")).MatchSnapshot(t, "hello world")
Expand Down