1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-12-02 09:21:40 +02:00

Merge pull request #2330 from jesseduffield/yet-more-test-migrations

This commit is contained in:
Jesse Duffield 2022-12-26 17:59:30 +11:00 committed by GitHub
commit cd418ec929
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 712 additions and 378 deletions

View File

@ -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:

View File

@ -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,14 +95,6 @@ func (self *Assert) InListContext() {
})
}
func (self *Assert) SelectedLine(matcher *matcher) {
self.matchString(matcher, "Unexpected selected line.",
func() string {
return self.gui.CurrentContext().GetView().SelectedLine()
},
)
}
func (self *Assert) InPrompt() {
self.assertWithRetries(func() (bool, string) {
currentView := self.gui.CurrentContext().GetView()
@ -193,46 +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()
},
)
}
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()
@ -277,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,
}
}

View File

@ -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))
@ -103,7 +133,7 @@ func (self *Input) PreviousItem() {
func (self *Input) ContinueMerge() {
self.Press(self.keys.Universal.CreateRebaseOptionsMenu)
self.assert.SelectedLine(Contains("continue"))
self.assert.CurrentView().SelectedLine(Contains("continue"))
self.Confirm()
}
@ -147,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)
@ -156,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, ""
}
@ -166,41 +197,41 @@ func (self *Input) NavigateToListItem(matcher *matcher) {
selectedLineIdx := view.SelectedLineIdx()
if selectedLineIdx == matchIndex {
self.assert.SelectedLine(matcher)
self.assert.CurrentView().SelectedLine(matcher)
return
}
if selectedLineIdx < matchIndex {
for i := selectedLineIdx; i < matchIndex; i++ {
self.NextItem()
}
self.assert.SelectedLine(matcher)
self.assert.CurrentView().SelectedLine(matcher)
return
} else {
for i := selectedLineIdx; i > matchIndex; i-- {
self.PreviousItem()
}
self.assert.SelectedLine(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 +240,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.SelectedLine(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()
}

View File

@ -1,35 +1,156 @@
package components
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 {
return true, ""
for _, rule := range self.rules {
ok, message := rule.testFn(value)
if ok {
continue
}
if self.prefix != "" {
return false, self.prefix + " " + message
}
return false, message
}
if self.prefix != "" {
return false, self.prefix + " " + message
}
return false, message
return true, ""
}
func (self *matcher) Contains(target string) *matcher {
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)
},
})
}
func (self *matcher) DoesNotContain(target string) *matcher {
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)
},
})
}
func (self *matcher) MatchesRegexp(target string) *matcher {
return self.appendRule(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)
},
})
}
func (self *matcher) Equals(target string) *matcher {
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 {
return &matcher{}
}
func Contains(target string) *matcher {
return Anything().Contains(target)
}
func DoesNotContain(target string) *matcher {
return Anything().DoesNotContain(target)
}
func MatchesRegexp(target string) *matcher {
return Anything().MatchesRegexp(target)
}
func Equals(target string) *matcher {
return Anything().Equals(target)
}

View File

@ -0,0 +1,114 @@
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))
})
return self.assertLines(matchers...)
}
// 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))
})
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
}
// 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
}

View File

