From 5d2584a1883df779d2ced5a3c44498a09179d83d Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sun, 25 Dec 2022 11:38:00 +1100 Subject: [PATCH 1/7] introduce ViewLines functions --- pkg/integration/components/assert.go | 48 +++++++++++++++++++ .../tests/bisect/from_other_branch.go | 15 +++--- .../tests/branch/checkout_by_name.go | 13 ++++- pkg/integration/tests/branch/delete.go | 15 ++++-- pkg/integration/tests/branch/rebase.go | 23 +++++++-- .../tests/branch/rebase_and_drop.go | 43 ++++++++++++----- pkg/integration/tests/branch/reset.go | 19 +++++--- .../tests/cherry_pick/cherry_pick.go | 37 +++++++++----- .../cherry_pick/cherry_pick_conflicts.go | 30 ++++++++---- pkg/integration/tests/commit/new_branch.go | 12 ++++- pkg/integration/tests/diff/diff.go | 5 +- .../tests/diff/diff_and_apply_patch.go | 5 +- pkg/integration/tests/diff/diff_commits.go | 7 ++- pkg/integration/tests/stash/rename.go | 6 ++- 14 files changed, 217 insertions(+), 61 deletions(-) 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") From fa0414777fcf266a05b777e2e8b7d487fd56f376 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Mon, 26 Dec 2022 10:42:19 +1100 Subject: [PATCH 2/7] rename SelectedLine to CurrentLine in tests --- pkg/integration/components/assert.go | 4 ++-- pkg/integration/components/input.go | 10 +++++----- pkg/integration/tests/bisect/basic.go | 12 ++++++------ pkg/integration/tests/branch/checkout_by_name.go | 2 +- pkg/integration/tests/branch/delete.go | 2 +- pkg/integration/tests/branch/rebase.go | 2 +- pkg/integration/tests/branch/rebase_and_drop.go | 6 +++--- .../tests/cherry_pick/cherry_pick_conflicts.go | 2 +- pkg/integration/tests/commit/staged.go | 2 +- pkg/integration/tests/commit/staged_without_hooks.go | 2 +- pkg/integration/tests/commit/unstaged.go | 2 +- pkg/integration/tests/custom_commands/basic.go | 2 +- .../tests/custom_commands/form_prompts.go | 2 +- .../tests/custom_commands/menu_from_command.go | 2 +- .../custom_commands/menu_from_commands_output.go | 2 +- .../tests/custom_commands/multiple_prompts.go | 2 +- pkg/integration/tests/diff/diff.go | 4 ++-- pkg/integration/tests/diff/diff_and_apply_patch.go | 6 +++--- pkg/integration/tests/diff/diff_commits.go | 4 ++-- pkg/integration/tests/file/discard_changes.go | 2 +- pkg/integration/tests/interactive_rebase/one.go | 8 ++++---- pkg/integration/tests/stash/rename.go | 2 +- 22 files changed, 41 insertions(+), 41 deletions(-) diff --git a/pkg/integration/components/assert.go b/pkg/integration/components/assert.go index 162b4a070..c81e25fab 100644 --- a/pkg/integration/components/assert.go +++ b/pkg/integration/components/assert.go @@ -143,7 +143,7 @@ func (self *Assert) InListContext() { }) } -func (self *Assert) SelectedLine(matcher *matcher) { +func (self *Assert) CurrentLine(matcher *matcher) { self.matchString(matcher, "Unexpected selected line.", func() string { return self.gui.CurrentContext().GetView().SelectedLine() @@ -151,7 +151,7 @@ func (self *Assert) SelectedLine(matcher *matcher) { ) } -func (self *Assert) SelectedLineIdx(expected int) { +func (self *Assert) CurrentLineIdx(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) diff --git a/pkg/integration/components/input.go b/pkg/integration/components/input.go index b6f2022c6..5905e2087 100644 --- a/pkg/integration/components/input.go +++ b/pkg/integration/components/input.go @@ -103,7 +103,7 @@ func (self *Input) PreviousItem() { func (self *Input) ContinueMerge() { self.Press(self.keys.Universal.CreateRebaseOptionsMenu) - self.assert.SelectedLine(Contains("continue")) + self.assert.CurrentLine(Contains("continue")) self.Confirm() } @@ -166,20 +166,20 @@ func (self *Input) NavigateToListItem(matcher *matcher) { selectedLineIdx := view.SelectedLineIdx() if selectedLineIdx == matchIndex { - self.assert.SelectedLine(matcher) + self.assert.CurrentLine(matcher) return } if selectedLineIdx < matchIndex { for i := selectedLineIdx; i < matchIndex; i++ { self.NextItem() } - self.assert.SelectedLine(matcher) + self.assert.CurrentLine(matcher) return } else { for i := selectedLineIdx; i > matchIndex; i-- { self.PreviousItem() } - self.assert.SelectedLine(matcher) + self.assert.CurrentLine(matcher) return } } @@ -213,7 +213,7 @@ func (self *Input) Typeahead(title *matcher, textToType string, expectedFirstOpt self.Type(textToType) self.Press(self.keys.Universal.TogglePanel) self.assert.CurrentViewName("suggestions") - self.assert.SelectedLine(expectedFirstOption) + self.assert.CurrentLine(expectedFirstOption) self.Confirm() } diff --git a/pkg/integration/tests/bisect/basic.go b/pkg/integration/tests/bisect/basic.go index f40b4fe39..eb44fa2ab 100644 --- a/pkg/integration/tests/bisect/basic.go +++ b/pkg/integration/tests/bisect/basic.go @@ -34,7 +34,7 @@ var Basic = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToCommitsWindow() - assert.SelectedLine(Contains("commit 10")) + assert.CurrentLine(Contains("commit 10")) input.NavigateToListItem(Contains("commit 09")) @@ -43,7 +43,7 @@ var Basic = NewIntegrationTest(NewIntegrationTestArgs{ assert.ViewContent("information", Contains("bisecting")) assert.CurrentViewName("commits") - assert.SelectedLine(Contains("<-- bad")) + assert.CurrentLine(Contains("<-- bad")) input.NavigateToListItem(Contains("commit 02")) @@ -51,14 +51,14 @@ var Basic = NewIntegrationTest(NewIntegrationTestArgs{ // lazygit will land us in the commit between our good and bad commits. assert.CurrentViewName("commits") - assert.SelectedLine(Contains("commit 05")) - assert.SelectedLine(Contains("<-- current")) + assert.CurrentLine(Contains("commit 05")) + assert.CurrentLine(Contains("<-- current")) markCommitAsBad() assert.CurrentViewName("commits") - assert.SelectedLine(Contains("commit 04")) - assert.SelectedLine(Contains("<-- current")) + assert.CurrentLine(Contains("commit 04")) + assert.CurrentLine(Contains("<-- current")) markCommitAsGood() diff --git a/pkg/integration/tests/branch/checkout_by_name.go b/pkg/integration/tests/branch/checkout_by_name.go index e34215037..652a1c58e 100644 --- a/pkg/integration/tests/branch/checkout_by_name.go +++ b/pkg/integration/tests/branch/checkout_by_name.go @@ -40,6 +40,6 @@ var CheckoutByName = NewIntegrationTest(NewIntegrationTestArgs{ Contains("@"), ) - assert.SelectedLine(Contains("new-branch")) + assert.CurrentLine(Contains("new-branch")) }, }) diff --git a/pkg/integration/tests/branch/delete.go b/pkg/integration/tests/branch/delete.go index 5192f1035..55e9b6aa5 100644 --- a/pkg/integration/tests/branch/delete.go +++ b/pkg/integration/tests/branch/delete.go @@ -39,6 +39,6 @@ var Delete = NewIntegrationTest(NewIntegrationTestArgs{ MatchesRegexp(`\*.*branch-two`), MatchesRegexp(`master`), ) - assert.SelectedLineIdx(1) + assert.CurrentLineIdx(1) }, }) diff --git a/pkg/integration/tests/branch/rebase.go b/pkg/integration/tests/branch/rebase.go index 96e3c1d72..8e60bd876 100644 --- a/pkg/integration/tests/branch/rebase.go +++ b/pkg/integration/tests/branch/rebase.go @@ -39,7 +39,7 @@ var Rebase = NewIntegrationTest(NewIntegrationTestArgs{ input.AcceptConfirmation(Equals("Auto-merge failed"), Contains("Conflicts!")) assert.CurrentViewName("files") - assert.SelectedLine(Contains("file")) + assert.CurrentLine(Contains("file")) // not using Confirm() convenience method because I suspect we might change this // keybinding to something more bespoke diff --git a/pkg/integration/tests/branch/rebase_and_drop.go b/pkg/integration/tests/branch/rebase_and_drop.go index 284f80f05..cb113997b 100644 --- a/pkg/integration/tests/branch/rebase_and_drop.go +++ b/pkg/integration/tests/branch/rebase_and_drop.go @@ -46,7 +46,7 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ input.AcceptConfirmation(Equals("Auto-merge failed"), Contains("Conflicts!")) assert.CurrentViewName("files") - assert.SelectedLine(Contains("file")) + assert.CurrentLine(Contains("file")) input.SwitchToCommitsWindow() assert.ViewTopLines( @@ -57,10 +57,10 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ MatchesRegexp("second change"), MatchesRegexp("original"), ) - assert.SelectedLineIdx(0) + assert.CurrentLineIdx(0) input.NextItem() input.Press(keys.Universal.Remove) - assert.SelectedLine(MatchesRegexp(`drop.*to remove`)) + assert.CurrentLine(MatchesRegexp(`drop.*to remove`)) input.SwitchToFilesWindow() diff --git a/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go b/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go index 6a9c47781..4095a563f 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go @@ -55,7 +55,7 @@ var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{ input.AcceptConfirmation(Equals("Auto-merge failed"), Contains("Conflicts!")) assert.CurrentViewName("files") - assert.SelectedLine(Contains("file")) + assert.CurrentLine(Contains("file")) // not using Confirm() convenience method because I suspect we might change this // keybinding to something more bespoke diff --git a/pkg/integration/tests/commit/staged.go b/pkg/integration/tests/commit/staged.go index acce2c76a..b39ab1b38 100644 --- a/pkg/integration/tests/commit/staged.go +++ b/pkg/integration/tests/commit/staged.go @@ -19,7 +19,7 @@ var Staged = NewIntegrationTest(NewIntegrationTestArgs{ assert.CommitCount(0) assert.CurrentViewName("files") - assert.SelectedLine(Contains("myfile")) + assert.CurrentLine(Contains("myfile")) // stage the file input.PrimaryAction() input.Enter() diff --git a/pkg/integration/tests/commit/staged_without_hooks.go b/pkg/integration/tests/commit/staged_without_hooks.go index bb0cba3c5..cc7b4bcaf 100644 --- a/pkg/integration/tests/commit/staged_without_hooks.go +++ b/pkg/integration/tests/commit/staged_without_hooks.go @@ -20,7 +20,7 @@ var StagedWithoutHooks = NewIntegrationTest(NewIntegrationTestArgs{ // stage the file assert.CurrentViewName("files") - assert.SelectedLine(Contains("myfile")) + assert.CurrentLine(Contains("myfile")) input.PrimaryAction() input.Enter() assert.CurrentViewName("stagingSecondary") diff --git a/pkg/integration/tests/commit/unstaged.go b/pkg/integration/tests/commit/unstaged.go index 92be9615b..7b12de6a3 100644 --- a/pkg/integration/tests/commit/unstaged.go +++ b/pkg/integration/tests/commit/unstaged.go @@ -21,7 +21,7 @@ var Unstaged = NewIntegrationTest(NewIntegrationTestArgs{ assert.CommitCount(0) assert.CurrentViewName("files") - assert.SelectedLine(Contains("myfile")) + assert.CurrentLine(Contains("myfile")) input.Enter() assert.CurrentViewName("staging") assert.ViewContent("stagingSecondary", NotContains("+myfile content")) diff --git a/pkg/integration/tests/custom_commands/basic.go b/pkg/integration/tests/custom_commands/basic.go index a97bdef4a..dfddb6d8c 100644 --- a/pkg/integration/tests/custom_commands/basic.go +++ b/pkg/integration/tests/custom_commands/basic.go @@ -31,6 +31,6 @@ var Basic = NewIntegrationTest(NewIntegrationTestArgs{ input.Press("a") assert.WorkingTreeFileCount(1) - assert.SelectedLine(Contains("myfile")) + assert.CurrentLine(Contains("myfile")) }, }) diff --git a/pkg/integration/tests/custom_commands/form_prompts.go b/pkg/integration/tests/custom_commands/form_prompts.go index e0502fbae..bfe559bf7 100644 --- a/pkg/integration/tests/custom_commands/form_prompts.go +++ b/pkg/integration/tests/custom_commands/form_prompts.go @@ -72,7 +72,7 @@ var FormPrompts = NewIntegrationTest(NewIntegrationTestArgs{ input.AcceptConfirmation(Equals("Are you sure?"), Equals("Are you REALLY sure you want to make this file? Up to you buddy.")) assert.WorkingTreeFileCount(1) - assert.SelectedLine(Contains("my file")) + assert.CurrentLine(Contains("my file")) assert.MainViewContent(Contains(`"BAR"`)) }, }) diff --git a/pkg/integration/tests/custom_commands/menu_from_command.go b/pkg/integration/tests/custom_commands/menu_from_command.go index 5d8fee71a..b75d77ef3 100644 --- a/pkg/integration/tests/custom_commands/menu_from_command.go +++ b/pkg/integration/tests/custom_commands/menu_from_command.go @@ -60,7 +60,7 @@ var MenuFromCommand = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToFilesWindow() assert.WorkingTreeFileCount(1) - assert.SelectedLine(Contains("output.txt")) + assert.CurrentLine(Contains("output.txt")) assert.MainViewContent(Contains("bar Branch: #feature/foo my branch feature/foo")) }, }) diff --git a/pkg/integration/tests/custom_commands/menu_from_commands_output.go b/pkg/integration/tests/custom_commands/menu_from_commands_output.go index 1a7860ebb..c4768aca0 100644 --- a/pkg/integration/tests/custom_commands/menu_from_commands_output.go +++ b/pkg/integration/tests/custom_commands/menu_from_commands_output.go @@ -56,7 +56,7 @@ var MenuFromCommandsOutput = NewIntegrationTest(NewIntegrationTestArgs{ assert.InPrompt() assert.CurrentViewTitle(Equals("Which git command do you want to run?")) - assert.SelectedLine(Equals("branch")) + assert.CurrentLine(Equals("branch")) input.Confirm() input.Menu(Equals("Branch:"), Equals("master")) diff --git a/pkg/integration/tests/custom_commands/multiple_prompts.go b/pkg/integration/tests/custom_commands/multiple_prompts.go index 5e6ebb6a2..ccb234f16 100644 --- a/pkg/integration/tests/custom_commands/multiple_prompts.go +++ b/pkg/integration/tests/custom_commands/multiple_prompts.go @@ -70,7 +70,7 @@ var MultiplePrompts = NewIntegrationTest(NewIntegrationTestArgs{ input.AcceptConfirmation(Equals("Are you sure?"), Equals("Are you REALLY sure you want to make this file? Up to you buddy.")) assert.WorkingTreeFileCount(1) - assert.SelectedLine(Contains("myfile")) + assert.CurrentLine(Contains("myfile")) assert.MainViewContent(Contains("BAR")) }, }) diff --git a/pkg/integration/tests/diff/diff.go b/pkg/integration/tests/diff/diff.go index da666377d..b9f88858c 100644 --- a/pkg/integration/tests/diff/diff.go +++ b/pkg/integration/tests/diff/diff.go @@ -42,10 +42,10 @@ var Diff = NewIntegrationTest(NewIntegrationTestArgs{ input.Enter() assert.CurrentViewName("subCommits") assert.MainViewContent(Contains("+second line")) - assert.SelectedLine(Contains("update")) + assert.CurrentLine(Contains("update")) input.Enter() assert.CurrentViewName("commitFiles") - assert.SelectedLine(Contains("file1")) + assert.CurrentLine(Contains("file1")) assert.MainViewContent(Contains("+second line")) input.Press(keys.Universal.Return) diff --git a/pkg/integration/tests/diff/diff_and_apply_patch.go b/pkg/integration/tests/diff/diff_and_apply_patch.go index c5d2b3e6e..0091579da 100644 --- a/pkg/integration/tests/diff/diff_and_apply_patch.go +++ b/pkg/integration/tests/diff/diff_and_apply_patch.go @@ -43,10 +43,10 @@ var DiffAndApplyPatch = NewIntegrationTest(NewIntegrationTestArgs{ input.Enter() assert.CurrentViewName("subCommits") assert.MainViewContent(Contains("+second line")) - assert.SelectedLine(Contains("update")) + assert.CurrentLine(Contains("update")) input.Enter() assert.CurrentViewName("commitFiles") - assert.SelectedLine(Contains("file1")) + assert.CurrentLine(Contains("file1")) assert.MainViewContent(Contains("+second line")) // add the file to the patch @@ -63,7 +63,7 @@ var DiffAndApplyPatch = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToFilesWindow() - assert.SelectedLine(Contains("file1")) + assert.CurrentLine(Contains("file1")) assert.MainViewContent(Contains("+second line")) }, }) diff --git a/pkg/integration/tests/diff/diff_commits.go b/pkg/integration/tests/diff/diff_commits.go index 39bf54d6f..03523de59 100644 --- a/pkg/integration/tests/diff/diff_commits.go +++ b/pkg/integration/tests/diff/diff_commits.go @@ -37,7 +37,7 @@ var DiffCommits = NewIntegrationTest(NewIntegrationTestArgs{ input.NextItem() input.NextItem() - assert.SelectedLine(Contains("first commit")) + assert.CurrentLine(Contains("first commit")) assert.MainViewContent(Contains("-second line\n-third line")) @@ -50,7 +50,7 @@ var DiffCommits = NewIntegrationTest(NewIntegrationTestArgs{ input.Enter() assert.CurrentViewName("commitFiles") - assert.SelectedLine(Contains("file1")) + assert.CurrentLine(Contains("file1")) assert.MainViewContent(Contains("+second line\n+third line")) }, }) diff --git a/pkg/integration/tests/file/discard_changes.go b/pkg/integration/tests/file/discard_changes.go index 87e39e96b..b08fc34d8 100644 --- a/pkg/integration/tests/file/discard_changes.go +++ b/pkg/integration/tests/file/discard_changes.go @@ -82,7 +82,7 @@ var DiscardChanges = NewIntegrationTest(NewIntegrationTestArgs{ discardOneByOne := func(files []statusFile) { for _, file := range files { - assert.SelectedLine(Contains(file.status + " " + file.label)) + assert.CurrentLine(Contains(file.status + " " + file.label)) input.Press(keys.Universal.Remove) input.Menu(Equals(file.menuTitle), Contains("discard all changes")) } diff --git a/pkg/integration/tests/interactive_rebase/one.go b/pkg/integration/tests/interactive_rebase/one.go index d516087ff..fdebd7ca8 100644 --- a/pkg/integration/tests/interactive_rebase/one.go +++ b/pkg/integration/tests/interactive_rebase/one.go @@ -20,19 +20,19 @@ var One = NewIntegrationTest(NewIntegrationTestArgs{ input.NavigateToListItem(Contains("commit 02")) input.Press(keys.Universal.Edit) - assert.SelectedLine(Contains("YOU ARE HERE")) + assert.CurrentLine(Contains("YOU ARE HERE")) input.PreviousItem() input.Press(keys.Commits.MarkCommitAsFixup) - assert.SelectedLine(Contains("fixup")) + assert.CurrentLine(Contains("fixup")) input.PreviousItem() input.Press(keys.Universal.Remove) - assert.SelectedLine(Contains("drop")) + assert.CurrentLine(Contains("drop")) input.PreviousItem() input.Press(keys.Commits.SquashDown) - assert.SelectedLine(Contains("squash")) + assert.CurrentLine(Contains("squash")) input.ContinueRebase() diff --git a/pkg/integration/tests/stash/rename.go b/pkg/integration/tests/stash/rename.go index de5385a56..98b16f96a 100644 --- a/pkg/integration/tests/stash/rename.go +++ b/pkg/integration/tests/stash/rename.go @@ -31,6 +31,6 @@ var Rename = NewIntegrationTest(NewIntegrationTestArgs{ input.Prompt(Equals("Rename stash: stash@{1}"), " baz") - assert.SelectedLine(Equals("On master: foo baz")) + assert.CurrentLine(Equals("On master: foo baz")) }, }) From 9a6f21ce429fedd949fdf9853c6ebf4892f858fd Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Mon, 26 Dec 2022 11:12:56 +1100 Subject: [PATCH 3/7] cleaner test assertions --- pkg/integration/components/assert.go | 178 ++++-------------- pkg/integration/components/input.go | 30 +-- pkg/integration/components/matcher.go | 46 +++++ pkg/integration/components/view_asserter.go | 111 +++++++++++ pkg/integration/tests/bisect/basic.go | 27 +-- .../tests/bisect/from_other_branch.go | 9 +- .../tests/branch/checkout_by_name.go | 18 +- pkg/integration/tests/branch/delete.go | 15 +- pkg/integration/tests/branch/rebase.go | 21 +-- .../tests/branch/rebase_and_drop.go | 43 +++-- pkg/integration/tests/branch/reset.go | 10 +- pkg/integration/tests/branch/suggestions.go | 2 +- .../tests/cherry_pick/cherry_pick.go | 20 +- .../cherry_pick/cherry_pick_conflicts.go | 35 ++-- .../tests/commit/commit_multiline.go | 2 +- pkg/integration/tests/commit/new_branch.go | 5 +- pkg/integration/tests/commit/revert.go | 16 +- pkg/integration/tests/commit/staged.go | 22 +-- .../tests/commit/staged_without_hooks.go | 26 +-- pkg/integration/tests/commit/unstaged.go | 11 +- .../tests/config/remote_named_star.go | 1 + .../tests/custom_commands/basic.go | 6 +- .../tests/custom_commands/form_prompts.go | 4 +- .../custom_commands/menu_from_command.go | 4 +- .../menu_from_commands_output.go | 5 +- .../tests/custom_commands/multiple_prompts.go | 4 +- pkg/integration/tests/diff/diff.go | 28 ++- .../tests/diff/diff_and_apply_patch.go | 29 ++- pkg/integration/tests/diff/diff_commits.go | 17 +- .../tests/file/dir_with_untracked_file.go | 9 +- pkg/integration/tests/file/discard_changes.go | 7 +- .../tests/interactive_rebase/amend_merge.go | 7 +- .../tests/interactive_rebase/one.go | 47 ++++- pkg/integration/tests/stash/rename.go | 5 +- 34 files changed, 442 insertions(+), 378 deletions(-) create mode 100644 pkg/integration/components/view_asserter.go diff --git a/pkg/integration/components/assert.go b/pkg/integration/components/assert.go index c81e25fab..ac6b99f0e 100644 --- a/pkg/integration/components/assert.go +++ b/pkg/integration/components/assert.go @@ -3,10 +3,9 @@ package components import ( "fmt" "os" - "regexp" - "strings" "time" + "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/gui/types" integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types" ) @@ -21,46 +20,6 @@ func NewAssert(gui integrationTypes.GuiDriver) *Assert { return &Assert{gui: gui} } -func Contains(target string) *matcher { - return NewMatcher( - fmt.Sprintf("contains '%s'", target), - func(value string) (bool, string) { - return strings.Contains(value, target), fmt.Sprintf("Expected '%s' to be found in '%s'", target, value) - }, - ) -} - -func NotContains(target string) *matcher { - return NewMatcher( - fmt.Sprintf("does not contain '%s'", target), - func(value string) (bool, string) { - return !strings.Contains(value, target), fmt.Sprintf("Expected '%s' to NOT be found in '%s'", target, value) - }, - ) -} - -func MatchesRegexp(target string) *matcher { - return NewMatcher( - fmt.Sprintf("matches regular expression '%s'", target), - func(value string) (bool, string) { - matched, err := regexp.MatchString(target, value) - if err != nil { - return false, fmt.Sprintf("Unexpected error parsing regular expression '%s': %s", target, err.Error()) - } - return matched, fmt.Sprintf("Expected '%s' to match regular expression '%s'", value, target) - }, - ) -} - -func Equals(target string) *matcher { - return NewMatcher( - fmt.Sprintf("equals '%s'", target), - func(value string) (bool, string) { - return target == value, fmt.Sprintf("Expected '%s' to equal '%s'", value, target) - }, - ) -} - func (self *Assert) WorkingTreeFileCount(expectedCount int) { self.assertWithRetries(func() (bool, string) { actualCount := len(self.gui.Model().Files) @@ -114,13 +73,6 @@ func (self *Assert) HeadCommitMessage(matcher *matcher) { ) } -func (self *Assert) CurrentViewName(expectedViewName string) { - self.assertWithRetries(func() (bool, string) { - actual := self.gui.CurrentContext().GetView().Name() - return actual == expectedViewName, fmt.Sprintf("Expected current view name to be '%s', but got '%s'", expectedViewName, actual) - }) -} - func (self *Assert) CurrentWindowName(expectedWindowName string) { self.assertWithRetries(func() (bool, string) { actual := self.gui.CurrentContext().GetView().Name() @@ -143,21 +95,6 @@ func (self *Assert) InListContext() { }) } -func (self *Assert) CurrentLine(matcher *matcher) { - self.matchString(matcher, "Unexpected selected line.", - func() string { - return self.gui.CurrentContext().GetView().SelectedLine() - }, - ) -} - -func (self *Assert) CurrentLineIdx(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() @@ -200,87 +137,6 @@ func (self *Assert) NotInPopup() { }) } -func (self *Assert) CurrentViewTitle(matcher *matcher) { - self.matchString(matcher, "Unexpected current view title.", - func() string { - return self.gui.CurrentContext().GetView().Title - }, - ) -} - -func (self *Assert) ViewContent(viewName string, matcher *matcher) { - self.matchString(matcher, fmt.Sprintf("Unexpected content in view '%s'.", viewName), - func() string { - return self.gui.View(viewName).Buffer() - }, - ) -} - -// 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 { - return self.gui.CurrentContext().GetView().Buffer() - }, - ) -} - -func (self *Assert) MainViewContent(matcher *matcher) { - self.matchString(matcher, "Unexpected main view content.", - func() string { - return self.gui.MainView().Buffer() - }, - ) -} - -func (self *Assert) SecondaryViewContent(matcher *matcher) { - self.matchString(matcher, "Unexpected secondary view title.", - func() string { - return self.gui.SecondaryView().Buffer() - }, - ) -} - func (self *Assert) matchString(matcher *matcher, context string, getValue func() string) { self.assertWithRetries(func() (bool, string) { value := getValue() @@ -325,3 +181,35 @@ func (self *Assert) FileSystemPathNotPresent(path string) { return os.IsNotExist(err), fmt.Sprintf("Expected path '%s' to not exist, but it does", path) }) } + +func (self *Assert) CurrentView() *ViewAsserter { + return &ViewAsserter{ + context: "current view", + getView: func() *gocui.View { return self.gui.CurrentContext().GetView() }, + assert: self, + } +} + +func (self *Assert) View(viewName string) *ViewAsserter { + return &ViewAsserter{ + context: fmt.Sprintf("%s view", viewName), + getView: func() *gocui.View { return self.gui.View(viewName) }, + assert: self, + } +} + +func (self *Assert) MainView() *ViewAsserter { + return &ViewAsserter{ + context: "main view", + getView: func() *gocui.View { return self.gui.MainView() }, + assert: self, + } +} + +func (self *Assert) SecondaryView() *ViewAsserter { + return &ViewAsserter{ + context: "secondary view", + getView: func() *gocui.View { return self.gui.SecondaryView() }, + assert: self, + } +} diff --git a/pkg/integration/components/input.go b/pkg/integration/components/input.go index 5905e2087..03aacd758 100644 --- a/pkg/integration/components/input.go +++ b/pkg/integration/components/input.go @@ -103,7 +103,7 @@ func (self *Input) PreviousItem() { func (self *Input) ContinueMerge() { self.Press(self.keys.Universal.CreateRebaseOptionsMenu) - self.assert.CurrentLine(Contains("continue")) + self.assert.CurrentView().SelectedLine(Contains("continue")) self.Confirm() } @@ -166,41 +166,41 @@ func (self *Input) NavigateToListItem(matcher *matcher) { selectedLineIdx := view.SelectedLineIdx() if selectedLineIdx == matchIndex { - self.assert.CurrentLine(matcher) + self.assert.CurrentView().SelectedLine(matcher) return } if selectedLineIdx < matchIndex { for i := selectedLineIdx; i < matchIndex; i++ { self.NextItem() } - self.assert.CurrentLine(matcher) + self.assert.CurrentView().SelectedLine(matcher) return } else { for i := selectedLineIdx; i > matchIndex; i-- { self.PreviousItem() } - self.assert.CurrentLine(matcher) + self.assert.CurrentView().SelectedLine(matcher) return } } func (self *Input) AcceptConfirmation(title *matcher, content *matcher) { self.assert.InConfirm() - self.assert.CurrentViewTitle(title) - self.assert.CurrentViewContent(content) + self.assert.CurrentView().Title(title) + self.assert.CurrentView().Content(content) self.Confirm() } func (self *Input) DenyConfirmation(title *matcher, content *matcher) { self.assert.InConfirm() - self.assert.CurrentViewTitle(title) - self.assert.CurrentViewContent(content) + self.assert.CurrentView().Title(title) + self.assert.CurrentView().Content(content) self.Cancel() } func (self *Input) Prompt(title *matcher, textToType string) { self.assert.InPrompt() - self.assert.CurrentViewTitle(title) + self.assert.CurrentView().Title(title) self.Type(textToType) self.Confirm() } @@ -209,24 +209,24 @@ func (self *Input) Prompt(title *matcher, textToType string) { // item to match the given matcher, then confirm that item. func (self *Input) Typeahead(title *matcher, textToType string, expectedFirstOption *matcher) { self.assert.InPrompt() - self.assert.CurrentViewTitle(title) + self.assert.CurrentView().Title(title) self.Type(textToType) self.Press(self.keys.Universal.TogglePanel) - self.assert.CurrentViewName("suggestions") - self.assert.CurrentLine(expectedFirstOption) + self.assert.CurrentView().Name("suggestions") + self.assert.CurrentView().SelectedLine(expectedFirstOption) self.Confirm() } func (self *Input) Menu(title *matcher, optionToSelect *matcher) { self.assert.InMenu() - self.assert.CurrentViewTitle(title) + self.assert.CurrentView().Title(title) self.NavigateToListItem(optionToSelect) self.Confirm() } func (self *Input) Alert(title *matcher, content *matcher) { self.assert.InListContext() - self.assert.CurrentViewTitle(title) - self.assert.CurrentViewContent(content) + self.assert.CurrentView().Title(title) + self.assert.CurrentView().Content(content) self.Confirm() } diff --git a/pkg/integration/components/matcher.go b/pkg/integration/components/matcher.go index 02b10b714..c8d47933c 100644 --- a/pkg/integration/components/matcher.go +++ b/pkg/integration/components/matcher.go @@ -1,5 +1,11 @@ package components +import ( + "fmt" + "regexp" + "strings" +) + // for making assertions on string values type matcher struct { // e.g. "contains 'foo'" @@ -33,3 +39,43 @@ func (self *matcher) context(prefix string) *matcher { return self } + +func Contains(target string) *matcher { + return NewMatcher( + fmt.Sprintf("contains '%s'", target), + func(value string) (bool, string) { + return strings.Contains(value, target), fmt.Sprintf("Expected '%s' to be found in '%s'", target, value) + }, + ) +} + +func NotContains(target string) *matcher { + return NewMatcher( + fmt.Sprintf("does not contain '%s'", target), + func(value string) (bool, string) { + return !strings.Contains(value, target), fmt.Sprintf("Expected '%s' to NOT be found in '%s'", target, value) + }, + ) +} + +func MatchesRegexp(target string) *matcher { + return NewMatcher( + fmt.Sprintf("matches regular expression '%s'", target), + func(value string) (bool, string) { + matched, err := regexp.MatchString(target, value) + if err != nil { + return false, fmt.Sprintf("Unexpected error parsing regular expression '%s': %s", target, err.Error()) + } + return matched, fmt.Sprintf("Expected '%s' to match regular expression '%s'", value, target) + }, + ) +} + +func Equals(target string) *matcher { + return NewMatcher( + fmt.Sprintf("equals '%s'", target), + func(value string) (bool, string) { + return target == value, fmt.Sprintf("Expected '%s' to equal '%s'", value, target) + }, + ) +} diff --git a/pkg/integration/components/view_asserter.go b/pkg/integration/components/view_asserter.go new file mode 100644 index 000000000..65535a598 --- /dev/null +++ b/pkg/integration/components/view_asserter.go @@ -0,0 +1,111 @@ +package components + +import ( + "fmt" + + "github.com/jesseduffield/gocui" +) + +type ViewAsserter struct { + // context is prepended to any error messages e.g. 'context: "current view"' + context string + getView func() *gocui.View + assert *Assert +} + +// asserts that the view has the expected name. This is typically used in tandem with the CurrentView method i.e.; +// assert.CurrentView().Name("commits") to assert that the current view is the commits view. +func (self *ViewAsserter) Name(expected string) *ViewAsserter { + self.assert.assertWithRetries(func() (bool, string) { + actual := self.getView().Name() + return actual == expected, fmt.Sprintf("%s: Expected view name to be '%s', but got '%s'", self.context, expected, actual) + }) + + return self +} + +// asserts that the view has the expected title +func (self *ViewAsserter) Title(expected *matcher) *ViewAsserter { + self.assert.assertWithRetries(func() (bool, string) { + actual := self.getView().Title + return expected.context(fmt.Sprintf("%s title", self.context)).test(actual) + }) + + return self +} + +// asserts that the view has lines matching the given matchers. So if three matchers +// are passed, we only check the first three lines of the view. +// This method is convenient when you have a list of commits but you only want to +// assert on the first couple of commits. +func (self *ViewAsserter) TopLines(matchers ...*matcher) *ViewAsserter { + self.assert.assertWithRetries(func() (bool, string) { + lines := self.getView().BufferLines() + return len(lines) >= len(matchers), fmt.Sprintf("unexpected number of lines in view. Expected at least %d, got %d", len(matchers), len(lines)) + }) + + view := self.getView() + + for i, matcher := range matchers { + self.assert.matchString(matcher, fmt.Sprintf("Unexpected content in view '%s'.", view.Name()), + func() string { + return view.BufferLines()[i] + }, + ) + } + + return self +} + +// asserts that the view has lines matching the given matchers. One matcher must be passed for each line. +// If you only care about the top n lines, use the TopLines method instead. +func (self *ViewAsserter) Lines(matchers ...*matcher) *ViewAsserter { + self.assert.assertWithRetries(func() (bool, string) { + lines := self.getView().BufferLines() + return len(lines) == len(matchers), fmt.Sprintf("unexpected number of lines in view. Expected %d, got %d", len(matchers), len(lines)) + }) + + view := self.getView() + + for i, matcher := range matchers { + self.assert.matchString(matcher, fmt.Sprintf("Unexpected content in view '%s'.", view.Name()), + func() string { + return view.BufferLines()[i] + }, + ) + } + + return self +} + +// asserts on the content of the view i.e. the stuff within the view's frame. +func (self *ViewAsserter) Content(matcher *matcher) *ViewAsserter { + self.assert.matchString(matcher, fmt.Sprintf("%s: Unexpected content.", self.context), + func() string { + return self.getView().Buffer() + }, + ) + + return self +} + +// asserts on the selected line of the view +func (self *ViewAsserter) SelectedLine(matcher *matcher) *ViewAsserter { + self.assert.matchString(matcher, fmt.Sprintf("%s: Unexpected selected line.", self.context), + func() string { + return self.getView().SelectedLine() + }, + ) + + return self +} + +// asserts on the index of the selected line. 0 is the first index, representing the line at the top of the view. +func (self *ViewAsserter) SelectedLineIdx(expected int) *ViewAsserter { + self.assert.assertWithRetries(func() (bool, string) { + actual := self.getView().SelectedLineIdx() + return expected == actual, fmt.Sprintf("%s: Expected selected line index to be %d, got %d", self.context, expected, actual) + }) + + return self +} diff --git a/pkg/integration/tests/bisect/basic.go b/pkg/integration/tests/bisect/basic.go index eb44fa2ab..58fcb8896 100644 --- a/pkg/integration/tests/bisect/basic.go +++ b/pkg/integration/tests/bisect/basic.go @@ -34,39 +34,40 @@ var Basic = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToCommitsWindow() - assert.CurrentLine(Contains("commit 10")) + assert.CurrentView().SelectedLine(Contains("commit 10")) input.NavigateToListItem(Contains("commit 09")) markCommitAsBad() - assert.ViewContent("information", Contains("bisecting")) + assert.View("information").Content(Contains("bisecting")) - assert.CurrentViewName("commits") - assert.CurrentLine(Contains("<-- bad")) + assert.CurrentView().Name("commits") + assert.CurrentView().SelectedLine(Contains("<-- bad")) input.NavigateToListItem(Contains("commit 02")) markCommitAsGood() // lazygit will land us in the commit between our good and bad commits. - assert.CurrentViewName("commits") - assert.CurrentLine(Contains("commit 05")) - assert.CurrentLine(Contains("<-- current")) + assert.CurrentView(). + Name("commits"). + SelectedLine(Contains("commit 05")). + SelectedLine(Contains("<-- current")) markCommitAsBad() - assert.CurrentViewName("commits") - assert.CurrentLine(Contains("commit 04")) - assert.CurrentLine(Contains("<-- current")) + assert.CurrentView(). + Name("commits"). + SelectedLine(Contains("commit 04")). + SelectedLine(Contains("<-- current")) markCommitAsGood() // commit 5 is the culprit because we marked 4 as good and 5 as bad. input.Alert(Equals("Bisect complete"), MatchesRegexp("(?s)commit 05.*Do you want to reset")) - assert.CurrentViewName("commits") - assert.CurrentViewContent(Contains("commit 04")) - assert.ViewContent("information", NotContains("bisecting")) + assert.CurrentView().Name("commits").Content(Contains("commit 04")) + assert.View("information").Content(NotContains("bisecting")) }, }) diff --git a/pkg/integration/tests/bisect/from_other_branch.go b/pkg/integration/tests/bisect/from_other_branch.go index 8c00f9d31..a523a4e3e 100644 --- a/pkg/integration/tests/bisect/from_other_branch.go +++ b/pkg/integration/tests/bisect/from_other_branch.go @@ -24,13 +24,13 @@ var FromOtherBranch = NewIntegrationTest(NewIntegrationTestArgs{ assert *Assert, keys config.KeybindingConfig, ) { - assert.ViewContent("information", Contains("bisecting")) + assert.View("information").Content(Contains("bisecting")) assert.AtLeastOneCommit() input.SwitchToCommitsWindow() - assert.ViewTopLines("commits", + assert.CurrentView().Name("commits").TopLines( MatchesRegexp(`<-- bad.*commit 08`), MatchesRegexp(`<-- current.*commit 07`), MatchesRegexp(`\?.*commit 06`), @@ -44,11 +44,10 @@ var FromOtherBranch = NewIntegrationTest(NewIntegrationTestArgs{ input.Alert(Equals("Bisect complete"), MatchesRegexp(`(?s)commit 08.*Do you want to reset`)) - assert.ViewContent("information", NotContains("bisecting")) + assert.View("information").Content(NotContains("bisecting")) // back in master branch which just had the one commit - assert.CurrentViewName("commits") - assert.CurrentViewLines( + assert.CurrentView().Name("commits").Lines( 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 652a1c58e..d8af26ee9 100644 --- a/pkg/integration/tests/branch/checkout_by_name.go +++ b/pkg/integration/tests/branch/checkout_by_name.go @@ -19,9 +19,8 @@ var CheckoutByName = NewIntegrationTest(NewIntegrationTestArgs{ }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { input.SwitchToBranchesWindow() - assert.CurrentViewName("localBranches") - assert.CurrentViewLines( + assert.CurrentView().Name("localBranches").Lines( Contains("master"), Contains("@"), ) @@ -33,13 +32,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.CurrentLine(Contains("new-branch")) + assert.CurrentView().Name("localBranches"). + Lines( + MatchesRegexp(`\*.*new-branch`), + Contains("master"), + Contains("@"), + ). + SelectedLine(Contains("new-branch")) }, }) diff --git a/pkg/integration/tests/branch/delete.go b/pkg/integration/tests/branch/delete.go index 55e9b6aa5..a873ebaef 100644 --- a/pkg/integration/tests/branch/delete.go +++ b/pkg/integration/tests/branch/delete.go @@ -18,9 +18,8 @@ var Delete = NewIntegrationTest(NewIntegrationTestArgs{ }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { input.SwitchToBranchesWindow() - assert.CurrentViewName("localBranches") - assert.CurrentViewLines( + assert.CurrentView().Name("localBranches").Lines( MatchesRegexp(`\*.*branch-two`), MatchesRegexp(`branch-one`), MatchesRegexp(`master`), @@ -34,11 +33,11 @@ var Delete = NewIntegrationTest(NewIntegrationTestArgs{ 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.CurrentViewLines( - MatchesRegexp(`\*.*branch-two`), - MatchesRegexp(`master`), - ) - assert.CurrentLineIdx(1) + assert.CurrentView().Name("localBranches"). + Lines( + MatchesRegexp(`\*.*branch-two`), + MatchesRegexp(`master`), + ). + SelectedLineIdx(1) }, }) diff --git a/pkg/integration/tests/branch/rebase.go b/pkg/integration/tests/branch/rebase.go index 8e60bd876..2b158e5e4 100644 --- a/pkg/integration/tests/branch/rebase.go +++ b/pkg/integration/tests/branch/rebase.go @@ -16,17 +16,15 @@ var Rebase = NewIntegrationTest(NewIntegrationTestArgs{ }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { input.SwitchToBranchesWindow() - assert.CurrentViewName("localBranches") + assert.CurrentView().Name("localBranches") - assert.ViewLines( - "localBranches", + assert.View("localBranches").Lines( Contains("first-change-branch"), Contains("second-change-branch"), Contains("original-branch"), ) - assert.ViewTopLines( - "commits", + assert.View("commits").TopLines( Contains("first change"), Contains("original"), ) @@ -35,27 +33,24 @@ var Rebase = NewIntegrationTest(NewIntegrationTestArgs{ 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'?")) - input.AcceptConfirmation(Equals("Auto-merge failed"), Contains("Conflicts!")) - assert.CurrentViewName("files") - assert.CurrentLine(Contains("file")) + assert.CurrentView().Name("files").SelectedLine(Contains("file")) // not using Confirm() convenience method because I suspect we might change this // keybinding to something more bespoke input.Press(keys.Universal.Confirm) - assert.CurrentViewName("mergeConflicts") + assert.CurrentView().Name("mergeConflicts") input.PrimaryAction() - assert.ViewContent("information", Contains("rebasing")) + assert.View("information").Content(Contains("rebasing")) input.AcceptConfirmation(Equals("continue"), Contains("all merge conflicts resolved. Continue?")) - assert.ViewContent("information", NotContains("rebasing")) + assert.View("information").Content(NotContains("rebasing")) - assert.ViewTopLines( - "commits", + assert.View("commits").TopLines( 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 cb113997b..5d62ed551 100644 --- a/pkg/integration/tests/branch/rebase_and_drop.go +++ b/pkg/integration/tests/branch/rebase_and_drop.go @@ -19,17 +19,14 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { input.SwitchToBranchesWindow() - assert.CurrentViewName("localBranches") - assert.ViewLines( - "localBranches", + assert.CurrentView().Name("localBranches").Lines( Contains("first-change-branch"), Contains("second-change-branch"), Contains("original-branch"), ) - assert.ViewTopLines( - "commits", + assert.View("commits").TopLines( Contains("to keep"), Contains("to remove"), Contains("first change"), @@ -41,26 +38,29 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ input.AcceptConfirmation(Equals("Rebasing"), Contains("Are you sure you want to rebase 'first-change-branch' on top of 'second-change-branch'?")) - assert.ViewContent("information", Contains("rebasing")) + assert.View("information").Content(Contains("rebasing")) input.AcceptConfirmation(Equals("Auto-merge failed"), Contains("Conflicts!")) - assert.CurrentViewName("files") - assert.CurrentLine(Contains("file")) + assert.CurrentView(). + Name("files"). + SelectedLine(Contains("file")) input.SwitchToCommitsWindow() - 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.CurrentLineIdx(0) + assert.CurrentView(). + Name("commits"). + TopLines( + MatchesRegexp(`pick.*to keep`), + MatchesRegexp(`pick.*to remove`), + MatchesRegexp("YOU ARE HERE.*second-change-branch unrelated change"), + MatchesRegexp("second change"), + MatchesRegexp("original"), + ). + SelectedLineIdx(0) + input.NextItem() input.Press(keys.Universal.Remove) - assert.CurrentLine(MatchesRegexp(`drop.*to remove`)) + assert.CurrentView().SelectedLine(MatchesRegexp(`drop.*to remove`)) input.SwitchToFilesWindow() @@ -68,15 +68,14 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ // keybinding to something more bespoke input.Press(keys.Universal.Confirm) - assert.CurrentViewName("mergeConflicts") + assert.CurrentView().Name("mergeConflicts") input.PrimaryAction() input.AcceptConfirmation(Equals("continue"), Contains("all merge conflicts resolved. Continue?")) - assert.ViewContent("information", NotContains("rebasing")) + assert.View("information").Content(NotContains("rebasing")) - assert.ViewTopLines( - "commits", + assert.View("commits").TopLines( Contains("to keep"), Contains("second-change-branch unrelated change"), Contains("second change"), diff --git a/pkg/integration/tests/branch/reset.go b/pkg/integration/tests/branch/reset.go index 4895a2cd8..d7b2db5a3 100644 --- a/pkg/integration/tests/branch/reset.go +++ b/pkg/integration/tests/branch/reset.go @@ -21,15 +21,14 @@ var Reset = NewIntegrationTest(NewIntegrationTestArgs{ shell.EmptyCommit("current-branch commit") }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { - assert.ViewLines("commits", + assert.View("commits").Lines( Contains("current-branch commit"), Contains("root commit"), ) input.SwitchToBranchesWindow() - assert.CurrentViewName("localBranches") - assert.CurrentViewLines( + assert.CurrentView().Name("localBranches").Lines( Contains("current-branch"), Contains("other-branch"), ) @@ -40,12 +39,11 @@ var Reset = NewIntegrationTest(NewIntegrationTestArgs{ input.Menu(Contains("reset to other-branch"), Contains("hard reset")) // ensure that we've returned from the menu before continuing - assert.CurrentViewName("localBranches") + assert.CurrentView().Name("localBranches") // assert that we now have the expected commits in the commit panel input.SwitchToCommitsWindow() - assert.CurrentViewName("commits") - assert.CurrentViewLines( + assert.CurrentView().Name("commits").Lines( Contains("other-branch commit"), Contains("root commit"), ) diff --git a/pkg/integration/tests/branch/suggestions.go b/pkg/integration/tests/branch/suggestions.go index 98cc3cf47..22c276556 100644 --- a/pkg/integration/tests/branch/suggestions.go +++ b/pkg/integration/tests/branch/suggestions.go @@ -22,7 +22,7 @@ var Suggestions = NewIntegrationTest(NewIntegrationTestArgs{ }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { input.SwitchToBranchesWindow() - assert.CurrentViewName("localBranches") + assert.CurrentView().Name("localBranches") input.Press(keys.Branches.CheckoutBranchByName) diff --git a/pkg/integration/tests/cherry_pick/cherry_pick.go b/pkg/integration/tests/cherry_pick/cherry_pick.go index 6d11b9a7e..7ca89f402 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick.go @@ -25,9 +25,8 @@ var CherryPick = NewIntegrationTest(NewIntegrationTestArgs{ }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { input.SwitchToBranchesWindow() - assert.CurrentViewName("localBranches") - assert.CurrentViewLines( + assert.CurrentView().Name("localBranches").Lines( Contains("first-branch"), Contains("second-branch"), Contains("master"), @@ -37,8 +36,7 @@ var CherryPick = NewIntegrationTest(NewIntegrationTestArgs{ input.Enter() - assert.CurrentViewName("subCommits") - assert.CurrentViewLines( + assert.CurrentView().Name("subCommits").Lines( Contains("four"), Contains("three"), Contains("base"), @@ -46,15 +44,14 @@ var CherryPick = NewIntegrationTest(NewIntegrationTestArgs{ // copy commits 'four' and 'three' input.Press(keys.Commits.CherryPickCopy) - assert.ViewContent("information", Contains("1 commit copied")) + assert.View("information").Content(Contains("1 commit copied")) input.NextItem() input.Press(keys.Commits.CherryPickCopy) - assert.ViewContent("information", Contains("2 commits copied")) + assert.View("information").Content(Contains("2 commits copied")) input.SwitchToCommitsWindow() - assert.CurrentViewName("commits") - assert.CurrentViewLines( + assert.CurrentView().Name("commits").Lines( Contains("two"), Contains("one"), Contains("base"), @@ -63,8 +60,7 @@ var CherryPick = NewIntegrationTest(NewIntegrationTestArgs{ 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.CurrentViewLines( + assert.CurrentView().Name("commits").Lines( Contains("four"), Contains("three"), Contains("two"), @@ -72,8 +68,8 @@ var CherryPick = NewIntegrationTest(NewIntegrationTestArgs{ Contains("base"), ) - assert.ViewContent("information", Contains("2 commits copied")) + assert.View("information").Content(Contains("2 commits copied")) input.Press(keys.Universal.Return) - assert.ViewContent("information", NotContains("commits copied")) + assert.View("information").Content(NotContains("commits copied")) }, }) diff --git a/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go b/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go index 4095a563f..3dfb995e2 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go @@ -16,9 +16,7 @@ var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{ }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { input.SwitchToBranchesWindow() - assert.CurrentViewName("localBranches") - - assert.CurrentViewLines( + assert.CurrentView().Name("localBranches").Lines( Contains("first-change-branch"), Contains("second-change-branch"), Contains("original-branch"), @@ -28,24 +26,21 @@ var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{ input.Enter() - assert.CurrentViewName("subCommits") - - assert.CurrentViewTopLines( + assert.CurrentView().Name("subCommits").TopLines( Contains("second-change-branch unrelated change"), Contains("second change"), ) input.Press(keys.Commits.CherryPickCopy) - assert.ViewContent("information", Contains("1 commit copied")) + assert.View("information").Content(Contains("1 commit copied")) input.NextItem() input.Press(keys.Commits.CherryPickCopy) - assert.ViewContent("information", Contains("2 commits copied")) + assert.View("information").Content(Contains("2 commits copied")) input.SwitchToCommitsWindow() - assert.CurrentViewName("commits") - assert.CurrentViewTopLines( + assert.CurrentView().Name("commits").TopLines( Contains("first change"), ) @@ -54,27 +49,26 @@ var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{ input.AcceptConfirmation(Equals("Auto-merge failed"), Contains("Conflicts!")) - assert.CurrentViewName("files") - assert.CurrentLine(Contains("file")) + assert.CurrentView().Name("files") + assert.CurrentView().SelectedLine(Contains("file")) // not using Confirm() convenience method because I suspect we might change this // keybinding to something more bespoke input.Press(keys.Universal.Confirm) - assert.CurrentViewName("mergeConflicts") + assert.CurrentView().Name("mergeConflicts") // picking 'Second change' input.NextItem() input.PrimaryAction() input.AcceptConfirmation(Equals("continue"), Contains("all merge conflicts resolved. Continue?")) - assert.CurrentViewName("files") + assert.CurrentView().Name("files") assert.WorkingTreeFileCount(0) input.SwitchToCommitsWindow() - assert.CurrentViewName("commits") - assert.CurrentViewTopLines( + assert.CurrentView().Name("commits").TopLines( Contains("second-change-branch unrelated change"), Contains("second change"), Contains("first change"), @@ -83,11 +77,12 @@ var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{ // 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")) + assert.MainView(). + Content(Contains("-First Change")). + Content(Contains("+Second Change")) - assert.ViewContent("information", Contains("2 commits copied")) + assert.View("information").Content(Contains("2 commits copied")) input.Press(keys.Universal.Return) - assert.ViewContent("information", NotContains("commits copied")) + assert.View("information").Content(NotContains("commits copied")) }, }) diff --git a/pkg/integration/tests/commit/commit_multiline.go b/pkg/integration/tests/commit/commit_multiline.go index 51e060ec3..79085926b 100644 --- a/pkg/integration/tests/commit/commit_multiline.go +++ b/pkg/integration/tests/commit/commit_multiline.go @@ -30,6 +30,6 @@ var CommitMultiline = NewIntegrationTest(NewIntegrationTestArgs{ assert.HeadCommitMessage(Equals("first line")) input.SwitchToCommitsWindow() - assert.MainViewContent(MatchesRegexp("first line\n\\s*\n\\s*third line")) + assert.MainView().Content(MatchesRegexp("first line\n\\s*\n\\s*third line")) }, }) diff --git a/pkg/integration/tests/commit/new_branch.go b/pkg/integration/tests/commit/new_branch.go index 349fff8ee..55887676b 100644 --- a/pkg/integration/tests/commit/new_branch.go +++ b/pkg/integration/tests/commit/new_branch.go @@ -20,8 +20,7 @@ var NewBranch = NewIntegrationTest(NewIntegrationTestArgs{ assert.CommitCount(3) input.SwitchToCommitsWindow() - assert.CurrentViewName("commits") - assert.CurrentViewLines( + assert.CurrentView().Name("commits").Lines( Contains("commit 3"), Contains("commit 2"), Contains("commit 1"), @@ -35,7 +34,7 @@ var NewBranch = NewIntegrationTest(NewIntegrationTestArgs{ assert.CurrentBranchName(branchName) - assert.ViewLines("commits", + assert.View("commits").Lines( Contains("commit 2"), Contains("commit 1"), ) diff --git a/pkg/integration/tests/commit/revert.go b/pkg/integration/tests/commit/revert.go index 448501763..c62124994 100644 --- a/pkg/integration/tests/commit/revert.go +++ b/pkg/integration/tests/commit/revert.go @@ -20,13 +20,21 @@ var Revert = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToCommitsWindow() + assert.CurrentView().Name("commits").Lines( + Contains("first commit"), + ) + input.Press(keys.Commits.RevertCommit) input.AcceptConfirmation(Equals("Revert commit"), MatchesRegexp(`Are you sure you want to revert \w+?`)) - assert.CommitCount(2) - assert.HeadCommitMessage(Contains("Revert \"first commit\"")) - input.PreviousItem() - assert.MainViewContent(Contains("-myfile content")) + assert.CurrentView().Name("commits"). + Lines( + Contains("Revert \"first commit\""), + Contains("first commit"), + ). + SelectedLineIdx(0) + + assert.MainView().Content(Contains("-myfile content")) assert.FileSystemPathNotPresent("myfile") }, }) diff --git a/pkg/integration/tests/commit/staged.go b/pkg/integration/tests/commit/staged.go index b39ab1b38..b018d9dfe 100644 --- a/pkg/integration/tests/commit/staged.go +++ b/pkg/integration/tests/commit/staged.go @@ -18,26 +18,26 @@ var Staged = NewIntegrationTest(NewIntegrationTestArgs{ Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { assert.CommitCount(0) - assert.CurrentViewName("files") - assert.CurrentLine(Contains("myfile")) + assert.CurrentView().Name("files") + assert.CurrentView().SelectedLine(Contains("myfile")) // stage the file input.PrimaryAction() input.Enter() - assert.CurrentViewName("stagingSecondary") + assert.CurrentView().Name("stagingSecondary") // we start with both lines having been staged - assert.ViewContent("stagingSecondary", Contains("+myfile content")) - assert.ViewContent("stagingSecondary", Contains("+with a second line")) - assert.ViewContent("staging", NotContains("+myfile content")) - assert.ViewContent("staging", NotContains("+with a second line")) + assert.View("stagingSecondary").Content(Contains("+myfile content")) + assert.View("stagingSecondary").Content(Contains("+with a second line")) + assert.View("staging").Content(NotContains("+myfile content")) + assert.View("staging").Content(NotContains("+with a second line")) // unstage the selected line input.PrimaryAction() // the line should have been moved to the main view - assert.ViewContent("stagingSecondary", NotContains("+myfile content")) - assert.ViewContent("stagingSecondary", Contains("+with a second line")) - assert.ViewContent("staging", Contains("+myfile content")) - assert.ViewContent("staging", NotContains("+with a second line")) + assert.View("stagingSecondary").Content(NotContains("+myfile content")) + assert.View("stagingSecondary").Content(Contains("+with a second line")) + assert.View("staging").Content(Contains("+myfile content")) + assert.View("staging").Content(NotContains("+with a second line")) input.Press(keys.Files.CommitChanges) commitMessage := "my commit message" diff --git a/pkg/integration/tests/commit/staged_without_hooks.go b/pkg/integration/tests/commit/staged_without_hooks.go index cc7b4bcaf..43d065db2 100644 --- a/pkg/integration/tests/commit/staged_without_hooks.go +++ b/pkg/integration/tests/commit/staged_without_hooks.go @@ -19,36 +19,36 @@ var StagedWithoutHooks = NewIntegrationTest(NewIntegrationTestArgs{ assert.CommitCount(0) // stage the file - assert.CurrentViewName("files") - assert.CurrentLine(Contains("myfile")) + assert.CurrentView().Name("files") + assert.CurrentView().SelectedLine(Contains("myfile")) input.PrimaryAction() input.Enter() - assert.CurrentViewName("stagingSecondary") + assert.CurrentView().Name("stagingSecondary") // we start with both lines having been staged - assert.ViewContent("stagingSecondary", Contains("+myfile content")) - assert.ViewContent("stagingSecondary", Contains("+with a second line")) - assert.ViewContent("staging", NotContains("+myfile content")) - assert.ViewContent("staging", NotContains("+with a second line")) + assert.View("stagingSecondary").Content(Contains("+myfile content")) + assert.View("stagingSecondary").Content(Contains("+with a second line")) + assert.View("staging").Content(NotContains("+myfile content")) + assert.View("staging").Content(NotContains("+with a second line")) // unstage the selected line input.PrimaryAction() // the line should have been moved to the main view - assert.ViewContent("stagingSecondary", NotContains("+myfile content")) - assert.ViewContent("stagingSecondary", Contains("+with a second line")) - assert.ViewContent("staging", Contains("+myfile content")) - assert.ViewContent("staging", NotContains("+with a second line")) + assert.View("stagingSecondary").Content(NotContains("+myfile content")) + assert.View("stagingSecondary").Content(Contains("+with a second line")) + assert.View("staging").Content(Contains("+myfile content")) + assert.View("staging").Content(NotContains("+with a second line")) input.Press(keys.Files.CommitChangesWithoutHook) assert.InCommitMessagePanel() - assert.CurrentViewContent(Contains("WIP")) + assert.CurrentView().Content(Contains("WIP")) commitMessage := ": my commit message" input.Type(commitMessage) input.Confirm() assert.CommitCount(1) assert.HeadCommitMessage(Equals("WIP" + commitMessage)) - assert.CurrentViewName("stagingSecondary") + assert.CurrentView().Name("stagingSecondary") // TODO: assert that the staging panel has been refreshed (it currently does not get correctly refreshed) }, diff --git a/pkg/integration/tests/commit/unstaged.go b/pkg/integration/tests/commit/unstaged.go index 7b12de6a3..a3c5b2812 100644 --- a/pkg/integration/tests/commit/unstaged.go +++ b/pkg/integration/tests/commit/unstaged.go @@ -20,15 +20,14 @@ var Unstaged = NewIntegrationTest(NewIntegrationTestArgs{ Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { assert.CommitCount(0) - assert.CurrentViewName("files") - assert.CurrentLine(Contains("myfile")) + assert.CurrentView().Name("files").SelectedLine(Contains("myfile")) input.Enter() - assert.CurrentViewName("staging") - assert.ViewContent("stagingSecondary", NotContains("+myfile content")) + assert.CurrentView().Name("staging") + assert.View("stagingSecondary").Content(NotContains("+myfile content")) // stage the first line input.PrimaryAction() - assert.ViewContent("staging", NotContains("+myfile content")) - assert.ViewContent("stagingSecondary", Contains("+myfile content")) + assert.View("staging").Content(NotContains("+myfile content")) + assert.View("stagingSecondary").Content(Contains("+myfile content")) input.Press(keys.Files.CommitChanges) assert.InCommitMessagePanel() diff --git a/pkg/integration/tests/config/remote_named_star.go b/pkg/integration/tests/config/remote_named_star.go index 3082c594f..fd28dea7b 100644 --- a/pkg/integration/tests/config/remote_named_star.go +++ b/pkg/integration/tests/config/remote_named_star.go @@ -21,6 +21,7 @@ var RemoteNamedStar = NewIntegrationTest(NewIntegrationTestArgs{ assert *Assert, keys config.KeybindingConfig, ) { + // here we're just asserting that we haven't panicked upon starting lazygit assert.AtLeastOneCommit() }, }) diff --git a/pkg/integration/tests/custom_commands/basic.go b/pkg/integration/tests/custom_commands/basic.go index dfddb6d8c..fc3cad569 100644 --- a/pkg/integration/tests/custom_commands/basic.go +++ b/pkg/integration/tests/custom_commands/basic.go @@ -30,7 +30,9 @@ var Basic = NewIntegrationTest(NewIntegrationTestArgs{ assert.WorkingTreeFileCount(0) input.Press("a") - assert.WorkingTreeFileCount(1) - assert.CurrentLine(Contains("myfile")) + + assert.View("files").Lines( + Contains("myfile"), + ) }, }) diff --git a/pkg/integration/tests/custom_commands/form_prompts.go b/pkg/integration/tests/custom_commands/form_prompts.go index bfe559bf7..8651efd39 100644 --- a/pkg/integration/tests/custom_commands/form_prompts.go +++ b/pkg/integration/tests/custom_commands/form_prompts.go @@ -72,7 +72,7 @@ var FormPrompts = NewIntegrationTest(NewIntegrationTestArgs{ input.AcceptConfirmation(Equals("Are you sure?"), Equals("Are you REALLY sure you want to make this file? Up to you buddy.")) assert.WorkingTreeFileCount(1) - assert.CurrentLine(Contains("my file")) - assert.MainViewContent(Contains(`"BAR"`)) + assert.CurrentView().SelectedLine(Contains("my file")) + assert.MainView().Content(Contains(`"BAR"`)) }, }) diff --git a/pkg/integration/tests/custom_commands/menu_from_command.go b/pkg/integration/tests/custom_commands/menu_from_command.go index b75d77ef3..7fee7ba6c 100644 --- a/pkg/integration/tests/custom_commands/menu_from_command.go +++ b/pkg/integration/tests/custom_commands/menu_from_command.go @@ -60,7 +60,7 @@ var MenuFromCommand = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToFilesWindow() assert.WorkingTreeFileCount(1) - assert.CurrentLine(Contains("output.txt")) - assert.MainViewContent(Contains("bar Branch: #feature/foo my branch feature/foo")) + assert.CurrentView().SelectedLine(Contains("output.txt")) + assert.MainView().Content(Contains("bar Branch: #feature/foo my branch feature/foo")) }, }) diff --git a/pkg/integration/tests/custom_commands/menu_from_commands_output.go b/pkg/integration/tests/custom_commands/menu_from_commands_output.go index c4768aca0..bfc26efcf 100644 --- a/pkg/integration/tests/custom_commands/menu_from_commands_output.go +++ b/pkg/integration/tests/custom_commands/menu_from_commands_output.go @@ -55,8 +55,9 @@ var MenuFromCommandsOutput = NewIntegrationTest(NewIntegrationTestArgs{ input.Press("a") assert.InPrompt() - assert.CurrentViewTitle(Equals("Which git command do you want to run?")) - assert.CurrentLine(Equals("branch")) + assert.CurrentView(). + Title(Equals("Which git command do you want to run?")). + SelectedLine(Equals("branch")) input.Confirm() input.Menu(Equals("Branch:"), Equals("master")) diff --git a/pkg/integration/tests/custom_commands/multiple_prompts.go b/pkg/integration/tests/custom_commands/multiple_prompts.go index ccb234f16..f3aa04728 100644 --- a/pkg/integration/tests/custom_commands/multiple_prompts.go +++ b/pkg/integration/tests/custom_commands/multiple_prompts.go @@ -70,7 +70,7 @@ var MultiplePrompts = NewIntegrationTest(NewIntegrationTestArgs{ input.AcceptConfirmation(Equals("Are you sure?"), Equals("Are you REALLY sure you want to make this file? Up to you buddy.")) assert.WorkingTreeFileCount(1) - assert.CurrentLine(Contains("myfile")) - assert.MainViewContent(Contains("BAR")) + assert.CurrentView().SelectedLine(Contains("myfile")) + assert.MainView().Content(Contains("BAR")) }, }) diff --git a/pkg/integration/tests/diff/diff.go b/pkg/integration/tests/diff/diff.go index b9f88858c..561b04be0 100644 --- a/pkg/integration/tests/diff/diff.go +++ b/pkg/integration/tests/diff/diff.go @@ -23,38 +23,36 @@ var Diff = NewIntegrationTest(NewIntegrationTestArgs{ }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { input.SwitchToBranchesWindow() - assert.CurrentViewName("localBranches") - assert.CurrentViewTopLines( + assert.CurrentView().Name("localBranches").TopLines( Contains("branch-a"), Contains("branch-b"), ) input.Press(keys.Universal.DiffingMenu) input.Menu(Equals("Diffing"), Contains(`diff branch-a`)) - assert.CurrentViewName("localBranches") + assert.CurrentView().Name("localBranches") - assert.ViewContent("information", Contains("showing output for: git diff branch-a branch-a")) + assert.View("information").Content(Contains("showing output for: git diff branch-a branch-a")) input.NextItem() - assert.ViewContent("information", Contains("showing output for: git diff branch-a branch-b")) - assert.MainViewContent(Contains("+second line")) + assert.View("information").Content(Contains("showing output for: git diff branch-a branch-b")) + assert.MainView().Content(Contains("+second line")) input.Enter() - assert.CurrentViewName("subCommits") - assert.MainViewContent(Contains("+second line")) - assert.CurrentLine(Contains("update")) + assert.CurrentView().Name("subCommits") + assert.MainView().Content(Contains("+second line")) + assert.CurrentView().SelectedLine(Contains("update")) input.Enter() - assert.CurrentViewName("commitFiles") - assert.CurrentLine(Contains("file1")) - assert.MainViewContent(Contains("+second line")) + assert.CurrentView().Name("commitFiles").SelectedLine(Contains("file1")) + assert.MainView().Content(Contains("+second line")) input.Press(keys.Universal.Return) input.Press(keys.Universal.Return) - assert.CurrentViewName("localBranches") + assert.CurrentView().Name("localBranches") input.Press(keys.Universal.DiffingMenu) input.Menu(Equals("Diffing"), Contains("reverse diff direction")) - assert.ViewContent("information", Contains("showing output for: git diff branch-a branch-b -R")) - assert.MainViewContent(Contains("-second line")) + assert.View("information").Content(Contains("showing output for: git diff branch-a branch-b -R")) + assert.MainView().Content(Contains("-second line")) }, }) diff --git a/pkg/integration/tests/diff/diff_and_apply_patch.go b/pkg/integration/tests/diff/diff_and_apply_patch.go index 0091579da..94b5f51d6 100644 --- a/pkg/integration/tests/diff/diff_and_apply_patch.go +++ b/pkg/integration/tests/diff/diff_and_apply_patch.go @@ -23,8 +23,7 @@ var DiffAndApplyPatch = NewIntegrationTest(NewIntegrationTestArgs{ }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { input.SwitchToBranchesWindow() - assert.CurrentViewName("localBranches") - assert.CurrentViewLines( + assert.CurrentView().Name("localBranches").Lines( Contains("branch-a"), Contains("branch-b"), ) @@ -33,21 +32,21 @@ var DiffAndApplyPatch = NewIntegrationTest(NewIntegrationTestArgs{ input.Menu(Equals("Diffing"), Equals("diff branch-a")) - assert.CurrentViewName("localBranches") + assert.CurrentView().Name("localBranches") - assert.ViewContent("information", Contains("showing output for: git diff branch-a branch-a")) + assert.View("information").Content(Contains("showing output for: git diff branch-a branch-a")) input.NextItem() - assert.ViewContent("information", Contains("showing output for: git diff branch-a branch-b")) - assert.MainViewContent(Contains("+second line")) + assert.View("information").Content(Contains("showing output for: git diff branch-a branch-b")) + assert.MainView().Content(Contains("+second line")) input.Enter() - assert.CurrentViewName("subCommits") - assert.MainViewContent(Contains("+second line")) - assert.CurrentLine(Contains("update")) + assert.CurrentView().Name("subCommits") + assert.MainView().Content(Contains("+second line")) + assert.CurrentView().SelectedLine(Contains("update")) input.Enter() - assert.CurrentViewName("commitFiles") - assert.CurrentLine(Contains("file1")) - assert.MainViewContent(Contains("+second line")) + assert.CurrentView().Name("commitFiles") + assert.CurrentView().SelectedLine(Contains("file1")) + assert.MainView().Content(Contains("+second line")) // add the file to the patch input.PrimaryAction() @@ -55,7 +54,7 @@ var DiffAndApplyPatch = NewIntegrationTest(NewIntegrationTestArgs{ input.Press(keys.Universal.DiffingMenu) input.Menu(Equals("Diffing"), Contains("exit diff mode")) - assert.ViewContent("information", NotContains("building patch")) + assert.View("information").Content(NotContains("building patch")) input.Press(keys.Universal.CreatePatchOptionsMenu) // adding the regex '$' here to distinguish the menu item from the 'apply patch in reverse' item @@ -63,7 +62,7 @@ var DiffAndApplyPatch = NewIntegrationTest(NewIntegrationTestArgs{ input.SwitchToFilesWindow() - assert.CurrentLine(Contains("file1")) - assert.MainViewContent(Contains("+second line")) + assert.CurrentView().SelectedLine(Contains("file1")) + assert.MainView().Content(Contains("+second line")) }, }) diff --git a/pkg/integration/tests/diff/diff_commits.go b/pkg/integration/tests/diff/diff_commits.go index 03523de59..280b6922c 100644 --- a/pkg/integration/tests/diff/diff_commits.go +++ b/pkg/integration/tests/diff/diff_commits.go @@ -20,9 +20,8 @@ var DiffCommits = NewIntegrationTest(NewIntegrationTestArgs{ }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { input.SwitchToCommitsWindow() - assert.CurrentViewName("commits") - assert.CurrentViewLines( + assert.CurrentView().Name("commits").Lines( Contains("third commit"), Contains("second commit"), Contains("first commit"), @@ -33,24 +32,24 @@ var DiffCommits = NewIntegrationTest(NewIntegrationTestArgs{ assert.NotInPopup() - assert.ViewContent("information", Contains("showing output for: git diff")) + assert.View("information").Content(Contains("showing output for: git diff")) input.NextItem() input.NextItem() - assert.CurrentLine(Contains("first commit")) + assert.CurrentView().SelectedLine(Contains("first commit")) - assert.MainViewContent(Contains("-second line\n-third line")) + assert.MainView().Content(Contains("-second line\n-third line")) input.Press(keys.Universal.DiffingMenu) input.Menu(Equals("Diffing"), Contains("reverse diff direction")) assert.NotInPopup() - assert.MainViewContent(Contains("+second line\n+third line")) + assert.MainView().Content(Contains("+second line\n+third line")) input.Enter() - assert.CurrentViewName("commitFiles") - assert.CurrentLine(Contains("file1")) - assert.MainViewContent(Contains("+second line\n+third line")) + assert.CurrentView().Name("commitFiles") + assert.CurrentView().SelectedLine(Contains("file1")) + assert.MainView().Content(Contains("+second line\n+third line")) }, }) diff --git a/pkg/integration/tests/file/dir_with_untracked_file.go b/pkg/integration/tests/file/dir_with_untracked_file.go index dc37798ee..acdb94499 100644 --- a/pkg/integration/tests/file/dir_with_untracked_file.go +++ b/pkg/integration/tests/file/dir_with_untracked_file.go @@ -24,9 +24,10 @@ var DirWithUntrackedFile = NewIntegrationTest(NewIntegrationTestArgs{ Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { assert.CommitCount(1) - assert.MainViewContent(NotContains("error: Could not access")) - // we show baz because it's a modified file but we don't show bar because it's untracked - // (though it would be cool if we could show that too) - assert.MainViewContent(Contains("baz")) + assert.MainView(). + Content(NotContains("error: Could not access")). + // we show baz because it's a modified file but we don't show bar because it's untracked + // (though it would be cool if we could show that too) + Content(Contains("baz")) }, }) diff --git a/pkg/integration/tests/file/discard_changes.go b/pkg/integration/tests/file/discard_changes.go index b08fc34d8..e44bb45d7 100644 --- a/pkg/integration/tests/file/discard_changes.go +++ b/pkg/integration/tests/file/discard_changes.go @@ -82,7 +82,7 @@ var DiscardChanges = NewIntegrationTest(NewIntegrationTestArgs{ discardOneByOne := func(files []statusFile) { for _, file := range files { - assert.CurrentLine(Contains(file.status + " " + file.label)) + assert.CurrentView().SelectedLine(Contains(file.status + " " + file.label)) input.Press(keys.Universal.Remove) input.Menu(Equals(file.menuTitle), Contains("discard all changes")) } @@ -98,10 +98,7 @@ var DiscardChanges = NewIntegrationTest(NewIntegrationTestArgs{ {status: "DU", label: "deleted-us.txt", menuTitle: "deleted-us.txt"}, }) - assert.InConfirm() - assert.CurrentViewTitle(Contains("continue")) - assert.CurrentViewContent(Contains("all merge conflicts resolved. Continue?")) - input.Press(keys.Universal.Return) + input.DenyConfirmation(Equals("continue"), Contains("all merge conflicts resolved. Continue?")) discardOneByOne([]statusFile{ {status: "MD", label: "change-delete.txt", menuTitle: "change-delete.txt"}, diff --git a/pkg/integration/tests/interactive_rebase/amend_merge.go b/pkg/integration/tests/interactive_rebase/amend_merge.go index 92f9f26a6..5ba891daf 100644 --- a/pkg/integration/tests/interactive_rebase/amend_merge.go +++ b/pkg/integration/tests/interactive_rebase/amend_merge.go @@ -31,7 +31,7 @@ var AmendMerge = NewIntegrationTest(NewIntegrationTestArgs{ assert.CommitCount(3) input.SwitchToCommitsWindow() - assert.CurrentViewName("commits") + assert.CurrentView().Name("commits") mergeCommitMessage := "Merge branch 'feature-branch' into development-branch" assert.HeadCommitMessage(Contains(mergeCommitMessage)) @@ -44,7 +44,8 @@ var AmendMerge = NewIntegrationTest(NewIntegrationTestArgs{ assert.HeadCommitMessage(Contains(mergeCommitMessage)) // assuring the post-merge file shows up in the merge commit. - assert.MainViewContent(Contains(postMergeFilename)) - assert.MainViewContent(Contains("++" + postMergeFileContent)) + assert.MainView(). + Content(Contains(postMergeFilename)). + Content(Contains("++" + postMergeFileContent)) }, }) diff --git a/pkg/integration/tests/interactive_rebase/one.go b/pkg/integration/tests/interactive_rebase/one.go index fdebd7ca8..0d6058e2f 100644 --- a/pkg/integration/tests/interactive_rebase/one.go +++ b/pkg/integration/tests/interactive_rebase/one.go @@ -16,26 +16,61 @@ var One = NewIntegrationTest(NewIntegrationTestArgs{ }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { input.SwitchToCommitsWindow() - assert.CurrentViewName("commits") + assert.CurrentView().Name("commits").Lines( + Contains("commit 05"), + Contains("commit 04"), + Contains("commit 03"), + Contains("commit 02"), + Contains("commit 01"), + ) input.NavigateToListItem(Contains("commit 02")) input.Press(keys.Universal.Edit) - assert.CurrentLine(Contains("YOU ARE HERE")) + + assert.CurrentView().Lines( + MatchesRegexp("pick.*commit 05"), + MatchesRegexp("pick.*commit 04"), + MatchesRegexp("pick.*commit 03"), + MatchesRegexp("YOU ARE HERE.*commit 02"), + Contains("commit 01"), + ) input.PreviousItem() input.Press(keys.Commits.MarkCommitAsFixup) - assert.CurrentLine(Contains("fixup")) + assert.CurrentView().Lines( + MatchesRegexp("pick.*commit 05"), + MatchesRegexp("pick.*commit 04"), + MatchesRegexp("fixup.*commit 03"), + MatchesRegexp("YOU ARE HERE.*commit 02"), + Contains("commit 01"), + ) input.PreviousItem() input.Press(keys.Universal.Remove) - assert.CurrentLine(Contains("drop")) + assert.CurrentView().Lines( + MatchesRegexp("pick.*commit 05"), + MatchesRegexp("drop.*commit 04"), + MatchesRegexp("fixup.*commit 03"), + MatchesRegexp("YOU ARE HERE.*commit 02"), + Contains("commit 01"), + ) input.PreviousItem() input.Press(keys.Commits.SquashDown) - assert.CurrentLine(Contains("squash")) + + assert.CurrentView().Lines( + MatchesRegexp("squash.*commit 05"), + MatchesRegexp("drop.*commit 04"), + MatchesRegexp("fixup.*commit 03"), + MatchesRegexp("YOU ARE HERE.*commit 02"), + Contains("commit 01"), + ) input.ContinueRebase() - assert.CommitCount(2) + assert.CurrentView().Lines( + Contains("commit 02"), + Contains("commit 01"), + ) }, }) diff --git a/pkg/integration/tests/stash/rename.go b/pkg/integration/tests/stash/rename.go index 98b16f96a..1eb44605e 100644 --- a/pkg/integration/tests/stash/rename.go +++ b/pkg/integration/tests/stash/rename.go @@ -20,9 +20,8 @@ var Rename = NewIntegrationTest(NewIntegrationTestArgs{ }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { input.SwitchToStashWindow() - assert.CurrentViewName("stash") - assert.CurrentViewLines( + assert.CurrentView().Name("stash").Lines( Equals("On master: bar"), Equals("On master: foo"), ) @@ -31,6 +30,6 @@ var Rename = NewIntegrationTest(NewIntegrationTestArgs{ input.Prompt(Equals("Rename stash: stash@{1}"), " baz") - assert.CurrentLine(Equals("On master: foo baz")) + assert.CurrentView().SelectedLine(Equals("On master: foo baz")) }, }) From c841ba82377a06b1ee562c377c2c7ac9319aa6e5 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Mon, 26 Dec 2022 16:49:54 +1100 Subject: [PATCH 4/7] add switch-to-view methods --- pkg/integration/components/input.go | 30 +++++++++++++++++++ pkg/integration/tests/bisect/basic.go | 2 +- .../tests/bisect/from_other_branch.go | 4 +-- .../tests/branch/checkout_by_name.go | 4 +-- pkg/integration/tests/branch/delete.go | 4 +-- pkg/integration/tests/branch/rebase.go | 3 +- .../tests/branch/rebase_and_drop.go | 9 +++--- pkg/integration/tests/branch/reset.go | 8 ++--- pkg/integration/tests/branch/suggestions.go | 3 +- .../tests/cherry_pick/cherry_pick.go | 8 ++--- .../cherry_pick/cherry_pick_conflicts.go | 12 ++++---- .../tests/commit/commit_multiline.go | 2 +- pkg/integration/tests/commit/new_branch.go | 4 +-- pkg/integration/tests/commit/revert.go | 4 +-- .../custom_commands/menu_from_command.go | 4 +-- .../menu_from_commands_output.go | 2 +- pkg/integration/tests/diff/diff.go | 4 +-- .../tests/diff/diff_and_apply_patch.go | 6 ++-- pkg/integration/tests/diff/diff_commits.go | 4 +-- .../tests/interactive_rebase/amend_merge.go | 3 +- .../tests/interactive_rebase/one.go | 4 +-- pkg/integration/tests/stash/rename.go | 4 +-- 22 files changed, 77 insertions(+), 51 deletions(-) diff --git a/pkg/integration/components/input.go b/pkg/integration/components/input.go index 03aacd758..796d1bf9d 100644 --- a/pkg/integration/components/input.go +++ b/pkg/integration/components/input.go @@ -45,26 +45,56 @@ func (self *Input) SwitchToStatusWindow() { self.assert.CurrentWindowName("status") } +// switch to status window and assert that the status view is on top +func (self *Input) SwitchToStatusView() { + self.SwitchToStatusWindow() + self.assert.CurrentView().Name("status") +} + func (self *Input) SwitchToFilesWindow() { self.press(self.keys.Universal.JumpToBlock[1]) self.assert.CurrentWindowName("files") } +// switch to files window and assert that the files view is on top +func (self *Input) SwitchToFilesView() { + self.SwitchToFilesWindow() + self.assert.CurrentView().Name("files") +} + func (self *Input) SwitchToBranchesWindow() { self.press(self.keys.Universal.JumpToBlock[2]) self.assert.CurrentWindowName("localBranches") } +// switch to branches window and assert that the branches view is on top +func (self *Input) SwitchToBranchesView() { + self.SwitchToBranchesWindow() + self.assert.CurrentView().Name("localBranches") +} + func (self *Input) SwitchToCommitsWindow() { self.press(self.keys.Universal.JumpToBlock[3]) self.assert.CurrentWindowName("commits") } +// switch to commits window and assert that the commits view is on top +func (self *Input) SwitchToCommitsView() { + self.SwitchToCommitsWindow() + self.assert.CurrentView().Name("commits") +} + func (self *Input) SwitchToStashWindow() { self.press(self.keys.Universal.JumpToBlock[4]) self.assert.CurrentWindowName("stash") } +// switch to stash window and assert that the stash view is on top +func (self *Input) SwitchToStashView() { + self.SwitchToStashWindow() + self.assert.CurrentView().Name("stash") +} + func (self *Input) Type(content string) { for _, char := range content { self.press(string(char)) diff --git a/pkg/integration/tests/bisect/basic.go b/pkg/integration/tests/bisect/basic.go index 58fcb8896..52e272c3a 100644 --- a/pkg/integration/tests/bisect/basic.go +++ b/pkg/integration/tests/bisect/basic.go @@ -32,7 +32,7 @@ var Basic = NewIntegrationTest(NewIntegrationTestArgs{ assert.AtLeastOneCommit() - input.SwitchToCommitsWindow() + input.SwitchToCommitsView() assert.CurrentView().SelectedLine(Contains("commit 10")) diff --git a/pkg/integration/tests/bisect/from_other_branch.go b/pkg/integration/tests/bisect/from_other_branch.go index a523a4e3e..36dad4705 100644 --- a/pkg/integration/tests/bisect/from_other_branch.go +++ b/pkg/integration/tests/bisect/from_other_branch.go @@ -28,9 +28,9 @@ var FromOtherBranch = NewIntegrationTest(NewIntegrationTestArgs{ assert.AtLeastOneCommit() - input.SwitchToCommitsWindow() + input.SwitchToCommitsView() - assert.CurrentView().Name("commits").TopLines( + assert.CurrentView().TopLines( MatchesRegexp(`<-- bad.*commit 08`), MatchesRegexp(`<-- current.*commit 07`), MatchesRegexp(`\?.*commit 06`), diff --git a/pkg/integration/tests/branch/checkout_by_name.go b/pkg/integration/tests/branch/checkout_by_name.go index d8af26ee9..d3742e8f9 100644 --- a/pkg/integration/tests/branch/checkout_by_name.go +++ b/pkg/integration/tests/branch/checkout_by_name.go @@ -18,9 +18,9 @@ var CheckoutByName = NewIntegrationTest(NewIntegrationTestArgs{ EmptyCommit("blah") }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { - input.SwitchToBranchesWindow() + input.SwitchToBranchesView() - assert.CurrentView().Name("localBranches").Lines( + assert.CurrentView().Lines( Contains("master"), Contains("@"), ) diff --git a/pkg/integration/tests/branch/delete.go b/pkg/integration/tests/branch/delete.go index a873ebaef..c90458546 100644 --- a/pkg/integration/tests/branch/delete.go +++ b/pkg/integration/tests/branch/delete.go @@ -17,9 +17,9 @@ var Delete = NewIntegrationTest(NewIntegrationTestArgs{ NewBranch("branch-two") }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { - input.SwitchToBranchesWindow() + input.SwitchToBranchesView() - assert.CurrentView().Name("localBranches").Lines( + assert.CurrentView().Lines( MatchesRegexp(`\*.*branch-two`), MatchesRegexp(`branch-one`), MatchesRegexp(`master`), diff --git a/pkg/integration/tests/branch/rebase.go b/pkg/integration/tests/branch/rebase.go index 2b158e5e4..ad0e40925 100644 --- a/pkg/integration/tests/branch/rebase.go +++ b/pkg/integration/tests/branch/rebase.go @@ -15,8 +15,7 @@ var Rebase = NewIntegrationTest(NewIntegrationTestArgs{ shared.MergeConflictsSetup(shell) }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { - input.SwitchToBranchesWindow() - assert.CurrentView().Name("localBranches") + input.SwitchToBranchesView() assert.View("localBranches").Lines( Contains("first-change-branch"), diff --git a/pkg/integration/tests/branch/rebase_and_drop.go b/pkg/integration/tests/branch/rebase_and_drop.go index 5d62ed551..5c1afe141 100644 --- a/pkg/integration/tests/branch/rebase_and_drop.go +++ b/pkg/integration/tests/branch/rebase_and_drop.go @@ -18,9 +18,9 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ shell.EmptyCommit("to keep") }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { - input.SwitchToBranchesWindow() + input.SwitchToBranchesView() - assert.CurrentView().Name("localBranches").Lines( + assert.CurrentView().Lines( Contains("first-change-branch"), Contains("second-change-branch"), Contains("original-branch"), @@ -46,9 +46,8 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ Name("files"). SelectedLine(Contains("file")) - input.SwitchToCommitsWindow() + input.SwitchToCommitsView() assert.CurrentView(). - Name("commits"). TopLines( MatchesRegexp(`pick.*to keep`), MatchesRegexp(`pick.*to remove`), @@ -62,7 +61,7 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ input.Press(keys.Universal.Remove) assert.CurrentView().SelectedLine(MatchesRegexp(`drop.*to remove`)) - input.SwitchToFilesWindow() + input.SwitchToFilesView() // not using Confirm() convenience method because I suspect we might change this // keybinding to something more bespoke diff --git a/pkg/integration/tests/branch/reset.go b/pkg/integration/tests/branch/reset.go index d7b2db5a3..8be35e4ec 100644 --- a/pkg/integration/tests/branch/reset.go +++ b/pkg/integration/tests/branch/reset.go @@ -26,9 +26,9 @@ var Reset = NewIntegrationTest(NewIntegrationTestArgs{ Contains("root commit"), ) - input.SwitchToBranchesWindow() + input.SwitchToBranchesView() - assert.CurrentView().Name("localBranches").Lines( + assert.CurrentView().Lines( Contains("current-branch"), Contains("other-branch"), ) @@ -42,8 +42,8 @@ var Reset = NewIntegrationTest(NewIntegrationTestArgs{ assert.CurrentView().Name("localBranches") // assert that we now have the expected commits in the commit panel - input.SwitchToCommitsWindow() - assert.CurrentView().Name("commits").Lines( + input.SwitchToCommitsView() + assert.CurrentView().Lines( Contains("other-branch commit"), Contains("root commit"), ) diff --git a/pkg/integration/tests/branch/suggestions.go b/pkg/integration/tests/branch/suggestions.go index 22c276556..7631ad735 100644 --- a/pkg/integration/tests/branch/suggestions.go +++ b/pkg/integration/tests/branch/suggestions.go @@ -21,8 +21,7 @@ var Suggestions = NewIntegrationTest(NewIntegrationTestArgs{ NewBranch("other-new-branch-3") }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { - input.SwitchToBranchesWindow() - assert.CurrentView().Name("localBranches") + input.SwitchToBranchesView() input.Press(keys.Branches.CheckoutBranchByName) diff --git a/pkg/integration/tests/cherry_pick/cherry_pick.go b/pkg/integration/tests/cherry_pick/cherry_pick.go index 7ca89f402..e306a016e 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick.go @@ -24,9 +24,9 @@ var CherryPick = NewIntegrationTest(NewIntegrationTestArgs{ Checkout("first-branch") }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { - input.SwitchToBranchesWindow() + input.SwitchToBranchesView() - assert.CurrentView().Name("localBranches").Lines( + assert.CurrentView().Lines( Contains("first-branch"), Contains("second-branch"), Contains("master"), @@ -49,9 +49,9 @@ var CherryPick = NewIntegrationTest(NewIntegrationTestArgs{ input.Press(keys.Commits.CherryPickCopy) assert.View("information").Content(Contains("2 commits copied")) - input.SwitchToCommitsWindow() + input.SwitchToCommitsView() - assert.CurrentView().Name("commits").Lines( + assert.CurrentView().Lines( Contains("two"), Contains("one"), Contains("base"), diff --git a/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go b/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go index 3dfb995e2..2aed02334 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go @@ -15,8 +15,8 @@ var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{ shared.MergeConflictsSetup(shell) }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { - input.SwitchToBranchesWindow() - assert.CurrentView().Name("localBranches").Lines( + input.SwitchToBranchesView() + assert.CurrentView().Lines( Contains("first-change-branch"), Contains("second-change-branch"), Contains("original-branch"), @@ -38,9 +38,9 @@ var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{ input.Press(keys.Commits.CherryPickCopy) assert.View("information").Content(Contains("2 commits copied")) - input.SwitchToCommitsWindow() + input.SwitchToCommitsView() - assert.CurrentView().Name("commits").TopLines( + assert.CurrentView().TopLines( Contains("first change"), ) @@ -66,9 +66,9 @@ var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{ assert.CurrentView().Name("files") assert.WorkingTreeFileCount(0) - input.SwitchToCommitsWindow() + input.SwitchToCommitsView() - assert.CurrentView().Name("commits").TopLines( + assert.CurrentView().TopLines( Contains("second-change-branch unrelated change"), Contains("second change"), Contains("first change"), diff --git a/pkg/integration/tests/commit/commit_multiline.go b/pkg/integration/tests/commit/commit_multiline.go index 79085926b..d19e09a72 100644 --- a/pkg/integration/tests/commit/commit_multiline.go +++ b/pkg/integration/tests/commit/commit_multiline.go @@ -29,7 +29,7 @@ var CommitMultiline = NewIntegrationTest(NewIntegrationTestArgs{ assert.CommitCount(1) assert.HeadCommitMessage(Equals("first line")) - input.SwitchToCommitsWindow() + input.SwitchToCommitsView() assert.MainView().Content(MatchesRegexp("first line\n\\s*\n\\s*third line")) }, }) diff --git a/pkg/integration/tests/commit/new_branch.go b/pkg/integration/tests/commit/new_branch.go index 55887676b..1702b0973 100644 --- a/pkg/integration/tests/commit/new_branch.go +++ b/pkg/integration/tests/commit/new_branch.go @@ -19,8 +19,8 @@ var NewBranch = NewIntegrationTest(NewIntegrationTestArgs{ Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { assert.CommitCount(3) - input.SwitchToCommitsWindow() - assert.CurrentView().Name("commits").Lines( + input.SwitchToCommitsView() + assert.CurrentView().Lines( Contains("commit 3"), Contains("commit 2"), Contains("commit 1"), diff --git a/pkg/integration/tests/commit/revert.go b/pkg/integration/tests/commit/revert.go index c62124994..e23091baf 100644 --- a/pkg/integration/tests/commit/revert.go +++ b/pkg/integration/tests/commit/revert.go @@ -18,9 +18,9 @@ var Revert = NewIntegrationTest(NewIntegrationTestArgs{ Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { assert.CommitCount(1) - input.SwitchToCommitsWindow() + input.SwitchToCommitsView() - assert.CurrentView().Name("commits").Lines( + assert.CurrentView().Lines( Contains("first commit"), ) diff --git a/pkg/integration/tests/custom_commands/menu_from_command.go b/pkg/integration/tests/custom_commands/menu_from_command.go index 7fee7ba6c..c4fe063e2 100644 --- a/pkg/integration/tests/custom_commands/menu_from_command.go +++ b/pkg/integration/tests/custom_commands/menu_from_command.go @@ -49,7 +49,7 @@ var MenuFromCommand = NewIntegrationTest(NewIntegrationTestArgs{ keys config.KeybindingConfig, ) { assert.WorkingTreeFileCount(0) - input.SwitchToBranchesWindow() + input.SwitchToBranchesView() input.Press("a") @@ -57,7 +57,7 @@ var MenuFromCommand = NewIntegrationTest(NewIntegrationTestArgs{ input.Prompt(Equals("Description"), " my branch") - input.SwitchToFilesWindow() + input.SwitchToFilesView() assert.WorkingTreeFileCount(1) assert.CurrentView().SelectedLine(Contains("output.txt")) diff --git a/pkg/integration/tests/custom_commands/menu_from_commands_output.go b/pkg/integration/tests/custom_commands/menu_from_commands_output.go index bfc26efcf..68c4db0f6 100644 --- a/pkg/integration/tests/custom_commands/menu_from_commands_output.go +++ b/pkg/integration/tests/custom_commands/menu_from_commands_output.go @@ -50,7 +50,7 @@ var MenuFromCommandsOutput = NewIntegrationTest(NewIntegrationTestArgs{ assert.CurrentBranchName("feature/bar") assert.WorkingTreeFileCount(0) - input.SwitchToBranchesWindow() + input.SwitchToBranchesView() input.Press("a") diff --git a/pkg/integration/tests/diff/diff.go b/pkg/integration/tests/diff/diff.go index 561b04be0..4bba36de8 100644 --- a/pkg/integration/tests/diff/diff.go +++ b/pkg/integration/tests/diff/diff.go @@ -22,9 +22,9 @@ var Diff = NewIntegrationTest(NewIntegrationTestArgs{ shell.Checkout("branch-a") }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { - input.SwitchToBranchesWindow() + input.SwitchToBranchesView() - assert.CurrentView().Name("localBranches").TopLines( + assert.CurrentView().TopLines( Contains("branch-a"), Contains("branch-b"), ) diff --git a/pkg/integration/tests/diff/diff_and_apply_patch.go b/pkg/integration/tests/diff/diff_and_apply_patch.go index 94b5f51d6..6e85b3911 100644 --- a/pkg/integration/tests/diff/diff_and_apply_patch.go +++ b/pkg/integration/tests/diff/diff_and_apply_patch.go @@ -22,8 +22,8 @@ var DiffAndApplyPatch = NewIntegrationTest(NewIntegrationTestArgs{ shell.Checkout("branch-a") }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { - input.SwitchToBranchesWindow() - assert.CurrentView().Name("localBranches").Lines( + input.SwitchToBranchesView() + assert.CurrentView().Lines( Contains("branch-a"), Contains("branch-b"), ) @@ -60,7 +60,7 @@ var DiffAndApplyPatch = NewIntegrationTest(NewIntegrationTestArgs{ // adding the regex '$' here to distinguish the menu item from the 'apply patch in reverse' item input.Menu(Equals("Patch Options"), MatchesRegexp("apply patch$")) - input.SwitchToFilesWindow() + input.SwitchToFilesView() assert.CurrentView().SelectedLine(Contains("file1")) assert.MainView().Content(Contains("+second line")) diff --git a/pkg/integration/tests/diff/diff_commits.go b/pkg/integration/tests/diff/diff_commits.go index 280b6922c..920686c2c 100644 --- a/pkg/integration/tests/diff/diff_commits.go +++ b/pkg/integration/tests/diff/diff_commits.go @@ -19,9 +19,9 @@ var DiffCommits = NewIntegrationTest(NewIntegrationTestArgs{ shell.Commit("third commit") }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { - input.SwitchToCommitsWindow() + input.SwitchToCommitsView() - assert.CurrentView().Name("commits").Lines( + assert.CurrentView().Lines( Contains("third commit"), Contains("second commit"), Contains("first commit"), diff --git a/pkg/integration/tests/interactive_rebase/amend_merge.go b/pkg/integration/tests/interactive_rebase/amend_merge.go index 5ba891daf..449d5f614 100644 --- a/pkg/integration/tests/interactive_rebase/amend_merge.go +++ b/pkg/integration/tests/interactive_rebase/amend_merge.go @@ -30,8 +30,7 @@ var AmendMerge = NewIntegrationTest(NewIntegrationTestArgs{ Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { assert.CommitCount(3) - input.SwitchToCommitsWindow() - assert.CurrentView().Name("commits") + input.SwitchToCommitsView() mergeCommitMessage := "Merge branch 'feature-branch' into development-branch" assert.HeadCommitMessage(Contains(mergeCommitMessage)) diff --git a/pkg/integration/tests/interactive_rebase/one.go b/pkg/integration/tests/interactive_rebase/one.go index 0d6058e2f..3c4c07a4d 100644 --- a/pkg/integration/tests/interactive_rebase/one.go +++ b/pkg/integration/tests/interactive_rebase/one.go @@ -15,8 +15,8 @@ var One = NewIntegrationTest(NewIntegrationTestArgs{ CreateNCommits(5) // these will appears at commit 05, 04, 04, down to 01 }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { - input.SwitchToCommitsWindow() - assert.CurrentView().Name("commits").Lines( + input.SwitchToCommitsView() + assert.CurrentView().Lines( Contains("commit 05"), Contains("commit 04"), Contains("commit 03"), diff --git a/pkg/integration/tests/stash/rename.go b/pkg/integration/tests/stash/rename.go index 1eb44605e..7088de423 100644 --- a/pkg/integration/tests/stash/rename.go +++ b/pkg/integration/tests/stash/rename.go @@ -19,9 +19,9 @@ var Rename = NewIntegrationTest(NewIntegrationTestArgs{ StashWithMessage("bar") }, Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { - input.SwitchToStashWindow() + input.SwitchToStashView() - assert.CurrentView().Name("stash").Lines( + assert.CurrentView().Lines( Equals("On master: bar"), Equals("On master: foo"), ) From 96310288eee4ec7ff45990fe8178c15a3299a037 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Mon, 26 Dec 2022 17:15:33 +1100 Subject: [PATCH 5/7] allow chaining matchers --- pkg/integration/components/input.go | 7 +- pkg/integration/components/matcher.go | 142 +++++++++++++----- pkg/integration/tests/bisect/basic.go | 8 +- .../tests/bisect/from_other_branch.go | 2 +- pkg/integration/tests/branch/rebase.go | 2 +- .../tests/branch/rebase_and_drop.go | 2 +- .../tests/cherry_pick/cherry_pick.go | 2 +- .../cherry_pick/cherry_pick_conflicts.go | 2 +- pkg/integration/tests/commit/staged.go | 8 +- .../tests/commit/staged_without_hooks.go | 16 +- pkg/integration/tests/commit/unstaged.go | 4 +- .../tests/diff/diff_and_apply_patch.go | 2 +- .../tests/file/dir_with_untracked_file.go | 2 +- 13 files changed, 132 insertions(+), 67 deletions(-) diff --git a/pkg/integration/components/input.go b/pkg/integration/components/input.go index 796d1bf9d..39f1991c1 100644 --- a/pkg/integration/components/input.go +++ b/pkg/integration/components/input.go @@ -177,8 +177,9 @@ func (self *Input) NavigateToListItem(matcher *matcher) { self.assert.assertWithRetries(func() (bool, string) { matchIndex = -1 var matches []string + lines := view.ViewBufferLines() // first we look for a duplicate on the current screen. We won't bother looking beyond that though. - for i, line := range view.ViewBufferLines() { + for i, line := range lines { ok, _ := matcher.test(line) if ok { matches = append(matches, line) @@ -186,9 +187,9 @@ func (self *Input) NavigateToListItem(matcher *matcher) { } } if len(matches) > 1 { - return false, fmt.Sprintf("Found %d matches for `%s`, expected only a single match. Lines:\n%s", len(matches), matcher.name, strings.Join(matches, "\n")) + return false, fmt.Sprintf("Found %d matches for `%s`, expected only a single match. Matching lines:\n%s", len(matches), matcher.name(), strings.Join(matches, "\n")) } else if len(matches) == 0 { - return false, fmt.Sprintf("Could not find item matching: %s", matcher.name) + return false, fmt.Sprintf("Could not find item matching: %s. Lines:\n%s", matcher.name(), strings.Join(lines, "\n")) } else { return true, "" } diff --git a/pkg/integration/components/matcher.go b/pkg/integration/components/matcher.go index c8d47933c..9885b7d5e 100644 --- a/pkg/integration/components/matcher.go +++ b/pkg/integration/components/matcher.go @@ -4,34 +4,118 @@ import ( "fmt" "regexp" "strings" + + "github.com/samber/lo" ) // for making assertions on string values type matcher struct { + rules []matcherRule + + // this is printed when there's an error so that it's clear what the context of the assertion is + prefix string +} + +type matcherRule struct { // e.g. "contains 'foo'" name string // returns a bool that says whether the test passed and if it returns false, it // also returns a string of the error message testFn func(string) (bool, string) - // this is printed when there's an error so that it's clear what the context of the assertion is - prefix string } func NewMatcher(name string, testFn func(string) (bool, string)) *matcher { - return &matcher{name: name, testFn: testFn} + rules := []matcherRule{{name: name, testFn: testFn}} + return &matcher{rules: rules} +} + +func (self *matcher) name() string { + if len(self.rules) == 0 { + return "anything" + } + + return strings.Join( + lo.Map(self.rules, func(rule matcherRule, _ int) string { return rule.name }), + ", ", + ) } func (self *matcher) test(value string) (bool, string) { - ok, message := self.testFn(value) - if ok { + // if there are no rules, then we pass the test by default + if len(self.rules) == 0 { return true, "" } - if self.prefix != "" { - return false, self.prefix + " " + message + for _, rule := range self.rules { + ok, message := rule.testFn(value) + if ok { + continue + } + + if self.prefix != "" { + return false, self.prefix + " " + message + } + + return false, message } - return false, message + return true, "" +} + +func (self *matcher) Contains(target string) *matcher { + rule := matcherRule{ + name: fmt.Sprintf("contains '%s'", target), + testFn: func(value string) (bool, string) { + return strings.Contains(value, target), fmt.Sprintf("Expected '%s' to be found in '%s'", target, value) + }, + } + + self.rules = append(self.rules, rule) + + return self +} + +func (self *matcher) DoesNotContain(target string) *matcher { + rule := matcherRule{ + name: fmt.Sprintf("does not contain '%s'", target), + testFn: func(value string) (bool, string) { + return !strings.Contains(value, target), fmt.Sprintf("Expected '%s' to NOT be found in '%s'", target, value) + }, + } + + self.rules = append(self.rules, rule) + + return self +} + +func (self *matcher) MatchesRegexp(target string) *matcher { + rule := matcherRule{ + name: fmt.Sprintf("matches regular expression '%s'", target), + testFn: func(value string) (bool, string) { + matched, err := regexp.MatchString(target, value) + if err != nil { + return false, fmt.Sprintf("Unexpected error parsing regular expression '%s': %s", target, err.Error()) + } + return matched, fmt.Sprintf("Expected '%s' to match regular expression '%s'", value, target) + }, + } + + self.rules = append(self.rules, rule) + + return self +} + +func (self *matcher) Equals(target string) *matcher { + rule := matcherRule{ + name: fmt.Sprintf("equals '%s'", target), + testFn: func(value string) (bool, string) { + return target == value, fmt.Sprintf("Expected '%s' to equal '%s'", value, target) + }, + } + + self.rules = append(self.rules, rule) + + return self } func (self *matcher) context(prefix string) *matcher { @@ -40,42 +124,24 @@ func (self *matcher) context(prefix string) *matcher { return self } -func Contains(target string) *matcher { - return NewMatcher( - fmt.Sprintf("contains '%s'", target), - func(value string) (bool, string) { - return strings.Contains(value, target), fmt.Sprintf("Expected '%s' to be found in '%s'", target, value) - }, - ) +// this matcher has no rules meaning it always passes the test. Use this +// when you don't care what value you're dealing with. +func Anything() *matcher { + return &matcher{} } -func NotContains(target string) *matcher { - return NewMatcher( - fmt.Sprintf("does not contain '%s'", target), - func(value string) (bool, string) { - return !strings.Contains(value, target), fmt.Sprintf("Expected '%s' to NOT be found in '%s'", target, value) - }, - ) +func Contains(target string) *matcher { + return Anything().Contains(target) +} + +func DoesNotContain(target string) *matcher { + return Anything().DoesNotContain(target) } func MatchesRegexp(target string) *matcher { - return NewMatcher( - fmt.Sprintf("matches regular expression '%s'", target), - func(value string) (bool, string) { - matched, err := regexp.MatchString(target, value) - if err != nil { - return false, fmt.Sprintf("Unexpected error parsing regular expression '%s': %s", target, err.Error()) - } - return matched, fmt.Sprintf("Expected '%s' to match regular expression '%s'", value, target) - }, - ) + return Anything().MatchesRegexp(target) } func Equals(target string) *matcher { - return NewMatcher( - fmt.Sprintf("equals '%s'", target), - func(value string) (bool, string) { - return target == value, fmt.Sprintf("Expected '%s' to equal '%s'", value, target) - }, - ) + return Anything().Equals(target) } diff --git a/pkg/integration/tests/bisect/basic.go b/pkg/integration/tests/bisect/basic.go index 52e272c3a..c6ad88c5b 100644 --- a/pkg/integration/tests/bisect/basic.go +++ b/pkg/integration/tests/bisect/basic.go @@ -52,15 +52,13 @@ var Basic = NewIntegrationTest(NewIntegrationTestArgs{ // lazygit will land us in the commit between our good and bad commits. assert.CurrentView(). Name("commits"). - SelectedLine(Contains("commit 05")). - SelectedLine(Contains("<-- current")) + SelectedLine(Contains("commit 05").Contains("<-- current")) markCommitAsBad() assert.CurrentView(). Name("commits"). - SelectedLine(Contains("commit 04")). - SelectedLine(Contains("<-- current")) + SelectedLine(Contains("commit 04").Contains("<-- current")) markCommitAsGood() @@ -68,6 +66,6 @@ var Basic = NewIntegrationTest(NewIntegrationTestArgs{ input.Alert(Equals("Bisect complete"), MatchesRegexp("(?s)commit 05.*Do you want to reset")) assert.CurrentView().Name("commits").Content(Contains("commit 04")) - assert.View("information").Content(NotContains("bisecting")) + assert.View("information").Content(DoesNotContain("bisecting")) }, }) diff --git a/pkg/integration/tests/bisect/from_other_branch.go b/pkg/integration/tests/bisect/from_other_branch.go index 36dad4705..cb31af972 100644 --- a/pkg/integration/tests/bisect/from_other_branch.go +++ b/pkg/integration/tests/bisect/from_other_branch.go @@ -44,7 +44,7 @@ var FromOtherBranch = NewIntegrationTest(NewIntegrationTestArgs{ input.Alert(Equals("Bisect complete"), MatchesRegexp(`(?s)commit 08.*Do you want to reset`)) - assert.View("information").Content(NotContains("bisecting")) + assert.View("information").Content(DoesNotContain("bisecting")) // back in master branch which just had the one commit assert.CurrentView().Name("commits").Lines( diff --git a/pkg/integration/tests/branch/rebase.go b/pkg/integration/tests/branch/rebase.go index ad0e40925..860331215 100644 --- a/pkg/integration/tests/branch/rebase.go +++ b/pkg/integration/tests/branch/rebase.go @@ -47,7 +47,7 @@ var Rebase = NewIntegrationTest(NewIntegrationTestArgs{ input.AcceptConfirmation(Equals("continue"), Contains("all merge conflicts resolved. Continue?")) - assert.View("information").Content(NotContains("rebasing")) + assert.View("information").Content(DoesNotContain("rebasing")) assert.View("commits").TopLines( Contains("second-change-branch unrelated change"), diff --git a/pkg/integration/tests/branch/rebase_and_drop.go b/pkg/integration/tests/branch/rebase_and_drop.go index 5c1afe141..479d240d9 100644 --- a/pkg/integration/tests/branch/rebase_and_drop.go +++ b/pkg/integration/tests/branch/rebase_and_drop.go @@ -72,7 +72,7 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ input.AcceptConfirmation(Equals("continue"), Contains("all merge conflicts resolved. Continue?")) - assert.View("information").Content(NotContains("rebasing")) + assert.View("information").Content(DoesNotContain("rebasing")) assert.View("commits").TopLines( Contains("to keep"), diff --git a/pkg/integration/tests/cherry_pick/cherry_pick.go b/pkg/integration/tests/cherry_pick/cherry_pick.go index e306a016e..e79e35b19 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick.go @@ -70,6 +70,6 @@ var CherryPick = NewIntegrationTest(NewIntegrationTestArgs{ assert.View("information").Content(Contains("2 commits copied")) input.Press(keys.Universal.Return) - assert.View("information").Content(NotContains("commits copied")) + assert.View("information").Content(DoesNotContain("commits copied")) }, }) diff --git a/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go b/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go index 2aed02334..4ed310e1d 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go @@ -83,6 +83,6 @@ var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{ assert.View("information").Content(Contains("2 commits copied")) input.Press(keys.Universal.Return) - assert.View("information").Content(NotContains("commits copied")) + assert.View("information").Content(DoesNotContain("commits copied")) }, }) diff --git a/pkg/integration/tests/commit/staged.go b/pkg/integration/tests/commit/staged.go index b018d9dfe..4a0c3eafc 100644 --- a/pkg/integration/tests/commit/staged.go +++ b/pkg/integration/tests/commit/staged.go @@ -27,17 +27,17 @@ var Staged = NewIntegrationTest(NewIntegrationTestArgs{ // we start with both lines having been staged assert.View("stagingSecondary").Content(Contains("+myfile content")) assert.View("stagingSecondary").Content(Contains("+with a second line")) - assert.View("staging").Content(NotContains("+myfile content")) - assert.View("staging").Content(NotContains("+with a second line")) + assert.View("staging").Content(DoesNotContain("+myfile content")) + assert.View("staging").Content(DoesNotContain("+with a second line")) // unstage the selected line input.PrimaryAction() // the line should have been moved to the main view - assert.View("stagingSecondary").Content(NotContains("+myfile content")) + assert.View("stagingSecondary").Content(DoesNotContain("+myfile content")) assert.View("stagingSecondary").Content(Contains("+with a second line")) assert.View("staging").Content(Contains("+myfile content")) - assert.View("staging").Content(NotContains("+with a second line")) + assert.View("staging").Content(DoesNotContain("+with a second line")) input.Press(keys.Files.CommitChanges) commitMessage := "my commit message" diff --git a/pkg/integration/tests/commit/staged_without_hooks.go b/pkg/integration/tests/commit/staged_without_hooks.go index 43d065db2..e2f0752f0 100644 --- a/pkg/integration/tests/commit/staged_without_hooks.go +++ b/pkg/integration/tests/commit/staged_without_hooks.go @@ -25,19 +25,19 @@ var StagedWithoutHooks = NewIntegrationTest(NewIntegrationTestArgs{ input.Enter() assert.CurrentView().Name("stagingSecondary") // we start with both lines having been staged - assert.View("stagingSecondary").Content(Contains("+myfile content")) - assert.View("stagingSecondary").Content(Contains("+with a second line")) - assert.View("staging").Content(NotContains("+myfile content")) - assert.View("staging").Content(NotContains("+with a second line")) + assert.View("stagingSecondary").Content( + Contains("+myfile content").Contains("+with a second line"), + ) + assert.View("staging").Content( + DoesNotContain("+myfile content").DoesNotContain("+with a second line"), + ) // unstage the selected line input.PrimaryAction() // the line should have been moved to the main view - assert.View("stagingSecondary").Content(NotContains("+myfile content")) - assert.View("stagingSecondary").Content(Contains("+with a second line")) - assert.View("staging").Content(Contains("+myfile content")) - assert.View("staging").Content(NotContains("+with a second line")) + assert.View("stagingSecondary").Content(DoesNotContain("+myfile content").Contains("+with a second line")) + assert.View("staging").Content(Contains("+myfile content").DoesNotContain("+with a second line")) input.Press(keys.Files.CommitChangesWithoutHook) assert.InCommitMessagePanel() diff --git a/pkg/integration/tests/commit/unstaged.go b/pkg/integration/tests/commit/unstaged.go index a3c5b2812..6e7e2a307 100644 --- a/pkg/integration/tests/commit/unstaged.go +++ b/pkg/integration/tests/commit/unstaged.go @@ -23,10 +23,10 @@ var Unstaged = NewIntegrationTest(NewIntegrationTestArgs{ assert.CurrentView().Name("files").SelectedLine(Contains("myfile")) input.Enter() assert.CurrentView().Name("staging") - assert.View("stagingSecondary").Content(NotContains("+myfile content")) + assert.View("stagingSecondary").Content(DoesNotContain("+myfile content")) // stage the first line input.PrimaryAction() - assert.View("staging").Content(NotContains("+myfile content")) + assert.View("staging").Content(DoesNotContain("+myfile content")) assert.View("stagingSecondary").Content(Contains("+myfile content")) input.Press(keys.Files.CommitChanges) diff --git a/pkg/integration/tests/diff/diff_and_apply_patch.go b/pkg/integration/tests/diff/diff_and_apply_patch.go index 6e85b3911..e963bb296 100644 --- a/pkg/integration/tests/diff/diff_and_apply_patch.go +++ b/pkg/integration/tests/diff/diff_and_apply_patch.go @@ -54,7 +54,7 @@ var DiffAndApplyPatch = NewIntegrationTest(NewIntegrationTestArgs{ input.Press(keys.Universal.DiffingMenu) input.Menu(Equals("Diffing"), Contains("exit diff mode")) - assert.View("information").Content(NotContains("building patch")) + assert.View("information").Content(DoesNotContain("building patch")) input.Press(keys.Universal.CreatePatchOptionsMenu) // adding the regex '$' here to distinguish the menu item from the 'apply patch in reverse' item diff --git a/pkg/integration/tests/file/dir_with_untracked_file.go b/pkg/integration/tests/file/dir_with_untracked_file.go index acdb94499..b85ea273b 100644 --- a/pkg/integration/tests/file/dir_with_untracked_file.go +++ b/pkg/integration/tests/file/dir_with_untracked_file.go @@ -25,7 +25,7 @@ var DirWithUntrackedFile = NewIntegrationTest(NewIntegrationTestArgs{ assert.CommitCount(1) assert.MainView(). - Content(NotContains("error: Could not access")). + Content(DoesNotContain("error: Could not access")). // we show baz because it's a modified file but we don't show bar because it's untracked // (though it would be cool if we could show that too) Content(Contains("baz")) From 09db4c4397c67f918bc09f7ca434be1eff5a2a06 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Mon, 26 Dec 2022 17:37:41 +1100 Subject: [PATCH 6/7] allow checking if line is selected in Lines and TopLines methods --- pkg/integration/components/matcher.go | 59 +++++++++++-------- pkg/integration/components/view_asserter.go | 25 ++++---- pkg/integration/tests/bisect/basic.go | 3 +- pkg/integration/tests/branch/delete.go | 5 +- .../tests/branch/rebase_and_drop.go | 21 ++++--- pkg/integration/tests/commit/revert.go | 5 +- pkg/integration/tests/diff/diff_commits.go | 3 +- 7 files changed, 68 insertions(+), 53 deletions(-) diff --git a/pkg/integration/components/matcher.go b/pkg/integration/components/matcher.go index 9885b7d5e..0bbb1109b 100644 --- a/pkg/integration/components/matcher.go +++ b/pkg/integration/components/matcher.go @@ -41,11 +41,6 @@ func (self *matcher) name() string { } func (self *matcher) test(value string) (bool, string) { - // if there are no rules, then we pass the test by default - if len(self.rules) == 0 { - return true, "" - } - for _, rule := range self.rules { ok, message := rule.testFn(value) if ok { @@ -63,33 +58,25 @@ func (self *matcher) test(value string) (bool, string) { } func (self *matcher) Contains(target string) *matcher { - rule := matcherRule{ + return self.appendRule(matcherRule{ name: fmt.Sprintf("contains '%s'", target), testFn: func(value string) (bool, string) { return strings.Contains(value, target), fmt.Sprintf("Expected '%s' to be found in '%s'", target, value) }, - } - - self.rules = append(self.rules, rule) - - return self + }) } func (self *matcher) DoesNotContain(target string) *matcher { - rule := matcherRule{ + return self.appendRule(matcherRule{ name: fmt.Sprintf("does not contain '%s'", target), testFn: func(value string) (bool, string) { return !strings.Contains(value, target), fmt.Sprintf("Expected '%s' to NOT be found in '%s'", target, value) }, - } - - self.rules = append(self.rules, rule) - - return self + }) } func (self *matcher) MatchesRegexp(target string) *matcher { - rule := matcherRule{ + return self.appendRule(matcherRule{ name: fmt.Sprintf("matches regular expression '%s'", target), testFn: func(value string) (bool, string) { matched, err := regexp.MatchString(target, value) @@ -98,32 +85,54 @@ func (self *matcher) MatchesRegexp(target string) *matcher { } return matched, fmt.Sprintf("Expected '%s' to match regular expression '%s'", value, target) }, - } - - self.rules = append(self.rules, rule) - - return self + }) } func (self *matcher) Equals(target string) *matcher { - rule := matcherRule{ + return self.appendRule(matcherRule{ name: fmt.Sprintf("equals '%s'", target), testFn: func(value string) (bool, string) { return target == value, fmt.Sprintf("Expected '%s' to equal '%s'", value, target) }, - } + }) +} +const IS_SELECTED_RULE_NAME = "is selected" + +// special rule that is only to be used in the TopLines and Lines methods, as a way of +// asserting that a given line is selected. +func (self *matcher) IsSelected() *matcher { + return self.appendRule(matcherRule{ + name: IS_SELECTED_RULE_NAME, + testFn: func(value string) (bool, string) { + panic("Special IsSelected matcher is not supposed to have its testFn method called. This rule should only be used within the .Lines() and .TopLines() method on a ViewAsserter.") + }, + }) +} + +func (self *matcher) appendRule(rule matcherRule) *matcher { self.rules = append(self.rules, rule) return self } +// adds context so that if the matcher test(s) fails, we understand what we were trying to test. +// E.g. prefix: "Unexpected content in view 'files'." func (self *matcher) context(prefix string) *matcher { self.prefix = prefix return self } +// if the matcher has an `IsSelected` rule, it returns true, along with the matcher after that rule has been removed +func (self *matcher) checkIsSelected() (bool, *matcher) { + check := lo.ContainsBy(self.rules, func(rule matcherRule) bool { return rule.name == IS_SELECTED_RULE_NAME }) + + self.rules = lo.Filter(self.rules, func(rule matcherRule, _ int) bool { return rule.name != IS_SELECTED_RULE_NAME }) + + return check, self +} + // this matcher has no rules meaning it always passes the test. Use this // when you don't care what value you're dealing with. func Anything() *matcher { diff --git a/pkg/integration/components/view_asserter.go b/pkg/integration/components/view_asserter.go index 65535a598..73f315993 100644 --- a/pkg/integration/components/view_asserter.go +++ b/pkg/integration/components/view_asserter.go @@ -44,17 +44,7 @@ func (self *ViewAsserter) TopLines(matchers ...*matcher) *ViewAsserter { return len(lines) >= len(matchers), fmt.Sprintf("unexpected number of lines in view. Expected at least %d, got %d", len(matchers), len(lines)) }) - view := self.getView() - - for i, matcher := range matchers { - self.assert.matchString(matcher, fmt.Sprintf("Unexpected content in view '%s'.", view.Name()), - func() string { - return view.BufferLines()[i] - }, - ) - } - - return self + return self.assertLines(matchers...) } // asserts that the view has lines matching the given matchers. One matcher must be passed for each line. @@ -65,14 +55,27 @@ func (self *ViewAsserter) Lines(matchers ...*matcher) *ViewAsserter { return len(lines) == len(matchers), fmt.Sprintf("unexpected number of lines in view. Expected %d, got %d", len(matchers), len(lines)) }) + return self.assertLines(matchers...) +} + +func (self *ViewAsserter) assertLines(matchers ...*matcher) *ViewAsserter { view := self.getView() for i, matcher := range matchers { + checkIsSelected, matcher := matcher.checkIsSelected() + self.assert.matchString(matcher, fmt.Sprintf("Unexpected content in view '%s'.", view.Name()), func() string { return view.BufferLines()[i] }, ) + + if checkIsSelected { + self.assert.assertWithRetries(func() (bool, string) { + lineIdx := view.SelectedLineIdx() + return lineIdx == i, fmt.Sprintf("Unexpected selected line index in view '%s'. Expected %d, got %d", view.Name(), i, lineIdx) + }) + } } return self diff --git a/pkg/integration/tests/bisect/basic.go b/pkg/integration/tests/bisect/basic.go index c6ad88c5b..45d66fa18 100644 --- a/pkg/integration/tests/bisect/basic.go +++ b/pkg/integration/tests/bisect/basic.go @@ -42,8 +42,7 @@ var Basic = NewIntegrationTest(NewIntegrationTestArgs{ assert.View("information").Content(Contains("bisecting")) - assert.CurrentView().Name("commits") - assert.CurrentView().SelectedLine(Contains("<-- bad")) + assert.CurrentView().Name("commits").SelectedLine(Contains("<-- bad")) input.NavigateToListItem(Contains("commit 02")) diff --git a/pkg/integration/tests/branch/delete.go b/pkg/integration/tests/branch/delete.go index c90458546..01bd4edda 100644 --- a/pkg/integration/tests/branch/delete.go +++ b/pkg/integration/tests/branch/delete.go @@ -36,8 +36,7 @@ var Delete = NewIntegrationTest(NewIntegrationTestArgs{ assert.CurrentView().Name("localBranches"). Lines( MatchesRegexp(`\*.*branch-two`), - MatchesRegexp(`master`), - ). - SelectedLineIdx(1) + MatchesRegexp(`master`).IsSelected(), + ) }, }) diff --git a/pkg/integration/tests/branch/rebase_and_drop.go b/pkg/integration/tests/branch/rebase_and_drop.go index 479d240d9..2ef65c3aa 100644 --- a/pkg/integration/tests/branch/rebase_and_drop.go +++ b/pkg/integration/tests/branch/rebase_and_drop.go @@ -27,7 +27,7 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ ) assert.View("commits").TopLines( - Contains("to keep"), + Contains("to keep").IsSelected(), Contains("to remove"), Contains("first change"), Contains("original"), @@ -44,22 +44,29 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ assert.CurrentView(). Name("files"). - SelectedLine(Contains("file")) + SelectedLine(MatchesRegexp("UU.*file")) input.SwitchToCommitsView() assert.CurrentView(). TopLines( - MatchesRegexp(`pick.*to keep`), + MatchesRegexp(`pick.*to keep`).IsSelected(), MatchesRegexp(`pick.*to remove`), MatchesRegexp("YOU ARE HERE.*second-change-branch unrelated change"), MatchesRegexp("second change"), MatchesRegexp("original"), - ). - SelectedLineIdx(0) + ) input.NextItem() input.Press(keys.Universal.Remove) - assert.CurrentView().SelectedLine(MatchesRegexp(`drop.*to remove`)) + + assert.CurrentView(). + TopLines( + MatchesRegexp(`pick.*to keep`), + MatchesRegexp(`drop.*to remove`).IsSelected(), + MatchesRegexp("YOU ARE HERE.*second-change-branch unrelated change"), + MatchesRegexp("second change"), + MatchesRegexp("original"), + ) input.SwitchToFilesView() @@ -76,7 +83,7 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ assert.View("commits").TopLines( Contains("to keep"), - Contains("second-change-branch unrelated change"), + Contains("second-change-branch unrelated change").IsSelected(), Contains("second change"), Contains("original"), ) diff --git a/pkg/integration/tests/commit/revert.go b/pkg/integration/tests/commit/revert.go index e23091baf..a9bd6373a 100644 --- a/pkg/integration/tests/commit/revert.go +++ b/pkg/integration/tests/commit/revert.go @@ -29,10 +29,9 @@ var Revert = NewIntegrationTest(NewIntegrationTestArgs{ assert.CurrentView().Name("commits"). Lines( - Contains("Revert \"first commit\""), + Contains("Revert \"first commit\"").IsSelected(), Contains("first commit"), - ). - SelectedLineIdx(0) + ) assert.MainView().Content(Contains("-myfile content")) assert.FileSystemPathNotPresent("myfile") diff --git a/pkg/integration/tests/diff/diff_commits.go b/pkg/integration/tests/diff/diff_commits.go index 920686c2c..efa44d818 100644 --- a/pkg/integration/tests/diff/diff_commits.go +++ b/pkg/integration/tests/diff/diff_commits.go @@ -48,8 +48,7 @@ var DiffCommits = NewIntegrationTest(NewIntegrationTestArgs{ input.Enter() - assert.CurrentView().Name("commitFiles") - assert.CurrentView().SelectedLine(Contains("file1")) + assert.CurrentView().Name("commitFiles").SelectedLine(Contains("file1")) assert.MainView().Content(Contains("+second line\n+third line")) }, }) From 8c890699656456ea8ce7201f65d7bcf3a681e018 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Mon, 26 Dec 2022 17:51:19 +1100 Subject: [PATCH 7/7] update readme --- pkg/integration/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/integration/README.md b/pkg/integration/README.md index 96b7f0089..d05e45f0c 100644 --- a/pkg/integration/README.md +++ b/pkg/integration/README.md @@ -39,8 +39,12 @@ The run step has four arguments passed in: ### Tips +#### Handle most setup in the `shell` part of the test + Try to do as much setup work as possible in your setup step. For example, if all you're testing is that the user is able to resolve merge conflicts, create the merge conflicts in the setup step. On the other hand, if you're testing to see that lazygit can warn the user about merge conflicts after an attempted merge, it's fine to wait until the run step to actually create the conflicts. If the run step is focused on the thing you're trying to test, the test will run faster and its intent will be clearer. +#### Assert after input + Use assertions to ensure that lazygit has processed all your keybindings so far. Each time you press a key, something should happen on the screen, so you should assert that that thing has happened. This means we won't get into trouble from keys being entered two quickly because at each stage we ensure the key has been processed. This also makes tests more readable because they help explain what we expect to be happening on-screen. For example: ```go @@ -48,6 +52,10 @@ input.Press(keys.Files.CommitChanges) assert.InCommitMessagePanel() ``` +Note that there are some `input` methods that have assertions baked in, such as the `SwitchToView` methods. + +#### Create helper functions for (very) frequently used test logic + If you find yourself doing something frequently in a test, consider making it a method in one of the helper arguments. For example, instead of calling `input.PressKey(keys.Universal.Confirm)` in 100 places, it's better to have a method `input.Confirm()`. This is not to say that everything should be made into a method on the input struct: just things that are particularly common in tests. Also, given how often we need to select a menu item or type into a prompt panel, there are some helper functions for that. For example: