branch

package
v0.49.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 13, 2025 License: MIT Imports: 4 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var CheckoutAutostash = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Check out a branch that requires performing autostash",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.CreateFileAndAdd("file", "a\n\nb")
		shell.Commit("add file")
		shell.UpdateFileAndAdd("file", "a\n\nc")
		shell.Commit("edit last line")

		shell.Checkout("HEAD^")
		shell.UpdateFile("file", "b\n\nb")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Files().
			Lines(
				Contains("file"),
			)

		t.Views().Branches().
			Focus().
			Lines(
				MatchesRegexp(`\*.*HEAD`).IsSelected(),
				Contains("master"),
			).
			NavigateToLine(Contains("master")).
			PressPrimaryAction()

		t.ExpectPopup().Confirmation().
			Title(Contains("Autostash?")).
			Content(Contains("You must stash and pop your changes to bring them across. Do this automatically? (enter/esc)")).
			Confirm()

		t.Views().Branches().
			Lines(
				Contains("master").IsSelected(),
			)

		t.Git().CurrentBranchName("master")

		t.Views().Files().
			Lines(
				Contains("file"),
			)
	},
})
View Source
var CheckoutByName = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Try to checkout branch by name. Verify that it also works on the branch with the special name @.",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.
			CreateNCommits(3).
			NewBranch("@").
			Checkout("master").
			EmptyCommit("blah")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Branches().
			Focus().
			Lines(
				Contains("master").IsSelected(),
				Contains("@"),
			).
			SelectNextItem().
			Press(keys.Branches.CheckoutBranchByName).
			Tap(func() {
				t.ExpectPopup().Prompt().Title(Equals("Branch name:")).Type("new-branch").Confirm()

				t.ExpectPopup().Alert().Title(Equals("Branch not found")).Content(Equals("Branch not found. Create a new branch named new-branch?")).Confirm()
			}).
			Lines(
				MatchesRegexp(`\*.*new-branch`).IsSelected(),
				Contains("master"),
				Contains("@"),
			)
	},
})
View Source
var CreateTag = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Create a new tag on branch",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.
			CreateNCommits(10).
			NewBranch("new-branch").
			EmptyCommit("new commit")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Branches().
			Focus().
			Lines(
				MatchesRegexp(`\*\s*new-branch`).IsSelected(),
				MatchesRegexp(`master`),
			).
			SelectNextItem().
			Press(keys.Branches.CreateTag)

		t.ExpectPopup().CommitMessagePanel().
			Title(Equals("Tag name")).
			Type("new-tag").
			Confirm()

		t.Views().Tags().Focus().
			Lines(
				MatchesRegexp(`new-tag`).IsSelected(),
			)

		t.Git().
			TagNamesAt("HEAD", []string{}).
			TagNamesAt("master", []string{"new-tag"})
	},
})
View Source
var Delete = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Try all combination of local and remote branch deletions",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.
			CloneIntoRemote("origin").
			EmptyCommit("blah").
			NewBranch("branch-one").
			EmptyCommit("on branch-one 01").
			PushBranchAndSetUpstream("origin", "branch-one").
			EmptyCommit("on branch-one 02").
			Checkout("master").
			Merge("branch-one").
			NewBranch("branch-two").
			EmptyCommit("on branch-two 01").
			PushBranchAndSetUpstream("origin", "branch-two").
			NewBranchFrom("branch-three", "master").
			EmptyCommit("on branch-three 01").
			NewBranch("current-head").
			EmptyCommit("on current-head").
			NewBranchFrom("branch-four", "master").
			EmptyCommit("on branch-four 01").
			PushBranchAndSetUpstream("origin", "branch-four").
			EmptyCommit("on branch-four 02").
			NewBranchFrom("branch-five", "master").
			EmptyCommit("on branch-five 01").
			PushBranchAndSetUpstream("origin", "branch-five").
			NewBranchFrom("branch-six", "master").
			EmptyCommit("on branch-six 01").
			PushBranchAndSetUpstream("origin", "branch-six").
			EmptyCommit("on branch-six 02").
			Checkout("current-head")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Branches().
			Focus().
			Lines(
				Contains("current-head").IsSelected(),
				Contains("branch-six ↑1"),
				Contains("branch-five ✓"),
				Contains("branch-four ↑1"),
				Contains("branch-three"),
				Contains("branch-two ✓"),
				Contains("master"),
				Contains("branch-one ↑1"),
			).
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Tooltip(Contains("You cannot delete the checked out branch!")).
					Title(Equals("Delete branch 'current-head'?")).
					Select(Contains("Delete local branch")).
					Confirm().
					Tap(func() {
						t.ExpectToast(Contains("You cannot delete the checked out branch!"))
					}).
					Cancel()
			}).
			NavigateToLine(Contains("branch-four")).
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Title(Equals("Delete branch 'branch-four'?")).
					Select(Contains("Delete local branch")).
					Confirm()
				t.ExpectPopup().
					Confirmation().
					Title(Equals("Force delete branch")).
					Content(Equals("'branch-four' is not fully merged. Are you sure you want to delete it?")).
					Confirm()
			}).
			Lines(
				Contains("current-head"),
				Contains("branch-six ↑1"),
				Contains("branch-five ✓"),
				Contains("branch-three").IsSelected(),
				Contains("branch-two ✓"),
				Contains("master"),
				Contains("branch-one ↑1"),
			).
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Title(Equals("Delete branch 'branch-three'?")).
					Select(Contains("Delete local branch")).
					Confirm()
			}).
			Lines(
				Contains("current-head"),
				Contains("branch-six ↑1"),
				Contains("branch-five ✓"),
				Contains("branch-two ✓").IsSelected(),
				Contains("master"),
				Contains("branch-one ↑1"),
			).
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Title(Equals("Delete branch 'branch-two'?")).
					Select(Contains("Delete local branch")).
					Confirm()
			}).
			Lines(
				Contains("current-head"),
				Contains("branch-six ↑1"),
				Contains("branch-five ✓"),
				Contains("master").IsSelected(),
				Contains("branch-one ↑1"),
			).
			SelectNextItem().
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Title(Equals("Delete branch 'branch-one'?")).
					Select(Contains("Delete remote branch")).
					Confirm()
			}).
			Tap(func() {
				t.ExpectPopup().
					Confirmation().
					Title(Equals("Delete branch 'branch-one'?")).
					Content(Equals("Are you sure you want to delete the remote branch 'branch-one' from 'origin'?")).
					Confirm()
			}).
			Tap(func() {
				checkRemoteBranches(t, keys, "origin", []string{
					"branch-five",
					"branch-four",
					"branch-six",
					"branch-two",
				})
			}).
			Lines(
				Contains("current-head"),
				Contains("branch-six ↑1"),
				Contains("branch-five ✓"),
				Contains("master"),
				Contains("branch-one (upstream gone)").IsSelected(),
			).
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Title(Equals("Delete branch 'branch-one'?")).
					Select(Contains("Delete local branch")).
					Confirm()
			}).
			Lines(
				Contains("current-head"),
				Contains("branch-six ↑1"),
				Contains("branch-five ✓"),
				Contains("master").IsSelected(),
			).
			NavigateToLine(Contains("branch-six")).
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Title(Equals("Delete branch 'branch-six'?")).
					Select(Contains("Delete local and remote branch")).
					Confirm()
				t.ExpectPopup().
					Confirmation().
					Title(Equals("Delete local and remote branch")).
					Content(Contains("Are you sure you want to delete both 'branch-six' from your machine, and 'branch-six' from 'origin'?").
						Contains("'branch-six' is not fully merged. Are you sure you want to delete it?")).
					Confirm()
			}).
			Lines(
				Contains("current-head"),
				Contains("branch-five ✓").IsSelected(),
				Contains("master"),
			).
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Title(Equals("Delete branch 'branch-five'?")).
					Select(Contains("Delete local and remote branch")).
					Confirm()
				t.ExpectPopup().
					Confirmation().
					Title(Equals("Delete local and remote branch")).
					Content(Equals("Are you sure you want to delete both 'branch-five' from your machine, and 'branch-five' from 'origin'?").
						DoesNotContain("not fully merged")).
					Confirm()
			}).
			Lines(
				Contains("current-head"),
				Contains("master").IsSelected(),
			)
	},
})
View Source
var DeleteMultiple = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Try some combinations of local and remote branch deletions with a range selection of branches",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig: func(config *config.AppConfig) {
		config.GetAppState().LocalBranchSortOrder = "alphabetic"
	},
	SetupRepo: func(shell *Shell) {
		shell.
			CloneIntoRemote("origin").
			CloneIntoRemote("other-remote").
			EmptyCommit("blah").
			NewBranch("branch-01").
			EmptyCommit("on branch-01 01").
			PushBranchAndSetUpstream("origin", "branch-01").
			EmptyCommit("on branch-01 02").
			NewBranch("branch-02").
			EmptyCommit("on branch-02 01").
			PushBranchAndSetUpstream("origin", "branch-02").
			NewBranchFrom("branch-03", "master").
			EmptyCommit("on branch-03 01").
			NewBranch("current-head").
			EmptyCommit("on current-head").
			NewBranchFrom("branch-04", "master").
			EmptyCommit("on branch-04 01").
			PushBranchAndSetUpstream("other-remote", "branch-04").
			EmptyCommit("on branch-04 02").
			NewBranchFrom("branch-05", "master").
			EmptyCommit("on branch-05 01").
			PushBranchAndSetUpstream("origin", "branch-05").
			NewBranchFrom("branch-06", "master").
			EmptyCommit("on branch-06 01").
			PushBranch("origin", "branch-06").
			PushBranchAndSetUpstream("other-remote", "branch-06").
			EmptyCommit("on branch-06 02").
			Checkout("current-head")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Branches().
			Focus().
			Lines(
				Contains("current-head").IsSelected(),
				Contains("branch-01 ↑1"),
				Contains("branch-02 ✓"),
				Contains("branch-03"),
				Contains("branch-04 ↑1"),
				Contains("branch-05 ✓"),
				Contains("branch-06 ↑1"),
				Contains("master"),
			).
			Press(keys.Universal.RangeSelectDown).
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Tooltip(Contains("You cannot delete the checked out branch!")).
					Title(Equals("Delete selected branches?")).
					Select(Contains("Delete local branches")).
					Confirm().
					Tap(func() {
						t.ExpectToast(Contains("You cannot delete the checked out branch!"))
					}).
					Cancel()
			}).
			NavigateToLine(Contains("branch-03")).
			Press(keys.Universal.RangeSelectDown).
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Title(Equals("Delete selected branches?")).
					Select(Contains("Delete local branches")).
					Confirm()
				t.ExpectPopup().
					Confirmation().
					Title(Equals("Force delete branch")).
					Content(Equals("Some of the selected branches are not fully merged. Are you sure you want to delete them?")).
					Confirm()
			}).
			Lines(
				Contains("current-head"),
				Contains("branch-01 ↑1"),
				Contains("branch-02 ✓"),
				Contains("branch-05 ✓").IsSelected(),
				Contains("branch-06 ↑1"),
				Contains("master"),
			).
			NavigateToLine(Contains("branch-05")).
			Press(keys.Universal.RangeSelectDown).
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Title(Equals("Delete selected branches?")).
					Select(Contains("Delete remote branches")).
					Confirm()
			}).
			Tap(func() {
				t.ExpectPopup().
					Confirmation().
					Title(Equals("Delete selected branches?")).
					Content(Equals("Are you sure you want to delete the remote branches of the selected branches from their respective remotes?")).
					Confirm()
			}).
			Tap(func() {
				checkRemoteBranches(t, keys, "origin", []string{
					"branch-01",
					"branch-02",
					"branch-06",
				})
				checkRemoteBranches(t, keys, "other-remote", []string{
					"branch-04",
				})
			}).
			Lines(
				Contains("current-head"),
				Contains("branch-01 ↑1"),
				Contains("branch-02 ✓"),
				Contains("branch-05 (upstream gone)").IsSelected(),
				Contains("branch-06 (upstream gone)").IsSelected(),
				Contains("master"),
			).
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Title(Equals("Delete selected branches?")).
					Select(Contains("Delete local and remote branches")).
					Confirm().
					Tap(func() {
						t.ExpectToast(Contains("Some of the selected branches have no upstream (or the upstream is not stored locally)"))
					}).
					Cancel()
			}).
			NavigateToLine(Contains("branch-01")).
			Press(keys.Universal.RangeSelectDown).
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Title(Equals("Delete selected branches?")).
					Select(Contains("Delete local and remote branches")).
					Confirm()
				t.ExpectPopup().
					Confirmation().
					Title(Equals("Delete local and remote branch")).
					Content(Contains("Are you sure you want to delete both the selected branches from your machine, and their remote branches from their respective remotes?").
						Contains("Some of the selected branches are not fully merged. Are you sure you want to delete them?")).
					Confirm()
			}).
			Lines(
				Contains("current-head"),
				Contains("branch-05 (upstream gone)").IsSelected(),
				Contains("branch-06 (upstream gone)"),
				Contains("master"),
			).
			Tap(func() {
				checkRemoteBranches(t, keys, "origin", []string{
					"branch-06",
				})
				checkRemoteBranches(t, keys, "other-remote", []string{
					"branch-04",
				})
			})
	},
})
View Source
var DeleteRemoteBranchWithCredentialPrompt = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Delete a remote branch where credentials are required",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig: func(config *config.AppConfig) {
	},
	SetupRepo: func(shell *Shell) {
		shell.EmptyCommit("one")

		shell.CloneIntoRemote("origin")

		shell.NewBranch("mybranch")

		shell.PushBranchAndSetUpstream("origin", "mybranch")

		shell.CopyHelpFile("pre-push", ".git/hooks/pre-push")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		deleteBranch := func() {
			t.Views().Branches().
				Focus().
				Press(keys.Universal.Remove)

			t.ExpectPopup().
				Menu().
				Title(Equals("Delete branch 'mybranch'?")).
				Select(Contains("Delete remote branch")).
				Confirm()

			t.ExpectPopup().
				Confirmation().
				Title(Equals("Delete branch 'mybranch'?")).
				Content(Equals("Are you sure you want to delete the remote branch 'mybranch' from 'origin'?")).
				Confirm()
		}

		t.Views().Status().Content(Equals("✓ repo → mybranch"))

		deleteBranch()

		t.ExpectPopup().Prompt().
			Title(Equals("Username")).
			Type("username").
			Confirm()

		t.ExpectPopup().Prompt().
			Title(Equals("Password")).
			Type("incorrect password").
			Confirm()

		t.ExpectPopup().Alert().
			Title(Equals("Error")).
			Content(Contains("incorrect username/password")).
			Confirm()

		t.Views().Status().Content(Equals("✓ repo → mybranch"))

		deleteBranch()

		t.ExpectPopup().Prompt().
			Title(Equals("Username")).
			Type("username").
			Confirm()

		t.ExpectPopup().Prompt().
			Title(Equals("Password")).
			Type("password").
			Confirm()

		t.Views().Status().Content(Equals("(upstream gone) repo → mybranch"))
		t.Views().Branches().TopLines(Contains("mybranch (upstream gone)"))
	},
})
View Source
var DeleteRemoteBranchWithDifferentName = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Delete a remote branch that has a different name than the local branch",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig: func(config *config.AppConfig) {
	},
	SetupRepo: func(shell *Shell) {
		shell.EmptyCommit("one")
		shell.CloneIntoRemote("origin")
		shell.NewBranch("mybranch-local")
		shell.PushBranchAndSetUpstream("origin", "mybranch-local:mybranch-remote")
		shell.Checkout("master")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Branches().
			Focus().
			Lines(
				Contains("master").IsSelected(),
				Contains("mybranch-local ✓"),
			).
			SelectNextItem().
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Title(Equals("Delete branch 'mybranch-local'?")).
					Select(Contains("Delete remote branch")).
					Confirm()
			}).
			Tap(func() {
				t.ExpectPopup().
					Confirmation().
					Title(Equals("Delete branch 'mybranch-remote'?")).
					Content(Equals("Are you sure you want to delete the remote branch 'mybranch-remote' from 'origin'?")).
					Confirm()
			}).
			Lines(
				Contains("master"),
				Contains("mybranch-local (upstream gone)").IsSelected(),
			)
	},
})
View Source
var DeleteWhileFiltering = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Delete a local branch while there's a filter in the branches panel",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig: func(config *config.AppConfig) {
		config.GetAppState().LocalBranchSortOrder = "alphabetic"
	},
	SetupRepo: func(shell *Shell) {
		shell.EmptyCommit("one")
		shell.NewBranch("branch1")
		shell.NewBranch("branch2")
		shell.Checkout("master")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Branches().
			Focus().
			Lines(
				Contains("master").IsSelected(),
				Contains("branch1"),
				Contains("branch2"),
			).
			FilterOrSearch("branch").
			Lines(
				Contains("branch1").IsSelected(),
				Contains("branch2"),
			).
			SelectNextItem().
			Press(keys.Universal.Remove).
			Tap(func() {
				t.ExpectPopup().
					Menu().
					Title(Equals("Delete branch 'branch2'?")).
					Select(Contains("Delete local branch")).
					Confirm()
			}).
			Lines(
				Contains("branch1").IsSelected(),
			)
	},
})

