diff --git a/pkg/commands/dummies.go b/pkg/commands/dummies.go new file mode 100644 index 000000000..34bf549d3 --- /dev/null +++ b/pkg/commands/dummies.go @@ -0,0 +1,58 @@ +package commands + +import ( + "io/ioutil" + + "github.com/jesseduffield/lazygit/pkg/config" + "github.com/jesseduffield/lazygit/pkg/i18n" + "github.com/sirupsen/logrus" + "github.com/spf13/viper" + yaml "gopkg.in/yaml.v2" +) + +// This file exports dummy constructors for use by tests in other packages + +// NewDummyOSCommand creates a new dummy OSCommand for testing +func NewDummyOSCommand() *OSCommand { + return NewOSCommand(NewDummyLog(), NewDummyAppConfig()) +} + +// NewDummyAppConfig creates a new dummy AppConfig for testing +func NewDummyAppConfig() *config.AppConfig { + appConfig := &config.AppConfig{ + Name: "lazygit", + Version: "unversioned", + Commit: "", + BuildDate: "", + Debug: false, + BuildSource: "", + UserConfig: viper.New(), + } + _ = yaml.Unmarshal([]byte{}, appConfig.AppState) + return appConfig +} + +// NewDummyLog creates a new dummy Log for testing +func NewDummyLog() *logrus.Entry { + log := logrus.New() + log.Out = ioutil.Discard + return log.WithField("test", "test") +} + +// NewDummyGitCommand creates a new dummy GitCommand for testing +func NewDummyGitCommand() *GitCommand { + return NewDummyGitCommandWithOSCommand(NewDummyOSCommand()) +} + +// NewDummyGitCommandWithOSCommand creates a new dummy GitCommand for testing +func NewDummyGitCommandWithOSCommand(osCommand *OSCommand) *GitCommand { + return &GitCommand{ + Log: NewDummyLog(), + OSCommand: osCommand, + Tr: i18n.NewLocalizer(NewDummyLog()), + Config: NewDummyAppConfig(), + getGlobalGitConfig: func(string) (string, error) { return "", nil }, + getLocalGitConfig: func(string) (string, error) { return "", nil }, + removeFile: func(string) error { return nil }, + } +} diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 6d488b149..711215d3b 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -635,7 +635,7 @@ func (c *GitCommand) PrepareInteractiveRebaseCommand(baseSha string, todo string splitCmd := str.ToArgv(fmt.Sprintf("git rebase --interactive --autostash %s", baseSha)) - cmd := exec.Command(splitCmd[0], splitCmd[1:]...) + cmd := c.OSCommand.command(splitCmd[0], splitCmd[1:]...) gitSequenceEditor := ex if todo == "" { diff --git a/pkg/commands/git_test.go b/pkg/commands/git_test.go index 5af2bfe51..fb9bf9a1e 100644 --- a/pkg/commands/git_test.go +++ b/pkg/commands/git_test.go @@ -5,13 +5,11 @@ import ( "io/ioutil" "os" "os/exec" - "strings" "testing" "time" "github.com/jesseduffield/lazygit/pkg/i18n" - "github.com/mgutz/str" - "github.com/sirupsen/logrus" + "github.com/jesseduffield/lazygit/pkg/test" "github.com/stretchr/testify/assert" gogit "gopkg.in/src-d/go-git.v4" ) @@ -55,57 +53,6 @@ func (f fileInfoMock) Sys() interface{} { return f.sys } -func newDummyLog() *logrus.Entry { - log := logrus.New() - log.Out = ioutil.Discard - return log.WithField("test", "test") -} - -func newDummyGitCommand() *GitCommand { - return &GitCommand{ - Log: newDummyLog(), - OSCommand: newDummyOSCommand(), - Tr: i18n.NewLocalizer(newDummyLog()), - Config: newDummyAppConfig(), - getGlobalGitConfig: func(string) (string, error) { return "", nil }, - getLocalGitConfig: func(string) (string, error) { return "", nil }, - removeFile: func(string) error { return nil }, - } -} - -// commandSwapper takes a command, verifies that it is what it's expected to be -// and then returns a replacement command that will actually be called by the os -type commandSwapper struct { - expect string - replace string -} - -// swapCommand verifies the command is what we expected, and swaps it out for a different command -func (i *commandSwapper) swapCommand(t *testing.T, cmd string, args []string) *exec.Cmd { - splitCmd := str.ToArgv(i.expect) - assert.EqualValues(t, splitCmd[0], cmd, fmt.Sprintf("received command: %s %s", cmd, strings.Join(args, " "))) - if len(splitCmd) > 1 { - assert.EqualValues(t, splitCmd[1:], args, fmt.Sprintf("received command: %s %s", cmd, strings.Join(args, " "))) - } - - splitCmd = str.ToArgv(i.replace) - return exec.Command(splitCmd[0], splitCmd[1:]...) -} - -func createMockCommand(t *testing.T, swappers []*commandSwapper) func(cmd string, args ...string) *exec.Cmd { - commandIndex := 0 - - return func(cmd string, args ...string) *exec.Cmd { - var command *exec.Cmd - if commandIndex > len(swappers)-1 { - assert.Fail(t, fmt.Sprintf("too many commands run. This command was (%s %s)", cmd, strings.Join(args, " "))) - } - command = swappers[commandIndex].swapCommand(t, cmd, args) - commandIndex++ - return command - } -} - // TestVerifyInGitRepo is a function. func TestVerifyInGitRepo(t *testing.T) { type scenario struct { @@ -312,7 +259,7 @@ func TestNewGitCommand(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { s.setup() - s.test(NewGitCommand(newDummyLog(), newDummyOSCommand(), i18n.NewLocalizer(newDummyLog()))) + s.test(NewGitCommand(NewDummyLog(), NewDummyOSCommand(), i18n.NewLocalizer(NewDummyLog()), NewDummyAppConfig())) }) } } @@ -362,7 +309,7 @@ func TestGitCommandGetStashEntries(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = s.command s.test(gitCmd.GetStashEntries()) @@ -372,7 +319,7 @@ func TestGitCommandGetStashEntries(t *testing.T) { // TestGitCommandGetStashEntryDiff is a function. func TestGitCommandGetStashEntryDiff(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "git", cmd) assert.EqualValues(t, []string{"stash", "show", "-p", "--color", "stash@{1}"}, args) @@ -464,7 +411,7 @@ func TestGitCommandGetStatusFiles(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = s.command s.test(gitCmd.GetStatusFiles()) @@ -474,7 +421,7 @@ func TestGitCommandGetStatusFiles(t *testing.T) { // TestGitCommandStashDo is a function. func TestGitCommandStashDo(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "git", cmd) assert.EqualValues(t, []string{"stash", "drop", "stash@{1}"}, args) @@ -487,7 +434,7 @@ func TestGitCommandStashDo(t *testing.T) { // TestGitCommandStashSave is a function. func TestGitCommandStashSave(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "git", cmd) assert.EqualValues(t, []string{"stash", "save", "A stash message"}, args) @@ -500,7 +447,7 @@ func TestGitCommandStashSave(t *testing.T) { // TestGitCommandCommitAmend is a function. func TestGitCommandCommitAmend(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "git", cmd) assert.EqualValues(t, []string{"commit", "--amend", "--allow-empty"}, args) @@ -586,7 +533,7 @@ func TestGitCommandMergeStatusFiles(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() s.test(gitCmd.MergeStatusFiles(s.oldFiles, s.newFiles)) }) @@ -644,55 +591,16 @@ func TestGitCommandGetCommitDifferences(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = s.command s.test(gitCmd.GetCommitDifferences("HEAD", "@{u}")) }) } } -// TestGitCommandGetUnpushedCommits is a function. -func TestGitCommandGetUnpushedCommits(t *testing.T) { - type scenario struct { - testName string - command func(string, ...string) *exec.Cmd - test func(map[string]bool) - } - - scenarios := []scenario{ - { - "Can't retrieve pushable commits", - func(string, ...string) *exec.Cmd { - return exec.Command("test") - }, - func(pushables map[string]bool) { - assert.EqualValues(t, map[string]bool{}, pushables) - }, - }, - { - "Retrieve pushable commits", - func(cmd string, args ...string) *exec.Cmd { - return exec.Command("echo", "8a2bb0e\n78976bc") - }, - func(pushables map[string]bool) { - assert.Len(t, pushables, 2) - assert.EqualValues(t, map[string]bool{"8a2bb0e": true, "78976bc": true}, pushables) - }, - }, - } - - for _, s := range scenarios { - t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() - gitCmd.OSCommand.command = s.command - s.test(gitCmd.GetUnpushedCommits()) - }) - } -} - // TestGitCommandRenameCommit is a function. func TestGitCommandRenameCommit(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "git", cmd) assert.EqualValues(t, []string{"commit", "--allow-empty", "--amend", "-m", "test"}, args) @@ -705,7 +613,7 @@ func TestGitCommandRenameCommit(t *testing.T) { // TestGitCommandResetToCommit is a function. func TestGitCommandResetToCommit(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "git", cmd) assert.EqualValues(t, []string{"reset", "78976bc"}, args) @@ -718,7 +626,7 @@ func TestGitCommandResetToCommit(t *testing.T) { // TestGitCommandNewBranch is a function. func TestGitCommandNewBranch(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "git", cmd) assert.EqualValues(t, []string{"checkout", "-b", "test"}, args) @@ -772,7 +680,7 @@ func TestGitCommandDeleteBranch(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = s.command s.test(gitCmd.DeleteBranch(s.branch, s.force)) }) @@ -781,7 +689,7 @@ func TestGitCommandDeleteBranch(t *testing.T) { // TestGitCommandMerge is a function. func TestGitCommandMerge(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "git", cmd) assert.EqualValues(t, []string{"merge", "--no-edit", "test"}, args) @@ -878,7 +786,7 @@ func TestGitCommandUsingGpg(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.getGlobalGitConfig = s.getGlobalGitConfig gitCmd.getLocalGitConfig = s.getLocalGitConfig s.test(gitCmd.usingGpg()) @@ -948,16 +856,16 @@ func TestGitCommandCommit(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.getGlobalGitConfig = s.getGlobalGitConfig gitCmd.OSCommand.command = s.command - s.test(gitCmd.Commit("test", false)) + s.test(gitCmd.Commit("test")) }) } } -// TestGitCommandCommitAmendFromFiles is a function. -func TestGitCommandCommitAmendFromFiles(t *testing.T) { +// TestGitCommandAmendHead is a function. +func TestGitCommandAmendHead(t *testing.T) { type scenario struct { testName string command func(string, ...string) *exec.Cmd @@ -970,7 +878,7 @@ func TestGitCommandCommitAmendFromFiles(t *testing.T) { "Amend commit using gpg", func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "bash", cmd) - assert.EqualValues(t, []string{"-c", `git commit --amend -m 'test'`}, args) + assert.EqualValues(t, []string{"-c", "git commit --amend --no-edit"}, args) return exec.Command("echo") }, @@ -986,7 +894,7 @@ func TestGitCommandCommitAmendFromFiles(t *testing.T) { "Amend commit without using gpg", func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"commit", "--amend", "-m", "test"}, args) + assert.EqualValues(t, []string{"commit", "--amend", "--no-edit"}, args) return exec.Command("echo") }, @@ -1002,7 +910,7 @@ func TestGitCommandCommitAmendFromFiles(t *testing.T) { "Amend commit without using gpg with an error", func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"commit", "--amend", "-m", "test"}, args) + assert.EqualValues(t, []string{"commit", "--amend", "--no-edit"}, args) return exec.Command("test") }, @@ -1018,10 +926,10 @@ func TestGitCommandCommitAmendFromFiles(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.getGlobalGitConfig = s.getGlobalGitConfig gitCmd.OSCommand.command = s.command - s.test(gitCmd.Commit("test", true)) + s.test(gitCmd.AmendHead()) }) } } @@ -1078,7 +986,7 @@ func TestGitCommandPush(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = s.command err := gitCmd.Push("test", s.forcePush, func(passOrUname string) string { return "\n" @@ -1088,73 +996,9 @@ func TestGitCommandPush(t *testing.T) { } } -// TestGitCommandSquashPreviousTwoCommits is a function. -func TestGitCommandSquashPreviousTwoCommits(t *testing.T) { - type scenario struct { - testName string - command func(string, ...string) *exec.Cmd - test func(error) - } - - scenarios := []scenario{ - { - "Git reset triggers an error", - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"reset", "--soft", "HEAD^"}, args) - - return exec.Command("test") - }, - func(err error) { - assert.NotNil(t, err) - }, - }, - { - "Git commit triggers an error", - func(cmd string, args ...string) *exec.Cmd { - if len(args) > 0 && args[0] == "reset" { - return exec.Command("echo") - } - - assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"commit", "--amend", "-m", "test"}, args) - - return exec.Command("test") - }, - func(err error) { - assert.NotNil(t, err) - }, - }, - { - "Stash succeeded", - func(cmd string, args ...string) *exec.Cmd { - if len(args) > 0 && args[0] == "reset" { - return exec.Command("echo") - } - - assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"commit", "--amend", "-m", "test"}, args) - - return exec.Command("echo") - }, - func(err error) { - assert.Nil(t, err) - }, - }, - } - - for _, s := range scenarios { - t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() - gitCmd.OSCommand.command = s.command - s.test(gitCmd.SquashPreviousTwoCommits("test")) - }) - } -} - // TestGitCommandCatFile is a function. func TestGitCommandCatFile(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "cat", cmd) assert.EqualValues(t, []string{"test.txt"}, args) @@ -1169,7 +1013,7 @@ func TestGitCommandCatFile(t *testing.T) { // TestGitCommandStageFile is a function. func TestGitCommandStageFile(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "git", cmd) assert.EqualValues(t, []string{"add", "test.txt"}, args) @@ -1220,7 +1064,7 @@ func TestGitCommandUnstageFile(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = s.command s.test(gitCmd.UnStageFile("test.txt", s.tracked)) }) @@ -1289,7 +1133,7 @@ func TestGitCommandIsInMergeState(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = s.command s.test(gitCmd.IsInMergeState()) }) @@ -1490,7 +1334,7 @@ func TestGitCommandRemoveFile(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { var cmdsCalled *[][]string - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command, cmdsCalled = s.command() gitCmd.removeFile = s.removeFile s.test(cmdsCalled, gitCmd.RemoveFile(s.file)) @@ -1511,14 +1355,14 @@ func TestGitCommandShow(t *testing.T) { { "regular commit", "456abcde", - createMockCommand(t, []*commandSwapper{ + test.CreateMockCommand(t, []*test.CommandSwapper{ { - expect: "git show --color 456abcde", - replace: "echo \"commit ccc771d8b13d5b0d4635db4463556366470fd4f6\nblah\"", + Expect: "git show --color 456abcde", + Replace: "echo \"commit ccc771d8b13d5b0d4635db4463556366470fd4f6\nblah\"", }, { - expect: "git rev-list -1 --merges 456abcde^...456abcde", - replace: "echo", + Expect: "git rev-list -1 --merges 456abcde^...456abcde", + Replace: "echo", }, }), func(result string, err error) { @@ -1529,18 +1373,18 @@ func TestGitCommandShow(t *testing.T) { { "merge commit", "456abcde", - createMockCommand(t, []*commandSwapper{ + test.CreateMockCommand(t, []*test.CommandSwapper{ { - expect: "git show --color 456abcde", - replace: "echo \"commit ccc771d8b13d5b0d4635db4463556366470fd4f6\nMerge: 1a6a69a 3b51d7c\"", + Expect: "git show --color 456abcde", + Replace: "echo \"commit ccc771d8b13d5b0d4635db4463556366470fd4f6\nMerge: 1a6a69a 3b51d7c\"", }, { - expect: "git rev-list -1 --merges 456abcde^...456abcde", - replace: "echo aa30e006433628ba9281652952b34d8aacda9c01", + Expect: "git rev-list -1 --merges 456abcde^...456abcde", + Replace: "echo aa30e006433628ba9281652952b34d8aacda9c01", }, { - expect: "git diff --color 1a6a69a...3b51d7c", - replace: "echo blah", + Expect: "git diff --color 1a6a69a...3b51d7c", + Replace: "echo blah", }, }), func(result string, err error) { @@ -1550,7 +1394,7 @@ func TestGitCommandShow(t *testing.T) { }, } - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() for _, s := range scenarios { gitCmd.OSCommand.command = s.command @@ -1598,7 +1442,7 @@ func TestGitCommandCheckout(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = s.command s.test(gitCmd.Checkout("test", s.force)) }) @@ -1607,7 +1451,7 @@ func TestGitCommandCheckout(t *testing.T) { // TestGitCommandGetBranchGraph is a function. func TestGitCommandGetBranchGraph(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "git", cmd) assert.EqualValues(t, []string{"log", "--graph", "--color", "--abbrev-commit", "--decorate", "--date=relative", "--pretty=medium", "-100", "test"}, args) @@ -1619,169 +1463,6 @@ func TestGitCommandGetBranchGraph(t *testing.T) { assert.NoError(t, err) } -// TestGitCommandGetCommits is a function. -func TestGitCommandGetCommits(t *testing.T) { - type scenario struct { - testName string - command func(string, ...string) *exec.Cmd - test func([]*Commit, error) - } - - scenarios := []scenario{ - { - "No data found", - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - - switch args[0] { - case "rev-list": - assert.EqualValues(t, []string{"rev-list", "@{u}..HEAD", "--abbrev-commit"}, args) - return exec.Command("echo") - case "log": - assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args) - return exec.Command("echo") - case "merge-base": - assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) - return exec.Command("test") - case "symbolic-ref": - assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) - return exec.Command("echo", "master") - } - - return nil - }, - func(commits []*Commit, err error) { - assert.NoError(t, err) - assert.Len(t, commits, 0) - }, - }, - { - "GetCommits returns 2 commits, 1 unpushed, the other merged", - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - - switch args[0] { - case "rev-list": - assert.EqualValues(t, []string{"rev-list", "@{u}..HEAD", "--abbrev-commit"}, args) - return exec.Command("echo", "8a2bb0e") - case "log": - assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args) - return exec.Command("echo", "8a2bb0e commit 1\n78976bc commit 2") - case "merge-base": - assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) - return exec.Command("echo", "78976bc") - case "symbolic-ref": - assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) - return exec.Command("echo", "master") - } - - return nil - }, - func(commits []*Commit, err error) { - assert.NoError(t, err) - assert.Len(t, commits, 2) - assert.EqualValues(t, []*Commit{ - { - Sha: "8a2bb0e", - Name: "commit 1", - Status: "unpushed", - DisplayString: "8a2bb0e commit 1", - }, - { - Sha: "78976bc", - Name: "commit 2", - Status: "merged", - DisplayString: "78976bc commit 2", - }, - }, commits) - }, - }, - { - "GetCommits bubbles up an error from setCommitMergedStatuses", - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - - switch args[0] { - case "rev-list": - assert.EqualValues(t, []string{"rev-list", "@{u}..HEAD", "--abbrev-commit"}, args) - return exec.Command("echo", "8a2bb0e") - case "log": - assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args) - return exec.Command("echo", "8a2bb0e commit 1\n78976bc commit 2") - case "merge-base": - assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) - return exec.Command("echo", "78976bc") - case "symbolic-ref": - assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) - // here's where we are returning the error - return exec.Command("test") - case "rev-parse": - assert.EqualValues(t, []string{"rev-parse", "--short", "HEAD"}, args) - // here too - return exec.Command("test") - } - - return nil - }, - func(commits []*Commit, err error) { - assert.Error(t, err) - assert.Len(t, commits, 0) - }, - }, - } - - for _, s := range scenarios { - t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() - gitCmd.OSCommand.command = s.command - s.test(gitCmd.GetCommits()) - }) - } -} - -// TestGitCommandGetLog is a function. -func TestGitCommandGetLog(t *testing.T) { - type scenario struct { - testName string - command func(string, ...string) *exec.Cmd - test func(string) - } - - scenarios := []scenario{ - { - "Retrieves logs", - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args) - - return exec.Command("echo", "6f0b32f commands/git : add GetCommits tests refactor\n9d9d775 circle : remove new line") - }, - func(output string) { - assert.EqualValues(t, "6f0b32f commands/git : add GetCommits tests refactor\n9d9d775 circle : remove new line\n", output) - }, - }, - { - "An error occurred when retrieving logs", - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args) - return exec.Command("test") - }, - func(output string) { - assert.Empty(t, output) - }, - }, - } - - for _, s := range scenarios { - t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() - gitCmd.OSCommand.command = s.command - s.test(gitCmd.GetLog()) - }) - } -} - // TestGitCommandDiff is a function. func TestGitCommandDiff(t *testing.T) { type scenario struct { @@ -1857,103 +1538,13 @@ func TestGitCommandDiff(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = s.command gitCmd.Diff(s.file, s.plain) }) } } -// TestGitCommandGetMergeBase is a function. -func TestGitCommandGetMergeBase(t *testing.T) { - type scenario struct { - testName string - command func(string, ...string) *exec.Cmd - test func(string, error) - } - - scenarios := []scenario{ - { - "swallows an error if the call to merge-base returns an error", - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - - switch args[0] { - case "symbolic-ref": - assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) - return exec.Command("echo", "master") - case "merge-base": - assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) - return exec.Command("test") - } - return nil - }, - func(output string, err error) { - assert.NoError(t, err) - assert.EqualValues(t, "", output) - }, - }, - { - "returns the commit when master", - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - - switch args[0] { - case "symbolic-ref": - assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) - return exec.Command("echo", "master") - case "merge-base": - assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) - return exec.Command("echo", "blah") - } - return nil - }, - func(output string, err error) { - assert.NoError(t, err) - assert.Equal(t, "blah\n", output) - }, - }, - { - "checks against develop when a feature branch", - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - - switch args[0] { - case "symbolic-ref": - assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) - return exec.Command("echo", "feature/test") - case "merge-base": - assert.EqualValues(t, []string{"merge-base", "HEAD", "develop"}, args) - return exec.Command("echo", "blah") - } - return nil - }, - func(output string, err error) { - assert.NoError(t, err) - assert.Equal(t, "blah\n", output) - }, - }, - { - "bubbles up error if there is one", - func(cmd string, args ...string) *exec.Cmd { - return exec.Command("test") - }, - func(output string, err error) { - assert.Error(t, err) - assert.Equal(t, "", output) - }, - }, - } - - for _, s := range scenarios { - t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() - gitCmd.OSCommand.command = s.command - s.test(gitCmd.getMergeBase()) - }) - } -} - // TestGitCommandCurrentBranchName is a function. func TestGitCommandCurrentBranchName(t *testing.T) { type scenario struct { @@ -2010,7 +1601,7 @@ func TestGitCommandCurrentBranchName(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = s.command s.test(gitCmd.CurrentBranchName()) }) @@ -2068,9 +1659,55 @@ func TestGitCommandApplyPatch(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := newDummyGitCommand() + gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = s.command s.test(gitCmd.ApplyPatch("test")) }) } } + +// TestGitCommandRebaseBranch is a function. +func TestGitCommandRebaseBranch(t *testing.T) { + type scenario struct { + testName string + arg string + command func(string, ...string) *exec.Cmd + test func(error) + } + + scenarios := []scenario{ + { + "successful rebase", + "master", + test.CreateMockCommand(t, []*test.CommandSwapper{ + { + Expect: "git rebase --interactive --autostash master", + Replace: "echo", + }, + }), + func(err error) { + assert.NoError(t, err) + }, + }, + { + "unsuccessful rebase", + "master", + test.CreateMockCommand(t, []*test.CommandSwapper{ + { + Expect: "git rebase --interactive --autostash master", + Replace: "test", + }, + }), + func(err error) { + assert.Error(t, err) + }, + }, + } + + gitCmd := NewDummyGitCommand() + + for _, s := range scenarios { + gitCmd.OSCommand.command = s.command + s.test(gitCmd.RebaseBranch(s.arg)) + } +} diff --git a/pkg/commands/os.go b/pkg/commands/os.go index b6ef1a07f..44202e003 100644 --- a/pkg/commands/os.go +++ b/pkg/commands/os.go @@ -50,6 +50,12 @@ func NewOSCommand(log *logrus.Entry, config config.AppConfigurer) *OSCommand { } } +// SetCommand sets the command function used by the struct. +// To be used for testing only +func (c *OSCommand) SetCommand(cmd func(string, ...string) *exec.Cmd) { + c.command = cmd +} + // RunCommandWithOutput wrapper around commands returning their output and error func (c *OSCommand) RunCommandWithOutput(command string) (string, error) { c.Log.WithField("command", command).Info("RunCommand") diff --git a/pkg/commands/os_test.go b/pkg/commands/os_test.go index a08c4b57d..2141b0e1e 100644 --- a/pkg/commands/os_test.go +++ b/pkg/commands/os_test.go @@ -6,30 +6,9 @@ import ( "os/exec" "testing" - "github.com/jesseduffield/lazygit/pkg/config" - "github.com/spf13/viper" "github.com/stretchr/testify/assert" - yaml "gopkg.in/yaml.v2" ) -func newDummyOSCommand() *OSCommand { - return NewOSCommand(newDummyLog(), newDummyAppConfig()) -} - -func newDummyAppConfig() *config.AppConfig { - appConfig := &config.AppConfig{ - Name: "lazygit", - Version: "unversioned", - Commit: "", - BuildDate: "", - Debug: false, - BuildSource: "", - UserConfig: viper.New(), - } - _ = yaml.Unmarshal([]byte{}, appConfig.AppState) - return appConfig -} - // TestOSCommandRunCommandWithOutput is a function. func TestOSCommandRunCommandWithOutput(t *testing.T) { type scenario struct { @@ -54,7 +33,7 @@ func TestOSCommandRunCommandWithOutput(t *testing.T) { } for _, s := range scenarios { - s.test(newDummyOSCommand().RunCommandWithOutput(s.command)) + s.test(NewDummyOSCommand().RunCommandWithOutput(s.command)) } } @@ -75,7 +54,7 @@ func TestOSCommandRunCommand(t *testing.T) { } for _, s := range scenarios { - s.test(newDummyOSCommand().RunCommand(s.command)) + s.test(NewDummyOSCommand().RunCommand(s.command)) } } @@ -122,7 +101,7 @@ func TestOSCommandOpenFile(t *testing.T) { } for _, s := range scenarios { - OSCmd := newDummyOSCommand() + OSCmd := NewDummyOSCommand() OSCmd.command = s.command OSCmd.Config.GetUserConfig().Set("os.openCommand", "open {{filename}}") @@ -251,7 +230,7 @@ func TestOSCommandEditFile(t *testing.T) { } for _, s := range scenarios { - OSCmd := newDummyOSCommand() + OSCmd := NewDummyOSCommand() OSCmd.command = s.command OSCmd.getGlobalGitConfig = s.getGlobalGitConfig OSCmd.getenv = s.getenv @@ -262,7 +241,7 @@ func TestOSCommandEditFile(t *testing.T) { // TestOSCommandQuote is a function. func TestOSCommandQuote(t *testing.T) { - osCommand := newDummyOSCommand() + osCommand := NewDummyOSCommand() actual := osCommand.Quote("hello `test`") @@ -273,7 +252,7 @@ func TestOSCommandQuote(t *testing.T) { // TestOSCommandQuoteSingleQuote tests the quote function with ' quotes explicitly for Linux func TestOSCommandQuoteSingleQuote(t *testing.T) { - osCommand := newDummyOSCommand() + osCommand := NewDummyOSCommand() osCommand.Platform.os = "linux" @@ -286,7 +265,7 @@ func TestOSCommandQuoteSingleQuote(t *testing.T) { // TestOSCommandQuoteDoubleQuote tests the quote function with " quotes explicitly for Linux func TestOSCommandQuoteDoubleQuote(t *testing.T) { - osCommand := newDummyOSCommand() + osCommand := NewDummyOSCommand() osCommand.Platform.os = "linux" @@ -299,7 +278,7 @@ func TestOSCommandQuoteDoubleQuote(t *testing.T) { // TestOSCommandUnquote is a function. func TestOSCommandUnquote(t *testing.T) { - osCommand := newDummyOSCommand() + osCommand := NewDummyOSCommand() actual := osCommand.Unquote(`hello "test"`) @@ -361,7 +340,7 @@ func TestOSCommandFileType(t *testing.T) { for _, s := range scenarios { s.setup() - s.test(newDummyOSCommand().FileType(s.path)) + s.test(NewDummyOSCommand().FileType(s.path)) _ = os.RemoveAll(s.path) } } @@ -392,7 +371,7 @@ func TestOSCommandCreateTempFile(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - s.test(newDummyOSCommand().CreateTempFile(s.filename, s.content)) + s.test(NewDummyOSCommand().CreateTempFile(s.filename, s.content)) }) } } diff --git a/pkg/commands/pull_request_test.go b/pkg/commands/pull_request_test.go index 774baf92e..3e997e9c5 100644 --- a/pkg/commands/pull_request_test.go +++ b/pkg/commands/pull_request_test.go @@ -144,7 +144,7 @@ func TestCreatePullRequest(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCommand := newDummyGitCommand() + gitCommand := NewDummyGitCommand() gitCommand.OSCommand.command = s.command gitCommand.OSCommand.Config.GetUserConfig().Set("os.openLinkCommand", "open {{link}}") dummyPullRequest := NewPullRequest(gitCommand) diff --git a/pkg/git/commit_list_builder_test.go b/pkg/git/commit_list_builder_test.go new file mode 100644 index 000000000..81bb7b3cb --- /dev/null +++ b/pkg/git/commit_list_builder_test.go @@ -0,0 +1,315 @@ +package git + +import ( + "os/exec" + "testing" + + "github.com/jesseduffield/lazygit/pkg/commands" + "github.com/jesseduffield/lazygit/pkg/i18n" + "github.com/stretchr/testify/assert" +) + +// NewDummyCommitListBuilder creates a new dummy CommitListBuilder for testing +func NewDummyCommitListBuilder() *CommitListBuilder { + osCommand := commands.NewDummyOSCommand() + + return &CommitListBuilder{ + Log: commands.NewDummyLog(), + GitCommand: commands.NewDummyGitCommandWithOSCommand(osCommand), + OSCommand: osCommand, + Tr: i18n.NewLocalizer(commands.NewDummyLog()), + CherryPickedCommits: []*commands.Commit{}, + } +} + +// TestCommitListBuilderGetUnpushedCommits is a function. +func TestCommitListBuilderGetUnpushedCommits(t *testing.T) { + type scenario struct { + testName string + command func(string, ...string) *exec.Cmd + test func(map[string]bool) + } + + scenarios := []scenario{ + { + "Can't retrieve pushable commits", + func(string, ...string) *exec.Cmd { + return exec.Command("test") + }, + func(pushables map[string]bool) { + assert.EqualValues(t, map[string]bool{}, pushables) + }, + }, + { + "Retrieve pushable commits", + func(cmd string, args ...string) *exec.Cmd { + return exec.Command("echo", "8a2bb0e\n78976bc") + }, + func(pushables map[string]bool) { + assert.Len(t, pushables, 2) + assert.EqualValues(t, map[string]bool{"8a2bb0e": true, "78976bc": true}, pushables) + }, + }, + } + + for _, s := range scenarios { + t.Run(s.testName, func(t *testing.T) { + c := NewDummyCommitListBuilder() + c.OSCommand.SetCommand(s.command) + s.test(c.getUnpushedCommits()) + }) + } +} + +// TestCommitListBuilderGetMergeBase is a function. +func TestCommitListBuilderGetMergeBase(t *testing.T) { + type scenario struct { + testName string + command func(string, ...string) *exec.Cmd + test func(string, error) + } + + scenarios := []scenario{ + { + "swallows an error if the call to merge-base returns an error", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + + switch args[0] { + case "symbolic-ref": + assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) + return exec.Command("echo", "master") + case "merge-base": + assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) + return exec.Command("test") + } + return nil + }, + func(output string, err error) { + assert.NoError(t, err) + assert.EqualValues(t, "", output) + }, + }, + { + "returns the commit when master", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + + switch args[0] { + case "symbolic-ref": + assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) + return exec.Command("echo", "master") + case "merge-base": + assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) + return exec.Command("echo", "blah") + } + return nil + }, + func(output string, err error) { + assert.NoError(t, err) + assert.Equal(t, "blah\n", output) + }, + }, + { + "checks against develop when a feature branch", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + + switch args[0] { + case "symbolic-ref": + assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) + return exec.Command("echo", "feature/test") + case "merge-base": + assert.EqualValues(t, []string{"merge-base", "HEAD", "develop"}, args) + return exec.Command("echo", "blah") + } + return nil + }, + func(output string, err error) { + assert.NoError(t, err) + assert.Equal(t, "blah\n", output) + }, + }, + { + "bubbles up error if there is one", + func(cmd string, args ...string) *exec.Cmd { + return exec.Command("test") + }, + func(output string, err error) { + assert.Error(t, err) + assert.Equal(t, "", output) + }, + }, + } + + for _, s := range scenarios { + t.Run(s.testName, func(t *testing.T) { + c := NewDummyCommitListBuilder() + c.OSCommand.SetCommand(s.command) + s.test(c.getMergeBase()) + }) + } +} + +// TestCommitListBuilderGetLog is a function. +func TestCommitListBuilderGetLog(t *testing.T) { + type scenario struct { + testName string + command func(string, ...string) *exec.Cmd + test func(string) + } + + scenarios := []scenario{ + { + "Retrieves logs", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args) + + return exec.Command("echo", "6f0b32f commands/git : add GetCommits tests refactor\n9d9d775 circle : remove new line") + }, + func(output string) { + assert.EqualValues(t, "6f0b32f commands/git : add GetCommits tests refactor\n9d9d775 circle : remove new line\n", output) + }, + }, + { + "An error occurred when retrieving logs", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args) + return exec.Command("test") + }, + func(output string) { + assert.Empty(t, output) + }, + }, + } + + for _, s := range scenarios { + t.Run(s.testName, func(t *testing.T) { + c := NewDummyCommitListBuilder() + c.OSCommand.SetCommand(s.command) + s.test(c.getLog()) + }) + } +} + +// TestCommitListBuilderGetCommits is a function. +func TestCommitListBuilderGetCommits(t *testing.T) { + type scenario struct { + testName string + command func(string, ...string) *exec.Cmd + test func([]*commands.Commit, error) + } + + scenarios := []scenario{ + { + "No data found", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + + switch args[0] { + case "rev-list": + assert.EqualValues(t, []string{"rev-list", "@{u}..HEAD", "--abbrev-commit"}, args) + return exec.Command("echo") + case "log": + assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args) + return exec.Command("echo") + case "merge-base": + assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) + return exec.Command("test") + case "symbolic-ref": + assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) + return exec.Command("echo", "master") + } + + return nil + }, + func(commits []*commands.Commit, err error) { + assert.NoError(t, err) + assert.Len(t, commits, 0) + }, + }, + { + "GetCommits returns 2 commits, 1 unpushed, the other merged", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + + switch args[0] { + case "rev-list": + assert.EqualValues(t, []string{"rev-list", "@{u}..HEAD", "--abbrev-commit"}, args) + return exec.Command("echo", "8a2bb0e") + case "log": + assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args) + return exec.Command("echo", "8a2bb0e commit 1\n78976bc commit 2") + case "merge-base": + assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) + return exec.Command("echo", "78976bc") + case "symbolic-ref": + assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) + return exec.Command("echo", "master") + } + + return nil + }, + func(commits []*commands.Commit, err error) { + assert.NoError(t, err) + assert.Len(t, commits, 2) + assert.EqualValues(t, []*commands.Commit{ + { + Sha: "8a2bb0e", + Name: "commit 1", + Status: "unpushed", + DisplayString: "8a2bb0e commit 1", + }, + { + Sha: "78976bc", + Name: "commit 2", + Status: "merged", + DisplayString: "78976bc commit 2", + }, + }, commits) + }, + }, + { + "GetCommits bubbles up an error from setCommitMergedStatuses", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + + switch args[0] { + case "rev-list": + assert.EqualValues(t, []string{"rev-list", "@{u}..HEAD", "--abbrev-commit"}, args) + return exec.Command("echo", "8a2bb0e") + case "log": + assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args) + return exec.Command("echo", "8a2bb0e commit 1\n78976bc commit 2") + case "merge-base": + assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) + return exec.Command("echo", "78976bc") + case "symbolic-ref": + assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) + // here's where we are returning the error + return exec.Command("test") + case "rev-parse": + assert.EqualValues(t, []string{"rev-parse", "--short", "HEAD"}, args) + // here too + return exec.Command("test") + } + + return nil + }, + func(commits []*commands.Commit, err error) { + assert.Error(t, err) + assert.Len(t, commits, 0) + }, + }, + } + + for _, s := range scenarios { + t.Run(s.testName, func(t *testing.T) { + c := NewDummyCommitListBuilder() + c.OSCommand.SetCommand(s.command) + s.test(c.GetCommits()) + }) + } +} diff --git a/pkg/git/patch_modifier_test.go b/pkg/git/patch_modifier_test.go index bc2073d55..72c3f62a7 100644 --- a/pkg/git/patch_modifier_test.go +++ b/pkg/git/patch_modifier_test.go @@ -4,21 +4,17 @@ import ( "io/ioutil" "testing" - "github.com/sirupsen/logrus" + "github.com/jesseduffield/lazygit/pkg/commands" "github.com/stretchr/testify/assert" ) -func newDummyLog() *logrus.Entry { - log := logrus.New() - log.Out = ioutil.Discard - return log.WithField("test", "test") -} - -func newDummyPatchModifier() *PatchModifier { +// NewDummyPatchModifier constructs a new dummy patch modifier for testing +func NewDummyPatchModifier() *PatchModifier { return &PatchModifier{ - Log: newDummyLog(), + Log: commands.NewDummyLog(), } } + func TestModifyPatchForLine(t *testing.T) { type scenario struct { testName string @@ -68,7 +64,7 @@ func TestModifyPatchForLine(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - p := newDummyPatchModifier() + p := NewDummyPatchModifier() beforePatch, err := ioutil.ReadFile(s.patchFilename) if err != nil { panic("Cannot open file at " + s.patchFilename) diff --git a/pkg/git/patch_parser_test.go b/pkg/git/patch_parser_test.go index 6670aaea2..ff2d1257f 100644 --- a/pkg/git/patch_parser_test.go +++ b/pkg/git/patch_parser_test.go @@ -4,14 +4,17 @@ import ( "io/ioutil" "testing" + "github.com/jesseduffield/lazygit/pkg/commands" "github.com/stretchr/testify/assert" ) -func newDummyPatchParser() *PatchParser { +// NewDummyPatchParser constructs a new dummy patch parser for testing +func NewDummyPatchParser() *PatchParser { return &PatchParser{ - Log: newDummyLog(), + Log: commands.NewDummyLog(), } } + func TestParsePatch(t *testing.T) { type scenario struct { testName string @@ -47,7 +50,7 @@ func TestParsePatch(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - p := newDummyPatchParser() + p := NewDummyPatchParser() beforePatch, err := ioutil.ReadFile(s.patchFilename) if err != nil { panic("Cannot open file at " + s.patchFilename) diff --git a/pkg/test/utils.go b/pkg/test/utils.go new file mode 100644 index 000000000..5603fd0ae --- /dev/null +++ b/pkg/test/utils.go @@ -0,0 +1,45 @@ +package test + +import ( + "fmt" + "os/exec" + "strings" + "testing" + + "github.com/mgutz/str" + "github.com/stretchr/testify/assert" +) + +// CommandSwapper takes a command, verifies that it is what it's expected to be +// and then returns a replacement command that will actually be called by the os +type CommandSwapper struct { + Expect string + Replace string +} + +// SwapCommand verifies the command is what we expected, and swaps it out for a different command +func (i *CommandSwapper) SwapCommand(t *testing.T, cmd string, args []string) *exec.Cmd { + splitCmd := str.ToArgv(i.Expect) + assert.EqualValues(t, splitCmd[0], cmd, fmt.Sprintf("received command: %s %s", cmd, strings.Join(args, " "))) + if len(splitCmd) > 1 { + assert.EqualValues(t, splitCmd[1:], args, fmt.Sprintf("received command: %s %s", cmd, strings.Join(args, " "))) + } + + splitCmd = str.ToArgv(i.Replace) + return exec.Command(splitCmd[0], splitCmd[1:]...) +} + +// CreateMockCommand creates a command function that will verify its receiving the right sequence of commands from lazygit +func CreateMockCommand(t *testing.T, swappers []*CommandSwapper) func(cmd string, args ...string) *exec.Cmd { + commandIndex := 0 + + return func(cmd string, args ...string) *exec.Cmd { + var command *exec.Cmd + if commandIndex > len(swappers)-1 { + assert.Fail(t, fmt.Sprintf("too many commands run. This command was (%s %s)", cmd, strings.Join(args, " "))) + } + command = swappers[commandIndex].SwapCommand(t, cmd, args) + commandIndex++ + return command + } +}