2 Commits

Author SHA1 Message Date
jimehbot[bot]
e17b04717f chore(main): release 0.2.1 (#15)
Co-authored-by: jimehbot[bot] <132453784+jimehbot[bot]@users.noreply.github.com>
2025-04-05 12:34:00 +01:00
550ba17fb0 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.
2025-04-05 12:28:57 +01:00
6 changed files with 262 additions and 52 deletions

View File

@@ -1,3 +1,3 @@
{
".": "0.2.0"
".": "0.2.1"
}

View File

@@ -2,6 +2,13 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [0.2.1](https://github.com/jimeh/go-golden/compare/v0.2.0...v0.2.1) (2025-04-05)
### Features
* **options:** add optional Options arguments to New() function ([#14](https://github.com/jimeh/go-golden/issues/14)) ([550ba17](https://github.com/jimeh/go-golden/commit/550ba17fb0be76372eab83f2494ee4ffff804fa6))
## [0.2.0](https://github.com/jimeh/go-golden/compare/v0.1.0...v0.2.0) (2025-03-24)

View File

@@ -257,14 +257,21 @@ type Golden struct {
}
// New returns a new *Golden instance with default values correctly populated.
func New() *Golden {
return &Golden{
// It accepts zero or more Option functions that can modify the default values.
func New(opts ...Option) *Golden {
g := &Golden{
DirMode: DefaultDirMode,
FileMode: DefaultFileMode,
Suffix: DefaultSuffix,
Dirname: DefaultDirname,
UpdateFunc: DefaultUpdateFunc,
}
for _, opt := range opts {
opt(g)
}
return g
}
// Do is a convenience function for calling Update(), Set(), and Get() in a

View File

@@ -11,6 +11,37 @@ import (
"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) {
t.Run("Default", func(t *testing.T) {
assert.IsType(t, &Golden{}, Default)
@@ -19,15 +50,7 @@ func TestDefaults(t *testing.T) {
assert.Equal(t, DefaultFileMode, Default.FileMode)
assert.Equal(t, DefaultSuffix, Default.Suffix)
assert.Equal(t, DefaultDirname, Default.Dirname)
// 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)
assertSameFunc(t, EnvUpdateFunc, Default.UpdateFunc)
})
t.Run("DefaultDirMode", func(t *testing.T) {
@@ -47,57 +70,129 @@ func TestDefaults(t *testing.T) {
})
t.Run("DefaultUpdateFunc", func(t *testing.T) {
gotFP := reflect.ValueOf(DefaultUpdateFunc).Pointer()
gotFuncName := runtime.FuncForPC(gotFP).Name()
wantFP := reflect.ValueOf(EnvUpdateFunc).Pointer()
wantFuncName := runtime.FuncForPC(wantFP).Name()
assert.Equal(t, wantFuncName, gotFuncName)
assertSameFunc(t, EnvUpdateFunc, DefaultUpdateFunc)
})
t.Run("customized Default* variables", func(t *testing.T) {
// 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) {
// 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
t.Run("defaults (no options)", func(t *testing.T) {
g := New()
assert.Equal(t, DefaultDirMode, 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)
})
// Set all the default values to new values.
DefaultDirMode = os.FileMode(0o700)
DefaultFileMode = os.FileMode(0o600)
DefaultSuffix = ".gold"
DefaultDirname = "goldenfiles"
// Test each option individually
t.Run("WithDirMode", func(t *testing.T) {
customMode := os.FileMode(0o700)
g := New(WithDirMode(customMode))
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 }
DefaultUpdateFunc = updateFunc
t.Run("WithFileMode", func(t *testing.T) {
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.
got := New()
t.Run("WithSuffix", func(t *testing.T) {
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)
assert.Equal(t, DefaultFileMode, got.FileMode)
assert.Equal(t, DefaultSuffix, got.Suffix)
assert.Equal(t, DefaultDirname, got.Dirname)
t.Run("WithDirname", func(t *testing.T) {
customDirname := "fixtures/generated"
g := New(WithDirname(customDirname))
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.
gotFP := reflect.ValueOf(got.UpdateFunc).Pointer()
gotFuncName := runtime.FuncForPC(gotFP).Name()
wantFP := reflect.ValueOf(updateFunc).Pointer()
wantFuncName := runtime.FuncForPC(wantFP).Name()
t.Run("WithUpdateFunc", func(t *testing.T) {
customUpdateFunc := func() bool { return true }
g := New(WithUpdateFunc(customUpdateFunc))
assert.Equal(t, DefaultDirMode, g.DirMode)
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) {

43
options.go Normal file
View 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
View 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)
}