Skip to content

Commit

Permalink
feat: add Update option on config
Browse files Browse the repository at this point in the history
  • Loading branch information
gkampitakis committed Sep 30, 2023
1 parent 1b2c33a commit 7d3b610
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 94 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ You can see more [examples](./examples/matchJSON_test.go#L96).

- the directory where snapshots are stored, _relative or absolute path_
- the filename where snapshots are stored
- programmatically control whether to update snapshots

```go
t.Run("snapshot tests", func(t *testing.T) {
Expand All @@ -219,6 +220,7 @@ t.Run("snapshot tests", func(t *testing.T) {
s := snaps.WithConfig(
snaps.Dir("my_dir"),
snaps.Filename("json_file"),
snaps.Update(false)
)

s.MatchJSON(t, `{"hello":"world"}`)
Expand Down Expand Up @@ -292,7 +294,7 @@ for obsolete snapshots.

When `go-snaps` detects that it runs on CI it will automatically fail when snapshots are missing. This is done to ensure new snapshots are committed alongside the tests and assertions are successful.

> `go-snaps` uses [ciinfo](https://github.com/gkampitakis/ciinfo) for detecting if it runs on CI environment.
> `go-snaps` uses [ciinfo](https://github.com/gkampitakis/ciinfo) for detecting if it runs on CI environment.
## No Color

Expand Down
2 changes: 1 addition & 1 deletion snaps/matchJSON.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func matchJSON(c *config, t testingT, input interface{}, matchers ...match.JSONM
return
}

if !shouldUpdateSingle(t.Name()) {
if !shouldUpdate(c.update) {
handleError(t, diff)
return
}
Expand Down
2 changes: 1 addition & 1 deletion snaps/matchSnapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func matchSnapshot(c *config, t testingT, values ...interface{}) {
return
}

if !shouldUpdateSingle(t.Name()) {
if !shouldUpdate(c.update) {
handleError(t, diff)
return
}
Expand Down
132 changes: 88 additions & 44 deletions snaps/matchSnapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,18 @@ func setupSnapshot(t *testing.T, file string, ci bool, update ...bool) string {
dir, _ := os.Getwd()
snapPath := filepath.Join(dir, "__snapshots__", file)
isCI = ci
shouldUpdatePrev := shouldUpdate
shouldUpdate = false
if len(update) > 0 {
shouldUpdate = update[0]
updateVARPrev := updateVAR
updateVAR = ""
if len(update) > 0 && update[0] {
updateVAR = "true"
}

t.Cleanup(func() {
os.Remove(snapPath)
testsRegistry = newRegistry()
testEvents = newTestEvents()
isCI = ciinfo.IsCI
shouldUpdate = shouldUpdatePrev
updateVAR = updateVARPrev
})

_, err := os.Stat(snapPath)
Expand Down Expand Up @@ -148,45 +148,89 @@ func TestMatchSnapshot(t *testing.T) {
test.Equal(t, 1, testEvents.items[erred])
})

t.Run("should update snapshot when 'shouldUpdate'", func(t *testing.T) {
snapPath := setupSnapshot(t, fileName, false, true)

printerExpectedCalls := []func(received interface{}){
func(received interface{}) { test.Equal(t, addedMsg, received.(string)) },
func(received interface{}) { test.Equal(t, updatedMsg, received.(string)) },
}
mockT := test.MockTestingT{
MockHelper: func() {},
MockName: func() string {
return "mock-name"
},
MockError: func(args ...interface{}) {
test.NotCalled(t)
},
MockLog: func(args ...interface{}) {
printerExpectedCalls[0](args[0])

// shift
printerExpectedCalls = printerExpectedCalls[1:]
},
}

// First call for creating the snapshot
MatchSnapshot(mockT, 10, "hello world")
test.Equal(t, 1, testEvents.items[added])

// Resetting registry to emulate the same MatchSnapshot call
testsRegistry = newRegistry()

// Second call with different params
MatchSnapshot(mockT, 100, "bye world")

test.Equal(
t,
"\n[mock-name - 1]\nint(100)\nbye world\n---\n",
test.GetFileContent(t, snapPath),
)
test.Equal(t, 1, testEvents.items[updated])
t.Run("should update snapshot", func(t *testing.T) {
t.Run("when 'updateVAR==true'", func(t *testing.T) {
snapPath := setupSnapshot(t, fileName, false, true)

printerExpectedCalls := []func(received interface{}){
func(received interface{}) { test.Equal(t, addedMsg, received.(string)) },
func(received interface{}) { test.Equal(t, updatedMsg, received.(string)) },
}
mockT := test.MockTestingT{
MockHelper: func() {},
MockName: func() string {
return "mock-name"
},
MockError: func(args ...interface{}) {
test.NotCalled(t)
},
MockLog: func(args ...interface{}) {
printerExpectedCalls[0](args[0])

// shift
printerExpectedCalls = printerExpectedCalls[1:]
},
}

// First call for creating the snapshot
MatchSnapshot(mockT, 10, "hello world")
test.Equal(t, 1, testEvents.items[added])

// Resetting registry to emulate the same MatchSnapshot call
testsRegistry = newRegistry()

// Second call with different params
MatchSnapshot(mockT, 100, "bye world")

test.Equal(
t,
"\n[mock-name - 1]\nint(100)\nbye world\n---\n",
test.GetFileContent(t, snapPath),
)
test.Equal(t, 1, testEvents.items[updated])
})

t.Run("when config update", func(t *testing.T) {
snapPath := setupSnapshot(t, fileName, false, false)

printerExpectedCalls := []func(received interface{}){
func(received interface{}) { test.Equal(t, addedMsg, received.(string)) },
func(received interface{}) { test.Equal(t, updatedMsg, received.(string)) },
}
mockT := test.MockTestingT{
MockHelper: func() {},
MockName: func() string {
return "mock-name"
},
MockError: func(args ...interface{}) {
test.NotCalled(t)
},
MockLog: func(args ...interface{}) {
printerExpectedCalls[0](args[0])

// shift
printerExpectedCalls = printerExpectedCalls[1:]
},
}

s := WithConfig(Update(true))
// First call for creating the snapshot
s.MatchSnapshot(mockT, 10, "hello world")
test.Equal(t, 1, testEvents.items[added])

// Resetting registry to emulate the same MatchSnapshot call
testsRegistry = newRegistry()

// Second call with different params
s.MatchSnapshot(mockT, 100, "bye world")

test.Equal(
t,
"\n[mock-name - 1]\nint(100)\nbye world\n---\n",
test.GetFileContent(t, snapPath),
)
test.Equal(t, 1, testEvents.items[updated])
})
})

t.Run("should print warning if no params provided", func(t *testing.T) {
Expand Down
12 changes: 11 additions & 1 deletion snaps/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ var (
type config struct {
filename string
snapsDir string
update *bool
}

// Update determines whether to update snapshots or not
//
// It respects if running on CI.
func Update(u bool) func(*config) {
return func(c *config) {
c.update = &u
}
}

// Specify folder name where snapshots are stored
Expand All @@ -53,7 +63,7 @@ func Dir(dir string) func(*config) {

// Create snaps with configuration
//
// e.g WithConfig(Filename("my_test")).MatchSnapshot(t, "hello world")
// e.g snaps.WithConfig(snaps.Filename("my_test")).MatchSnapshot(t, "hello world")
func WithConfig(args ...func(*config)) *config {
s := defaultConfig

Expand Down
21 changes: 13 additions & 8 deletions snaps/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ import (
var (
errSnapNotFound = errors.New("snapshot not found")
isCI = ciinfo.IsCI
envVar = os.Getenv("UPDATE_SNAPS")
shouldUpdate = envVar == "true" && !isCI
shouldClean = shouldUpdate || envVar == "clean" && !isCI
updateVAR = os.Getenv("UPDATE_SNAPS")
shouldClean = (updateVAR == "true" || updateVAR == "clean") && !isCI
defaultConfig = config{
snapsDir: "__snapshots__",
}
Expand Down Expand Up @@ -113,9 +112,15 @@ func snapshotScanner(r io.Reader) *bufio.Scanner {
return s
}

// shouldUpdateSingle returns if a single should be updated or not
//
// it depends on the general should update or if the given name on `UPDATE_SNAPS` matches the current test.
func shouldUpdateSingle(tName string) bool {
return shouldUpdate || (!isCI && envVar != "" && strings.HasPrefix(tName, envVar))
// shouldUpdate determines whether snapshots should be updated
func shouldUpdate(u *bool) bool {
if isCI {
return false
}

if u != nil {
return *u
}

return updateVAR == "true"
}
38 changes: 0 additions & 38 deletions snaps/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,41 +44,3 @@ func TestBaseCaller(t *testing.T) {
TestBaseCallerNested(t)
})
}

func TestShouldUpdateSingle(t *testing.T) {
setup := func() {
shouldUpdate = false
isCI = false
envVar = ""
}

t.Run("should be true if shouldUpdate", func(t *testing.T) {
setup()

shouldUpdate = true
test.True(t, shouldUpdateSingle(""))
})

t.Run("should be true if specific test provided from envVar", func(t *testing.T) {
setup()
envVar = "mock-test/"
shouldUpdate = false

test.True(t, shouldUpdateSingle("mock-test/should_pass - 1"))
test.False(t, shouldUpdateSingle("mock-test-2/should_pass - 1"))
})

t.Run("should be false if running on CI", func(t *testing.T) {
setup()
envVar = "mock-test/"
isCI = true

test.False(t, shouldUpdateSingle("mock-test/should_pass - 1"))
})

t.Run("should be false if not envVar provided", func(t *testing.T) {
setup()

test.False(t, shouldUpdateSingle("mock-test"))
})
}

0 comments on commit 7d3b610

Please sign in to comment.