diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2021-04-10 11:40:42 +1000 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2021-04-10 11:54:38 +1000 |
commit | e42e7e5cbd9d075ee24ae8f91ba9e12bdd42fafc (patch) | |
tree | 61d65a544c056b3bf0384cf6954b81b292eb4b07 /pkg/commands/files_test.go | |
parent | 93fac1f3124f87009091230f61cc13b5e5473cb5 (diff) |
fix commit amend
Diffstat (limited to 'pkg/commands/files_test.go')
-rw-r--r-- | pkg/commands/files_test.go | 467 |
1 files changed, 467 insertions, 0 deletions
diff --git a/pkg/commands/files_test.go b/pkg/commands/files_test.go new file mode 100644 index 000000000..62aa388cb --- /dev/null +++ b/pkg/commands/files_test.go @@ -0,0 +1,467 @@ +package commands + +import ( + "fmt" + "os/exec" + "runtime" + "testing" + + "github.com/jesseduffield/lazygit/pkg/commands/models" + "github.com/jesseduffield/lazygit/pkg/secureexec" + "github.com/jesseduffield/lazygit/pkg/test" + "github.com/stretchr/testify/assert" +) + +// TestGitCommandCatFile tests emitting a file using commands, where commands vary by OS. +func TestGitCommandCatFile(t *testing.T) { + var osCmd string + switch os := runtime.GOOS; os { + case "windows": + osCmd = "type" + default: + osCmd = "cat" + } + gitCmd := NewDummyGitCommand() + gitCmd.OSCommand.Command = func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, osCmd, cmd) + assert.EqualValues(t, []string{"test.txt"}, args) + + return secureexec.Command("echo", "-n", "test") + } + + o, err := gitCmd.CatFile("test.txt") + assert.NoError(t, err) + assert.Equal(t, "test", o) +} + +// TestGitCommandStageFile is a function. +func TestGitCommandStageFile(t *testing.T) { + 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) + + return secureexec.Command("echo") + } + + assert.NoError(t, gitCmd.StageFile("test.txt")) +} + +// TestGitCommandUnstageFile is a function. +func TestGitCommandUnstageFile(t *testing.T) { + type scenario struct { + testName string + command func(string, ...string) *exec.Cmd + test func(error) + reset bool + } + + scenarios := []scenario{ + { + "Remove an untracked file from staging", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + assert.EqualValues(t, []string{"rm", "--cached", "--force", "--", "test.txt"}, args) + + return secureexec.Command("echo") + }, + func(err error) { + assert.NoError(t, err) + }, + false, + }, + { + "Remove a tracked file from staging", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + assert.EqualValues(t, []string{"reset", "HEAD", "--", "test.txt"}, args) + + return secureexec.Command("echo") + }, + func(err error) { + assert.NoError(t, err) + }, + true, + }, + } + + for _, s := range scenarios { + t.Run(s.testName, func(t *testing.T) { + gitCmd := NewDummyGitCommand() + gitCmd.OSCommand.Command = s.command + s.test(gitCmd.UnStageFile([]string{"test.txt"}, s.reset)) + }) + } +} + +// TestGitCommandDiscardAllFileChanges is a function. +// these tests don't cover everything, in part because we already have an integration +// test which does cover everything. I don't want to unnecessarily assert on the 'how' +// when the 'what' is what matters +func TestGitCommandDiscardAllFileChanges(t *testing.T) { + type scenario struct { + testName string + command func() (func(string, ...string) *exec.Cmd, *[][]string) + test func(*[][]string, error) + file *models.File + removeFile func(string) error + } + + scenarios := []scenario{ + { + "An error occurred when resetting", + func() (func(string, ...string) *exec.Cmd, *[][]string) { + cmdsCalled := [][]string{} + return func(cmd string, args ...string) *exec.Cmd { + cmdsCalled = append(cmdsCalled, args) + + return secureexec.Command("test") + }, &cmdsCalled + }, + func(cmdsCalled *[][]string, err error) { + assert.Error(t, err) + assert.Len(t, *cmdsCalled, 1) + assert.EqualValues(t, *cmdsCalled, [][]string{ + {"reset", "--", "test"}, + }) + }, + &models.File{ + Name: "test", + HasStagedChanges: true, + }, + func(string) error { + return nil + }, + }, + { + "An error occurred when removing file", + func() (func(string, ...string) *exec.Cmd, *[][]string) { + cmdsCalled := [][]string{} + return func(cmd string, args ...string) *exec.Cmd { + cmdsCalled = append(cmdsCalled, args) + + return secureexec.Command("test") + }, &cmdsCalled + }, + func(cmdsCalled *[][]string, err error) { + assert.Error(t, err) + assert.EqualError(t, err, "an error occurred when removing file") + assert.Len(t, *cmdsCalled, 0) + }, + &models.File{ + Name: "test", + Tracked: false, + Added: true, + }, + func(string) error { + return fmt.Errorf("an error occurred when removing file") + }, + }, + { + "An error occurred with checkout", + func() (func(string, ...string) *exec.Cmd, *[][]string) { + cmdsCalled := [][]string{} + return func(cmd string, args ...string) *exec.Cmd { + cmdsCalled = append(cmdsCalled, args) + + return secureexec.Command("test") + }, &cmdsCalled + }, + func(cmdsCalled *[][]string, err error) { + assert.Error(t, err) + assert.Len(t, *cmdsCalled, 1) + assert.EqualValues(t, *cmdsCalled, [][]string{ + {"checkout", "--", "test"}, + }) + }, + &models.File{ + Name: "test", + Tracked: true, + HasStagedChanges: false, + }, + func(string) error { + return nil + }, + }, + { + "Checkout only", + func() (func(string, ...string) *exec.Cmd, *[][]string) { + cmdsCalled := [][]string{} + return func(cmd string, args ...string) *exec.Cmd { + cmdsCalled = append(cmdsCalled, args) + + return secureexec.Command("echo") + }, &cmdsCalled + }, + func(cmdsCalled *[][]string, err error) { + assert.NoError(t, err) + assert.Len(t, *cmdsCalled, 1) + assert.EqualValues(t, *cmdsCalled, [][]string{ + {"checkout", "--", "test"}, + }) + }, + &models.File{ + Name: "test", + Tracked: true, + HasStagedChanges: false, + }, + func(string) error { + return nil + }, + }, + { + "Reset and checkout staged changes", + func() (func(string, ...string) *exec.Cmd, *[][]string) { + cmdsCalled := [][]string{} + return func(cmd string, args ...string) *exec.Cmd { + cmdsCalled = append(cmdsCalled, args) + + return secureexec.Command("echo") + }, &cmdsCalled + }, + func(cmdsCalled *[][]string, err error) { + assert.NoError(t, err) + assert.Len(t, *cmdsCalled, 2) + assert.EqualValues(t, *cmdsCalled, [][]string{ + {"reset", "--", "test"}, + {"checkout", "--", "test"}, + }) + }, + &models.File{ + Name: "test", + Tracked: true, + HasStagedChanges: true, + }, + func(string) error { + return nil + }, + }, + { + "Reset and checkout merge conflicts", + func() (func(string, ...string) *exec.Cmd, *[][]string) { + cmdsCalled := [][]string{} + return func(cmd string, args ...string) *exec.Cmd { + cmdsCalled = append(cmdsCalled, args) + + return secureexec.Command("echo") + }, &cmdsCalled + }, + func(cmdsCalled *[][]string, err error) { + assert.NoError(t, err) + assert.Len(t, *cmdsCalled, 2) + assert.EqualValues(t, *cmdsCalled, [][]string{ + {"reset", "--", "test"}, + {"checkout", "--", "test"}, + }) + }, + &models.File{ + Name: "test", + Tracked: true, + HasMergeConflicts: true, + }, + func(string) error { + return nil + }, + }, + { + "Reset and remove", + func() (func(string, ...string) *exec.Cmd, *[][]string) { + cmdsCalled := [][]string{} + return func(cmd string, args ...string) *exec.Cmd { + cmdsCalled = append(cmdsCalled, args) + + return secureexec.Command("echo") + }, &cmdsCalled + }, + func(cmdsCalled *[][]string, err error) { + assert.NoError(t, err) + assert.Len(t, *cmdsCalled, 1) + assert.EqualValues(t, *cmdsCalled, [][]string{ + {"reset", "--", "test"}, + }) + }, + &models.File{ + Name: "test", + Tracked: false, + Added: true, + HasStagedChanges: true, + }, + func(filename string) error { + assert.Equal(t, "test", filename) + return nil + }, + }, + { + "Remove only", + func() (func(string, ...string) *exec.Cmd, *[][]string) { + cmdsCalled := [][]string{} + return func(cmd string, args ...string) *exec.Cmd { + cmdsCalled = append(cmdsCalled, args) + + return secureexec.Command("echo") + }, &cmdsCalled + }, + func(cmdsCalled *[][]string, err error) { + assert.NoError(t, err) + assert.Len(t, *cmdsCalled, 0) + }, + &models.File{ + Name: "test", + Tracked: false, + Added: true, + HasStagedChanges: false, + }, + func(filename string) error { + assert.Equal(t, "test", filename) + return nil + }, + }, + } + + for _, s := range scenarios { + t.Run(s.testName, func(t *testing.T) { + var cmdsCalled *[][]string + gitCmd := NewDummyGitCommand() + gitCmd.OSCommand.Command, cmdsCalled = s.command() + gitCmd.removeFile = s.removeFile + s.test(cmdsCalled, gitCmd.DiscardAllFileChanges(s.file)) + }) + } +} + +// TestGitCommandDiff is a function. +func TestGitCommandDiff(t *testing.T) { + type scenario struct { + testName string + command func(string, ...string) *exec.Cmd + file *models.File + plain bool + cached bool + } + + scenarios := []scenario{ + { + "Default case", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + assert.EqualValues(t, []string{"diff", "--submodule", "--no-ext-diff", "--color=always", "--", "test.txt"}, args) + + return secureexec.Command("echo") + }, + &models.File{ + Name: "test.txt", + HasStagedChanges: false, + Tracked: true, + }, + false, + false, + }, + { + "cached", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + assert.EqualValues(t, []string{"diff", "--submodule", "--no-ext-diff", "--color=always", "--cached", "--", "test.txt"}, args) + + return secureexec.Command("echo") + }, + &models.File{ + Name: "test.txt", + HasStagedChanges: false, + Tracked: true, + }, + false, + true, + }, + { + "plain", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + assert.EqualValues(t, []string{"diff", "--submodule", "--no-ext-diff", "--color=never", "--", "test.txt"}, args) + + return secureexec.Command("echo") + }, + &models.File{ + Name: "test.txt", + HasStagedChanges: false, + Tracked: true, + }, + true, + false, + }, + { + "File not tracked and file has no staged changes", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + assert.EqualValues(t, []string{"diff", "--submodule", "--no-ext-diff", "--color=always", "--no-index", "--", "/dev/null", "test.txt"}, args) + + return secureexec.Command("echo") + }, + &models.File{ + Name: "test.txt", + HasStagedChanges: false, + Tracked: false, + }, + false, + false, + }, + } + + for _, s := range scenarios { + t.Run(s.testName, func(t *testing.T) { + gitCmd := NewDummyGitCommand() + gitCmd.OSCommand.Command = s.command + gitCmd.WorktreeFileDiff(s.file, s.plain, s.cached) + }) + } +} + +// TestGitCommandCheckoutFile is a function. +func TestGitCommandCheckoutFile(t *testing.T) { + type scenario struct { + testName string + commitSha string + fileName string + command func(string, ...string) *exec.Cmd + test func(error) + } + + scenarios := []scenario{ + { + "typical case", + "11af912", + "test999.txt", + test.CreateMockCommand(t, []*test.CommandSwapper{ + { + Expect: "git checkout 11af912 test999.txt", + Replace: "echo", + }, + }), + func(err error) { + assert.NoError(t, err) + }, + }, + { + "returns error if there is one", + "11af912", + "test999.txt", + test.CreateMockCommand(t, []*test.CommandSwapper{ + { + Expect: "git checkout 11af912 test999.txt", + Replace: "test", + }, + }), + func(err error) { + assert.Error(t, err) + }, + }, + } + + gitCmd := NewDummyGitCommand() + + for _, s := range scenarios { + t.Run(s.testName, func(t *testing.T) { + gitCmd.OSCommand.Command = s.command + s.test(gitCmd.CheckoutFile(s.commitSha, s.fileName)) + }) + } +} |