@@ -7,93 +7,99 @@ import (
77 "bytes"
88 "encoding/json"
99 "fmt"
10+ "slices"
1011 "strings"
1112 "testing"
1213
13- "github.com/tidwall/gjson"
14- "github.com/tidwall/pretty"
15-
16- "github.com/ory/x/stringslice"
17-
1814 "github.com/bradleyjkemp/cupaloy/v2"
1915 "github.com/stretchr/testify/require"
16+ "github.com/tidwall/gjson"
2017 "github.com/tidwall/sjson"
2118)
2219
2320type (
24- ExceptOpt interface {
25- apply (t * testing.T , raw []byte ) []byte
21+ Opt = func (* options )
22+ options struct {
23+ modifiers []func (t * testing.T , raw []byte ) []byte
24+ name string
2625 }
27- exceptPaths []string
28- exceptNestedKeys []string
29- replacement struct { str , replacement string }
3026)
3127
32- func (e exceptPaths ) apply (t * testing.T , raw []byte ) []byte {
33- for _ , ee := range e {
34- var err error
35- raw , err = sjson .DeleteBytes (raw , ee )
36- require .NoError (t , err )
28+ func ExceptPaths (keys ... string ) Opt {
29+ return func (o * options ) {
30+ o .modifiers = append (o .modifiers , func (t * testing.T , raw []byte ) []byte {
31+ for _ , key := range keys {
32+ var err error
33+ raw , err = sjson .DeleteBytes (raw , key )
34+ require .NoError (t , err )
35+ }
36+ return raw
37+ })
3738 }
38- return raw
39- }
40-
41- func (e exceptNestedKeys ) apply (t * testing.T , raw []byte ) []byte {
42- parsed := gjson .ParseBytes (raw )
43- require .True (t , parsed .IsObject () || parsed .IsArray ())
44- return deleteMatches (t , "" , parsed , e , []string {}, raw )
4539}
4640
47- func (r * replacement ) apply (_ * testing.T , raw []byte ) []byte {
48- return bytes .ReplaceAll (raw , []byte (r .str ), []byte (r .replacement ))
41+ func ExceptNestedKeys (nestedKeys ... string ) Opt {
42+ return func (o * options ) {
43+ o .modifiers = append (o .modifiers , func (t * testing.T , raw []byte ) []byte {
44+ parsed := gjson .ParseBytes (raw )
45+ require .True (t , parsed .IsObject () || parsed .IsArray ())
46+ return deleteMatches (t , "" , parsed , nestedKeys , []string {}, raw )
47+ })
48+ }
4949}
5050
51- func ExceptPaths (keys ... string ) ExceptOpt {
52- return exceptPaths (keys )
51+ func WithReplacement (str , replace string ) Opt {
52+ return func (o * options ) {
53+ o .modifiers = append (o .modifiers , func (t * testing.T , raw []byte ) []byte {
54+ return bytes .ReplaceAll (raw , []byte (str ), []byte (replace ))
55+ })
56+ }
5357}
5458
55- func ExceptNestedKeys (nestedKeys ... string ) ExceptOpt {
56- return exceptNestedKeys (nestedKeys )
59+ func WithName (name string ) Opt {
60+ return func (o * options ) {
61+ o .name = name
62+ }
5763}
5864
59- func WithReplacement (str , replace string ) ExceptOpt {
60- return & replacement {str : str , replacement : replace }
65+ func newOptions (opts ... Opt ) * options {
66+ o := & options {}
67+ for _ , opt := range opts {
68+ opt (o )
69+ }
70+ return o
6171}
6272
63- func SnapshotTJSON (t * testing.T , compare []byte , except ... ExceptOpt ) {
64- t .Helper ()
65- for _ , e := range except {
66- compare = e .apply (t , compare )
73+ func (o * options ) applyModifiers (t * testing.T , compare []byte ) []byte {
74+ for _ , modifier := range o .modifiers {
75+ compare = modifier (t , compare )
6776 }
68-
69- cupaloy .New (
70- cupaloy .CreateNewAutomatically (true ),
71- cupaloy .FailOnUpdate (true ),
72- cupaloy .SnapshotFileExtension (".json" ),
73- ).SnapshotT (t , pretty .Pretty (compare ))
77+ return compare
7478}
7579
76- func SnapshotTJSONString (t * testing.T , str string , except ... ExceptOpt ) {
77- t .Helper ()
78- SnapshotTJSON (t , []byte (str ), except ... )
80+ var snapshot = cupaloy .New (cupaloy .SnapshotFileExtension (".json" ))
81+
82+ func SnapshotTJSON [C ~ string | ~ []byte ](t * testing.T , compare C , opts ... Opt ) {
83+ SnapshotT (t , json .RawMessage (compare ), opts ... )
7984}
8085
81- func SnapshotT (t * testing.T , actual interface {}, except ... ExceptOpt ) {
86+ func SnapshotT (t * testing.T , actual any , opts ... Opt ) {
8287 t .Helper ()
8388 compare , err := json .MarshalIndent (actual , "" , " " )
8489 require .NoErrorf (t , err , "%+v" , actual )
85- for _ , e := range except {
86- compare = e .apply (t , compare )
87- }
8890
89- cupaloy .New (
90- cupaloy .CreateNewAutomatically (true ),
91- cupaloy .FailOnUpdate (true ),
92- cupaloy .SnapshotFileExtension (".json" ),
93- ).SnapshotT (t , compare )
91+ o := newOptions (opts ... )
92+ compare = o .applyModifiers (t , compare )
93+
94+ if o .name == "" {
95+ snapshot .SnapshotT (t , compare )
96+ } else {
97+ name := strings .ReplaceAll (t .Name ()+ "_" + o .name , "/" , "-" )
98+ require .NoError (t , snapshot .SnapshotWithName (name , compare ))
99+ }
94100}
95101
96- // SnapshotTExcept is deprecated in favor of SnapshotT with ExceptOpt .
102+ // SnapshotTExcept is deprecated in favor of SnapshotT with Opt .
97103//
98104// DEPRECATED: please use SnapshotT instead
99105func SnapshotTExcept (t * testing.T , actual interface {}, except []string ) {
@@ -105,11 +111,7 @@ func SnapshotTExcept(t *testing.T, actual interface{}, except []string) {
105111 require .NoError (t , err , "%s" , e )
106112 }
107113
108- cupaloy .New (
109- cupaloy .CreateNewAutomatically (true ),
110- cupaloy .FailOnUpdate (true ),
111- cupaloy .SnapshotFileExtension (".json" ),
112- ).SnapshotT (t , compare )
114+ snapshot .SnapshotT (t , compare )
113115}
114116
115117func deleteMatches (t * testing.T , key string , result gjson.Result , matches []string , parents []string , content []byte ) []byte {
@@ -132,33 +134,11 @@ func deleteMatches(t *testing.T, key string, result gjson.Result, matches []stri
132134 })
133135 }
134136
135- if stringslice . Has (matches , key ) {
137+ if slices . Contains (matches , key ) {
136138 content , err := sjson .DeleteBytes (content , strings .Join (path , "." ))
137139 require .NoError (t , err )
138140 return content
139141 }
140142
141143 return content
142144}
143-
144- // SnapshotTExceptMatchingKeys works like SnapshotTExcept but deletes keys that match the given matches recursively.
145- //
146- // So instead of having deeply nested keys like `foo.bar.baz.0.key_to_delete` you can have `key_to_delete` and
147- // all occurences of `key_to_delete` will be removed.
148- //
149- // DEPRECATED: please use SnapshotT instead
150- func SnapshotTExceptMatchingKeys (t * testing.T , actual interface {}, matches []string ) {
151- t .Helper ()
152- compare , err := json .MarshalIndent (actual , "" , " " )
153- require .NoError (t , err , "%+v" , actual )
154-
155- parsed := gjson .ParseBytes (compare )
156- require .True (t , parsed .IsObject () || parsed .IsArray ())
157- compare = deleteMatches (t , "" , parsed , matches , []string {}, compare )
158-
159- cupaloy .New (
160- cupaloy .CreateNewAutomatically (true ),
161- cupaloy .FailOnUpdate (true ),
162- cupaloy .SnapshotFileExtension (".json" ),
163- ).SnapshotT (t , compare )
164- }
0 commit comments