diff --git a/bromide.go b/bromide.go new file mode 100644 index 0000000..d4810ef --- /dev/null +++ b/bromide.go @@ -0,0 +1,89 @@ +package bromide + +import ( + "fmt" + "io" + "os" + "strconv" + "strings" + "testing" + + "github.com/hexops/valast" + "github.com/sergi/go-diff/diffmatchpatch" +) + +const folder = "snapshots" + +func Snapshot[K comparable](t *testing.T, item K) { + t.Helper() + + update := false + if u := os.Getenv("UPDATE_SNAPSHOTS"); u != "" { + v, err := strconv.ParseBool(u) + if err != nil { + t.Errorf("unable to parse boolean : %s", err.Error()) + return + } + + update = v + } + + currentDir, err := os.Getwd() + if err != nil { + t.Errorf("Error getting current directory: %v", err) + } + + snapshotDir := fmt.Sprintf("%s/%s", currentDir, folder) + name := fmt.Sprintf("%s/%s.snap", snapshotDir, t.Name()) + + incoming := serialize(item) + + if err := os.MkdirAll(snapshotDir, 0755); err != nil { + panic("unable to create snapshot directory") + } + + file, err := os.Open(name) + if err != nil { + if !os.IsNotExist(err) { + panic("unable to open existing snapshot") + } + + file, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0644) + if err != nil { + panic("unable to create new snapshot" + err.Error()) + } + defer file.Close() + + if _, err := file.WriteString(incoming); err != nil { + panic("unable to create new snapshot") + } + + t.Errorf("created snapshot") + return + } + defer file.Close() + + existing := new(strings.Builder) + io.Copy(existing, file) + + if existing.String() != incoming { + dmp := diffmatchpatch.New() + + diffs := dmp.DiffMain(existing.String(), incoming, true) + + t.Log("snapshot does not match") + t.Log(dmp.DiffPrettyText(diffs)) + + if update { + os.WriteFile(name, []byte(incoming), 0644) + return + } + + t.Fail() + return + } +} + +func serialize[K any](item K) string { + return valast.StringWithOptions(item, &valast.Options{Unqualify: false}) +} diff --git a/bromide_test.go b/bromide_test.go new file mode 100644 index 0000000..339b353 --- /dev/null +++ b/bromide_test.go @@ -0,0 +1,20 @@ +package bromide_test + +import ( + "testing" + + "github.com/cobbinma/bromide" +) + +type testStruct struct { + example string + again int +} + +func Test_Snapshot(t *testing.T) { + hello := testStruct{ + example: "hello", + again: 5, + } + bromide.Snapshot(t, hello) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a476680 --- /dev/null +++ b/go.mod @@ -0,0 +1,13 @@ +module github.com/cobbinma/bromide + +go 1.22.0 + +require ( + github.com/google/go-cmp v0.5.9 // indirect + github.com/hexops/valast v1.4.4 // indirect + github.com/sergi/go-diff v1.3.1 // indirect + golang.org/x/mod v0.7.0 // indirect + golang.org/x/sys v0.3.0 // indirect + golang.org/x/tools v0.4.0 // indirect + mvdan.cc/gofumpt v0.4.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..7db8c10 --- /dev/null +++ b/go.sum @@ -0,0 +1,26 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/hexops/valast v1.4.4 h1:rETyycw+/L2ZVJHHNxEBgh8KUn+87WugH9MxcEv9PGs= +github.com/hexops/valast v1.4.4/go.mod h1:Jcy1pNH7LNraVaAZDLyv21hHg2WBv9Nf9FL6fGxU7o4= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +mvdan.cc/gofumpt v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM= +mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ= diff --git a/snapshots/Test_Snapshot.snap b/snapshots/Test_Snapshot.snap new file mode 100644 index 0000000..d8bc518 --- /dev/null +++ b/snapshots/Test_Snapshot.snap @@ -0,0 +1 @@ +testStruct{example: "hello", again: 5} \ No newline at end of file