summaryrefslogtreecommitdiffstats
path: root/pkg/commands/files_test.go
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2021-04-10 11:40:42 +1000
committerJesse Duffield <jessedduffield@gmail.com>2021-04-10 11:54:38 +1000
commite42e7e5cbd9d075ee24ae8f91ba9e12bdd42fafc (patch)
tree61d65a544c056b3bf0384cf6954b81b292eb4b07 /pkg/commands/files_test.go
parent93fac1f3124f87009091230f61cc13b5e5473cb5 (diff)
fix commit amend
Diffstat (limited to 'pkg/commands/files_test.go')
-rw-r--r--pkg/commands/files_test.go467
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))
+ })
+ }
+}