@ -32,41 +32,39 @@ var Basic = NewIntegrationTest(NewIntegrationTestArgs{
assert.AtLeastOneCommit()
input.SwitchToCommitsWindow()
input.SwitchToCommitsView()
assert.SelectedLine(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.SelectedLine(Contains("<-- bad"))
assert.CurrentView().Name("commits").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.SelectedLine(Contains("commit 05"))
assert.SelectedLine(Contains("<-- current"))
assert.CurrentView().
Name("commits").
SelectedLine(Contains("commit 05").Contains("<-- current"))
markCommitAsBad()
assert.CurrentViewName("commits")
assert.SelectedLine(Contains("commit 04"))
assert.SelectedLine(Contains("<-- current"))
assert.CurrentView().
Name("commits").
SelectedLine(Contains("commit 04").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(DoesNotContain("bisecting"))
},
})

View File

@ -24,29 +24,31 @@ var FromOtherBranch = NewIntegrationTest(NewIntegrationTestArgs{
assert *Assert,
keys config.KeybindingConfig,
) {
assert.ViewContent("information", Contains("bisecting"))
assert.View("information").Content(Contains("bisecting"))
assert.AtLeastOneCommit()
input.SwitchToCommitsWindow()
input.SwitchToCommitsView()
assert.SelectedLine(Contains("<-- bad"))
assert.SelectedLine(Contains("commit 08"))
assert.CurrentView().TopLines(
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`))
input.Alert(Equals("Bisect complete"), MatchesRegexp(`(?s)commit 08.*Do you want to reset`))
assert.ViewContent("information", NotContains("bisecting"))
assert.View("information").Content(DoesNotContain("bisecting"))
// back in master branch which just had the one commit
assert.CurrentViewName("commits")
assert.CommitCount(1)
assert.SelectedLine(Contains("only commit on master"))
assert.CurrentView().Name("commits").Lines(
Contains("only commit on master"),
)
},
})

View File

@ -18,19 +18,26 @@ var CheckoutByName = NewIntegrationTest(NewIntegrationTestArgs{
EmptyCommit("blah")
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
input.SwitchToBranchesView()
assert.SelectedLine(Contains("master"))
assert.CurrentView().Lines(
Contains("master"),
Contains("@"),
)
input.NextItem()
assert.SelectedLine(Contains("@"))
input.Press(keys.Branches.CheckoutBranchByName)
input.Prompt(Equals("Branch name:"), "new-branch")
input.Alert(Equals("Branch not found"), Equals("Branch not found. Create a new branch named new-branch?"))
assert.CurrentViewName("localBranches")
assert.SelectedLine(Contains("new-branch"))
assert.CurrentView().Name("localBranches").
Lines(
MatchesRegexp(`\*.*new-branch`),
Contains("master"),
Contains("@"),
).
SelectedLine(Contains("new-branch"))
},
})

View File

@ -17,21 +17,26 @@ var Delete = NewIntegrationTest(NewIntegrationTestArgs{
NewBranch("branch-two")
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
input.SwitchToBranchesView()
assert.CurrentView().Lines(
MatchesRegexp(`\*.*branch-two`),
MatchesRegexp(`branch-one`),
MatchesRegexp(`master`),
)
assert.SelectedLine(Contains("branch-two"))
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.CurrentView().Name("localBranches").
Lines(
MatchesRegexp(`\*.*branch-two`),
MatchesRegexp(`master`).IsSelected(),
)
},
})

View File

@ -15,35 +15,44 @@ var Rebase = NewIntegrationTest(NewIntegrationTestArgs{
shared.MergeConflictsSetup(shell)
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
input.SwitchToBranchesView()
assert.View("localBranches").Lines(
Contains("first-change-branch"),
Contains("second-change-branch"),
Contains("original-branch"),
)
assert.View("commits").TopLines(
Contains("first change"),
Contains("original"),
)
assert.SelectedLine(Contains("first-change-branch"))
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'?"))
input.AcceptConfirmation(Equals("Auto-merge failed"), Contains("Conflicts!"))
assert.CurrentViewName("files")
assert.SelectedLine(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(DoesNotContain("rebasing"))
// this proves we actually have integrated the changes from second-change-branch
assert.ViewContent("commits", Contains("second-change-branch unrelated change"))
assert.View("commits").TopLines(
Contains("second-change-branch unrelated change"),
Contains("second change"),
Contains("original"),
)
},
})

View File

@ -18,48 +18,74 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{
shell.EmptyCommit("to keep")
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
input.SwitchToBranchesView()
assert.CurrentView().Lines(
Contains("first-change-branch"),
Contains("second-change-branch"),
Contains("original-branch"),
)
assert.View("commits").TopLines(
Contains("to keep").IsSelected(),
Contains("to remove"),
Contains("first change"),
Contains("original"),
)
assert.SelectedLine(Contains("first-change-branch"))
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'?"))
assert.ViewContent("information", Contains("rebasing"))
assert.View("information").Content(Contains("rebasing"))
input.AcceptConfirmation(Equals("Auto-merge failed"), Contains("Conflicts!"))
assert.CurrentViewName("files")
assert.SelectedLine(Contains("file"))
assert.CurrentView().
Name("files").
SelectedLine(MatchesRegexp("UU.*file"))
input.SwitchToCommitsView()
assert.CurrentView().
TopLines(
MatchesRegexp(`pick.*to keep`).IsSelected(),
MatchesRegexp(`pick.*to remove`),
MatchesRegexp("YOU ARE HERE.*second-change-branch unrelated change"),
MatchesRegexp("second change"),
MatchesRegexp("original"),
)
input.SwitchToCommitsWindow()
assert.SelectedLine(Contains("pick")) // this means it's a rebasing commit
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"))
input.SwitchToFilesWindow()
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()
// 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()
input.AcceptConfirmation(Equals("continue"), Contains("all merge conflicts resolved. Continue?"))
assert.ViewContent("information", NotContains("rebasing"))
assert.View("information").Content(DoesNotContain("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.View("commits").TopLines(
Contains("to keep"),
Contains("second-change-branch unrelated change").IsSelected(),
Contains("second change"),
Contains("original"),
)
},
})

View File

@ -21,26 +21,31 @@ var Reset = NewIntegrationTest(NewIntegrationTestArgs{
shell.EmptyCommit("current-branch commit")
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
assert.View("commits").Lines(
Contains("current-branch commit"),
Contains("root commit"),
)
assert.SelectedLine(Contains("current-branch"))
input.SwitchToBranchesView()
assert.CurrentView().Lines(
Contains("current-branch"),
Contains("other-branch"),
)
input.NextItem()
assert.SelectedLine(Contains("other-branch"))
input.Press(keys.Commits.ViewResetOptions)
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.CommitCount(2)
assert.SelectedLine(Contains("other-branch commit"))
input.NextItem()
assert.SelectedLine(Contains("root commit"))
input.SwitchToCommitsView()
assert.CurrentView().Lines(
Contains("other-branch commit"),
Contains("root commit"),
)
},
})

View File

@ -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.CurrentViewName("localBranches")
input.SwitchToBranchesView()
input.Press(keys.Branches.CheckoutBranchByName)

View File

@ -24,41 +24,52 @@ var CherryPick = NewIntegrationTest(NewIntegrationTestArgs{
Checkout("first-branch")
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
input.SwitchToBranchesView()
assert.CurrentView().Lines(
Contains("first-branch"),
Contains("second-branch"),
Contains("master"),
)
assert.SelectedLine(Contains("first-branch"))
input.NextItem()
assert.SelectedLine(Contains("second-branch"))
input.Enter()
assert.CurrentViewName("subCommits")
assert.SelectedLine(Contains("four"))
input.Press(keys.Commits.CherryPickCopy)
assert.ViewContent("information", Contains("1 commit copied"))
assert.CurrentView().Name("subCommits").Lines(
Contains("four"),
Contains("three"),
Contains("base"),
)
// copy commits 'four' and 'three'
input.Press(keys.Commits.CherryPickCopy)
assert.View("information").Content(Contains("1 commit copied"))
input.NextItem()
assert.SelectedLine(Contains("three"))
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")
input.SwitchToCommitsView()
assert.CurrentView().Lines(
Contains("two"),
Contains("one"),
Contains("base"),
)
assert.SelectedLine(Contains("two"))
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.CurrentView().Name("commits").Lines(
Contains("four"),
Contains("three"),
Contains("two"),
Contains("one"),
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(DoesNotContain("commits copied"))
},
})

View File

@ -15,67 +15,74 @@ var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{
shared.MergeConflictsSetup(shell)
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
input.SwitchToBranchesView()
assert.CurrentView().Lines(
Contains("first-change-branch"),
Contains("second-change-branch"),
Contains("original-branch"),
)
assert.SelectedLine(Contains("first-change-branch"))
input.NextItem()
assert.SelectedLine(Contains("second-change-branch"))
input.Enter()
assert.CurrentViewName("subCommits")
assert.SelectedLine(Contains("second-change-branch unrelated change"))
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()
assert.SelectedLine(Contains("second change"))
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")
input.SwitchToCommitsView()
assert.CurrentView().TopLines(
Contains("first change"),
)
assert.SelectedLine(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?"))
input.AcceptConfirmation(Equals("Auto-merge failed"), Contains("Conflicts!"))
assert.CurrentViewName("files")
assert.SelectedLine(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")
input.SwitchToCommitsView()
assert.SelectedLine(Contains("second-change-branch unrelated change"))
assert.CurrentView().TopLines(
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.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(DoesNotContain("commits copied"))
},
})

View File

@ -29,7 +29,7 @@ var CommitMultiline = NewIntegrationTest(NewIntegrationTestArgs{
assert.CommitCount(1)
assert.HeadCommitMessage(Equals("first line"))
input.SwitchToCommitsWindow()
assert.MainViewContent(MatchesRegexp("first line\n\\s*\n\\s*third line"))
input.SwitchToCommitsView()
assert.MainView().Content(MatchesRegexp("first line\n\\s*\n\\s*third line"))
},
})

View File

@ -19,8 +19,12 @@ var NewBranch = NewIntegrationTest(NewIntegrationTestArgs{
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
assert.CommitCount(3)
input.SwitchToCommitsWindow()
assert.CurrentViewName("commits")
input.SwitchToCommitsView()
assert.CurrentView().Lines(
Contains("commit 3"),
Contains("commit 2"),
Contains("commit 1"),
)
input.NextItem()
input.Press(keys.Universal.New)
@ -28,8 +32,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.View("commits").Lines(
Contains("commit 2"),
Contains("commit 1"),
)
},
})

View File

@ -18,15 +18,22 @@ var Revert = NewIntegrationTest(NewIntegrationTestArgs{
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
assert.CommitCount(1)
input.SwitchToCommitsWindow()
input.SwitchToCommitsView()
assert.CurrentView().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\"").IsSelected(),
Contains("first commit"),
)
assert.MainView().Content(Contains("-myfile content"))
assert.FileSystemPathNotPresent("myfile")
},
})

View File

@ -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.SelectedLine(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(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.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(DoesNotContain("+myfile content"))
assert.View("stagingSecondary").Content(Contains("+with a second line"))
assert.View("staging").Content(Contains("+myfile content"))
assert.View("staging").Content(DoesNotContain("+with a second line"))
input.Press(keys.Files.CommitChanges)
commitMessage := "my commit message"

View File

@ -19,36 +19,36 @@ var StagedWithoutHooks = NewIntegrationTest(NewIntegrationTestArgs{
assert.CommitCount(0)
// stage the file
assert.CurrentViewName("files")
assert.SelectedLine(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").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.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(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()
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)
},

View File

@ -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.SelectedLine(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(DoesNotContain("+myfile content"))
// stage the first line
input.PrimaryAction()
assert.ViewContent("staging", NotContains("+myfile content"))
assert.ViewContent("stagingSecondary", Contains("+myfile content"))
assert.View("staging").Content(DoesNotContain("+myfile content"))
assert.View("stagingSecondary").Content(Contains("+myfile content"))
input.Press(keys.Files.CommitChanges)
assert.InCommitMessagePanel()

View File

@ -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()
},
})

View File

@ -30,7 +30,9 @@ var Basic = NewIntegrationTest(NewIntegrationTestArgs{
assert.WorkingTreeFileCount(0)
input.Press("a")
assert.WorkingTreeFileCount(1)
assert.SelectedLine(Contains("myfile"))
assert.View("files").Lines(
Contains("myfile"),
)
},
})

View File

@ -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.MainViewContent(Contains(`"BAR"`))
assert.CurrentView().SelectedLine(Contains("my file"))
assert.MainView().Content(Contains(`"BAR"`))
},
})

View File

@ -49,7 +49,7 @@ var MenuFromCommand = NewIntegrationTest(NewIntegrationTestArgs{
keys config.KeybindingConfig,
) {
assert.WorkingTreeFileCount(0)
input.SwitchToBranchesWindow()
input.SwitchToBranchesView()
input.Press("a")
@ -57,10 +57,10 @@ var MenuFromCommand = NewIntegrationTest(NewIntegrationTestArgs{
input.Prompt(Equals("Description"), " my branch")
input.SwitchToFilesWindow()
input.SwitchToFilesView()
assert.WorkingTreeFileCount(1)
assert.SelectedLine(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"))
},
})

View File

@ -50,13 +50,14 @@ var MenuFromCommandsOutput = NewIntegrationTest(NewIntegrationTestArgs{
assert.CurrentBranchName("feature/bar")
assert.WorkingTreeFileCount(0)
input.SwitchToBranchesWindow()
input.SwitchToBranchesView()
input.Press("a")
assert.InPrompt()
assert.CurrentViewTitle(Equals("Which git command do you want to run?"))
assert.SelectedLine(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"))

View File

@ -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.MainViewContent(Contains("BAR"))
assert.CurrentView().SelectedLine(Contains("myfile"))
assert.MainView().Content(Contains("BAR"))
},
})

View File

@ -22,36 +22,37 @@ var Diff = NewIntegrationTest(NewIntegrationTestArgs{
shell.Checkout("branch-a")
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
input.SwitchToBranchesView()
assert.SelectedLine(Contains("branch-a"))
assert.CurrentView().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.SelectedLine(Contains("update"))
assert.CurrentView().Name("subCommits")
assert.MainView().Content(Contains("+second line"))
assert.CurrentView().SelectedLine(Contains("update"))
input.Enter()
assert.CurrentViewName("commitFiles")
assert.SelectedLine(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"))
},
})

View File

@ -22,29 +22,31 @@ var DiffAndApplyPatch = NewIntegrationTest(NewIntegrationTestArgs{
shell.Checkout("branch-a")
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
input.SwitchToBranchesView()
assert.CurrentView().Lines(
Contains("branch-a"),
Contains("branch-b"),
)
assert.SelectedLine(Contains("branch-a"))
input.Press(keys.Universal.DiffingMenu)
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.SelectedLine(Contains("update"))
assert.CurrentView().Name("subCommits")
assert.MainView().Content(Contains("+second line"))
assert.CurrentView().SelectedLine(Contains("update"))
input.Enter()
assert.CurrentViewName("commitFiles")
assert.SelectedLine(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()
@ -52,15 +54,15 @@ 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(DoesNotContain("building patch"))
input.Press(keys.Universal.CreatePatchOptionsMenu)
// 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.SelectedLine(Contains("file1"))
assert.MainViewContent(Contains("+second line"))
assert.CurrentView().SelectedLine(Contains("file1"))
assert.MainView().Content(Contains("+second line"))
},
})

View File

@ -19,35 +19,36 @@ var DiffCommits = NewIntegrationTest(NewIntegrationTestArgs{
shell.Commit("third commit")
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToCommitsWindow()
assert.CurrentViewName("commits")
input.SwitchToCommitsView()
assert.SelectedLine(Contains("third commit"))
assert.CurrentView().Lines(
Contains("third commit"),
Contains("second commit"),
Contains("first commit"),
)
input.Press(keys.Universal.DiffingMenu)
input.Menu(Equals("Diffing"), MatchesRegexp(`diff \w+`))
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.CurrentView().SelectedLine(Contains("first commit"))
assert.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.SelectedLine(Contains("file1"))
assert.MainViewContent(Contains("+second line\n+third line"))
assert.CurrentView().Name("commitFiles").SelectedLine(Contains("file1"))
assert.MainView().Content(Contains("+second line\n+third line"))
},
})

View File

@ -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(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"))
},
})

View File

@ -82,7 +82,7 @@ var DiscardChanges = NewIntegrationTest(NewIntegrationTestArgs{
discardOneByOne := func(files []statusFile) {
for _, file := range files {
assert.SelectedLine(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"},

View File

@ -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.CurrentViewName("commits")
input.SwitchToCommitsView()
mergeCommitMessage := "Merge branch 'feature-branch' into development-branch"
assert.HeadCommitMessage(Contains(mergeCommitMessage))
@ -44,7 +43,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))
},
})

View File

@ -15,27 +15,62 @@ 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.CurrentViewName("commits")
input.SwitchToCommitsView()
assert.CurrentView().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.SelectedLine(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.SelectedLine(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.SelectedLine(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.SelectedLine(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"),
)
},
})

View File

@ -19,16 +19,17 @@ var Rename = NewIntegrationTest(NewIntegrationTestArgs{
StashWithMessage("bar")
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToStashWindow()
assert.CurrentViewName("stash")
input.SwitchToStashView()
assert.SelectedLine(Equals("On master: bar"))
assert.CurrentView().Lines(
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")
assert.SelectedLine(Equals("On master: foo baz"))
assert.CurrentView().SelectedLine(Equals("On master: foo baz"))
},
})