Skip to content

Commit

Permalink
feat: add json format config (#121)
Browse files Browse the repository at this point in the history
Co-authored-by: Wasutan Kitijerapat <wasutan.k@lmwn.com>
  • Loading branch information
kitimark and Wasutan Kitijerapat authored Feb 14, 2025
1 parent 8740883 commit e004bc1
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 6 deletions.
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

0 comments on commit e004bc1

Please sign in to comment.