mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-28 16:02:01 +03:00
another integration test
This commit is contained in:
@ -2,8 +2,10 @@ package gui
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
guiTypes "github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/integration/types"
|
"github.com/jesseduffield/lazygit/pkg/integration/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -67,8 +69,23 @@ func (self *AssertImpl) CurrentBranchName(expectedViewName string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *AssertImpl) InListContext() {
|
||||||
|
self.assertWithRetries(func() (bool, string) {
|
||||||
|
currentContext := self.gui.currentContext()
|
||||||
|
_, ok := currentContext.(guiTypes.IListContext)
|
||||||
|
return ok, fmt.Sprintf("Expected current context to be a list context, but got %s", currentContext.GetKey())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *AssertImpl) SelectedLineContains(text string) {
|
||||||
|
self.assertWithRetries(func() (bool, string) {
|
||||||
|
line := self.gui.currentContext().GetView().SelectedLine()
|
||||||
|
return strings.Contains(line, text), fmt.Sprintf("Expected selected line to contain '%s', but got '%s'", text, line)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (self *AssertImpl) assertWithRetries(test func() (bool, string)) {
|
func (self *AssertImpl) assertWithRetries(test func() (bool, string)) {
|
||||||
waitTimes := []int{0, 100, 200, 400, 800, 1600}
|
waitTimes := []int{0, 1, 5, 10, 200, 500, 1000}
|
||||||
|
|
||||||
var message string
|
var message string
|
||||||
for _, waitTime := range waitTimes {
|
for _, waitTime := range waitTimes {
|
||||||
@ -81,6 +98,10 @@ func (self *AssertImpl) assertWithRetries(test func() (bool, string)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.Fail(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *AssertImpl) Fail(message string) {
|
||||||
self.gui.g.Close()
|
self.gui.g.Close()
|
||||||
// need to give the gui time to close
|
// need to give the gui time to close
|
||||||
time.Sleep(time.Millisecond * 100)
|
time.Sleep(time.Millisecond * 100)
|
||||||
|
107
pkg/gui/input.go
107
pkg/gui/input.go
@ -1,29 +1,45 @@
|
|||||||
package gui
|
package gui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazygit/pkg/config"
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||||
|
guiTypes "github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/integration/types"
|
"github.com/jesseduffield/lazygit/pkg/integration/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InputImpl struct {
|
type InputImpl struct {
|
||||||
g *gocui.Gui
|
gui *Gui
|
||||||
keys config.KeybindingConfig
|
keys config.KeybindingConfig
|
||||||
|
assert types.Assert
|
||||||
|
pushKeyDelay int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewInputImpl(gui *Gui, keys config.KeybindingConfig, assert types.Assert, pushKeyDelay int) *InputImpl {
|
||||||
|
return &InputImpl{
|
||||||
|
gui: gui,
|
||||||
|
keys: keys,
|
||||||
|
assert: assert,
|
||||||
|
pushKeyDelay: pushKeyDelay,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.Input = &InputImpl{}
|
var _ types.Input = &InputImpl{}
|
||||||
|
|
||||||
func (self *InputImpl) PushKeys(keyStrs ...string) {
|
func (self *InputImpl) PressKeys(keyStrs ...string) {
|
||||||
for _, keyStr := range keyStrs {
|
for _, keyStr := range keyStrs {
|
||||||
self.pushKey(keyStr)
|
self.pressKey(keyStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *InputImpl) pushKey(keyStr string) {
|
func (self *InputImpl) pressKey(keyStr string) {
|
||||||
|
self.Wait(self.pushKeyDelay)
|
||||||
|
|
||||||
key := keybindings.GetKey(keyStr)
|
key := keybindings.GetKey(keyStr)
|
||||||
|
|
||||||
var r rune
|
var r rune
|
||||||
@ -36,58 +52,115 @@ func (self *InputImpl) pushKey(keyStr string) {
|
|||||||
tcellKey = tcell.Key(v)
|
tcellKey = tcell.Key(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.g.ReplayedEvents.Keys <- gocui.NewTcellKeyEventWrapper(
|
self.gui.g.ReplayedEvents.Keys <- gocui.NewTcellKeyEventWrapper(
|
||||||
tcell.NewEventKey(tcellKey, r, tcell.ModNone),
|
tcell.NewEventKey(tcellKey, r, tcell.ModNone),
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *InputImpl) SwitchToStatusWindow() {
|
func (self *InputImpl) SwitchToStatusWindow() {
|
||||||
self.pushKey(self.keys.Universal.JumpToBlock[0])
|
self.pressKey(self.keys.Universal.JumpToBlock[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *InputImpl) SwitchToFilesWindow() {
|
func (self *InputImpl) SwitchToFilesWindow() {
|
||||||
self.pushKey(self.keys.Universal.JumpToBlock[1])
|
self.pressKey(self.keys.Universal.JumpToBlock[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *InputImpl) SwitchToBranchesWindow() {
|
func (self *InputImpl) SwitchToBranchesWindow() {
|
||||||
self.pushKey(self.keys.Universal.JumpToBlock[2])
|
self.pressKey(self.keys.Universal.JumpToBlock[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *InputImpl) SwitchToCommitsWindow() {
|
func (self *InputImpl) SwitchToCommitsWindow() {
|
||||||
self.pushKey(self.keys.Universal.JumpToBlock[3])
|
self.pressKey(self.keys.Universal.JumpToBlock[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *InputImpl) SwitchToStashWindow() {
|
func (self *InputImpl) SwitchToStashWindow() {
|
||||||
self.pushKey(self.keys.Universal.JumpToBlock[4])
|
self.pressKey(self.keys.Universal.JumpToBlock[4])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *InputImpl) Type(content string) {
|
func (self *InputImpl) Type(content string) {
|
||||||
for _, char := range content {
|
for _, char := range content {
|
||||||
self.pushKey(string(char))
|
self.pressKey(string(char))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *InputImpl) Confirm() {
|
func (self *InputImpl) Confirm() {
|
||||||
self.pushKey(self.keys.Universal.Confirm)
|
self.pressKey(self.keys.Universal.Confirm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *InputImpl) Cancel() {
|
func (self *InputImpl) Cancel() {
|
||||||
self.pushKey(self.keys.Universal.Return)
|
self.pressKey(self.keys.Universal.Return)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *InputImpl) Select() {
|
func (self *InputImpl) Select() {
|
||||||
self.pushKey(self.keys.Universal.Select)
|
self.pressKey(self.keys.Universal.Select)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *InputImpl) NextItem() {
|
func (self *InputImpl) NextItem() {
|
||||||
self.pushKey(self.keys.Universal.NextItem)
|
self.pressKey(self.keys.Universal.NextItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *InputImpl) PreviousItem() {
|
func (self *InputImpl) PreviousItem() {
|
||||||
self.pushKey(self.keys.Universal.PrevItem)
|
self.pressKey(self.keys.Universal.PrevItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *InputImpl) ContinueMerge() {
|
||||||
|
self.PressKeys(self.keys.Universal.CreateRebaseOptionsMenu)
|
||||||
|
self.assert.SelectedLineContains("continue")
|
||||||
|
self.Confirm()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *InputImpl) ContinueRebase() {
|
||||||
|
self.ContinueMerge()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *InputImpl) Wait(milliseconds int) {
|
func (self *InputImpl) Wait(milliseconds int) {
|
||||||
time.Sleep(time.Duration(milliseconds) * time.Millisecond)
|
time.Sleep(time.Duration(milliseconds) * time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *InputImpl) log(message string) {
|
||||||
|
self.gui.c.LogAction(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: this currently assumes that ViewBufferLines returns all the lines that can be accessed.
|
||||||
|
// If this changes in future, we'll need to update this code to first attempt to find the item
|
||||||
|
// in the current page and failing that, jump to the top of the view and iterate through all of it,
|
||||||
|
// looking for the item.
|
||||||
|
func (self *InputImpl) NavigateToListItemContainingText(text string) {
|
||||||
|
self.assert.InListContext()
|
||||||
|
|
||||||
|
currentContext := self.gui.currentContext().(guiTypes.IListContext)
|
||||||
|
view := currentContext.GetView()
|
||||||
|
|
||||||
|
// first we look for a duplicate on the current screen. We won't bother looking beyond that though.
|
||||||
|
matchCount := 0
|
||||||
|
matchIndex := -1
|
||||||
|
for i, line := range view.ViewBufferLines() {
|
||||||
|
if strings.Contains(line, text) {
|
||||||
|
matchCount++
|
||||||
|
matchIndex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if matchCount > 1 {
|
||||||
|
self.assert.Fail(fmt.Sprintf("Found %d matches for %s, expected only a single match", matchCount, text))
|
||||||
|
}
|
||||||
|
if matchCount == 1 {
|
||||||
|
selectedLineIdx := view.SelectedLineIdx()
|
||||||
|
if selectedLineIdx == matchIndex {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if selectedLineIdx < matchIndex {
|
||||||
|
for i := selectedLineIdx; i < matchIndex; i++ {
|
||||||
|
self.NextItem()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
for i := selectedLineIdx; i > matchIndex; i-- {
|
||||||
|
self.PreviousItem()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assert.Fail(fmt.Sprintf("Could not find item containing text: %s", text))
|
||||||
|
}
|
||||||
|
@ -21,10 +21,15 @@ func (gui *Gui) handleTestMode() {
|
|||||||
go func() {
|
go func() {
|
||||||
time.Sleep(time.Millisecond * 100)
|
time.Sleep(time.Millisecond * 100)
|
||||||
|
|
||||||
|
shell := &integration.ShellImpl{}
|
||||||
|
assert := &AssertImpl{gui: gui}
|
||||||
|
keys := gui.Config.GetUserConfig().Keybinding
|
||||||
|
input := NewInputImpl(gui, keys, assert, integration.KeyPressDelay())
|
||||||
|
|
||||||
test.Run(
|
test.Run(
|
||||||
&integration.ShellImpl{},
|
shell,
|
||||||
&InputImpl{g: gui.g, keys: gui.Config.GetUserConfig().Keybinding},
|
input,
|
||||||
&AssertImpl{gui: gui},
|
assert,
|
||||||
gui.c.UserConfig.Keybinding,
|
gui.c.UserConfig.Keybinding,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package integration
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/jesseduffield/generics/slices"
|
"github.com/jesseduffield/generics/slices"
|
||||||
"github.com/jesseduffield/lazygit/pkg/integration/types"
|
"github.com/jesseduffield/lazygit/pkg/integration/types"
|
||||||
@ -31,6 +32,21 @@ func PlayingIntegrationTest() bool {
|
|||||||
return IntegrationTestName() != ""
|
return IntegrationTestName() != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is the delay in milliseconds between keypresses
|
||||||
|
// defaults to zero
|
||||||
|
func KeyPressDelay() int {
|
||||||
|
delayStr := os.Getenv("KEY_PRESS_DELAY")
|
||||||
|
if delayStr == "" {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
delay, err := strconv.Atoi(delayStr)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return delay
|
||||||
|
}
|
||||||
|
|
||||||
// OLD integration test format stuff
|
// OLD integration test format stuff
|
||||||
|
|
||||||
func Replaying() bool {
|
func Replaying() bool {
|
||||||
|
@ -23,12 +23,12 @@ var Suggestions = types.NewTest(types.NewTestArgs{
|
|||||||
Run: func(shell types.Shell, input types.Input, assert types.Assert, keys config.KeybindingConfig) {
|
Run: func(shell types.Shell, input types.Input, assert types.Assert, keys config.KeybindingConfig) {
|
||||||
input.SwitchToBranchesWindow()
|
input.SwitchToBranchesWindow()
|
||||||
|
|
||||||
input.PushKeys(keys.Branches.CheckoutBranchByName)
|
input.PressKeys(keys.Branches.CheckoutBranchByName)
|
||||||
assert.CurrentViewName("confirmation")
|
assert.CurrentViewName("confirmation")
|
||||||
|
|
||||||
input.Type("branch-to")
|
input.Type("branch-to")
|
||||||
|
|
||||||
input.PushKeys(keys.Universal.TogglePanel)
|
input.PressKeys(keys.Universal.TogglePanel)
|
||||||
assert.CurrentViewName("suggestions")
|
assert.CurrentViewName("suggestions")
|
||||||
|
|
||||||
// we expect the first suggestion to be the branch we want because it most
|
// we expect the first suggestion to be the branch we want because it most
|
||||||
|
@ -20,7 +20,7 @@ var Commit = types.NewTest(types.NewTestArgs{
|
|||||||
input.Select()
|
input.Select()
|
||||||
input.NextItem()
|
input.NextItem()
|
||||||
input.Select()
|
input.Select()
|
||||||
input.PushKeys(keys.Files.CommitChanges)
|
input.PressKeys(keys.Files.CommitChanges)
|
||||||
|
|
||||||
commitMessage := "my commit message"
|
commitMessage := "my commit message"
|
||||||
input.Type(commitMessage)
|
input.Type(commitMessage)
|
||||||
|
@ -23,7 +23,7 @@ var NewBranch = types.NewTest(types.NewTestArgs{
|
|||||||
assert.CurrentViewName("commits")
|
assert.CurrentViewName("commits")
|
||||||
input.NextItem()
|
input.NextItem()
|
||||||
|
|
||||||
input.PushKeys(keys.Universal.New)
|
input.PressKeys(keys.Universal.New)
|
||||||
|
|
||||||
assert.CurrentViewName("confirmation")
|
assert.CurrentViewName("confirmation")
|
||||||
|
|
||||||
|
41
pkg/integration/integration_tests/interactive_rebase/one.go
Normal file
41
pkg/integration/integration_tests/interactive_rebase/one.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package interactive_rebase
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/integration/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var One = types.NewTest(types.NewTestArgs{
|
||||||
|
Description: "Begins an interactive rebase, then fixups, drops, and squashes some commits",
|
||||||
|
ExtraCmdArgs: "",
|
||||||
|
Skip: false,
|
||||||
|
SetupConfig: func(config *config.AppConfig) {},
|
||||||
|
SetupRepo: func(shell types.Shell) {
|
||||||
|
shell.
|
||||||
|
CreateNCommits(5) // these will appears at commit 05, 04, 04, down to 01
|
||||||
|
},
|
||||||
|
Run: func(shell types.Shell, input types.Input, assert types.Assert, keys config.KeybindingConfig) {
|
||||||
|
input.SwitchToCommitsWindow()
|
||||||
|
assert.CurrentViewName("commits")
|
||||||
|
|
||||||
|
input.NavigateToListItemContainingText("commit 02")
|
||||||
|
input.PressKeys(keys.Universal.Edit)
|
||||||
|
assert.SelectedLineContains("YOU ARE HERE")
|
||||||
|
|
||||||
|
input.PreviousItem()
|
||||||
|
input.PressKeys(keys.Commits.MarkCommitAsFixup)
|
||||||
|
assert.SelectedLineContains("fixup")
|
||||||
|
|
||||||
|
input.PreviousItem()
|
||||||
|
input.PressKeys(keys.Universal.Remove)
|
||||||
|
assert.SelectedLineContains("drop")
|
||||||
|
|
||||||
|
input.PreviousItem()
|
||||||
|
input.PressKeys(keys.Commits.SquashDown)
|
||||||
|
assert.SelectedLineContains("squash")
|
||||||
|
|
||||||
|
input.ContinueRebase()
|
||||||
|
|
||||||
|
assert.CommitCount(2)
|
||||||
|
},
|
||||||
|
})
|
@ -3,6 +3,8 @@ package integration_tests
|
|||||||
import (
|
import (
|
||||||
"github.com/jesseduffield/lazygit/pkg/integration/integration_tests/branch"
|
"github.com/jesseduffield/lazygit/pkg/integration/integration_tests/branch"
|
||||||
"github.com/jesseduffield/lazygit/pkg/integration/integration_tests/commit"
|
"github.com/jesseduffield/lazygit/pkg/integration/integration_tests/commit"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/integration/integration_tests/interactive_rebase"
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/integration/types"
|
"github.com/jesseduffield/lazygit/pkg/integration/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,4 +15,5 @@ var Tests = []types.Test{
|
|||||||
commit.Commit,
|
commit.Commit,
|
||||||
commit.NewBranch,
|
commit.NewBranch,
|
||||||
branch.Suggestions,
|
branch.Suggestions,
|
||||||
|
interactive_rebase.One,
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,10 @@ func (s *ShellImpl) NewBranch(name string) types.Shell {
|
|||||||
return s.RunCommand("git checkout -b " + name)
|
return s.RunCommand("git checkout -b " + name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ShellImpl) GitAdd(path string) types.Shell {
|
||||||
|
return s.RunCommand(fmt.Sprintf("git add \"%s\"", path))
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ShellImpl) GitAddAll() types.Shell {
|
func (s *ShellImpl) GitAddAll() types.Shell {
|
||||||
return s.RunCommand("git add -A")
|
return s.RunCommand("git add -A")
|
||||||
}
|
}
|
||||||
@ -51,3 +55,21 @@ func (s *ShellImpl) Commit(message string) types.Shell {
|
|||||||
func (s *ShellImpl) EmptyCommit(message string) types.Shell {
|
func (s *ShellImpl) EmptyCommit(message string) types.Shell {
|
||||||
return s.RunCommand(fmt.Sprintf("git commit --allow-empty -m \"%s\"", message))
|
return s.RunCommand(fmt.Sprintf("git commit --allow-empty -m \"%s\"", message))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ShellImpl) CreateFileAndAdd(fileName string, fileContents string) types.Shell {
|
||||||
|
return s.
|
||||||
|
CreateFile(fileName, fileContents).
|
||||||
|
GitAdd(fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ShellImpl) CreateNCommits(n int) types.Shell {
|
||||||
|
for i := 1; i <= n; i++ {
|
||||||
|
s.CreateFileAndAdd(
|
||||||
|
fmt.Sprintf("file%02d.txt", i),
|
||||||
|
fmt.Sprintf("file%02d content", i),
|
||||||
|
).
|
||||||
|
Commit(fmt.Sprintf("commit %02d", i))
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
@ -31,9 +31,16 @@ type Shell interface {
|
|||||||
RunCommand(command string) Shell
|
RunCommand(command string) Shell
|
||||||
CreateFile(name string, content string) Shell
|
CreateFile(name string, content string) Shell
|
||||||
NewBranch(branchName string) Shell
|
NewBranch(branchName string) Shell
|
||||||
|
GitAdd(path string) Shell
|
||||||
GitAddAll() Shell
|
GitAddAll() Shell
|
||||||
Commit(message string) Shell
|
Commit(message string) Shell
|
||||||
EmptyCommit(message string) Shell
|
EmptyCommit(message string) Shell
|
||||||
|
// convenience method for creating a file and adding it
|
||||||
|
CreateFileAndAdd(fileName string, fileContents string) Shell
|
||||||
|
// creates commits 01, 02, 03, ..., n with a new file in each
|
||||||
|
// The reason for padding with zeroes is so that it's easier to do string
|
||||||
|
// matches on the commit messages when there are many of them
|
||||||
|
CreateNCommits(n int) Shell
|
||||||
}
|
}
|
||||||
|
|
||||||
// through this interface our test interacts with the lazygit gui
|
// through this interface our test interacts with the lazygit gui
|
||||||
@ -41,7 +48,7 @@ type Shell interface {
|
|||||||
type Input interface {
|
type Input interface {
|
||||||
// key is something like 'w' or '<space>'. It's best not to pass a direct value,
|
// key is something like 'w' or '<space>'. It's best not to pass a direct value,
|
||||||
// but instead to go through the default user config to get a more meaningful key name
|
// but instead to go through the default user config to get a more meaningful key name
|
||||||
PushKeys(keys ...string)
|
PressKeys(keys ...string)
|
||||||
// for typing into a popup prompt
|
// for typing into a popup prompt
|
||||||
Type(content string)
|
Type(content string)
|
||||||
// for when you want to allow lazygit to process something before continuing
|
// for when you want to allow lazygit to process something before continuing
|
||||||
@ -62,6 +69,15 @@ type Input interface {
|
|||||||
NextItem()
|
NextItem()
|
||||||
// i.e. pressing up arrow
|
// i.e. pressing up arrow
|
||||||
PreviousItem()
|
PreviousItem()
|
||||||
|
// this will look for a list item in the current panel and if it finds it, it will
|
||||||
|
// enter the keypresses required to navigate to it.
|
||||||
|
// The test will fail if:
|
||||||
|
// - the user is not in a list item
|
||||||
|
// - no list item is found containing the given text
|
||||||
|
// - multiple list items are found containing the given text in the initial page of items
|
||||||
|
NavigateToListItemContainingText(text string)
|
||||||
|
ContinueRebase()
|
||||||
|
ContinueMerge()
|
||||||
}
|
}
|
||||||
|
|
||||||
// through this interface we assert on the state of the lazygit gui
|
// through this interface we assert on the state of the lazygit gui
|
||||||
@ -71,6 +87,10 @@ type Assert interface {
|
|||||||
HeadCommitMessage(string)
|
HeadCommitMessage(string)
|
||||||
CurrentViewName(expectedViewName string)
|
CurrentViewName(expectedViewName string)
|
||||||
CurrentBranchName(expectedBranchName string)
|
CurrentBranchName(expectedBranchName string)
|
||||||
|
InListContext()
|
||||||
|
SelectedLineContains(text string)
|
||||||
|
// for when you just want to fail the test yourself
|
||||||
|
Fail(errorMessage string)
|
||||||
}
|
}
|
||||||
|
|
||||||
type TestImpl struct {
|
type TestImpl struct {
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
# This is a combination of 3 commits.
|
||||||
|
# This is the 1st commit message:
|
||||||
|
|
||||||
|
commit 02
|
||||||
|
|
||||||
|
# The commit message #2 will be skipped:
|
||||||
|
|
||||||
|
# commit 03
|
||||||
|
|
||||||
|
# This is the commit message #3:
|
||||||
|
|
||||||
|
commit 05
|
||||||
|
|
||||||
|
# Please enter the commit message for your changes. Lines starting
|
||||||
|
# with '#' will be ignored, and an empty message aborts the commit.
|
||||||
|
#
|
||||||
|
# Date: Mon Aug 8 21:32:34 2022 +1000
|
||||||
|
#
|
||||||
|
# interactive rebase in progress; onto a1a6f7b
|
||||||
|
# Last commands done (4 commands done):
|
||||||
|
# drop 84b1ae9 commit 04
|
||||||
|
# squash aa2585a commit 05
|
||||||
|
# No commands remaining.
|
||||||
|
# You are currently rebasing branch 'master' on 'a1a6f7b'.
|
||||||
|
#
|
||||||
|
# Changes to be committed:
|
||||||
|
# new file: file02.txt
|
||||||
|
# new file: file03.txt
|
||||||
|
# new file: file05.txt
|
||||||
|
#
|
@ -0,0 +1 @@
|
|||||||
|
ref: refs/heads/master
|
@ -0,0 +1 @@
|
|||||||
|
aa2585aff7d2278341ca816f187e623503d7c4fb
|
@ -0,0 +1 @@
|
|||||||
|
aa2585aff7d2278341ca816f187e623503d7c4fb
|
@ -0,0 +1,10 @@
|
|||||||
|
[core]
|
||||||
|
repositoryformatversion = 0
|
||||||
|
filemode = true
|
||||||
|
bare = false
|
||||||
|
logallrefupdates = true
|
||||||
|
ignorecase = true
|
||||||
|
precomposeunicode = true
|
||||||
|
[user]
|
||||||
|
email = CI@example.com
|
||||||
|
name = CI
|
@ -0,0 +1 @@
|
|||||||
|
Unnamed repository; edit this file 'description' to name the repository.
|
Binary file not shown.
@ -0,0 +1,7 @@
|
|||||||
|
# git ls-files --others --exclude-from=.git/info/exclude
|
||||||
|
# Lines that start with '#' are comments.
|
||||||
|
# For a project mostly in C, the following would be a good set of
|
||||||
|
# exclude patterns (uncomment them if you want to use them):
|
||||||
|
# *.[oa]
|
||||||
|
# *~
|
||||||
|
.DS_Store
|
@ -0,0 +1,10 @@
|
|||||||
|
0000000000000000000000000000000000000000 a1a6f7bda6aeaa08ec75f590845780fde90d901c CI <CI@example.com> 1659958354 +1000 commit (initial): commit 01
|
||||||
|
a1a6f7bda6aeaa08ec75f590845780fde90d901c cb7e56856ecee89fa44c613e094fcf962fe18cf1 CI <CI@example.com> 1659958354 +1000 commit: commit 02
|
||||||
|
cb7e56856ecee89fa44c613e094fcf962fe18cf1 6741ab4fe22a3d36b6c64397fc4295dbae1ba71d CI <CI@example.com> 1659958354 +1000 commit: commit 03
|
||||||
|
6741ab4fe22a3d36b6c64397fc4295dbae1ba71d 84b1ae9d83049341897c9388afffdc9049c3317f CI <CI@example.com> 1659958354 +1000 commit: commit 04
|
||||||
|
84b1ae9d83049341897c9388afffdc9049c3317f aa2585aff7d2278341ca816f187e623503d7c4fb CI <CI@example.com> 1659958354 +1000 commit: commit 05
|
||||||
|
aa2585aff7d2278341ca816f187e623503d7c4fb a1a6f7bda6aeaa08ec75f590845780fde90d901c CI <CI@example.com> 1659958355 +1000 rebase (start): checkout a1a6f7bda6aeaa08ec75f590845780fde90d901c
|
||||||
|
a1a6f7bda6aeaa08ec75f590845780fde90d901c cb7e56856ecee89fa44c613e094fcf962fe18cf1 CI <CI@example.com> 1659958355 +1000 rebase: fast-forward
|
||||||
|
cb7e56856ecee89fa44c613e094fcf962fe18cf1 9c68b57ac7b652fbebc5e93a9a1b72014400c269 CI <CI@example.com> 1659958355 +1000 rebase (continue) (fixup): # This is a combination of 2 commits.
|
||||||
|
9c68b57ac7b652fbebc5e93a9a1b72014400c269 f4316f7a6df3fe5b7e8da1b2c8767ed1e825dc05 CI <CI@example.com> 1659958355 +1000 rebase (continue) (squash): commit 02
|
||||||
|
f4316f7a6df3fe5b7e8da1b2c8767ed1e825dc05 f4316f7a6df3fe5b7e8da1b2c8767ed1e825dc05 CI <CI@example.com> 1659958355 +1000 rebase (continue) (finish): returning to refs/heads/master
|
@ -0,0 +1,6 @@
|
|||||||
|
0000000000000000000000000000000000000000 a1a6f7bda6aeaa08ec75f590845780fde90d901c CI <CI@example.com> 1659958354 +1000 commit (initial): commit 01
|
||||||
|
a1a6f7bda6aeaa08ec75f590845780fde90d901c cb7e56856ecee89fa44c613e094fcf962fe18cf1 CI <CI@example.com> 1659958354 +1000 commit: commit 02
|
||||||
|
cb7e56856ecee89fa44c613e094fcf962fe18cf1 6741ab4fe22a3d36b6c64397fc4295dbae1ba71d CI <CI@example.com> 1659958354 +1000 commit: commit 03
|
||||||
|
6741ab4fe22a3d36b6c64397fc4295dbae1ba71d 84b1ae9d83049341897c9388afffdc9049c3317f CI <CI@example.com> 1659958354 +1000 commit: commit 04
|
||||||
|
84b1ae9d83049341897c9388afffdc9049c3317f aa2585aff7d2278341ca816f187e623503d7c4fb CI <CI@example.com> 1659958354 +1000 commit: commit 05
|
||||||
|
aa2585aff7d2278341ca816f187e623503d7c4fb f4316f7a6df3fe5b7e8da1b2c8767ed1e825dc05 CI <CI@example.com> 1659958355 +1000 rebase (continue) (finish): refs/heads/master onto a1a6f7bda6aeaa08ec75f590845780fde90d901c
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,3 @@
|
|||||||
|
x<01><>M
|
||||||
|
<EFBFBD>0<10>a<EFBFBD>9<EFBFBD><39><05>ɟ<11><>1<EFBFBD><31>
|
||||||
|
֖<12><>ۅp<><70>,<><DEBA><EFBFBD><EFBFBD>h<<3C>
|
@ -0,0 +1,3 @@
|
|||||||
|
x<01><>M
|
||||||
|
<EFBFBD>0@a<>9<EFBFBD><39>I2?m@D<><44>cL<63>
|
||||||
|
֖<12><>ۅp<><70><16>,<2C><><EFBFBD><10><1C>f<06>U<EFBFBD>[L<><4C>L<EFBFBD><4C><EFBFBD>sE<73><45><EFBFBD>&K#dnݪ<><DDAA>:<3A>@A35<33>Q<EFBFBD><51>d)B<><42>V(&<26>Y-dBu<42><75><EFBFBD>e<EFBFBD><65><06><>v<EFBFBD><76><EFBFBD><EFBFBD><EFBFBD>Ne<4E>/<10>S<EFBFBD><11><><18><>n<EFBFBD><6E>T<EFBFBD>?<3F>σ'<27><05>u;<3B>
|
@ -0,0 +1,2 @@
|
|||||||
|
x<01><><EFBFBD>J<EFBFBD>0<10>=<3D>)z<14>Iڴ<49>Ȳ<EFBFBD><C8B2><EFBFBD><EFBFBD><02>fb<66>6mi"<22><>F<EFBFBD> ^<5E>9}<7D><>3<EFBFBD><33><EFBFBD><0B><>{(;3p<33><70>ڌ<>9<EFBFBD><39>;<3B><>%á<><12><1E>2%Y<><59>v^
|
||||||
|
<EFBFBD><EFBFBD>><0C>SOL<4F><4C><EFBFBD>Am<>tz0<[<5B><16>(<28><>L<EFBFBD><0E><_o<17><><EFBFBD><EFBFBD>|<1A>t<06>kk<6B>iu<07>E<><45>T<EFBFBD>t}袁<>)f<>CP<43>..T<><54><EFBFBD>@}<7D>z,<2C>~Yeb<65><62>+H<>3<EFBFBD><33><EFBFBD>8*<2A>m<EFBFBD><05>q<EFBFBD><71>1<EFBFBD>{<7B>6<EFBFBD>5<EFBFBD><35>X؊Oz d<>
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,4 @@
|
|||||||
|
x<01><>A
|
||||||
|
1<0C>a<EFBFBD>=E<><45>4<EFBFBD><34>m@D<><44><EFBFBD>h3)
|
||||||
|
<EFBFBD><19>
|
||||||
|
<1E>.<<3C>ۏ<EFBFBD><DB8F><EFBFBD><EFBFBD><EFBFBD>G<EFBFBD><47><EFBFBD><EFBFBD>wU<77>pLJ9<39><D78A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>$BT!*<2A><>ly<6C>W<EFBFBD><57><17><>KB<4B>=$<24>Ҙ<C298>Ex<45> B<>&<26><>}<7D><>|<7C><><EFBFBD>v<EFBFBD>On<4F>SO<53><4F><EFBFBD><EFBFBD>@̔<><CC94>=<3D>s<EFBFBD><1D><><EFBFBD><EFBFBD><EFBFBD>z<EFBFBD><7A>|<01>);=
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
f4316f7a6df3fe5b7e8da1b2c8767ed1e825dc05
|
@ -0,0 +1 @@
|
|||||||
|
file01 content
|
@ -0,0 +1 @@
|
|||||||
|
file02 content
|
@ -0,0 +1 @@
|
|||||||
|
file03 content
|
@ -0,0 +1 @@
|
|||||||
|
file05 content
|
15
vendor/github.com/jesseduffield/gocui/view.go
generated
vendored
15
vendor/github.com/jesseduffield/gocui/view.go
generated
vendored
@ -465,6 +465,14 @@ func (v *View) Cursor() (x, y int) {
|
|||||||
return v.cx, v.cy
|
return v.cx, v.cy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *View) CursorX() int {
|
||||||
|
return v.cx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) CursorY() int {
|
||||||
|
return v.cy
|
||||||
|
}
|
||||||
|
|
||||||
// SetOrigin sets the origin position of the view's internal buffer,
|
// SetOrigin sets the origin position of the view's internal buffer,
|
||||||
// so the buffer starts to be printed from this point, which means that
|
// so the buffer starts to be printed from this point, which means that
|
||||||
// it is linked with the origin point of view. It can be used to
|
// it is linked with the origin point of view. It can be used to
|
||||||
@ -1235,6 +1243,13 @@ func (v *View) SelectedLineIdx() int {
|
|||||||
return seletedLineIdx
|
return seletedLineIdx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expected to only be used in tests
|
||||||
|
func (v *View) SelectedLine() string {
|
||||||
|
line := v.lines[v.SelectedLineIdx()]
|
||||||
|
str := lineType(line).String()
|
||||||
|
return strings.Replace(str, "\x00", " ", -1)
|
||||||
|
}
|
||||||
|
|
||||||
func (v *View) SelectedPoint() (int, int) {
|
func (v *View) SelectedPoint() (int, int) {
|
||||||
cx, cy := v.Cursor()
|
cx, cy := v.Cursor()
|
||||||
ox, oy := v.Origin()
|
ox, oy := v.Origin()
|
||||||
|
Reference in New Issue
Block a user