package git_commands import ( "testing" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/config" "github.com/stretchr/testify/assert" ) func TestCommitRewordCommit(t *testing.T) { type scenario struct { testName string runner *oscommands.FakeCmdObjRunner summary string description string } scenarios := []scenario{ { "Single line reword", oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"commit", "--allow-empty", "--amend", "--only", "-m", "test"}, "", nil), "test", "", }, { "Multi line reword", oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"commit", "--allow-empty", "--amend", "--only", "-m", "test", "-m", "line 2\nline 3"}, "", nil), "test", "line 2\nline 3", }, } for _, s := range scenarios { s := s t.Run(s.testName, func(t *testing.T) { instance := buildCommitCommands(commonDeps{runner: s.runner}) assert.NoError(t, instance.RewordLastCommit(s.summary, s.description)) s.runner.CheckForMissingCalls() }) } } func TestCommitResetToCommit(t *testing.T) { runner := oscommands.NewFakeRunner(t). ExpectGitArgs([]string{"reset", "--hard", "78976bc"}, "", nil) instance := buildCommitCommands(commonDeps{runner: runner}) assert.NoError(t, instance.ResetToCommit("78976bc", "hard", []string{})) runner.CheckForMissingCalls() } func TestCommitCommitCmdObj(t *testing.T) { type scenario struct { testName string summary string description string configSignoff bool configSkipHookPrefix string expectedArgs []string } scenarios := []scenario{ { testName: "Commit", summary: "test", configSignoff: false, configSkipHookPrefix: "", expectedArgs: []string{"commit", "-m", "test"}, }, { testName: "Commit with --no-verify flag", summary: "WIP: test", configSignoff: false, configSkipHookPrefix: "WIP", expectedArgs: []string{"commit", "--no-verify", "-m", "WIP: test"}, }, { testName: "Commit with multiline message", summary: "line1", description: "line2", configSignoff: false, configSkipHookPrefix: "", expectedArgs: []string{"commit", "-m", "line1", "-m", "line2"}, }, { testName: "Commit with signoff", summary: "test", configSignoff: true, configSkipHookPrefix: "", expectedArgs: []string{"commit", "--signoff", "-m", "test"}, }, { testName: "Commit with signoff and no-verify", summary: "WIP: test", configSignoff: true, configSkipHookPrefix: "WIP", expectedArgs: []string{"commit", "--no-verify", "--signoff", "-m", "WIP: test"}, }, } for _, s := range scenarios { s := s t.Run(s.testName, func(t *testing.T) { userConfig := config.GetDefaultConfig() userConfig.Git.Commit.SignOff = s.configSignoff userConfig.Git.SkipHookPrefix = s.configSkipHookPrefix runner := oscommands.NewFakeRunner(t).ExpectGitArgs(s.expectedArgs, "", nil) instance := buildCommitCommands(commonDeps{userConfig: userConfig, runner: runner}) assert.NoError(t, instance.CommitCmdObj(s.summary, s.description).Run()) runner.CheckForMissingCalls() }) } } func TestCommitCommitEditorCmdObj(t *testing.T) { type scenario struct { testName string configSignoff bool expected []string } scenarios := []scenario{ { testName: "Commit using editor", configSignoff: false, expected: []string{"commit"}, }, { testName: "Commit with --signoff", configSignoff: true, expected: []string{"commit", "--signoff"}, }, } for _, s := range scenarios { s := s t.Run(s.testName, func(t *testing.T) { userConfig := config.GetDefaultConfig() userConfig.Git.Commit.SignOff = s.configSignoff runner := oscommands.NewFakeRunner(t).ExpectGitArgs(s.expected, "", nil) instance := buildCommitCommands(commonDeps{userConfig: userConfig, runner: runner}) assert.NoError(t, instance.CommitEditorCmdObj().Run()) runner.CheckForMissingCalls() }) } } func TestCommitCreateFixupCommit(t *testing.T) { type scenario struct { testName string sha string runner *oscommands.FakeCmdObjRunner test func(error) } scenarios := []scenario{ { testName: "valid case", sha: "12345", runner: oscommands.NewFakeRunner(t). ExpectGitArgs([]string{"commit", "--fixup=12345"}, "", nil), test: func(err error) { assert.NoError(t, err) }, }, } for _, s := range scenarios { s := s t.Run(s.testName, func(t *testing.T) { instance := buildCommitCommands(commonDeps{runner: s.runner}) s.test(instance.CreateFixupCommit(s.sha)) s.runner.CheckForMissingCalls() }) } } func TestCommitShowCmdObj(t *testing.T) { type scenario struct { testName string filterPath string contextSize int ignoreWhitespace bool expected []string } scenarios := []scenario{ { testName: "Default case without filter path", filterPath: "", contextSize: 3, ignoreWhitespace: false, expected: []string{"show", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890"}, }, { testName: "Default case with filter path", filterPath: "file.txt", contextSize: 3, ignoreWhitespace: false, expected: []string{"show", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890", "--", "file.txt"}, }, { testName: "Show diff with custom context size", filterPath: "", contextSize: 77, ignoreWhitespace: false, expected: []string{"show", "--submodule", "--color=always", "--unified=77", "--stat", "--decorate", "-p", "1234567890"}, }, { testName: "Show diff, ignoring whitespace", filterPath: "", contextSize: 77, ignoreWhitespace: true, expected: []string{"show", "--submodule", "--color=always", "--unified=77", "--stat", "--decorate", "-p", "1234567890", "--ignore-all-space"}, }, } for _, s := range scenarios { s := s t.Run(s.testName, func(t *testing.T) { userConfig := config.GetDefaultConfig() userConfig.Git.DiffContextSize = s.contextSize runner := oscommands.NewFakeRunner(t).ExpectGitArgs(s.expected, "", nil) instance := buildCommitCommands(commonDeps{userConfig: userConfig, runner: runner}) assert.NoError(t, instance.ShowCmdObj("1234567890", s.filterPath, s.ignoreWhitespace).Run()) runner.CheckForMissingCalls() }) } } func TestGetCommitMsg(t *testing.T) { type scenario struct { testName string input string expectedOutput string } scenarios := []scenario{ { "empty", ` commit deadbeef`, ``, }, { "no line breaks (single line)", `commit deadbeef use generics to DRY up context code`, `use generics to DRY up context code`, }, { "with line breaks", `commit deadbeef Merge pull request #1750 from mark2185/fix-issue-template 'git-rev parse' should be 'git rev-parse'`, `Merge pull request #1750 from mark2185/fix-issue-template 'git-rev parse' should be 'git rev-parse'`, }, } for _, s := range scenarios { s := s t.Run(s.testName, func(t *testing.T) { instance := buildCommitCommands(commonDeps{ runner: oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"rev-list", "--format=%B", "--max-count=1", "deadbeef"}, s.input, nil), }) output, err := instance.GetCommitMessage("deadbeef") assert.NoError(t, err) assert.Equal(t, s.expectedOutput, output) }) } } func TestGetCommitMessageFromHistory(t *testing.T) { type scenario struct { testName string runner *oscommands.FakeCmdObjRunner test func(string, error) } scenarios := []scenario{ { "Empty message", oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"log", "-1", "--skip=2", "--pretty=%H"}, "", nil).ExpectGitArgs([]string{"rev-list", "--format=%B", "--max-count=1"}, "", nil), func(output string, err error) { assert.Error(t, err) }, }, { "Default case to retrieve a commit in history", oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"log", "-1", "--skip=2", "--pretty=%H"}, "sha3 \n", nil).ExpectGitArgs([]string{"rev-list", "--format=%B", "--max-count=1", "sha3"}, `commit sha3 use generics to DRY up context code`, nil), func(output string, err error) { assert.NoError(t, err) assert.Equal(t, "use generics to DRY up context code", output) }, }, } for _, s := range scenarios { s := s t.Run(s.testName, func(t *testing.T) { instance := buildCommitCommands(commonDeps{runner: s.runner}) output, err := instance.GetCommitMessageFromHistory(2) s.test(output, err) }) } }