mirror of
https://github.com/jimeh/go-golden.git
synced 2026-02-19 03:16:38 +00:00
feat(options): add optional Options arguments to New() function (#14)
Enables simpler creation of custom *Golden instances, as you can just pass in the custom values to New(), rather than modifying fields after increating the Golden instance.
This commit is contained in:
11
golden.go
11
golden.go
@@ -257,14 +257,21 @@ type Golden struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new *Golden instance with default values correctly populated.
|
// New returns a new *Golden instance with default values correctly populated.
|
||||||
func New() *Golden {
|
// It accepts zero or more Option functions that can modify the default values.
|
||||||
return &Golden{
|
func New(opts ...Option) *Golden {
|
||||||
|
g := &Golden{
|
||||||
DirMode: DefaultDirMode,
|
DirMode: DefaultDirMode,
|
||||||
FileMode: DefaultFileMode,
|
FileMode: DefaultFileMode,
|
||||||
Suffix: DefaultSuffix,
|
Suffix: DefaultSuffix,
|
||||||
Dirname: DefaultDirname,
|
Dirname: DefaultDirname,
|
||||||
UpdateFunc: DefaultUpdateFunc,
|
UpdateFunc: DefaultUpdateFunc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(g)
|
||||||
|
}
|
||||||
|
|
||||||
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do is a convenience function for calling Update(), Set(), and Get() in a
|
// Do is a convenience function for calling Update(), Set(), and Get() in a
|
||||||
|
|||||||
193
golden_test.go
193
golden_test.go
@@ -11,6 +11,37 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// assertSameFunc asserts that two functions are the same by comparing their
|
||||||
|
// function names via reflection.
|
||||||
|
func assertSameFunc(t *testing.T, want, got interface{}) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
// Verify both arguments are functions
|
||||||
|
wantType := reflect.TypeOf(want)
|
||||||
|
gotType := reflect.TypeOf(got)
|
||||||
|
|
||||||
|
if wantType.Kind() != reflect.Func {
|
||||||
|
t.Fatalf(
|
||||||
|
"assertSameFunc: 'want' argument is not a function, got %s",
|
||||||
|
wantType.Kind(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if gotType.Kind() != reflect.Func {
|
||||||
|
t.Fatalf(
|
||||||
|
"assertSameFunc: 'got' argument is not a function, got %s",
|
||||||
|
gotType.Kind(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
gotFP := reflect.ValueOf(got).Pointer()
|
||||||
|
gotFuncName := runtime.FuncForPC(gotFP).Name()
|
||||||
|
wantFP := reflect.ValueOf(want).Pointer()
|
||||||
|
wantFuncName := runtime.FuncForPC(wantFP).Name()
|
||||||
|
|
||||||
|
assert.Equal(t, wantFuncName, gotFuncName)
|
||||||
|
}
|
||||||
|
|
||||||
func TestDefaults(t *testing.T) {
|
func TestDefaults(t *testing.T) {
|
||||||
t.Run("Default", func(t *testing.T) {
|
t.Run("Default", func(t *testing.T) {
|
||||||
assert.IsType(t, &Golden{}, Default)
|
assert.IsType(t, &Golden{}, Default)
|
||||||
@@ -19,15 +50,7 @@ func TestDefaults(t *testing.T) {
|
|||||||
assert.Equal(t, DefaultFileMode, Default.FileMode)
|
assert.Equal(t, DefaultFileMode, Default.FileMode)
|
||||||
assert.Equal(t, DefaultSuffix, Default.Suffix)
|
assert.Equal(t, DefaultSuffix, Default.Suffix)
|
||||||
assert.Equal(t, DefaultDirname, Default.Dirname)
|
assert.Equal(t, DefaultDirname, Default.Dirname)
|
||||||
|
assertSameFunc(t, EnvUpdateFunc, Default.UpdateFunc)
|
||||||
// Use runtime.FuncForPC() to verify the UpdateFunc value is set to
|
|
||||||
// the EnvUpdateFunc function by default.
|
|
||||||
gotFP := reflect.ValueOf(Default.UpdateFunc).Pointer()
|
|
||||||
gotFuncName := runtime.FuncForPC(gotFP).Name()
|
|
||||||
wantFP := reflect.ValueOf(EnvUpdateFunc).Pointer()
|
|
||||||
wantFuncName := runtime.FuncForPC(wantFP).Name()
|
|
||||||
|
|
||||||
assert.Equal(t, wantFuncName, gotFuncName)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("DefaultDirMode", func(t *testing.T) {
|
t.Run("DefaultDirMode", func(t *testing.T) {
|
||||||
@@ -47,57 +70,129 @@ func TestDefaults(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("DefaultUpdateFunc", func(t *testing.T) {
|
t.Run("DefaultUpdateFunc", func(t *testing.T) {
|
||||||
gotFP := reflect.ValueOf(DefaultUpdateFunc).Pointer()
|
assertSameFunc(t, EnvUpdateFunc, DefaultUpdateFunc)
|
||||||
gotFuncName := runtime.FuncForPC(gotFP).Name()
|
})
|
||||||
wantFP := reflect.ValueOf(EnvUpdateFunc).Pointer()
|
|
||||||
wantFuncName := runtime.FuncForPC(wantFP).Name()
|
t.Run("customized Default* variables", func(t *testing.T) {
|
||||||
assert.Equal(t, wantFuncName, gotFuncName)
|
// Capture the default values before we change them.
|
||||||
|
defaultDirMode := DefaultDirMode
|
||||||
|
defaultFileMode := DefaultFileMode
|
||||||
|
defaultSuffix := DefaultSuffix
|
||||||
|
defaultDirname := DefaultDirname
|
||||||
|
defaultUpdateFunc := DefaultUpdateFunc
|
||||||
|
|
||||||
|
// Restore the default values after the test.
|
||||||
|
t.Cleanup(func() {
|
||||||
|
DefaultDirMode = defaultDirMode
|
||||||
|
DefaultFileMode = defaultFileMode
|
||||||
|
DefaultSuffix = defaultSuffix
|
||||||
|
DefaultDirname = defaultDirname
|
||||||
|
DefaultUpdateFunc = defaultUpdateFunc
|
||||||
|
})
|
||||||
|
|
||||||
|
// Set all the default values to new values.
|
||||||
|
DefaultDirMode = os.FileMode(0o700)
|
||||||
|
DefaultFileMode = os.FileMode(0o600)
|
||||||
|
DefaultSuffix = ".gold"
|
||||||
|
DefaultDirname = "goldenfiles"
|
||||||
|
|
||||||
|
updateFunc := func() bool { return true }
|
||||||
|
DefaultUpdateFunc = updateFunc
|
||||||
|
|
||||||
|
// Create a new Golden instance with the new values.
|
||||||
|
got := New()
|
||||||
|
|
||||||
|
assert.Equal(t, DefaultDirMode, got.DirMode)
|
||||||
|
assert.Equal(t, DefaultFileMode, got.FileMode)
|
||||||
|
assert.Equal(t, DefaultSuffix, got.Suffix)
|
||||||
|
assert.Equal(t, DefaultDirname, got.Dirname)
|
||||||
|
assertSameFunc(t, updateFunc, got.UpdateFunc)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestNew is a horribly hack to test that the New() function uses the
|
|
||||||
// package-level Default* variables.
|
|
||||||
func TestNew(t *testing.T) {
|
func TestNew(t *testing.T) {
|
||||||
// Capture the default values before we change them.
|
t.Run("defaults (no options)", func(t *testing.T) {
|
||||||
defaultDirMode := DefaultDirMode
|
g := New()
|
||||||
defaultFileMode := DefaultFileMode
|
assert.Equal(t, DefaultDirMode, g.DirMode)
|
||||||
defaultSuffix := DefaultSuffix
|
assert.Equal(t, DefaultFileMode, g.FileMode)
|
||||||
defaultDirname := DefaultDirname
|
assert.Equal(t, DefaultSuffix, g.Suffix)
|
||||||
defaultUpdateFunc := DefaultUpdateFunc
|
assert.Equal(t, DefaultDirname, g.Dirname)
|
||||||
|
assertSameFunc(t, EnvUpdateFunc, g.UpdateFunc)
|
||||||
// Restore the default values after the test.
|
|
||||||
t.Cleanup(func() {
|
|
||||||
DefaultDirMode = defaultDirMode
|
|
||||||
DefaultFileMode = defaultFileMode
|
|
||||||
DefaultSuffix = defaultSuffix
|
|
||||||
DefaultDirname = defaultDirname
|
|
||||||
DefaultUpdateFunc = defaultUpdateFunc
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Set all the default values to new values.
|
// Test each option individually
|
||||||
DefaultDirMode = os.FileMode(0o700)
|
t.Run("WithDirMode", func(t *testing.T) {
|
||||||
DefaultFileMode = os.FileMode(0o600)
|
customMode := os.FileMode(0o700)
|
||||||
DefaultSuffix = ".gold"
|
g := New(WithDirMode(customMode))
|
||||||
DefaultDirname = "goldenfiles"
|
assert.Equal(t, customMode, g.DirMode)
|
||||||
|
assert.Equal(t, DefaultFileMode, g.FileMode)
|
||||||
|
assert.Equal(t, DefaultSuffix, g.Suffix)
|
||||||
|
assert.Equal(t, DefaultDirname, g.Dirname)
|
||||||
|
assertSameFunc(t, EnvUpdateFunc, g.UpdateFunc)
|
||||||
|
})
|
||||||
|
|
||||||
updateFunc := func() bool { return true }
|
t.Run("WithFileMode", func(t *testing.T) {
|
||||||
DefaultUpdateFunc = updateFunc
|
customMode := os.FileMode(0o600)
|
||||||
|
g := New(WithFileMode(customMode))
|
||||||
|
assert.Equal(t, DefaultDirMode, g.DirMode)
|
||||||
|
assert.Equal(t, customMode, g.FileMode)
|
||||||
|
assert.Equal(t, DefaultSuffix, g.Suffix)
|
||||||
|
assert.Equal(t, DefaultDirname, g.Dirname)
|
||||||
|
assertSameFunc(t, EnvUpdateFunc, g.UpdateFunc)
|
||||||
|
})
|
||||||
|
|
||||||
// Create a new Golden instance with the new values.
|
t.Run("WithSuffix", func(t *testing.T) {
|
||||||
got := New()
|
customSuffix := ".my-suffix"
|
||||||
|
g := New(WithSuffix(customSuffix))
|
||||||
|
assert.Equal(t, DefaultDirMode, g.DirMode)
|
||||||
|
assert.Equal(t, DefaultFileMode, g.FileMode)
|
||||||
|
assert.Equal(t, customSuffix, g.Suffix)
|
||||||
|
assert.Equal(t, DefaultDirname, g.Dirname)
|
||||||
|
assertSameFunc(t, EnvUpdateFunc, g.UpdateFunc)
|
||||||
|
})
|
||||||
|
|
||||||
assert.Equal(t, DefaultDirMode, got.DirMode)
|
t.Run("WithDirname", func(t *testing.T) {
|
||||||
assert.Equal(t, DefaultFileMode, got.FileMode)
|
customDirname := "fixtures/generated"
|
||||||
assert.Equal(t, DefaultSuffix, got.Suffix)
|
g := New(WithDirname(customDirname))
|
||||||
assert.Equal(t, DefaultDirname, got.Dirname)
|
assert.Equal(t, DefaultDirMode, g.DirMode)
|
||||||
|
assert.Equal(t, DefaultFileMode, g.FileMode)
|
||||||
|
assert.Equal(t, DefaultSuffix, g.Suffix)
|
||||||
|
assert.Equal(t, customDirname, g.Dirname)
|
||||||
|
assertSameFunc(t, EnvUpdateFunc, g.UpdateFunc)
|
||||||
|
})
|
||||||
|
|
||||||
// Verify the UpdateFunc value is set to the new value.
|
t.Run("WithUpdateFunc", func(t *testing.T) {
|
||||||
gotFP := reflect.ValueOf(got.UpdateFunc).Pointer()
|
customUpdateFunc := func() bool { return true }
|
||||||
gotFuncName := runtime.FuncForPC(gotFP).Name()
|
g := New(WithUpdateFunc(customUpdateFunc))
|
||||||
wantFP := reflect.ValueOf(updateFunc).Pointer()
|
assert.Equal(t, DefaultDirMode, g.DirMode)
|
||||||
wantFuncName := runtime.FuncForPC(wantFP).Name()
|
assert.Equal(t, DefaultFileMode, g.FileMode)
|
||||||
|
assert.Equal(t, DefaultSuffix, g.Suffix)
|
||||||
|
assert.Equal(t, DefaultDirname, g.Dirname)
|
||||||
|
assertSameFunc(t, customUpdateFunc, g.UpdateFunc)
|
||||||
|
})
|
||||||
|
|
||||||
assert.Equal(t, wantFuncName, gotFuncName)
|
// Test multiple options at once
|
||||||
|
t.Run("MultipleOptions", func(t *testing.T) {
|
||||||
|
customDirMode := os.FileMode(0o700)
|
||||||
|
customFileMode := os.FileMode(0o600)
|
||||||
|
customSuffix := ".fixture"
|
||||||
|
customDirname := "fixtures"
|
||||||
|
customUpdateFunc := func() bool { return true }
|
||||||
|
|
||||||
|
g := New(
|
||||||
|
WithDirMode(customDirMode),
|
||||||
|
WithFileMode(customFileMode),
|
||||||
|
WithSuffix(customSuffix),
|
||||||
|
WithDirname(customDirname),
|
||||||
|
WithUpdateFunc(customUpdateFunc),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.Equal(t, customDirMode, g.DirMode)
|
||||||
|
assert.Equal(t, customFileMode, g.FileMode)
|
||||||
|
assert.Equal(t, customSuffix, g.Suffix)
|
||||||
|
assert.Equal(t, customDirname, g.Dirname)
|
||||||
|
assertSameFunc(t, customUpdateFunc, g.UpdateFunc)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDo(t *testing.T) {
|
func TestDo(t *testing.T) {
|
||||||
|
|||||||
43
options.go
Normal file
43
options.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package golden
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Option is a function that modifies a Golden instance.
|
||||||
|
type Option func(*Golden)
|
||||||
|
|
||||||
|
// WithDirMode sets the directory mode for a Golden instance.
|
||||||
|
func WithDirMode(mode os.FileMode) Option {
|
||||||
|
return func(g *Golden) {
|
||||||
|
g.DirMode = mode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFileMode sets the file mode for a Golden instance.
|
||||||
|
func WithFileMode(mode os.FileMode) Option {
|
||||||
|
return func(g *Golden) {
|
||||||
|
g.FileMode = mode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSuffix sets the file suffix for a Golden instance.
|
||||||
|
func WithSuffix(suffix string) Option {
|
||||||
|
return func(g *Golden) {
|
||||||
|
g.Suffix = suffix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDirname sets the directory name for a Golden instance.
|
||||||
|
func WithDirname(dirname string) Option {
|
||||||
|
return func(g *Golden) {
|
||||||
|
g.Dirname = dirname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithUpdateFunc sets the update function for a Golden instance.
|
||||||
|
func WithUpdateFunc(updateFunc UpdateFunc) Option {
|
||||||
|
return func(g *Golden) {
|
||||||
|
g.UpdateFunc = updateFunc
|
||||||
|
}
|
||||||
|
}
|
||||||
58
options_test.go
Normal file
58
options_test.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package golden
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWithDirMode(t *testing.T) {
|
||||||
|
customMode := os.FileMode(0o700)
|
||||||
|
g := &Golden{}
|
||||||
|
|
||||||
|
opt := WithDirMode(customMode)
|
||||||
|
opt(g)
|
||||||
|
|
||||||
|
assert.Equal(t, customMode, g.DirMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithFileMode(t *testing.T) {
|
||||||
|
customMode := os.FileMode(0o600)
|
||||||
|
g := &Golden{}
|
||||||
|
|
||||||
|
opt := WithFileMode(customMode)
|
||||||
|
opt(g)
|
||||||
|
|
||||||
|
assert.Equal(t, customMode, g.FileMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithSuffix(t *testing.T) {
|
||||||
|
customSuffix := ".custom"
|
||||||
|
g := &Golden{}
|
||||||
|
|
||||||
|
opt := WithSuffix(customSuffix)
|
||||||
|
opt(g)
|
||||||
|
|
||||||
|
assert.Equal(t, customSuffix, g.Suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithDirname(t *testing.T) {
|
||||||
|
customDirname := "custom-testdata"
|
||||||
|
g := &Golden{}
|
||||||
|
|
||||||
|
opt := WithDirname(customDirname)
|
||||||
|
opt(g)
|
||||||
|
|
||||||
|
assert.Equal(t, customDirname, g.Dirname)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithUpdateFunc(t *testing.T) {
|
||||||
|
customUpdateFunc := func() bool { return true }
|
||||||
|
g := &Golden{}
|
||||||
|
|
||||||
|
opt := WithUpdateFunc(customUpdateFunc)
|
||||||
|
opt(g)
|
||||||
|
|
||||||
|
assertSameFunc(t, customUpdateFunc, g.UpdateFunc)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user