diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b8a1393..ad6a567 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -32,6 +32,32 @@ jobs:
- name: Check if mods are tidy
run: make check-tidy
+ cov:
+ name: Coverage
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-go@v2
+ with:
+ go-version: 1.15
+ - uses: actions/cache@v2
+ with:
+ path: ~/go/pkg/mod
+ key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+ restore-keys: |
+ ${{ runner.os }}-go-
+ - name: Publish coverage
+ uses: paambaati/codeclimate-action@v2.7.4
+ env:
+ VERBOSE: "true"
+ GOMAXPROCS: 4
+ CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
+ with:
+ coverageCommand: make cov
+ prefix: github.com/${{ github.repository }}
+ coverageLocations: |
+ ${{ github.workspace }}/coverage.out:gocov
+
test:
name: Test
strategy:
diff --git a/.gitignore b/.gitignore
index ede5c9f..f65385f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
bin/*
-testdata/*
coverage.out
+
+testdata/*
+!testdata/TestExample*
diff --git a/Makefile b/Makefile
index c57f9fc..15b676b 100644
--- a/Makefile
+++ b/Makefile
@@ -88,6 +88,18 @@ format: $(TOOLDIR)/goimports $(TOOLDIR)/gofumpt
bench:
go test $(V) -count=1 -bench=$(BENCH) $(TESTARGS) ./...
+.PHONY: golden-update
+golden-update:
+ GOLDEN_UPDATE=1 $(MAKE) test
+
+.PHONY: golden-clean
+golden-clean:
+ find . -type f -name '*.golden' -path '*/testdata/*' -delete
+ find . -type d -empty -path '*/testdata/*' -delete
+
+.PHONY: golden-regen
+golden-regen: golden-clean golden-update
+
#
# Code Generation
#
@@ -171,7 +183,7 @@ check-tidy:
# Serve docs
.PHONY: docs
-docs: godoc
+docs: $(TOOLDIR)/godoc
$(info serviing docs on http://127.0.0.1:6060/pkg/$(GOMODNAME)/)
@godoc -http=127.0.0.1:6060
diff --git a/README.md b/README.md
index 12ab269..d78ae36 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,80 @@
-# go-golden
+
+ go-golden
+
-Yet another Go package for working with `*.golden` test files.
+
+
+ Yet another Go package for working with `*.golden` test files, with a focus
+ on simplicity through it's default behavior.
+
+
-Currently a work in progress.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Golden file names are based on the name of the test function and any subtest
+names by calling t.Name(). File names are sanitized to ensure they're compatible
+with Linux, macOS and Windows systems regardless of what crazy characters might
+be in a subtest's name.
+
+## Import
+
+```
+import "github.com/jimeh/go-golden"
+```
+
+## Usage
+
+Typical usage should look something like this:
+
+```go
+func TestExampleMyStruct(t *testing.T) {
+ got, err := json.Marshal(&MyStruct{Foo: "Bar"})
+ require.NoError(t, err)
+
+ if golden.Update() {
+ golden.Set(t, got)
+ }
+ want := golden.Get(t)
+
+ assert.Equal(t, want, got)
+}
+```
+
+The above example will read/write to:
+
+ testdata/TestExampleMyStruct.golden
+
+To update the golden file (have `golden.Update()` return true), simply set the
+`GOLDEN_UPDATE` environment variable to one of `1`, `y`, `t`, `yes`, `on`, or
+`true` when running tests.
+
+## Documentation
+
+Please see the
+[Go Reference](https://pkg.go.dev/github.com/jimeh/go-golden#section-documentation)
+for documentation and examples.
+
+## License
+
+[MIT](https://github.com/jimeh/go-golden/blob/master/LICENSE)
diff --git a/example_test.go b/example_test.go
new file mode 100644
index 0000000..d60f678
--- /dev/null
+++ b/example_test.go
@@ -0,0 +1,108 @@
+package golden_test
+
+import (
+ "encoding/json"
+ "encoding/xml"
+ "testing"
+
+ "github.com/jimeh/go-golden"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+type MyStruct struct {
+ Foo string `json:"foo,omitempty"`
+}
+
+// TestExampleMyStruct reads/writes the following golden file:
+//
+// testdata/TestExampleMyStruct.golden
+//
+func TestExampleMyStruct(t *testing.T) {
+ got, err := json.Marshal(&MyStruct{Foo: "Bar"})
+ require.NoError(t, err)
+
+ if golden.Update() {
+ golden.Set(t, got)
+ }
+ want := golden.Get(t)
+
+ assert.Equal(t, want, got)
+}
+
+// TestExampleMyStructTabular reads/writes the following golden files:
+//
+// testdata/TestExampleMyStructTabular/empty_struct.golden
+// testdata/TestExampleMyStructTabular/full_struct.golden
+//
+func TestExampleMyStructTabular(t *testing.T) {
+ tests := []struct {
+ name string
+ obj *MyStruct
+ }{
+ {name: "empty struct", obj: &MyStruct{}},
+ {name: "full struct", obj: &MyStruct{Foo: "Bar"}},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := json.Marshal(tt.obj)
+ require.NoError(t, err)
+
+ if golden.Update() {
+ golden.Set(t, got)
+ }
+ want := golden.Get(t)
+
+ assert.Equal(t, want, got)
+ })
+ }
+}
+
+// TestExampleMyStructP reads/writes the following golden file:
+//
+// testdata/TestExampleMyStructP/json.golden
+// testdata/TestExampleMyStructP/xml.golden
+//
+func TestExampleMyStructP(t *testing.T) {
+ gotJSON, _ := json.Marshal(&MyStruct{Foo: "Bar"})
+ gotXML, _ := xml.Marshal(&MyStruct{Foo: "Bar"})
+
+ if golden.Update() {
+ golden.SetP(t, "json", gotJSON)
+ golden.SetP(t, "xml", gotXML)
+ }
+
+ assert.Equal(t, golden.GetP(t, "json"), gotJSON)
+ assert.Equal(t, golden.GetP(t, "xml"), gotXML)
+}
+
+// TestExampleMyStructTabularP reads/writes the following golden file:
+//
+// testdata/TestExampleMyStructTabularP/empty_struct/json.golden
+// testdata/TestExampleMyStructTabularP/empty_struct/xml.golden
+// testdata/TestExampleMyStructTabularP/full_struct/json.golden
+// testdata/TestExampleMyStructTabularP/full_struct/xml.golden
+//
+func TestExampleMyStructTabularP(t *testing.T) {
+ tests := []struct {
+ name string
+ obj *MyStruct
+ }{
+ {name: "empty struct", obj: &MyStruct{}},
+ {name: "full struct", obj: &MyStruct{Foo: "Bar"}},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ gotJSON, _ := json.Marshal(tt.obj)
+ gotXML, _ := xml.Marshal(tt.obj)
+
+ if golden.Update() {
+ golden.SetP(t, "json", gotJSON)
+ golden.SetP(t, "xml", gotXML)
+ }
+
+ assert.Equal(t, golden.GetP(t, "json"), gotJSON)
+ assert.Equal(t, golden.GetP(t, "xml"), gotXML)
+ })
+ }
+}
diff --git a/global.go b/global.go
deleted file mode 100644
index 3787797..0000000
--- a/global.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package golden
-
-import "testing"
-
-var global = New()
-
-// Updating returns true when golden is set to update golden files. Used to
-// determine if golden.Set() should be called or not.
-func Updating() bool {
- return global.Updating()
-}
-
-// Get returns the content of the default golden file for the given *testing.T
-// instance as determined by t.Name(). If no golden file can be found/read, it
-// will fail the test with t.Fatal().
-func Get(t *testing.T) []byte {
- return global.Get(t)
-}
-
-// Set writes given data of the default golden file for the given *testing.T
-// instance as determined by t.Name(). If writing fails it will fail the test
-// with t.Fatal() detailing the error.
-func Set(t *testing.T, data []byte) {
- global.Set(t, data)
-}
-
-// File returns the filename for the default golden file for the given
-// *testing.T instance as determined by t.Name().
-func File(t *testing.T) string {
- return global.File(t)
-}
-
-// GetNamed return the content of the specifically named golden file belonging
-// to the given *testing.T instance as determined by t.Name(). If no golden file
-// can be found/read, it will fail the test with t.Fatal().
-func GetNamed(t *testing.T, name string) []byte {
- return global.GetNamed(t, name)
-}
-
-// SetNamed writes given data of the specifically named golden file belonging to
-// the given *testing.T instance as determined by t.Name(). If writing fails it
-// will fail the test with t.Fatal() detailing the error.
-func SetNamed(t *testing.T, name string, data []byte) {
- global.SetNamed(t, name, data)
-}
-
-func NamedFile(t *testing.T, name string) string {
- return global.NamedFile(t, name)
-}
diff --git a/golden.go b/golden.go
index 2e7d266..3e3c5f8 100644
--- a/golden.go
+++ b/golden.go
@@ -1,10 +1,132 @@
-// Package golden is yet another package for working with *.golden test files.
+// Package golden is yet another package for working with *.golden test files,
+// with a focus on simplicity through it's default behavior.
+//
+// Golden file names are based on the name of the test function and any subtest
+// names by calling t.Name(). File names are sanitized to ensure they're
+// compatible with Linux, macOS and Windows systems regardless of what crazy
+// characters might be in a subtest's name.
+//
+// Usage
+//
+// Typical usage should look something like this:
+//
+// func TestExampleMyStruct(t *testing.T) {
+// got, err := json.Marshal(&MyStruct{Foo: "Bar"})
+// require.NoError(t, err)
+//
+// if golden.Update() {
+// golden.Set(t, got)
+// }
+// want := golden.Get(t)
+//
+// assert.Equal(t, want, got)
+// }
+//
+// The above example will read/write to:
+//
+// testdata/TestExampleMyStruct.golden
+//
+// To update the golden file (have golden.Update() return true), simply set the
+// GOLDEN_UPDATE environment variable to one of "1", "y", "t", "yes", "on", or
+// "true" when running tests.
+//
+// Sub-Tests
+//
+// As the golden filename is based on t.Name(), it works with sub-tests too,
+// ensuring each sub-test gets it's own golden file. For example:
+//
+// func TestExampleMyStructTabular(t *testing.T) {
+// tests := []struct {
+// name string
+// obj *MyStruct
+// }{
+// {name: "empty struct", obj: &MyStruct{}},
+// {name: "full struct", obj: &MyStruct{Foo: "Bar"}},
+// }
+// for _, tt := range tests {
+// t.Run(tt.name, func(t *testing.T) {
+// got, err := json.Marshal(tt.obj)
+// require.NoError(t, err)
+//
+// if golden.Update() {
+// golden.Set(t, got)
+// }
+// want := golden.Get(t)
+//
+// assert.Equal(t, want, got)
+// })
+// }
+// }
+//
+// The above example will read/write to:
+//
+// testdata/TestExampleMyStructTabular/empty_struct.golden
+// testdata/TestExampleMyStructTabular/full_struct.golden
+//
+// Multiple Golden Files in a Single Test
+//
+// The "P" suffixed methods, GetP(), SetP(), and FileP(), all take a name
+// argument which allows using specific golden files within a given *testing.T
+// instance.
+//
+// func TestExampleMyStructP(t *testing.T) {
+// gotJSON, _ := json.Marshal(&MyStruct{Foo: "Bar"})
+// gotXML, _ := xml.Marshal(&MyStruct{Foo: "Bar"})
+//
+// if golden.Update() {
+// golden.SetP(t, "json", gotJSON)
+// golden.SetP(t, "xml", gotXML)
+// }
+//
+// assert.Equal(t, golden.GetP(t, "json"), gotJSON)
+// assert.Equal(t, golden.GetP(t, "xml"), gotXML)
+// }
+//
+// The above example will read/write to:
+//
+// testdata/TestExampleMyStructP/json.golden
+// testdata/TestExampleMyStructP/xml.golden
+//
+// This works with tabular tests too of course:
+//
+// func TestExampleMyStructTabularP(t *testing.T) {
+// tests := []struct {
+// name string
+// obj *MyStruct
+// }{
+// {name: "empty struct", obj: &MyStruct{}},
+// {name: "full struct", obj: &MyStruct{Foo: "Bar"}},
+// }
+// for _, tt := range tests {
+// t.Run(tt.name, func(t *testing.T) {
+// gotJSON, _ := json.Marshal(tt.obj)
+// gotXML, _ := xml.Marshal(tt.obj)
+//
+// if golden.Update() {
+// golden.SetP(t, "json", gotJSON)
+// golden.SetP(t, "xml", gotXML)
+// }
+//
+// assert.Equal(t, golden.GetP(t, "json"), gotJSON)
+// assert.Equal(t, golden.GetP(t, "xml"), gotXML)
+// })
+// }
+// }
+//
+// The above example will read/write to:
+//
+// testdata/TestExampleMyStructTabularP/empty_struct/json.golden
+// testdata/TestExampleMyStructTabularP/empty_struct/xml.golden
+// testdata/TestExampleMyStructTabularP/full_struct/json.golden
+// testdata/TestExampleMyStructTabularP/full_struct/xml.golden
+//
package golden
import (
"io/ioutil"
"os"
"path/filepath"
+ "strings"
"testing"
)
@@ -15,54 +137,190 @@ const (
DefaultDirname = "testdata"
)
-type Golden struct {
- DirMode os.FileMode
- FileMode os.FileMode
- Suffix string
- Dirname string
- UpdatingFunc UpdatingFunc
+var DefaultUpdateFunc = EnvUpdateFunc
+
+var global = New()
+
+// File returns the filename of the golden file for the given *testing.T
+// instance as determined by t.Name().
+func File(t *testing.T) string {
+ return global.File(t)
}
+// Get returns the content of the golden file for the given *testing.T instance
+// as determined by t.Name(). If no golden file can be found/read, it will fail
+// the test by calling t.Fatal().
+func Get(t *testing.T) []byte {
+ return global.Get(t)
+}
+
+// Set writes given data to the golden file for the given *testing.T instance as
+// determined by t.Name(). If writing fails it will fail the test by calling
+// t.Fatal() with error details.
+func Set(t *testing.T, data []byte) {
+ global.Set(t, data)
+}
+
+// FileP returns the filename of the specifically named golden file for the
+// given *testing.T instance as determined by t.Name().
+func FileP(t *testing.T, name string) string {
+ return global.FileP(t, name)
+}
+
+// GetP returns the content of the specifically named golden file belonging
+// to the given *testing.T instance as determined by t.Name(). If no golden file
+// can be found/read, it will fail the test with t.Fatal().
+//
+// This is very similar to Get(), but it allows multiple different golden files
+// to be used within the same one *testing.T instance.
+func GetP(t *testing.T, name string) []byte {
+ return global.GetP(t, name)
+}
+
+// SetP writes given data of the specifically named golden file belonging to
+// the given *testing.T instance as determined by t.Name(). If writing fails it
+// will fail the test with t.Fatal() detailing the error.
+//
+// This is very similar to Set(), but it allows multiple different golden files
+// to be used within the same one *testing.T instance.
+func SetP(t *testing.T, name string, data []byte) {
+ global.SetP(t, name, data)
+}
+
+// Update returns true when golden is set to update golden files. Used to
+// determine if golden.Set() or golden.Write() should be called or not.
+//
+// Default behavior uses EnvUpdateFunc() to check if the "GOLDEN_UPDATE"
+// environment variable is set to a truthy value. To customize create a custom
+// *Golden instance with New() and set a new UpdateFunc value.
+func Update() bool {
+ return global.Update()
+}
+
+// Golden handles all interactions with golden files. The top-level package
+// functions all just proxy through to a default global *Golden instance.
+type Golden struct {
+ // DirMode determines the file system permissions of any folders created to
+ // hold golden files.
+ DirMode os.FileMode
+
+ // FileMode determines the file system permissions of any created or updated
+ // golden files written to disk.
+ FileMode os.FileMode
+
+ // Suffix determines the filename suffix for all golden files. Typically
+ // this should be ".golden", but can be changed here if needed.
+ Suffix string
+
+ // Dirname is the name of the top-level directory at the root of the package
+ // which holds all golden files. Typically this should "testdata", but can
+ // be changed here if needed.
+ Dirname string
+
+ // UpdateFunc is used to determine if golden files should be updated or
+ // not. Its boolean return value is returned by Update().
+ UpdateFunc UpdateFunc
+}
+
+// New returns a new *Golden instance with default values correctly
+// populated. This is ideally how you should create a custom *Golden, and then
+// modify the relevant fields as you see fit.
func New() *Golden {
return &Golden{
- DirMode: DefaultDirMode,
- FileMode: DefaultFileMode,
- Suffix: DefaultSuffix,
- Dirname: DefaultDirname,
- UpdatingFunc: EnvVarUpdatingFunc,
+ DirMode: DefaultDirMode,
+ FileMode: DefaultFileMode,
+ Suffix: DefaultSuffix,
+ Dirname: DefaultDirname,
+ UpdateFunc: DefaultUpdateFunc,
}
}
-// Updating returns true when the function assigned to UpdatingFunc returns
-// true.
-func (s *Golden) Updating() bool {
- return s.UpdatingFunc()
-}
-
-// Get returns the content of the default golden file for the given *testing.T
-// instance as determined by t.Name(). If no golden file can be found/read, it
-// will fail the test with t.Fatal().
-func (s *Golden) Get(t *testing.T) []byte {
- return s.GetNamed(t, "")
-}
-
-// Set writes given data of the default golden file for the given *testing.T
-// instance as determined by t.Name(). If writing fails it will fail the test
-// with t.Fatal() detailing the error.
-func (s *Golden) Set(t *testing.T, data []byte) {
- s.SetNamed(t, "", data)
-}
-
+// File returns the filename of the golden file for the given *testing.T
+// instance as determined by t.Name().
func (s *Golden) File(t *testing.T) string {
- return s.NamedFile(t, "")
+ return s.file(t, "")
}
-func (s *Golden) GetNamed(t *testing.T, name string) []byte {
- if t == nil {
+// Get returns the content of the golden file for the given *testing.T instance
+// as determined by t.Name(). If no golden file can be found/read, it will fail
+// the test by calling t.Fatal().
+func (s *Golden) Get(t *testing.T) []byte {
+ return s.get(t, "")
+}
+
+// Set writes given data to the golden file for the given *testing.T instance as
+// determined by t.Name(). If writing fails it will fail the test by calling
+// t.Fatal() with error details.
+func (s *Golden) Set(t *testing.T, data []byte) {
+ s.set(t, "", data)
+}
+
+// FileP returns the filename of the specifically named golden file for the
+// given *testing.T instance as determined by t.Name().
+func (s *Golden) FileP(t *testing.T, name string) string {
+ if name == "" {
+ if t != nil {
+ t.Fatal("golden: name cannot be empty")
+ }
+ return ""
+ }
+
+ return s.file(t, name)
+}
+
+// GetP returns the content of the specifically named golden file belonging
+// to the given *testing.T instance as determined by t.Name(). If no golden file
+// can be found/read, it will fail the test with t.Fatal().
+//
+// This is very similar to Get(), but it allows multiple different golden files
+// to be used within the same one *testing.T instance.
+func (s *Golden) GetP(t *testing.T, name string) []byte {
+ if name == "" {
+ t.Fatal("golden: name cannot be empty")
return nil
}
- f := s.NamedFile(t, name)
+ return s.get(t, name)
+}
+
+// SetP writes given data of the specifically named golden file belonging to
+// the given *testing.T instance as determined by t.Name(). If writing fails it
+// will fail the test with t.Fatal() detailing the error.
+//
+// This is very similar to Set(), but it allows multiple different golden files
+// to be used within the same one *testing.T instance.
+func (s *Golden) SetP(t *testing.T, name string, data []byte) {
+ if name == "" {
+ t.Fatal("golden: name cannot be empty")
+ }
+
+ s.set(t, name, data)
+}
+
+func (s *Golden) file(t *testing.T, name string) string {
+ if t.Name() == "" {
+ t.Fatalf("golden: could not determine filename for: %+v", t)
+ return ""
+ }
+
+ base := []string{s.Dirname, filepath.FromSlash(t.Name())}
+ if name != "" {
+ base = append(base, name)
+ }
+
+ f := filepath.Clean(filepath.Join(base...) + s.Suffix)
+
+ dirty := strings.Split(f, string(os.PathSeparator))
+ clean := make([]string, 0, len(dirty))
+ for _, s := range dirty {
+ clean = append(clean, sanitizeFilename(s))
+ }
+
+ return strings.Join(clean, string(os.PathSeparator))
+}
+
+func (s *Golden) get(t *testing.T, name string) []byte {
+ f := s.file(t, name)
b, err := ioutil.ReadFile(f)
if err != nil {
@@ -72,12 +330,8 @@ func (s *Golden) GetNamed(t *testing.T, name string) []byte {
return b
}
-func (s *Golden) SetNamed(t *testing.T, name string, data []byte) {
- if t == nil {
- return
- }
-
- f := s.NamedFile(t, name)
+func (s *Golden) set(t *testing.T, name string, data []byte) {
+ f := s.file(t, name)
dir := filepath.Dir(f)
t.Logf("golden: writing .golden file: %s", f)
@@ -94,16 +348,12 @@ func (s *Golden) SetNamed(t *testing.T, name string, data []byte) {
}
}
-func (s *Golden) NamedFile(t *testing.T, name string) string {
- if t == nil || t.Name() == "" {
- t.Fatalf("golden: could not determine filename for: %+v", t)
- return ""
- }
-
- base := []string{s.Dirname, filepath.FromSlash(t.Name())}
- if name != "" {
- base = append(base, name)
- }
-
- return filepath.Clean(filepath.Join(base...) + s.Suffix)
+// Update returns true when golden is set to update golden files. Used to
+// determine if golden.Set() or golden.Write() should be called or not.
+//
+// Default behavior uses EnvUpdateFunc() to check if the "GOLDEN_UPDATE"
+// environment variable is set to a truthy value. To customize set a new
+// UpdateFunc value on *Golden.
+func (s *Golden) Update() bool {
+ return s.UpdateFunc()
}
diff --git a/global_test.go b/golden_test.go
similarity index 56%
rename from global_test.go
rename to golden_test.go
index 6a5c8bd..a077a32 100644
--- a/global_test.go
+++ b/golden_test.go
@@ -11,98 +11,6 @@ import (
"github.com/stretchr/testify/require"
)
-func TestUpdating(t *testing.T) {
- tests := []struct {
- name string
- env map[string]string
- want bool
- }{
- {
- name: "GOLDEN_UPDATE not set",
- want: false,
- },
- {
- name: "GOLDEN_UPDATE set to 0",
- env: map[string]string{"GOLDEN_UPDATE": "0"},
- want: false,
- },
- {
- name: "GOLDEN_UPDATE set to 1",
- env: map[string]string{"GOLDEN_UPDATE": "1"},
- want: true,
- },
- {
- name: "GOLDEN_UPDATE set to 2",
- env: map[string]string{"GOLDEN_UPDATE": "2"},
- want: false,
- },
- {
- name: "GOLDEN_UPDATE set to y",
- env: map[string]string{"GOLDEN_UPDATE": "y"},
- want: true,
- },
- {
- name: "GOLDEN_UPDATE set to n",
- env: map[string]string{"GOLDEN_UPDATE": "n"},
- want: false,
- },
- {
- name: "GOLDEN_UPDATE set to t",
- env: map[string]string{"GOLDEN_UPDATE": "t"},
- want: true,
- },
- {
- name: "GOLDEN_UPDATE set to f",
- env: map[string]string{"GOLDEN_UPDATE": "f"},
- want: false,
- },
- {
- name: "GOLDEN_UPDATE set to yes",
- env: map[string]string{"GOLDEN_UPDATE": "yes"},
- want: true,
- },
- {
- name: "GOLDEN_UPDATE set to no",
- env: map[string]string{"GOLDEN_UPDATE": "no"},
- want: false,
- },
- {
- name: "GOLDEN_UPDATE set to on",
- env: map[string]string{"GOLDEN_UPDATE": "on"},
- want: true,
- },
- {
- name: "GOLDEN_UPDATE set to off",
- env: map[string]string{"GOLDEN_UPDATE": "off"},
- want: false,
- },
- {
- name: "GOLDEN_UPDATE set to true",
- env: map[string]string{"GOLDEN_UPDATE": "true"},
- want: true,
- },
- {
- name: "GOLDEN_UPDATE set to false",
- env: map[string]string{"GOLDEN_UPDATE": "false"},
- want: false,
- },
- {
- name: "GOLDEN_UPDATE set to foobarnopebbq",
- env: map[string]string{"GOLDEN_UPDATE": "foobarnopebbq"},
- want: false,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- envctl.WithClean(tt.env, func() {
- got := Updating()
-
- assert.Equal(t, tt.want, got)
- })
- })
- }
-}
-
func TestFile(t *testing.T) {
got := File(t)
@@ -122,11 +30,11 @@ func TestFile(t *testing.T) {
},
{
name: "foo/bar",
- want: filepath.Join("testdata", "TestFile", "foo/bar.golden"),
+ want: filepath.Join("testdata", "TestFile", "foo", "bar.golden"),
},
{
name: `"foobar"`,
- want: filepath.Join("testdata", "TestFile", "\"foobar\".golden"),
+ want: filepath.Join("testdata", "TestFile", "_foobar_.golden"),
},
}
for _, tt := range tests {
@@ -140,9 +48,9 @@ func TestFile(t *testing.T) {
func TestGet(t *testing.T) {
t.Cleanup(func() {
- err := os.RemoveAll(filepath.Join("testdata", t.Name()))
+ err := os.RemoveAll(filepath.Join("testdata", "TestGet"))
require.NoError(t, err)
- err = os.Remove(filepath.Join("testdata", t.Name()+".golden"))
+ err = os.Remove(filepath.Join("testdata", "TestGet.golden"))
require.NoError(t, err)
})
@@ -188,7 +96,7 @@ func TestGet(t *testing.T) {
{
name: "thing: it's a thing!",
file: filepath.Join(
- "testdata", "TestGet", "thing:_it's_a_thing!.golden",
+ "testdata", "TestGet", "thing__it's_a_thing!.golden",
),
want: []byte("A thing? Really? Are we getting lazy? :P"),
},
@@ -214,9 +122,9 @@ func TestGet(t *testing.T) {
func TestSet(t *testing.T) {
t.Cleanup(func() {
- err := os.RemoveAll(filepath.Join("testdata", t.Name()))
+ err := os.RemoveAll(filepath.Join("testdata", "TestSet"))
require.NoError(t, err)
- err = os.Remove(filepath.Join("testdata", t.Name()+".golden"))
+ err = os.Remove(filepath.Join("testdata", "TestSet.golden"))
require.NoError(t, err)
})
@@ -258,7 +166,7 @@ func TestSet(t *testing.T) {
{
name: "thing: it's a thing!",
file: filepath.Join(
- "testdata", "TestSet", "thing:_it's_a_thing!.golden",
+ "testdata", "TestSet", "thing__it's_a_thing!.golden",
),
content: []byte("A thing? Really? Are we getting lazy? :P"),
},
@@ -278,34 +186,74 @@ func TestSet(t *testing.T) {
}
}
-func TestGetNamed(t *testing.T) {
+func TestFileP(t *testing.T) {
+ got := FileP(t, "sub-name")
+ assert.Equal(t,
+ filepath.Join("testdata", "TestFileP", "sub-name.golden"), got,
+ )
+
+ tests := []struct {
+ name string
+ named string
+ want string
+ }{
+ {
+ name: "",
+ named: "sub-thing",
+ want: filepath.Join(
+ "testdata", "TestFileP", "#00", "sub-thing.golden",
+ ),
+ },
+ {
+ name: "fozbaz",
+ named: "email",
+ want: filepath.Join(
+ "testdata", "TestFileP", "fozbaz", "email.golden",
+ ),
+ },
+ {
+ name: "fozbaz",
+ named: "json",
+ want: filepath.Join(
+ "testdata", "TestFileP", "fozbaz#01", "json.golden",
+ ),
+ },
+ {
+ name: "foo/bar",
+ named: "hello/world",
+ want: filepath.Join(
+ "testdata", "TestFileP",
+ "foo", "bar",
+ "hello", "world.golden",
+ ),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := FileP(t, tt.named)
+
+ assert.Equal(t, tt.want, got)
+ })
+ }
+}
+
+func TestGetP(t *testing.T) {
t.Cleanup(func() {
- err := os.RemoveAll(filepath.Join("testdata", t.Name()))
- require.NoError(t, err)
- err = os.Remove(filepath.Join("testdata", t.Name()+".golden"))
+ err := os.RemoveAll(filepath.Join("testdata", "TestGetP"))
require.NoError(t, err)
})
- err := os.MkdirAll(filepath.Join("testdata", "TestGetNamed"), 0o755)
+ err := os.MkdirAll(filepath.Join("testdata", "TestGetP"), 0o755)
require.NoError(t, err)
- content := []byte("this is the default golden file for TestGetNamed")
+ content := []byte("this is the named golden file for TestGetP")
err = ioutil.WriteFile( //nolint:gosec
- filepath.Join("testdata", "TestGetNamed.golden"), content, 0o644,
- )
- require.NoError(t, err)
-
- got := GetNamed(t, "")
- assert.Equal(t, content, got)
-
- content = []byte("this is the named golden file for TestGetNamed")
- err = ioutil.WriteFile( //nolint:gosec
- filepath.Join("testdata", "TestGetNamed", "sub-name.golden"),
+ filepath.Join("testdata", "TestGetP", "sub-name.golden"),
content, 0o644,
)
require.NoError(t, err)
- got = GetNamed(t, "sub-name")
+ got := GetP(t, "sub-name")
assert.Equal(t, content, got)
tests := []struct {
@@ -314,16 +262,11 @@ func TestGetNamed(t *testing.T) {
file string
want []byte
}{
- {
- name: "",
- file: filepath.Join("testdata", "TestGetNamed", "#00.golden"),
- want: []byte("number double-zero here"),
- },
{
name: "",
named: "sub-zero-one",
file: filepath.Join(
- "testdata", "TestGetNamed", "#01/sub-zero-one.golden",
+ "testdata", "TestGetP", "#00", "sub-zero-one.golden",
),
want: []byte("number zero-one here"),
},
@@ -331,7 +274,7 @@ func TestGetNamed(t *testing.T) {
name: "foobar",
named: "email",
file: filepath.Join(
- "testdata", "TestGetNamed", "foobar/email.golden",
+ "testdata", "TestGetP", "foobar", "email.golden",
),
want: []byte("foobar email here"),
},
@@ -339,7 +282,7 @@ func TestGetNamed(t *testing.T) {
name: "foobar",
named: "json",
file: filepath.Join(
- "testdata", "TestGetNamed", "foobar#01/json.golden",
+ "testdata", "TestGetP", "foobar#01", "json.golden",
),
want: []byte("foobar json here"),
},
@@ -347,7 +290,7 @@ func TestGetNamed(t *testing.T) {
name: "foo/bar",
named: "hello/world",
file: filepath.Join(
- "testdata", "TestGetNamed",
+ "testdata", "TestGetP",
"foo", "bar",
"hello", "world.golden",
),
@@ -357,7 +300,7 @@ func TestGetNamed(t *testing.T) {
name: "john's lost flip-flop",
named: "left",
file: filepath.Join(
- "testdata", "TestGetNamed", "john's_lost_flip-flop",
+ "testdata", "TestGetP", "john's_lost_flip-flop",
"left.golden",
),
want: []byte("Did John lose his left flip-flop again?"),
@@ -366,7 +309,7 @@ func TestGetNamed(t *testing.T) {
name: "john's lost flip-flop",
named: "right",
file: filepath.Join(
- "testdata", "TestGetNamed", "john's_lost_flip-flop#01",
+ "testdata", "TestGetP", "john's_lost_flip-flop#01",
"right.golden",
),
want: []byte("Did John lose his right flip-flop again?"),
@@ -375,14 +318,14 @@ func TestGetNamed(t *testing.T) {
name: "thing: it's",
named: "a thing!",
file: filepath.Join(
- "testdata", "TestGetNamed", "thing:_it's", "a thing!.golden",
+ "testdata", "TestGetP", "thing__it's", "a_thing!.golden",
),
want: []byte("A thing? Really? Are we getting lazy? :P"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- f := NamedFile(t, tt.named)
+ f := FileP(t, tt.named)
dir := filepath.Dir(f)
err := os.MkdirAll(dir, 0o755)
@@ -391,7 +334,7 @@ func TestGetNamed(t *testing.T) {
err = ioutil.WriteFile(f, tt.want, 0o644) //nolint:gosec
require.NoError(t, err)
- got := GetNamed(t, tt.named)
+ got := GetP(t, tt.named)
assert.Equal(t, filepath.FromSlash(tt.file), f)
assert.Equal(t, tt.want, got)
@@ -399,27 +342,17 @@ func TestGetNamed(t *testing.T) {
}
}
-func TestSetNamed(t *testing.T) {
+func TestSetP(t *testing.T) {
t.Cleanup(func() {
- err := os.RemoveAll(filepath.Join("testdata", t.Name()))
- require.NoError(t, err)
- err = os.Remove(filepath.Join("testdata", t.Name()+".golden"))
+ err := os.RemoveAll(filepath.Join("testdata", "TestSetP"))
require.NoError(t, err)
})
- content := []byte("This is the default golden file for TestSetNamed ^_^")
- SetNamed(t, "", content)
+ content := []byte("This is the named golden file for TestSetP ^_^")
+ SetP(t, "sub-name", content)
- b, err := ioutil.ReadFile(filepath.Join("testdata", "TestSetNamed.golden"))
- require.NoError(t, err)
-
- assert.Equal(t, content, b)
-
- content = []byte("This is the named golden file for TestSetNamed ^_^")
- SetNamed(t, "sub-name", content)
-
- b, err = ioutil.ReadFile(
- filepath.Join("testdata", "TestSetNamed", "sub-name.golden"),
+ b, err := ioutil.ReadFile(
+ filepath.Join("testdata", "TestSetP", "sub-name.golden"),
)
require.NoError(t, err)
@@ -431,16 +364,11 @@ func TestSetNamed(t *testing.T) {
file string
content []byte
}{
- {
- name: "",
- file: filepath.Join("testdata", "TestSetNamed", "#00.golden"),
- content: []byte("number double-zero strikes again"),
- },
{
name: "",
named: "sub-zero-one",
file: filepath.Join(
- "testdata", "TestSetNamed", "#01", "sub-zero-one.golden",
+ "testdata", "TestSetP", "#00", "sub-zero-one.golden",
),
content: []byte("number zero-one sub-zero-one strikes again"),
},
@@ -448,7 +376,7 @@ func TestSetNamed(t *testing.T) {
name: "foobar",
named: "email",
file: filepath.Join(
- "testdata", "TestSetNamed", "foobar", "email.golden",
+ "testdata", "TestSetP", "foobar", "email.golden",
),
content: []byte("foobar here"),
},
@@ -456,22 +384,15 @@ func TestSetNamed(t *testing.T) {
name: "foobar",
named: "json",
file: filepath.Join(
- "testdata", "TestSetNamed", "foobar#01", "json.golden",
+ "testdata", "TestSetP", "foobar#01", "json.golden",
),
content: []byte("foobar here"),
},
- {
- name: "foo/bar",
- file: filepath.Join(
- "testdata", "TestSetNamed", "foo", "bar.golden",
- ),
- content: []byte("foo/bar style sub-sub-folders works too"),
- },
{
name: "john's lost flip-flop",
named: "left",
file: filepath.Join(
- "testdata", "TestSetNamed", "john's_lost_flip-flop",
+ "testdata", "TestSetP", "john's_lost_flip-flop",
"left.golden",
),
content: []byte("Did John lose his left flip-flop again?"),
@@ -480,7 +401,7 @@ func TestSetNamed(t *testing.T) {
name: "john's lost flip-flop",
named: "right",
file: filepath.Join(
- "testdata", "TestSetNamed", "john's_lost_flip-flop#01",
+ "testdata", "TestSetP", "john's_lost_flip-flop#01",
"right.golden",
),
content: []byte("Did John lose his right flip-flop again?"),
@@ -489,16 +410,16 @@ func TestSetNamed(t *testing.T) {
name: "thing: it's",
named: "a thing!",
file: filepath.Join(
- "testdata", "TestSetNamed", "thing:_it's", "a thing!.golden",
+ "testdata", "TestSetP", "thing__it's", "a_thing!.golden",
),
content: []byte("A thing? Really? Are we getting lazy? :P"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- f := NamedFile(t, tt.named)
+ f := FileP(t, tt.named)
- SetNamed(t, tt.named, tt.content)
+ SetP(t, tt.named, tt.content)
got, err := ioutil.ReadFile(f)
require.NoError(t, err)
@@ -509,53 +430,14 @@ func TestSetNamed(t *testing.T) {
}
}
-func TestNamedFile(t *testing.T) {
- got := NamedFile(t, "")
- assert.Equal(t, "testdata/TestNamedFile.golden", got)
-
- got = NamedFile(t, "sub-name")
- assert.Equal(t, "testdata/TestNamedFile/sub-name.golden", got)
-
- tests := []struct {
- name string
- named string
- want string
- }{
- {
- name: "",
- named: "",
- want: "testdata/TestNamedFile/#00.golden",
- },
- {
- name: "",
- named: "sub-thing",
- want: "testdata/TestNamedFile/#01/sub-thing.golden",
- },
- {
- name: "foobar",
- want: "testdata/TestNamedFile/foobar.golden",
- },
- {
- name: "fozbaz",
- named: "email",
- want: "testdata/TestNamedFile/fozbaz/email.golden",
- },
- {
- name: "fozbaz",
- named: "json",
- want: "testdata/TestNamedFile/fozbaz#01/json.golden",
- },
- {
- name: "foo/bar",
- named: "hello/world",
- want: "testdata/TestNamedFile/foo/bar/hello/world.golden",
- },
- }
- for _, tt := range tests {
+func TestUpdate(t *testing.T) {
+ for _, tt := range envUpdateFuncTestCases {
t.Run(tt.name, func(t *testing.T) {
- got := NamedFile(t, tt.named)
+ envctl.WithClean(tt.env, func() {
+ got := Update()
- assert.Equal(t, tt.want, got)
+ assert.Equal(t, tt.want, got)
+ })
})
}
}
diff --git a/sanitize.go b/sanitize.go
new file mode 100644
index 0000000..c77d741
--- /dev/null
+++ b/sanitize.go
@@ -0,0 +1,34 @@
+package golden
+
+import (
+ "regexp"
+ "strings"
+)
+
+var (
+ whitespaceChars = regexp.MustCompile(`\s`)
+ illegalChars = regexp.MustCompile(`[\/\?<>\\:\*\|"]`)
+ controlChars = regexp.MustCompile(`[\x00-\x1f\x80-\x9f]`)
+ reservedNames = regexp.MustCompile(`^\.+$`)
+ winReserved = regexp.MustCompile(
+ `(?i)^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$`,
+ )
+)
+
+func sanitizeFilename(name string) string {
+ if reservedNames.MatchString(name) || winReserved.MatchString(name) {
+ var b []byte
+ for i := 0; i < len(name); i++ {
+ b = append(b, byte('_'))
+ }
+
+ return string(b)
+ }
+
+ r := strings.TrimRight(name, ". ")
+ r = whitespaceChars.ReplaceAllString(r, "_")
+ r = illegalChars.ReplaceAllString(r, "_")
+ r = controlChars.ReplaceAllString(r, "_")
+
+ return r
+}
diff --git a/sanitize_test.go b/sanitize_test.go
new file mode 100644
index 0000000..c98b93b
--- /dev/null
+++ b/sanitize_test.go
@@ -0,0 +1,124 @@
+package golden
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func Test_sanitizeFilename(t *testing.T) {
+ tests := []struct {
+ name string
+ filename string
+ want string
+ }{
+ {
+ name: "empty",
+ filename: "",
+ want: "",
+ },
+ {
+ name: ".",
+ filename: ".",
+ want: "_",
+ },
+ {
+ name: "..",
+ filename: "..",
+ want: "__",
+ },
+ {
+ name: "...",
+ filename: "...",
+ want: "___",
+ },
+ {
+ name: "clean",
+ filename: "foo-bar-nope.golden",
+ want: "foo-bar-nope.golden",
+ },
+ {
+ name: "with spaces",
+ filename: "foo bar nope.golden",
+ want: "foo__bar_nope.golden",
+ },
+ {
+ name: "illegal chars",
+ filename: `foo/?<>\:*|"bar.golden`,
+ want: "foo_________bar.golden",
+ },
+ {
+ name: "control chars",
+ filename: "foo\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b" +
+ "\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a" +
+ "\x1b\x1c\x1d\x1e\x1fbar.golden",
+ want: "foo________________________________bar.golden",
+ },
+ {
+ name: "trailing whitespace",
+ filename: "foobar.golden ",
+ want: "foobar.golden",
+ },
+ {
+ name: "trailing dots",
+ filename: "foobar.golden......",
+ want: "foobar.golden",
+ },
+ {
+ name: "trailing whitespace and dots",
+ filename: "foobar.golden .. .. .. ",
+ want: "foobar.golden",
+ },
+ {name: "con", filename: "con", want: "___"},
+ {name: "prn", filename: "prn", want: "___"},
+ {name: "aux", filename: "aux", want: "___"},
+ {name: "nul", filename: "nul", want: "___"},
+ {name: "com1", filename: "com1", want: "____"},
+ {name: "com2", filename: "com2", want: "____"},
+ {name: "com3", filename: "com3", want: "____"},
+ {name: "com4", filename: "com4", want: "____"},
+ {name: "com5", filename: "com5", want: "____"},
+ {name: "com6", filename: "com6", want: "____"},
+ {name: "com7", filename: "com7", want: "____"},
+ {name: "com8", filename: "com8", want: "____"},
+ {name: "com9", filename: "com9", want: "____"},
+ {name: "lpt1", filename: "lpt1", want: "____"},
+ {name: "lpt2", filename: "lpt2", want: "____"},
+ {name: "lpt3", filename: "lpt3", want: "____"},
+ {name: "lpt4", filename: "lpt4", want: "____"},
+ {name: "lpt5", filename: "lpt5", want: "____"},
+ {name: "lpt6", filename: "lpt6", want: "____"},
+ {name: "lpt7", filename: "lpt7", want: "____"},
+ {name: "lpt8", filename: "lpt8", want: "____"},
+ {name: "lpt9", filename: "lpt9", want: "____"},
+ {name: "CON", filename: "CON", want: "___"},
+ {name: "PRN", filename: "PRN", want: "___"},
+ {name: "AUX", filename: "AUX", want: "___"},
+ {name: "NUL", filename: "NUL", want: "___"},
+ {name: "COM1", filename: "COM1", want: "____"},
+ {name: "COM2", filename: "COM2", want: "____"},
+ {name: "COM3", filename: "COM3", want: "____"},
+ {name: "COM4", filename: "COM4", want: "____"},
+ {name: "COM5", filename: "COM5", want: "____"},
+ {name: "COM6", filename: "COM6", want: "____"},
+ {name: "COM7", filename: "COM7", want: "____"},
+ {name: "COM8", filename: "COM8", want: "____"},
+ {name: "COM9", filename: "COM9", want: "____"},
+ {name: "LPT1", filename: "LPT1", want: "____"},
+ {name: "LPT2", filename: "LPT2", want: "____"},
+ {name: "LPT3", filename: "LPT3", want: "____"},
+ {name: "LPT4", filename: "LPT4", want: "____"},
+ {name: "LPT5", filename: "LPT5", want: "____"},
+ {name: "LPT6", filename: "LPT6", want: "____"},
+ {name: "LPT7", filename: "LPT7", want: "____"},
+ {name: "LPT8", filename: "LPT8", want: "____"},
+ {name: "LPT9", filename: "LPT9", want: "____"},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := sanitizeFilename(tt.filename)
+
+ assert.Equal(t, tt.want, got)
+ })
+ }
+}
diff --git a/testdata/TestExampleMyStruct.golden b/testdata/TestExampleMyStruct.golden
new file mode 100644
index 0000000..7129afe
--- /dev/null
+++ b/testdata/TestExampleMyStruct.golden
@@ -0,0 +1 @@
+{"foo":"Bar"}
\ No newline at end of file
diff --git a/testdata/TestExampleMyStructP/json.golden b/testdata/TestExampleMyStructP/json.golden
new file mode 100644
index 0000000..7129afe
--- /dev/null
+++ b/testdata/TestExampleMyStructP/json.golden
@@ -0,0 +1 @@
+{"foo":"Bar"}
\ No newline at end of file
diff --git a/testdata/TestExampleMyStructP/xml.golden b/testdata/TestExampleMyStructP/xml.golden
new file mode 100644
index 0000000..4e49261
--- /dev/null
+++ b/testdata/TestExampleMyStructP/xml.golden
@@ -0,0 +1 @@
+Bar
\ No newline at end of file
diff --git a/testdata/TestExampleMyStructTabular/empty_struct.golden b/testdata/TestExampleMyStructTabular/empty_struct.golden
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/testdata/TestExampleMyStructTabular/empty_struct.golden
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/testdata/TestExampleMyStructTabular/full_struct.golden b/testdata/TestExampleMyStructTabular/full_struct.golden
new file mode 100644
index 0000000..7129afe
--- /dev/null
+++ b/testdata/TestExampleMyStructTabular/full_struct.golden
@@ -0,0 +1 @@
+{"foo":"Bar"}
\ No newline at end of file
diff --git a/testdata/TestExampleMyStructTabularP/empty_struct/json.golden b/testdata/TestExampleMyStructTabularP/empty_struct/json.golden
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/testdata/TestExampleMyStructTabularP/empty_struct/json.golden
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/testdata/TestExampleMyStructTabularP/empty_struct/xml.golden b/testdata/TestExampleMyStructTabularP/empty_struct/xml.golden
new file mode 100644
index 0000000..554a1bf
--- /dev/null
+++ b/testdata/TestExampleMyStructTabularP/empty_struct/xml.golden
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/testdata/TestExampleMyStructTabularP/full_struct/json.golden b/testdata/TestExampleMyStructTabularP/full_struct/json.golden
new file mode 100644
index 0000000..7129afe
--- /dev/null
+++ b/testdata/TestExampleMyStructTabularP/full_struct/json.golden
@@ -0,0 +1 @@
+{"foo":"Bar"}
\ No newline at end of file
diff --git a/testdata/TestExampleMyStructTabularP/full_struct/xml.golden b/testdata/TestExampleMyStructTabularP/full_struct/xml.golden
new file mode 100644
index 0000000..4e49261
--- /dev/null
+++ b/testdata/TestExampleMyStructTabularP/full_struct/xml.golden
@@ -0,0 +1 @@
+Bar
\ No newline at end of file
diff --git a/updating.go b/update.go
similarity index 54%
rename from updating.go
rename to update.go
index 94dd6e2..e7d7ce9 100644
--- a/updating.go
+++ b/update.go
@@ -4,11 +4,14 @@ import "os"
var truthyStrings = []string{"1", "y", "t", "yes", "on", "true"}
-type UpdatingFunc func() bool
+type UpdateFunc func() bool
-// EnvVarUpdateFunc checks if the GOLDEN_UPDATE environment variable is set to
+// EnvUpdateFunc checks if the GOLDEN_UPDATE environment variable is set to
// one of "1", "y", "t", "yes", "on", or "true".
-func EnvVarUpdatingFunc() bool {
+//
+// This is also the default UpdateFunc used to determine the return value of
+// Update().
+func EnvUpdateFunc() bool {
env := os.Getenv("GOLDEN_UPDATE")
for _, v := range truthyStrings {
if env == v {
diff --git a/update_test.go b/update_test.go
new file mode 100644
index 0000000..26937a7
--- /dev/null
+++ b/update_test.go
@@ -0,0 +1,106 @@
+package golden
+
+import (
+ "testing"
+
+ "github.com/jimeh/envctl"
+ "github.com/stretchr/testify/assert"
+)
+
+var envUpdateFuncTestCases = []struct {
+ name string
+ env map[string]string
+ want bool
+}{
+ {
+ name: "GOLDEN_UPDATE not set",
+ want: false,
+ },
+ {
+ name: "GOLDEN_UPDATE set to empty string",
+ env: map[string]string{"GOLDEN_UPDATE": ""},
+ want: false,
+ },
+ {
+ name: "GOLDEN_UPDATE set to 0",
+ env: map[string]string{"GOLDEN_UPDATE": "0"},
+ want: false,
+ },
+ {
+ name: "GOLDEN_UPDATE set to 1",
+ env: map[string]string{"GOLDEN_UPDATE": "1"},
+ want: true,
+ },
+ {
+ name: "GOLDEN_UPDATE set to 2",
+ env: map[string]string{"GOLDEN_UPDATE": "2"},
+ want: false,
+ },
+ {
+ name: "GOLDEN_UPDATE set to y",
+ env: map[string]string{"GOLDEN_UPDATE": "y"},
+ want: true,
+ },
+ {
+ name: "GOLDEN_UPDATE set to n",
+ env: map[string]string{"GOLDEN_UPDATE": "n"},
+ want: false,
+ },
+ {
+ name: "GOLDEN_UPDATE set to t",
+ env: map[string]string{"GOLDEN_UPDATE": "t"},
+ want: true,
+ },
+ {
+ name: "GOLDEN_UPDATE set to f",
+ env: map[string]string{"GOLDEN_UPDATE": "f"},
+ want: false,
+ },
+ {
+ name: "GOLDEN_UPDATE set to yes",
+ env: map[string]string{"GOLDEN_UPDATE": "yes"},
+ want: true,
+ },
+ {
+ name: "GOLDEN_UPDATE set to no",
+ env: map[string]string{"GOLDEN_UPDATE": "no"},
+ want: false,
+ },
+ {
+ name: "GOLDEN_UPDATE set to on",
+ env: map[string]string{"GOLDEN_UPDATE": "on"},
+ want: true,
+ },
+ {
+ name: "GOLDEN_UPDATE set to off",
+ env: map[string]string{"GOLDEN_UPDATE": "off"},
+ want: false,
+ },
+ {
+ name: "GOLDEN_UPDATE set to true",
+ env: map[string]string{"GOLDEN_UPDATE": "true"},
+ want: true,
+ },
+ {
+ name: "GOLDEN_UPDATE set to false",
+ env: map[string]string{"GOLDEN_UPDATE": "false"},
+ want: false,
+ },
+ {
+ name: "GOLDEN_UPDATE set to foobarnopebbq",
+ env: map[string]string{"GOLDEN_UPDATE": "foobarnopebbq"},
+ want: false,
+ },
+}
+
+func TestEnvUpdateFunc(t *testing.T) {
+ for _, tt := range envUpdateFuncTestCases {
+ t.Run(tt.name, func(t *testing.T) {
+ envctl.WithClean(tt.env, func() {
+ got := EnvUpdateFunc()
+
+ assert.Equal(t, tt.want, got)
+ })
+ })
+ }
+}