Regression test for deleting the last branch in the unfiltered list while filtering is on. This used to cause a segfault.

View Source
var DetachedHead = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Create a new branch on detached head",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.
			CreateNCommits(10).
			Checkout("HEAD^")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Branches().
			Focus().
			Lines(
				MatchesRegexp(`\*.*HEAD`).IsSelected(),
				MatchesRegexp(`master`),
			).
			Press(keys.Universal.New)

		t.ExpectPopup().Prompt().
			Title(MatchesRegexp(`^New branch name \(branch is off of '[0-9a-f]+'\)$`)).
			Type("new-branch").
			Confirm()

		t.Views().Branches().
			Lines(
				MatchesRegexp(`\* new-branch`).IsSelected(),
				MatchesRegexp(`master`),
			)

		t.Git().CurrentBranchName("new-branch")
	},
})
View Source
var NewBranchAutostash = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Create a new branch that requires performing autostash",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.CreateFileAndAdd("file", "a\n\nb")
		shell.Commit("add file")
		shell.UpdateFileAndAdd("file", "a\n\nc")
		shell.Commit("edit last line")

		shell.Checkout("HEAD^")
		shell.UpdateFile("file", "b\n\nb")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Files().
			Lines(
				Contains("file"),
			)

		t.Views().Branches().
			Focus().
			Lines(
				MatchesRegexp(`\*.*HEAD`).IsSelected(),
				Contains("master"),
			).
			NavigateToLine(Contains("master")).
			Press(keys.Universal.New)

		t.ExpectPopup().Prompt().
			Title(Contains("New branch name (branch is off of 'master')")).
			Type("new-branch").
			Confirm()

		t.ExpectPopup().Confirmation().
			Title(Contains("Autostash?")).
			Content(Contains("You must stash and pop your changes to bring them across. Do this automatically? (enter/esc)")).
			Confirm()

		t.Views().Branches().
			Lines(
				Contains("new-branch").IsSelected(),
				Contains("master"),
			)

		t.Git().CurrentBranchName("new-branch")

		t.Views().Files().
			Lines(
				Contains("file"),
			)
	},
})
View Source
var NewBranchFromRemoteTrackingDifferentName = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Set tracking information when creating a new branch from a remote branch",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.EmptyCommit("commit")
		shell.NewBranch("other_branch")
		shell.CloneIntoRemote("origin")
		shell.Checkout("master")
		shell.RunCommand([]string{"git", "branch", "-D", "other_branch"})
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Remotes().
			Focus().
			Lines(
				Contains("origin").IsSelected(),
			).
			PressEnter()

		t.Views().RemoteBranches().
			IsFocused().
			Lines(
				Contains("master").IsSelected(),
				Contains("other_branch"),
			).
			SelectNextItem().
			Press(keys.Universal.New)

		t.ExpectPopup().Prompt().
			Title(Equals("New branch name (branch is off of 'origin/other_branch')")).
			Clear().
			Type("different_name").
			Confirm()

		t.Views().Branches().
			Focus().
			Lines(
				Contains("different_name").DoesNotContain("✓"),
				Contains("master"),
			)
	},
})
View Source
var NewBranchFromRemoteTrackingSameName = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Set tracking information when creating a new branch from a remote branch",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.EmptyCommit("commit")
		shell.NewBranch("other_branch")
		shell.CloneIntoRemote("origin")
		shell.Checkout("master")
		shell.RunCommand([]string{"git", "branch", "-D", "other_branch"})
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Remotes().
			Focus().
			Lines(
				Contains("origin").IsSelected(),
			).
			PressEnter()

		t.Views().RemoteBranches().
			IsFocused().
			Lines(
				Contains("master").IsSelected(),
				Contains("other_branch"),
			).
			SelectNextItem().
			Press(keys.Universal.New)

		t.ExpectPopup().Prompt().
			Title(Equals("New branch name (branch is off of 'origin/other_branch')")).
			Confirm()

		t.Views().Branches().
			Focus().
			Lines(
				Contains("other_branch").Contains("✓"),
				Contains("master"),
			)
	},
})
View Source
var NewBranchWithPrefix = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Creating a new branch from a commit with a default name",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig: func(cfg *config.AppConfig) {
		cfg.GetUserConfig().Git.BranchPrefix = "myprefix/"
	},
	SetupRepo: func(shell *Shell) {
		shell.
			EmptyCommit("commit 1")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().
			Focus().
			Lines(
				Contains("commit 1").IsSelected(),
			).
			SelectNextItem().
			Press(keys.Universal.New).
			Tap(func() {
				branchName := "my-branch-name"
				t.ExpectPopup().Prompt().Title(Contains("New branch name")).Type(branchName).Confirm()
				t.Git().CurrentBranchName("myprefix/" + branchName)
			})
	},
})
View Source
var NewBranchWithPrefixUsingRunCommand = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Creating a new branch with a branch prefix using a runCommand",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig: func(cfg *config.AppConfig) {
		cfg.GetUserConfig().Git.BranchPrefix = "myprefix/{{ runCommand \"echo dynamic\" }}/"
	},
	SetupRepo: func(shell *Shell) {
		shell.
			EmptyCommit("commit 1")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().
			Focus().
			Lines(
				Contains("commit 1").IsSelected(),
			).
			SelectNextItem().
			Press(keys.Universal.New).
			Tap(func() {
				t.ExpectPopup().Prompt().
					Title(Contains("New branch name")).
					InitialText(Equals("myprefix/dynamic/")).
					Type("my-branch").
					Confirm()
				t.Git().CurrentBranchName("myprefix/dynamic/my-branch")
			})
	},
})
View Source
var OpenPullRequestInvalidTargetRemoteName = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Open up a pull request, specifying a non-existing target remote",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {

		shell.CreateFileAndAdd("file", "content1")
		shell.Commit("one")

		shell.NewBranch("branch-1")

		shell.CloneIntoRemote("upstream")
		shell.CloneIntoRemote("origin")

		shell.SetBranchUpstream("branch-1", "origin/branch-1")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {

		t.Views().
			Branches().
			Focus().
			Press(keys.Branches.ViewPullRequestOptions)

		t.ExpectPopup().
			Menu().
			Title(Equals("View create pull request options")).
			Select(Contains("Select branch")).
			Confirm()

		t.ExpectPopup().
			Prompt().
			Title(Equals("Select target remote")).
			Type("non-existing-remote").
			Confirm()

		t.ExpectPopup().Alert().
			Title(Equals("Error")).
			Content(Contains("A remote named 'non-existing-remote' does not exist")).
			Confirm()
	},
})
View Source
var OpenPullRequestNoUpstream = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Open up a pull request with a missing upstream branch",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo:    func(shell *Shell) {},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().
			Branches().
			Focus().
			Press(keys.Branches.CreatePullRequest)

		t.ExpectPopup().Alert().
			Title(Equals("Error")).
			Content(Contains("Cannot open a pull request for a branch with no upstream")).
			Confirm()
	},
})
View Source
var OpenPullRequestSelectRemoteAndTargetBranch = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Open up a pull request, specifying a remote and target branch",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig: func(config *config.AppConfig) {
		config.GetUserConfig().OS.OpenLink = "echo {{link}} > /tmp/openlink"
	},
	SetupRepo: func(shell *Shell) {

		shell.CreateFileAndAdd("file", "content1")
		shell.Commit("one")

		shell.NewBranch("branch-1")
		shell.CloneIntoRemote("upstream")

		shell.NewBranch("branch-2")
		shell.CloneIntoRemote("origin")

		shell.SetBranchUpstream("branch-2", "origin/branch-2")

		shell.RunCommand([]string{"git", "remote", "set-url", "origin", "https://github.com/my-personal-fork/lazygit"})
		shell.RunCommand([]string{"git", "remote", "set-url", "upstream", "https://github.com/jesseduffield/lazygit"})
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {

		t.Views().
			Branches().
			Focus().
			Press(keys.Branches.ViewPullRequestOptions)

		t.ExpectPopup().
			Menu().
			Title(Equals("View create pull request options")).
			Select(Contains("Select branch")).
			Confirm()

		t.ExpectPopup().
			Prompt().
			Title(Equals("Select target remote")).
			SuggestionLines(
				Equals("origin"),
				Equals("upstream")).
			ConfirmSuggestion(Equals("upstream"))

		t.ExpectPopup().
			Prompt().
			Title(Equals("branch-2 → upstream/")).
			SuggestionLines(
				Equals("branch-1"),
				Equals("master")).
			ConfirmSuggestion(Equals("master"))

		t.FileSystem().FileContent(
			"/tmp/openlink",
			Equals("https://github.com/my-personal-fork/lazygit/compare/master...branch-2?expand=1\n"))
	},
})
View Source
var OpenWithCliArg = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Open straight to branches panel using a CLI arg",
	ExtraCmdArgs: []string{"branch"},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Branches().IsFocused()
	},
})
View Source
var Rebase = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Rebase onto another branch, deal with the conflicts.",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shared.MergeConflictsSetup(shell)
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().TopLines(
			Contains("first change"),
			Contains("original"),
		)

		t.Views().Branches().
			Focus().
			Lines(
				Contains("first-change-branch"),
				Contains("second-change-branch"),
				Contains("original-branch"),
			).
			SelectNextItem().
			Press(keys.Branches.RebaseBranch)

		t.ExpectPopup().Menu().
			Title(Equals("Rebase 'first-change-branch'")).
			Select(Contains("Simple rebase")).
			Confirm()

		t.Common().AcknowledgeConflicts()

		t.Views().Files().
			IsFocused().
			SelectedLine(Contains("file")).
			PressEnter()

		t.Views().MergeConflicts().
			IsFocused().
			PressPrimaryAction()

		t.Views().Information().Content(Contains("Rebasing"))

		t.Common().ContinueOnConflictsResolved()

		t.Views().Information().Content(DoesNotContain("Rebasing"))

		t.Views().Commits().TopLines(
			Contains("second-change-branch unrelated change"),
			Contains("second change"),
			Contains("original"),
		)
	},
})
View Source
var RebaseAbortOnConflict = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Rebase onto another branch, abort when there are conflicts.",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shared.MergeConflictsSetup(shell)
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().TopLines(
			Contains("first change"),
			Contains("original"),
		)

		t.Views().Branches().
			Focus().
			Lines(
				Contains("first-change-branch"),
				Contains("second-change-branch"),
				Contains("original-branch"),
			).
			SelectNextItem().
			Press(keys.Branches.RebaseBranch)

		t.ExpectPopup().Menu().
			Title(Equals("Rebase 'first-change-branch'")).
			Select(Contains("Simple rebase")).
			Confirm()

		t.ExpectPopup().Menu().
			Title(Equals("Conflicts!")).
			Select(Contains("Abort the rebase")).
			Confirm()

		t.Views().Branches().
			IsFocused()

		t.Views().Files().
			IsEmpty()
	},
})
View Source
var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Rebase onto another branch, deal with the conflicts. Also mark a commit to be dropped before continuing.",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shared.MergeConflictsSetup(shell)

		shell.EmptyCommit("to remove")
		shell.EmptyCommit("to keep")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().
			TopLines(
				Contains("to keep"),
				Contains("to remove"),
				Contains("first change"),
				Contains("original"),
			)

		t.Views().Branches().
			Focus().
			Lines(
				Contains("first-change-branch").IsSelected(),
				Contains("second-change-branch"),
				Contains("original-branch"),
			).
			SelectNextItem().
			Press(keys.Branches.RebaseBranch)

		t.ExpectPopup().Menu().
			Title(Equals("Rebase 'first-change-branch'")).
			Select(Contains("Simple rebase")).
			Confirm()

		t.Views().Information().Content(Contains("Rebasing"))

		t.Common().AcknowledgeConflicts()

		t.Views().Files().IsFocused().
			SelectedLine(MatchesRegexp("UU.*file"))

		t.Views().Commits().
			Focus().
			TopLines(
				MatchesRegexp(`pick.*to keep`).IsSelected(),
				MatchesRegexp(`pick.*to remove`),
				MatchesRegexp(`conflict.*YOU ARE HERE.*first change`),
				MatchesRegexp("second-change-branch unrelated change"),
				MatchesRegexp("second change"),
				MatchesRegexp("original"),
			).
			SelectNextItem().
			Press(keys.Universal.Remove).
			TopLines(
				MatchesRegexp(`pick.*to keep`),
				MatchesRegexp(`drop.*to remove`).IsSelected(),
				MatchesRegexp(`conflict.*YOU ARE HERE.*first change`),
				MatchesRegexp("second-change-branch unrelated change"),
				MatchesRegexp("second change"),
				MatchesRegexp("original"),
			)

		t.Views().Files().
			Focus().
			PressEnter()

		t.Views().MergeConflicts().
			IsFocused().
			PressPrimaryAction()

		t.Common().ContinueOnConflictsResolved()

		t.Views().Information().Content(DoesNotContain("Rebasing"))

		t.Views().Commits().TopLines(
			Contains("to keep"),
			Contains("second-change-branch unrelated change").IsSelected(),
			Contains("second change"),
			Contains("original"),
		)
	},
})
View Source
var RebaseCancelOnConflict = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Rebase onto another branch, cancel when there are conflicts.",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shared.MergeConflictsSetup(shell)
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().TopLines(
			Contains("first change"),
			Contains("original"),
		)

		t.Views().Branches().
			Focus().
			Lines(
				Contains("first-change-branch"),
				Contains("second-change-branch"),
				Contains("original-branch"),
			).
			SelectNextItem().
			Press(keys.Branches.RebaseBranch)

		t.ExpectPopup().Menu().
			Title(Equals("Rebase 'first-change-branch'")).
			Select(Contains("Simple rebase")).
			Confirm()

		t.ExpectPopup().Menu().
			Title(Equals("Conflicts!")).
			Select(Contains("Abort the rebase")).
			Cancel()

		t.Views().Branches().
			IsFocused()

		t.Views().Files().
			Lines(
				Contains("UU file"),
			)
	},
})
View Source
var RebaseConflictsFixBuildErrors = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Rebase onto another branch, deal with the conflicts. While continue prompt is showing, fix build errors; get another prompt when continuing.",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shared.MergeConflictsSetup(shell)
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().TopLines(
			Contains("first change"),
			Contains("original"),
		)

		t.Views().Branches().
			Focus().
			Lines(
				Contains("first-change-branch"),
				Contains("second-change-branch"),
				Contains("original-branch"),
			).
			SelectNextItem().
			Press(keys.Branches.RebaseBranch)

		t.ExpectPopup().Menu().
			Title(Equals("Rebase 'first-change-branch'")).
			Select(Contains("Simple rebase")).
			Confirm()

		t.Common().AcknowledgeConflicts()

		t.Views().Files().
			IsFocused().
			SelectedLine(Contains("file")).
			PressEnter()

		t.Views().MergeConflicts().
			IsFocused().
			SelectNextItem().
			PressPrimaryAction()

		t.Views().Information().Content(Contains("Rebasing"))

		popup := t.ExpectPopup().Confirmation().
			Title(Equals("Continue")).
			Content(Contains("All merge conflicts resolved. Continue?"))

		t.Shell().UpdateFile("file", "make it compile again")

		popup.Confirm()

		t.ExpectPopup().Confirmation().
			Title(Equals("Continue")).
			Content(Contains("Files have been modified since conflicts were resolved. Auto-stage them and continue?")).
			Confirm()

		t.Views().Information().Content(DoesNotContain("Rebasing"))

		t.Views().Commits().TopLines(
			Contains("first change"),
			Contains("second-change-branch unrelated change"),
			Contains("second change"),
			Contains("original"),
		)
	},
})
View Source
var RebaseCopiedBranch = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Make a copy of a branch, rebase it, check that the original branch is unaffected",
	ExtraCmdArgs: []string{},
	Skip:         false,
	GitVersion:   AtLeast("2.38.0"),
	SetupConfig: func(config *config.AppConfig) {
		config.GetAppState().GitLogShowGraph = "never"
	},
	SetupRepo: func(shell *Shell) {
		shell.
			EmptyCommit("master 1").
			EmptyCommit("master 2").
			NewBranchFrom("branch1", "master^").
			EmptyCommit("branch 1").
			EmptyCommit("branch 2").
			NewBranch("branch2")

		shell.SetConfig("rebase.updateRefs", "true")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().Lines(
			Contains("CI * branch 2"),
			Contains("CI branch 1"),
			Contains("CI master 1"),
		)

		t.Views().Branches().
			Focus().
			Lines(
				Contains("branch2").IsSelected(),
				Contains("branch1"),
				Contains("master"),
			).
			NavigateToLine(Contains("master")).
			Press(keys.Branches.RebaseBranch).
			Tap(func() {
				t.ExpectPopup().Menu().
					Title(Equals("Rebase 'branch2'")).
					Select(Contains("Simple rebase")).
					Confirm()
			})

		t.Views().Commits().Lines(
			Contains("CI branch 2"),
			Contains("CI branch 1"),
			Contains("CI master 2"),
			Contains("CI master 1"),
		)

		t.Views().Branches().
			Focus().
			NavigateToLine(Contains("branch1")).
			PressPrimaryAction()

		t.Views().Commits().Lines(
			Contains("CI branch 2"),
			Contains("CI branch 1"),
			Contains("CI master 1"),
		)
	},
})
View Source
var RebaseDoesNotAutosquash = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Rebase a branch that has fixups onto another branch, and verify that the fixups are not squashed even if rebase.autoSquash is enabled globally.",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.SetConfig("rebase.autoSquash", "true")

		shell.
			EmptyCommit("base").
			NewBranch("my-branch").
			Checkout("master").
			EmptyCommit("master commit").
			Checkout("my-branch").
			EmptyCommit("branch commit").
			EmptyCommit("fixup! branch commit")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().
			Lines(
				Contains("fixup! branch commit"),
				Contains("branch commit"),
				Contains("base"),
			)

		t.Views().Branches().
			Focus().
			Lines(
				Contains("my-branch").IsSelected(),
				Contains("master"),
			).
			SelectNextItem().
			Press(keys.Branches.RebaseBranch)

		t.ExpectPopup().Menu().
			Title(Equals("Rebase 'my-branch'")).
			Select(Contains("Simple rebase")).
			Confirm()

		t.Views().Commits().Lines(
			Contains("fixup! branch commit"),
			Contains("branch commit"),
			Contains("master commit"),
			Contains("base"),
		)
	},
})
View Source
var RebaseFromMarkedBase = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Rebase onto another branch from a marked base commit",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.
			NewBranch("base-branch").
			EmptyCommit("one").
			EmptyCommit("two").
			EmptyCommit("three").
			NewBranch("active-branch").
			EmptyCommit("active one").
			EmptyCommit("active two").
			EmptyCommit("active three").
			Checkout("base-branch").
			NewBranch("target-branch").
			EmptyCommit("target one").
			EmptyCommit("target two").
			Checkout("active-branch")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().
			Focus().
			Lines(
				Contains("active three"),
				Contains("active two"),
				Contains("active one"),
				Contains("three"),
				Contains("two"),
				Contains("one"),
			).
			NavigateToLine(Contains("active one")).
			Press(keys.Commits.MarkCommitAsBaseForRebase).
			Lines(
				Contains("active three").Contains("✓"),
				Contains("active two").Contains("✓"),
				Contains("↑↑↑ Will rebase from here ↑↑↑ active one"),
				Contains("three").DoesNotContain("✓"),
				Contains("two").DoesNotContain("✓"),
				Contains("one").DoesNotContain("✓"),
			)

		t.Views().Information().Content(Contains("Marked a base commit for rebase"))

		t.Views().Branches().
			Focus().
			Lines(
				Contains("active-branch"),
				Contains("target-branch"),
				Contains("base-branch"),
			).
			SelectNextItem().
			Press(keys.Branches.RebaseBranch)

		t.ExpectPopup().Menu().
			Title(Equals("Rebase 'active-branch' from marked base")).
			Select(Contains("Simple rebase")).
			Confirm()

		t.Views().Commits().Lines(
			Contains("active three").DoesNotContain("✓"),
			Contains("active two").DoesNotContain("✓"),
			Contains("target two").DoesNotContain("✓"),
			Contains("target one").DoesNotContain("✓"),
			Contains("three").DoesNotContain("✓"),
			Contains("two").DoesNotContain("✓"),
			Contains("one").DoesNotContain("✓"),
		)
	},
})
View Source
var RebaseOntoBaseBranch = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Rebase the current branch onto its base branch",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig: func(config *config.AppConfig) {
		config.GetUserConfig().Gui.ShowDivergenceFromBaseBranch = "arrowAndNumber"
	},
	SetupRepo: func(shell *Shell) {
		shell.
			EmptyCommit("master 1").
			EmptyCommit("master 2").
			EmptyCommit("master 3").
			NewBranchFrom("feature", "master^").
			EmptyCommit("feature 1").
			EmptyCommit("feature 2")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().Lines(
			Contains("feature 2"),
			Contains("feature 1"),
			Contains("master 2"),
			Contains("master 1"),
		)

		t.Views().Branches().
			Focus().
			Lines(
				Contains("feature ↓1").IsSelected(),
				Contains("master"),
			).
			Press(keys.Branches.RebaseBranch)

		t.ExpectPopup().Menu().
			Title(Equals("Rebase 'feature'")).
			Select(Contains("Rebase onto base branch (master)")).
			Confirm()

		t.Views().Commits().Lines(
			Contains("feature 2"),
			Contains("feature 1"),
			Contains("master 3"),
			Contains("master 2"),
			Contains("master 1"),
		)
	},
})
View Source
var RebaseToUpstream = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Rebase the current branch to the selected branch upstream",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.
			CloneIntoRemote("origin").
			EmptyCommit("ensure-master").
			EmptyCommit("to-be-added").
			PushBranchAndSetUpstream("origin", "master").
			RenameCurrentBranch("master-local").
			HardReset("HEAD~1").
			NewBranchFrom("base-branch", "master-local").
			EmptyCommit("base-branch-commit").
			NewBranch("target").
			EmptyCommit("target-commit")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().Lines(
			Contains("target-commit"),
			Contains("base-branch-commit"),
			Contains("ensure-master"),
		)

		t.Views().Branches().
			Focus().
			Lines(
				Contains("target").IsSelected(),
				Contains("base-branch"),
				Contains("master-local"),
			).
			SelectNextItem().
			Lines(
				Contains("target"),
				Contains("base-branch").IsSelected(),
				Contains("master-local"),
			).
			Press(keys.Branches.SetUpstream).
			Tap(func() {
				t.ExpectPopup().Menu().
					Title(Equals("Upstream options")).
					Select(Contains("Rebase checked-out branch onto upstream of selected branch")).
					Tooltip(Contains("Disabled: The selected branch has no upstream (or the upstream is not stored locally)")).
					Confirm().
					Tap(func() {
						t.ExpectToast(Equals("Disabled: The selected branch has no upstream (or the upstream is not stored locally)"))
					}).
					Cancel()
			}).
			SelectNextItem().
			Lines(
				Contains("target"),
				Contains("base-branch"),
				Contains("master-local").IsSelected(),
			).
			Press(keys.Branches.SetUpstream).
			Tap(func() {
				t.ExpectPopup().Menu().
					Title(Equals("Upstream options")).
					Select(Contains("Rebase checked-out branch onto origin/master...")).
					Confirm()
				t.ExpectPopup().Menu().
					Title(Equals("Rebase 'target'")).
					Select(Contains("Simple rebase")).
					Confirm()
			})

		t.Views().Commits().Lines(
			Contains("target-commit"),
			Contains("base-branch-commit"),
			Contains("to-be-added"),
			Contains("ensure-master"),
		)
	},
})
View Source
var Rename = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Rename a branch, replacing spaces in the name with dashes",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.EmptyCommit("commit")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Branches().
			Focus().
			Lines(
				Contains("master"),
			).
			Press(keys.Branches.RenameBranch).
			Tap(func() {
				t.ExpectPopup().Prompt().
					Title(Contains("Enter new branch name")).
					InitialText(Equals("master")).
					Clear().
					Type("new branch name").
					Confirm()
			}).
			Lines(
				Contains("new-branch-name"),
			)
	},
})
View Source
var Reset = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Hard reset to another branch",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.NewBranch("current-branch")
		shell.EmptyCommit("root commit")

		shell.NewBranch("other-branch")
		shell.EmptyCommit("other-branch commit")

		shell.Checkout("current-branch")
		shell.EmptyCommit("current-branch commit")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().Lines(
			Contains("current-branch commit"),
			Contains("root commit"),
		)

		t.Views().Branches().
			Focus().
			Lines(
				Contains("current-branch").IsSelected(),
				Contains("other-branch"),
			).
			SelectNextItem().
			Press(keys.Commits.ViewResetOptions)

		t.ExpectPopup().Menu().
			Title(Contains("Reset to other-branch")).
			Select(Contains("Hard reset")).
			Confirm()

		t.Views().Commits().
			Lines(
				Contains("other-branch commit"),
				Contains("root commit"),
			)
	},
})
View Source
var ResetToUpstream = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Hard reset the current branch to the selected branch upstream",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.
			CloneIntoRemote("origin").
			NewBranch("hard-branch").
			EmptyCommit("hard commit").
			PushBranchAndSetUpstream("origin", "hard-branch").
			NewBranch("soft-branch").
			EmptyCommit("soft commit").
			PushBranchAndSetUpstream("origin", "soft-branch").
			RenameCurrentBranch("soft-branch-local").
			NewBranch("base").
			EmptyCommit("base-branch commit").
			CreateFile("file-1", "content").
			GitAdd("file-1").
			Commit("commit with file").
			CreateFile("file-2", "content").
			GitAdd("file-2")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {

		t.Views().Branches().
			Focus().
			Lines(
				Contains("base").IsSelected(),
				Contains("soft-branch-local"),
				Contains("hard-branch"),
			).
			Press(keys.Branches.SetUpstream).
			Tap(func() {
				t.ExpectPopup().Menu().
					Title(Equals("Upstream options")).
					Select(Contains("Reset checked-out branch onto upstream of selected branch")).
					Tooltip(Contains("Disabled: The selected branch has no upstream (or the upstream is not stored locally)")).
					Confirm().
					Tap(func() {
						t.ExpectToast(Equals("Disabled: The selected branch has no upstream (or the upstream is not stored locally)"))
					}).
					Cancel()
			}).
			SelectNextItem().
			Lines(
				Contains("base"),
				Contains("soft-branch-local").IsSelected(),
				Contains("hard-branch"),
			).
			Press(keys.Branches.SetUpstream).
			Tap(func() {
				t.ExpectPopup().Menu().
					Title(Equals("Upstream options")).
					Select(Contains("Reset checked-out branch onto origin/soft-branch...")).
					Confirm()

				t.ExpectPopup().Menu().
					Title(Equals("Reset to origin/soft-branch")).
					Select(Contains("Soft reset")).
					Confirm()
			})
		t.Views().Commits().Lines(
			Contains("soft commit"),
			Contains("hard commit"),
		)
		t.Views().Files().Lines(
			Equals("▼ /"),
			Equals("  A  file-1"),
			Equals("  A  file-2"),
		)

		t.Views().Branches().
			Focus().
			Lines(
				Contains("base"),
				Contains("soft-branch-local").IsSelected(),
				Contains("hard-branch"),
			).
			NavigateToLine(Contains("hard-branch")).
			Press(keys.Branches.SetUpstream).
			Tap(func() {
				t.ExpectPopup().Menu().
					Title(Equals("Upstream options")).
					Select(Contains("Reset checked-out branch onto origin/hard-branch...")).
					Confirm()

				t.ExpectPopup().Menu().
					Title(Equals("Reset to origin/hard-branch")).
					Select(Contains("Hard reset")).
					Confirm()
			})
		t.Views().Commits().Lines(Contains("hard commit"))
		t.Views().Files().IsEmpty()
	},
})
View Source
var SelectCommitsOfCurrentBranch = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Select all commits of the current branch",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.EmptyCommit("master 01")
		shell.EmptyCommit("master 02")
		shell.NewBranch("branch1")
		shell.CreateNCommits(2)
		shell.NewBranchFrom("branch2", "master")
		shell.CreateNCommits(3)
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().
			Focus().
			Lines(
				Contains("commit 03").IsSelected(),
				Contains("commit 02"),
				Contains("commit 01"),
				Contains("master 02"),
				Contains("master 01"),
			).
			Press(keys.Commits.SelectCommitsOfCurrentBranch).
			Lines(
				Contains("commit 03").IsSelected(),
				Contains("commit 02").IsSelected(),
				Contains("commit 01").IsSelected(),
				Contains("master 02"),
				Contains("master 01"),
			).
			PressEscape().
			Lines(
				Contains("commit 03").IsSelected(),
				Contains("commit 02"),
				Contains("commit 01"),
				Contains("master 02"),
				Contains("master 01"),
			)

		t.Views().Branches().
			Focus().
			Lines(
				Contains("branch2").IsSelected(),
				Contains("branch1"),
				Contains("master"),
			).
			SelectNextItem().
			PressEnter()

		t.Views().SubCommits().
			IsFocused().
			Lines(
				Contains("commit 02").IsSelected(),
				Contains("commit 01"),
				Contains("master 02"),
				Contains("master 01"),
			).
			Press(keys.Commits.SelectCommitsOfCurrentBranch).
			Lines(
				Contains("commit 02").IsSelected(),
				Contains("commit 01").IsSelected(),
				Contains("master 02"),
				Contains("master 01"),
			)
	},
})
View Source
var SetUpstream = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Set the upstream of a branch",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.EmptyCommit("one")
		shell.CloneIntoRemote("origin")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Branches().
			Focus().
			Press(keys.Universal.NextScreenMode).
			Lines(
				Contains("master").DoesNotContain("origin master").IsSelected(),
			).
			Press(keys.Branches.SetUpstream).
			Tap(func() {
				t.ExpectPopup().Menu().
					Title(Equals("Upstream options")).
					Select(Contains(" Set upstream of selected branch")).
					Confirm()

				t.ExpectPopup().Prompt().
					Title(Equals("Enter upstream as '<remote> <branchname>'")).
					SuggestionLines(Equals("origin master")).
					ConfirmFirstSuggestion()
			}).
			Lines(
				Contains("master").Contains("origin master").IsSelected(),
			)
	},
})
View Source
var ShowDivergenceFromBaseBranch = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Show divergence from base branch",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig: func(config *config.AppConfig) {
		config.GetUserConfig().Gui.ShowDivergenceFromBaseBranch = "arrowAndNumber"
	},
	SetupRepo: func(shell *Shell) {
		shell.
			EmptyCommit("master 1").
			EmptyCommit("master 2").
			EmptyCommit("master 3").
			NewBranchFrom("feature", "master^").
			EmptyCommit("feature 1").
			EmptyCommit("feature 2")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Branches().
			Focus().
			Lines(
				Contains("feature ↓1").IsSelected(),
				Contains("master"),
			).
			Press(keys.Branches.SetUpstream)

		t.ExpectPopup().Menu().Title(Contains("Upstream")).
			Select(Contains("View divergence from base branch (master)")).Confirm()

		t.Views().SubCommits().
			IsFocused().
			Title(Contains("Commits (feature <-> master)")).
			Lines(
				DoesNotContainAnyOf("↓", "↑").Contains("--- Remote ---"),
				Contains("↓").Contains("master 3"),
				DoesNotContainAnyOf("↓", "↑").Contains("--- Local ---"),
				Contains("↑").Contains("feature 2"),
				Contains("↑").Contains("feature 1"),
			)
	},
})
View Source
var ShowDivergenceFromUpstream = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Show divergence from upstream",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.CreateFileAndAdd("file", "content1")
		shell.Commit("one")
		shell.UpdateFileAndAdd("file", "content2")
		shell.Commit("two")
		shell.CreateFileAndAdd("file3", "content3")
		shell.Commit("three")

		shell.CloneIntoRemote("origin")

		shell.SetBranchUpstream("master", "origin/master")

		shell.HardReset("HEAD^^")
		shell.CreateFileAndAdd("file4", "content4")
		shell.Commit("four")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().
			Lines(
				Contains("four"),
				Contains("one"),
			)

		t.Views().Branches().
			Focus().
			Lines(Contains("master")).
			Press(keys.Branches.SetUpstream)

		t.ExpectPopup().Menu().Title(Contains("Upstream")).Select(Contains("View divergence from upstream")).Confirm()

		t.Views().SubCommits().
			IsFocused().
			Title(Contains("Commits (master <-> origin/master)")).
			Lines(
				DoesNotContainAnyOf("↓", "↑").Contains("--- Remote ---"),
				Contains("↓").Contains("three"),
				Contains("↓").Contains("two"),
				DoesNotContainAnyOf("↓", "↑").Contains("--- Local ---"),
				Contains("↑").Contains("four"),
			)
	},
})
View Source
var ShowDivergenceFromUpstreamNoDivergence = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Show divergence from upstream when the divergence view is empty",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.EmptyCommit("commit1")
		shell.CloneIntoRemote("origin")
		shell.SetBranchUpstream("master", "origin/master")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Branches().
			Focus().
			Lines(Contains("master")).
			Press(keys.Branches.SetUpstream)

		t.ExpectPopup().Menu().Title(Contains("Upstream")).Select(Contains("View divergence from upstream")).Confirm()

		t.Views().SubCommits().
			IsFocused().
			Title(Contains("Commits (master <-> origin/master)")).
			Lines(
				Contains("--- Remote ---"),
				Contains("--- Local ---"),
			)
	},
})
View Source
var SortLocalBranches = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Sort local branches by recency, date or alphabetically",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.
			EmptyCommit("commit").
			NewBranch("first").
			EmptyCommitWithDate("commit", "2023-04-07 10:00:00").
			NewBranch("second").
			EmptyCommitWithDate("commit", "2023-04-07 12:00:00").
			NewBranch("third").
			EmptyCommitWithDate("commit", "2023-04-07 11:00:00").
			Checkout("master")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {

		t.Views().Branches().
			Focus().
			Lines(
				Contains("master").IsSelected(),
				Contains("third"),
				Contains("second"),
				Contains("first"),
			).
			SelectNextItem()

		t.Views().Branches().
			Press(keys.Branches.SortOrder)

		t.ExpectPopup().Menu().Title(Equals("Sort order")).
			Lines(
				Contains("r (•) Recency").IsSelected(),
				Contains("a ( ) Alphabetical"),
				Contains("d ( ) Date"),
				Contains("      Cancel"),
			).
			Select(Contains("-committerdate")).
			Confirm()

		t.Views().Branches().
			IsFocused().
			Lines(
				Contains("master").IsSelected(),
				Contains("second"),
				Contains("third"),
				Contains("first"),
			)

		t.Views().Branches().
			Press(keys.Branches.SortOrder)

		t.ExpectPopup().Menu().Title(Equals("Sort order")).
			Lines(
				Contains("r ( ) Recency").IsSelected(),
				Contains("a ( ) Alphabetical"),
				Contains("d (•) Date"),
				Contains("      Cancel"),
			).
			Select(Contains("refname")).
			Confirm()

		t.Views().Branches().
			IsFocused().
			Lines(
				Contains("master").IsSelected(),
				Contains("first"),
				Contains("second"),
				Contains("third"),
			)
	},
})
View Source
var SortRemoteBranches = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Sort remote branches alphabetically or by date",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.NewBranch("first")
		shell.EmptyCommitWithDate("commit", "2023-04-07 10:00:00")
		shell.NewBranch("second")
		shell.EmptyCommitWithDate("commit", "2023-04-07 12:00:00")
		shell.NewBranch("third")
		shell.EmptyCommitWithDate("commit", "2023-04-07 11:00:00")
		shell.CloneIntoRemote("origin")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Remotes().
			Focus().
			Lines(
				Contains("origin").IsSelected(),
			).
			PressEnter()

		t.Views().RemoteBranches().
			IsFocused().
			Lines(
				Contains("first").IsSelected(),
				Contains("second"),
				Contains("third"),
			).
			SelectNextItem()

		t.Views().RemoteBranches().
			Press(keys.Branches.SortOrder)

		t.ExpectPopup().Menu().Title(Equals("Sort order")).
			Lines(
				Contains("a (•) Alphabetical").IsSelected(),
				Contains("d ( ) Date"),
				Contains("      Cancel"),
			).
			Select(Contains("-committerdate")).
			Confirm()

		t.Views().RemoteBranches().
			IsFocused().
			Lines(
				Contains("second").IsSelected(),
				Contains("third"),
				Contains("first"),
			)
	},
})
View Source
var SquashMerge = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Squash merge a branch both with and without committing",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.NewBranch("original-branch").
			EmptyCommit("one").
			NewBranch("change-worktree-branch").
			CreateFileAndAdd("work", "content").
			Commit("work").
			Checkout("original-branch").
			NewBranch("change-commit-branch").
			CreateFileAndAdd("file", "content").
			Commit("file").
			Checkout("original-branch")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Commits().TopLines(
			Contains("one"),
		)

		t.Views().Branches().
			Focus().
			Lines(
				Contains("original-branch").IsSelected(),
				Contains("change-commit-branch"),
				Contains("change-worktree-branch"),
			).
			SelectNextItem().
			Press(keys.Branches.MergeIntoCurrentBranch)

		t.ExpectPopup().Menu().
			Title(Equals("Merge")).
			Select(Contains("Squash merge and commit")).
			Confirm()

		t.Views().Commits().TopLines(
			Contains("Squash merge change-commit-branch into original-branch"),
			Contains("one"),
		)

		t.Views().Branches().
			Focus().
			NavigateToLine(Contains("change-worktree-branch")).
			Press(keys.Branches.MergeIntoCurrentBranch)

		t.ExpectPopup().Menu().
			Title(Equals("Merge")).
			Select(Contains("Squash merge and leave uncommitted")).
			Confirm()

		t.Views().Files().Focus().Lines(
			Contains("work"),
		)
	},
})
View Source
var Suggestions = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Checking out a branch with name suggestions",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.
			EmptyCommit("my commit message").
			NewBranch("new-branch").
			NewBranch("new-branch-2").
			NewBranch("new-branch-3").
			NewBranch("branch-to-checkout").
			NewBranch("other-new-branch-2").
			NewBranch("other-new-branch-3")
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Branches().
			Focus().
			Press(keys.Branches.CheckoutBranchByName)

		t.ExpectPopup().Prompt().
			Title(Equals("Branch name:")).
			Type("branch-to").
			SuggestionTopLines(Contains("branch-to-checkout")).
			ConfirmFirstSuggestion()

		t.Git().CurrentBranchName("branch-to-checkout")
	},
})
View Source
var UnsetUpstream = NewIntegrationTest(NewIntegrationTestArgs{
	Description:  "Unset upstream of selected branch, both when it exists and when it doesn't",
	ExtraCmdArgs: []string{},
	Skip:         false,
	SetupConfig:  func(config *config.AppConfig) {},
	SetupRepo: func(shell *Shell) {
		shell.
			EmptyCommit("one").
			NewBranch("branch_to_remove").
			Checkout("master").
			CloneIntoRemote("origin").
			SetBranchUpstream("master", "origin/master").
			SetBranchUpstream("branch_to_remove", "origin/branch_to_remove").
			RunCommand([]string{"git", "push", "origin", "--delete", "branch_to_remove"})
	},
	Run: func(t *TestDriver, keys config.KeybindingConfig) {
		t.Views().Branches().
			Focus().
			Press(keys.Universal.NextScreenMode).
			SelectedLines(
				Contains("master").Contains("origin master"),
			).
			Press(keys.Branches.SetUpstream).
			Tap(func() {
				t.ExpectPopup().Menu().
					Title(Equals("Upstream options")).
					Select(Contains("Unset upstream of selected branch")).
					Confirm()
			}).
			SelectedLines(
				Contains("master").DoesNotContain("origin master"),
			)

		t.Views().Branches().
			Focus().
			SelectNextItem().
			SelectedLines(
				Contains("branch_to_remove").Contains("origin branch_to_remove").Contains("upstream gone"),
			).
			Press(keys.Branches.SetUpstream).
			Tap(func() {
				t.ExpectPopup().Menu().
					Title(Equals("Upstream options")).
					Select(Contains("Unset upstream of selected branch")).
					Confirm()
			}).
			SelectedLines(
				Contains("branch_to_remove").DoesNotContain("origin branch_to_remove").DoesNotContain("upstream gone"),
			)
	},
})

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL