diff --git a/pkg/integration/components/assert.go b/pkg/integration/components/assert.go index 95998b759..162b4a070 100644 --- a/pkg/integration/components/assert.go +++ b/pkg/integration/components/assert.go @@ -151,6 +151,13 @@ func (self *Assert) SelectedLine(matcher *matcher) { ) } +func (self *Assert) SelectedLineIdx(expected int) { + self.assertWithRetries(func() (bool, string) { + actual := self.gui.CurrentContext().GetView().SelectedLineIdx() + return expected == actual, fmt.Sprintf("Expected selected line index to be %d, got %d", expected, actual) + }) +} + func (self *Assert) InPrompt() { self.assertWithRetries(func() (bool, string) { currentView := self.gui.CurrentContext().GetView() @@ -209,6 +216,47 @@ func (self *Assert) ViewContent(viewName string, matcher *matcher) { ) } +// asserts that the given view has lines matching the given matchers. +func (self *Assert) ViewLines(viewName string, matchers ...*matcher) { + self.assertWithRetries(func() (bool, string) { + lines := self.gui.View(viewName).BufferLines() + return len(lines) == len(matchers), fmt.Sprintf("unexpected number of lines in view. Expected %d, got %d", len(matchers), len(lines)) + }) + + for i, matcher := range matchers { + self.matchString(matcher, fmt.Sprintf("Unexpected content in view '%s'.", viewName), + func() string { + return self.gui.View(viewName).BufferLines()[i] + }, + ) + } +} + +func (self *Assert) CurrentViewLines(matchers ...*matcher) { + self.ViewLines(self.gui.CurrentContext().GetView().Name(), matchers...) +} + +// asserts that the given view has lines matching the given matchers. So if three matchers +// are passed, we only check the first three lines of the view. +func (self *Assert) ViewTopLines(viewName string, matchers ...*matcher) { + self.assertWithRetries(func() (bool, string) { + lines := self.gui.View(viewName).BufferLines() + return len(lines) >= len(matchers), fmt.Sprintf("unexpected number of lines in view. Expected at least %d, got %d", len(matchers), len(lines)) + }) + + for i, matcher := range matchers { + self.matchString(matcher, fmt.Sprintf("Unexpected content in view '%s'.", viewName), + func() string { + return self.gui.View(viewName).BufferLines()[i] + }, + ) + } +} + +func (self *Assert) CurrentViewTopLines(matchers ...*matcher) { + self.ViewTopLines(self.gui.CurrentContext().GetView().Name(), matchers...) +} + func (self *Assert) CurrentViewContent(matcher *matcher) { self.matchString(matcher, "Unexpected content in current view.", func() string { diff --git a/pkg/integration/tests/bisect/from_other_branch.go b/pkg/integration/tests/bisect/from_other_branch.go index 85829b741..8c00f9d31 100644 --- a/pkg/integration/tests/bisect/from_other_branch.go +++ b/pkg/integration/tests/bisect/from_other_branch.go @@ -30,12 +30,14 @@ var FromOtherBranch = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToCommitsWindow() - assert.SelectedLine(Contains("<-- bad")) - assert.SelectedLine(Contains("commit 08")) + assert.ViewTopLines("commits", + MatchesRegexp(`<-- bad.*commit 08`), + MatchesRegexp(`<-- current.*commit 07`), + MatchesRegexp(`\?.*commit 06`), + MatchesRegexp(`<-- good.*commit 05`), + ) input.NextItem() - assert.SelectedLine(Contains("<-- current")) - assert.SelectedLine(Contains("commit 07")) input.Press(keys.Commits.ViewBisectOptions) input.Menu(Equals("Bisect"), MatchesRegexp(`mark .* as good`)) @@ -46,7 +48,8 @@ var FromOtherBranch = NewIntegrationTest(NewIntegrationTestArgs{ // back in master branch which just had the one commit assert.CurrentViewName("commits") - assert.CommitCount(1) - assert.SelectedLine(Contains("only commit on master")) + assert.CurrentViewLines( + Contains("only commit on master"), + ) }, }) diff --git a/pkg/integration/tests/branch/checkout_by_name.go b/pkg/integration/tests/branch/checkout_by_name.go index de5c0131c..e34215037 100644 --- a/pkg/integration/tests/branch/checkout_by_name.go +++ b/pkg/integration/tests/branch/checkout_by_name.go @@ -21,9 +21,12 @@ var CheckoutByName = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToBranchesWindow() assert.CurrentViewName("localBranches") - assert.SelectedLine(Contains("master")) + assert.CurrentViewLines( + Contains("master"), + Contains("@"), + ) input.NextItem() - assert.SelectedLine(Contains("@")) + input.Press(keys.Branches.CheckoutBranchByName) input.Prompt(Equals("Branch name:"), "new-branch") @@ -31,6 +34,12 @@ var CheckoutByName = NewIntegrationTest(NewIntegrationTestArgs{ input.Alert(Equals("Branch not found"), Equals("Branch not found. Create a new branch named new-branch?")) assert.CurrentViewName("localBranches") + assert.CurrentViewLines( + MatchesRegexp(`\*.*new-branch`), + Contains("master"), + Contains("@"), + ) + assert.SelectedLine(Contains("new-branch")) }, }) diff --git a/pkg/integration/tests/branch/delete.go b/pkg/integration/tests/branch/delete.go index 524b8e365..5192f1035 100644 --- a/pkg/integration/tests/branch/delete.go +++ b/pkg/integration/tests/branch/delete.go @@ -20,18 +20,25 @@ var Delete = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToBranchesWindow() assert.CurrentViewName("localBranches") - assert.SelectedLine(Contains("branch-two")) + assert.CurrentViewLines( + MatchesRegexp(`\*.*branch-two`), + MatchesRegexp(`branch-one`), + MatchesRegexp(`master`), + ) + input.Press(keys.Universal.Remove) input.Alert(Equals("Error"), Contains("You cannot delete the checked out branch!")) input.NextItem() - assert.SelectedLine(Contains("branch-one")) input.Press(keys.Universal.Remove) input.AcceptConfirmation(Equals("Delete Branch"), Contains("Are you sure you want to delete the branch 'branch-one'?")) assert.CurrentViewName("localBranches") - assert.SelectedLine(Contains("master")) - assert.CurrentViewContent(NotContains("branch-one")) + assert.CurrentViewLines( + MatchesRegexp(`\*.*branch-two`), + MatchesRegexp(`master`), + ) + assert.SelectedLineIdx(1) }, }) diff --git a/pkg/integration/tests/branch/rebase.go b/pkg/integration/tests/branch/rebase.go index 665efe7d6..96e3c1d72 100644 --- a/pkg/integration/tests/branch/rebase.go +++ b/pkg/integration/tests/branch/rebase.go @@ -18,9 +18,20 @@ var Rebase = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToBranchesWindow() assert.CurrentViewName("localBranches") - assert.SelectedLine(Contains("first-change-branch")) + assert.ViewLines( + "localBranches", + Contains("first-change-branch"), + Contains("second-change-branch"), + Contains("original-branch"), + ) + + assert.ViewTopLines( + "commits", + Contains("first change"), + Contains("original"), + ) + input.NextItem() - assert.SelectedLine(Contains("second-change-branch")) input.Press(keys.Branches.RebaseBranch) input.AcceptConfirmation(Equals("Rebasing"), Contains("Are you sure you want to rebase 'first-change-branch' on top of 'second-change-branch'?")) @@ -43,7 +54,11 @@ var Rebase = NewIntegrationTest(NewIntegrationTestArgs{ assert.ViewContent("information", NotContains("rebasing")) - // this proves we actually have integrated the changes from second-change-branch - assert.ViewContent("commits", Contains("second-change-branch unrelated change")) + assert.ViewTopLines( + "commits", + Contains("second-change-branch unrelated change"), + Contains("second change"), + Contains("original"), + ) }, }) diff --git a/pkg/integration/tests/branch/rebase_and_drop.go b/pkg/integration/tests/branch/rebase_and_drop.go index bb5b53855..284f80f05 100644 --- a/pkg/integration/tests/branch/rebase_and_drop.go +++ b/pkg/integration/tests/branch/rebase_and_drop.go @@ -21,9 +21,22 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToBranchesWindow() assert.CurrentViewName("localBranches") - assert.SelectedLine(Contains("first-change-branch")) + assert.ViewLines( + "localBranches", + Contains("first-change-branch"), + Contains("second-change-branch"), + Contains("original-branch"), + ) + + assert.ViewTopLines( + "commits", + Contains("to keep"), + Contains("to remove"), + Contains("first change"), + Contains("original"), + ) + input.NextItem() - assert.SelectedLine(Contains("second-change-branch")) input.Press(keys.Branches.RebaseBranch) input.AcceptConfirmation(Equals("Rebasing"), Contains("Are you sure you want to rebase 'first-change-branch' on top of 'second-change-branch'?")) @@ -36,13 +49,18 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ assert.SelectedLine(Contains("file")) input.SwitchToCommitsWindow() - assert.SelectedLine(Contains("pick")) // this means it's a rebasing commit + assert.ViewTopLines( + "commits", + MatchesRegexp(`pick.*to keep`), + MatchesRegexp(`pick.*to remove`), + MatchesRegexp("YOU ARE HERE.*second-change-branch unrelated change"), + MatchesRegexp("second change"), + MatchesRegexp("original"), + ) + assert.SelectedLineIdx(0) input.NextItem() input.Press(keys.Universal.Remove) - // this is the commit name - assert.SelectedLine(Contains("to remove")) - // the commit has been marked to drop once we continue the rebase. - assert.SelectedLine(Contains("drop")) + assert.SelectedLine(MatchesRegexp(`drop.*to remove`)) input.SwitchToFilesWindow() @@ -57,9 +75,12 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ assert.ViewContent("information", NotContains("rebasing")) - // this proves we actually have integrated the changes from second-change-branch - assert.ViewContent("commits", Contains("second-change-branch unrelated change")) - assert.ViewContent("commits", Contains("to keep")) - assert.ViewContent("commits", NotContains("to remove")) + assert.ViewTopLines( + "commits", + Contains("to keep"), + Contains("second-change-branch unrelated change"), + Contains("second change"), + Contains("original"), + ) }, }) diff --git a/pkg/integration/tests/branch/reset.go b/pkg/integration/tests/branch/reset.go index d4cadb49f..4895a2cd8 100644 --- a/pkg/integration/tests/branch/reset.go +++ b/pkg/integration/tests/branch/reset.go @@ -21,12 +21,19 @@ var Reset = NewIntegrationTest(NewIntegrationTestArgs{ shell.EmptyCommit("current-branch commit") }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { + assert.ViewLines("commits", + Contains("current-branch commit"), + Contains("root commit"), + ) + input.SwitchToBranchesWindow() assert.CurrentViewName("localBranches") - assert.SelectedLine(Contains("current-branch")) + assert.CurrentViewLines( + Contains("current-branch"), + Contains("other-branch"), + ) input.NextItem() - assert.SelectedLine(Contains("other-branch")) input.Press(keys.Commits.ViewResetOptions) @@ -38,9 +45,9 @@ var Reset = NewIntegrationTest(NewIntegrationTestArgs{ // assert that we now have the expected commits in the commit panel input.SwitchToCommitsWindow() assert.CurrentViewName("commits") - assert.CommitCount(2) - assert.SelectedLine(Contains("other-branch commit")) - input.NextItem() - assert.SelectedLine(Contains("root commit")) + assert.CurrentViewLines( + Contains("other-branch commit"), + Contains("root commit"), + ) }, }) diff --git a/pkg/integration/tests/cherry_pick/cherry_pick.go b/pkg/integration/tests/cherry_pick/cherry_pick.go index 444cf35e4..6d11b9a7e 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick.go @@ -27,35 +27,50 @@ var CherryPick = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToBranchesWindow() assert.CurrentViewName("localBranches") - assert.SelectedLine(Contains("first-branch")) + assert.CurrentViewLines( + Contains("first-branch"), + Contains("second-branch"), + Contains("master"), + ) + input.NextItem() - assert.SelectedLine(Contains("second-branch")) input.Enter() assert.CurrentViewName("subCommits") - assert.SelectedLine(Contains("four")) + assert.CurrentViewLines( + Contains("four"), + Contains("three"), + Contains("base"), + ) + + // copy commits 'four' and 'three' input.Press(keys.Commits.CherryPickCopy) assert.ViewContent("information", Contains("1 commit copied")) - input.NextItem() - assert.SelectedLine(Contains("three")) input.Press(keys.Commits.CherryPickCopy) assert.ViewContent("information", Contains("2 commits copied")) input.SwitchToCommitsWindow() assert.CurrentViewName("commits") - assert.SelectedLine(Contains("two")) + assert.CurrentViewLines( + Contains("two"), + Contains("one"), + Contains("base"), + ) + input.Press(keys.Commits.PasteCommits) input.Alert(Equals("Cherry-Pick"), Contains("Are you sure you want to cherry-pick the copied commits onto this branch?")) assert.CurrentViewName("commits") - assert.SelectedLine(Contains("four")) - input.NextItem() - assert.SelectedLine(Contains("three")) - input.NextItem() - assert.SelectedLine(Contains("two")) + assert.CurrentViewLines( + Contains("four"), + Contains("three"), + Contains("two"), + Contains("one"), + Contains("base"), + ) assert.ViewContent("information", Contains("2 commits copied")) input.Press(keys.Universal.Return) diff --git a/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go b/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go index 377e21e76..6a9c47781 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go @@ -18,26 +18,37 @@ var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToBranchesWindow() assert.CurrentViewName("localBranches") - assert.SelectedLine(Contains("first-change-branch")) + assert.CurrentViewLines( + Contains("first-change-branch"), + Contains("second-change-branch"), + Contains("original-branch"), + ) + input.NextItem() - assert.SelectedLine(Contains("second-change-branch")) input.Enter() assert.CurrentViewName("subCommits") - assert.SelectedLine(Contains("second-change-branch unrelated change")) + + assert.CurrentViewTopLines( + Contains("second-change-branch unrelated change"), + Contains("second change"), + ) + input.Press(keys.Commits.CherryPickCopy) assert.ViewContent("information", Contains("1 commit copied")) input.NextItem() - assert.SelectedLine(Contains("second change")) input.Press(keys.Commits.CherryPickCopy) assert.ViewContent("information", Contains("2 commits copied")) input.SwitchToCommitsWindow() assert.CurrentViewName("commits") - assert.SelectedLine(Contains("first change")) + assert.CurrentViewTopLines( + Contains("first change"), + ) + input.Press(keys.Commits.PasteCommits) input.Alert(Equals("Cherry-Pick"), Contains("Are you sure you want to cherry-pick the copied commits onto this branch?")) @@ -63,16 +74,17 @@ var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToCommitsWindow() assert.CurrentViewName("commits") - assert.SelectedLine(Contains("second-change-branch unrelated change")) + assert.CurrentViewTopLines( + Contains("second-change-branch unrelated change"), + Contains("second change"), + Contains("first change"), + ) input.NextItem() - assert.SelectedLine(Contains("second change")) // because we picked 'Second change' when resolving the conflict, // we now see this commit as having replaced First Change with Second Change, // as opposed to replacing 'Original' with 'Second change' assert.MainViewContent(Contains("-First Change")) assert.MainViewContent(Contains("+Second Change")) - input.NextItem() - assert.SelectedLine(Contains("first change")) assert.ViewContent("information", Contains("2 commits copied")) input.Press(keys.Universal.Return) diff --git a/pkg/integration/tests/commit/new_branch.go b/pkg/integration/tests/commit/new_branch.go index 3557acbcf..349fff8ee 100644 --- a/pkg/integration/tests/commit/new_branch.go +++ b/pkg/integration/tests/commit/new_branch.go @@ -21,6 +21,11 @@ var NewBranch = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToCommitsWindow() assert.CurrentViewName("commits") + assert.CurrentViewLines( + Contains("commit 3"), + Contains("commit 2"), + Contains("commit 1"), + ) input.NextItem() input.Press(keys.Universal.New) @@ -28,8 +33,11 @@ var NewBranch = NewIntegrationTest(NewIntegrationTestArgs{ branchName := "my-branch-name" input.Prompt(Contains("New Branch Name"), branchName) - assert.CommitCount(2) - assert.HeadCommitMessage(Contains("commit 2")) assert.CurrentBranchName(branchName) + + assert.ViewLines("commits", + Contains("commit 2"), + Contains("commit 1"), + ) }, }) diff --git a/pkg/integration/tests/diff/diff.go b/pkg/integration/tests/diff/diff.go index 3e87c934b..da666377d 100644 --- a/pkg/integration/tests/diff/diff.go +++ b/pkg/integration/tests/diff/diff.go @@ -25,7 +25,10 @@ var Diff = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToBranchesWindow() assert.CurrentViewName("localBranches") - assert.SelectedLine(Contains("branch-a")) + assert.CurrentViewTopLines( + Contains("branch-a"), + Contains("branch-b"), + ) input.Press(keys.Universal.DiffingMenu) input.Menu(Equals("Diffing"), Contains(`diff branch-a`)) diff --git a/pkg/integration/tests/diff/diff_and_apply_patch.go b/pkg/integration/tests/diff/diff_and_apply_patch.go index a965fffd5..c5d2b3e6e 100644 --- a/pkg/integration/tests/diff/diff_and_apply_patch.go +++ b/pkg/integration/tests/diff/diff_and_apply_patch.go @@ -24,8 +24,11 @@ var DiffAndApplyPatch = NewIntegrationTest(NewIntegrationTestArgs{ Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { input.SwitchToBranchesWindow() assert.CurrentViewName("localBranches") + assert.CurrentViewLines( + Contains("branch-a"), + Contains("branch-b"), + ) - assert.SelectedLine(Contains("branch-a")) input.Press(keys.Universal.DiffingMenu) input.Menu(Equals("Diffing"), Equals("diff branch-a")) diff --git a/pkg/integration/tests/diff/diff_commits.go b/pkg/integration/tests/diff/diff_commits.go index 2a2802ec8..39bf54d6f 100644 --- a/pkg/integration/tests/diff/diff_commits.go +++ b/pkg/integration/tests/diff/diff_commits.go @@ -22,7 +22,11 @@ var DiffCommits = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToCommitsWindow() assert.CurrentViewName("commits") - assert.SelectedLine(Contains("third commit")) + assert.CurrentViewLines( + Contains("third commit"), + Contains("second commit"), + Contains("first commit"), + ) input.Press(keys.Universal.DiffingMenu) input.Menu(Equals("Diffing"), MatchesRegexp(`diff \w+`)) @@ -33,7 +37,6 @@ var DiffCommits = NewIntegrationTest(NewIntegrationTestArgs{ input.NextItem() input.NextItem() - assert.SelectedLine(Contains("first commit")) assert.MainViewContent(Contains("-second line\n-third line")) diff --git a/pkg/integration/tests/stash/rename.go b/pkg/integration/tests/stash/rename.go index c325822e6..de5385a56 100644 --- a/pkg/integration/tests/stash/rename.go +++ b/pkg/integration/tests/stash/rename.go @@ -22,9 +22,11 @@ var Rename = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToStashWindow() assert.CurrentViewName("stash") - assert.SelectedLine(Equals("On master: bar")) + assert.CurrentViewLines( + Equals("On master: bar"), + Equals("On master: foo"), + ) input.NextItem() - assert.SelectedLine(Equals("On master: foo")) input.Press(keys.Stash.RenameStash) input.Prompt(Equals("Rename stash: stash@{1}"), " baz")