1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-11-28 09:08:41 +02:00

Merge pull request #2137 from jesseduffield/more-integration-tests

This commit is contained in:
Jesse Duffield 2022-09-17 11:09:49 -07:00 committed by GitHub
commit ee348751a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
722 changed files with 3874 additions and 2467 deletions

View File

@ -13,7 +13,7 @@ Usage:
See https://github.com/jesseduffield/lazygit/tree/master/pkg/integration/README.md
CLI mode:
> go run cmd/integration_test/main.go cli [--slow] <test1> <test2> ...
> go run cmd/integration_test/main.go cli [--slow] [--sandbox] <test1> <test2> ...
If you pass no test names, it runs all tests
Accepted environment variables:
KEY_PRESS_DELAY (e.g. 200): the number of milliseconds to wait between keypresses
@ -42,12 +42,19 @@ func main() {
case "cli":
testNames := os.Args[2:]
slow := false
sandbox := false
// get the next arg if it's --slow
if len(os.Args) > 2 && (os.Args[2] == "--slow" || os.Args[2] == "-slow") {
testNames = os.Args[3:]
slow = true
if len(os.Args) > 2 {
if os.Args[2] == "--slow" || os.Args[2] == "-slow" {
testNames = os.Args[3:]
slow = true
} else if os.Args[2] == "--sandbox" || os.Args[2] == "-sandbox" {
testNames = os.Args[3:]
sandbox = true
}
}
clients.RunCLI(testNames, slow)
clients.RunCLI(testNames, slow, sandbox)
case "tui":
clients.RunTUI()
default:

8
go.mod
View File

@ -11,14 +11,14 @@ require (
github.com/creack/pty v1.1.11
github.com/fsmiamoto/git-todo-parser v0.0.2
github.com/fsnotify/fsnotify v1.4.7
github.com/gdamore/tcell/v2 v2.5.2
github.com/gdamore/tcell/v2 v2.5.3
github.com/go-errors/errors v1.4.2
github.com/gookit/color v1.4.2
github.com/imdario/mergo v0.3.11
github.com/integrii/flaggy v1.4.0
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
github.com/jesseduffield/go-git/v5 v5.1.2-0.20201006095850-341962be15a4
github.com/jesseduffield/gocui v0.3.1-0.20220815095708-156fda5e0419
github.com/jesseduffield/gocui v0.3.1-0.20220916034937-22d48fda22d6
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e
github.com/jesseduffield/yaml v2.1.0+incompatible
@ -61,13 +61,13 @@ require (
github.com/onsi/ginkgo v1.10.3 // indirect
github.com/onsi/gomega v1.7.1 // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
github.com/rivo/uniseg v0.3.4 // indirect
github.com/rivo/uniseg v0.4.2 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/xanzy/ssh-agent v0.2.1 // indirect
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 // indirect
golang.org/x/exp v0.0.0-20220318154914-8dddf5d87bd8 // indirect
golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c // indirect
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 // indirect
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect

16
go.sum
View File

@ -35,8 +35,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell/v2 v2.4.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU=
github.com/gdamore/tcell/v2 v2.5.2 h1:tKzG29kO9p2V++3oBY2W9zUjYu7IK1MENFeY/BzJSVY=
github.com/gdamore/tcell/v2 v2.5.2/go.mod h1:wSkrPaXoiIWZqW/g7Px4xc79di6FTcpB8tvaKJ6uGBo=
github.com/gdamore/tcell/v2 v2.5.3 h1:b9XQrT6QGbgI7JvZOJXFNczOQeIYbo8BfeSMzt2sAV0=
github.com/gdamore/tcell/v2 v2.5.3/go.mod h1:wSkrPaXoiIWZqW/g7Px4xc79di6FTcpB8tvaKJ6uGBo=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
@ -72,8 +72,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
github.com/jesseduffield/go-git/v5 v5.1.2-0.20201006095850-341962be15a4 h1:GOQrmaE8i+KEdB8NzAegKYd4tPn/inM0I1uo0NXFerg=
github.com/jesseduffield/go-git/v5 v5.1.2-0.20201006095850-341962be15a4/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
github.com/jesseduffield/gocui v0.3.1-0.20220815095708-156fda5e0419 h1:p3Ix7RUcy4X16Lk5jTSfTxecJT7ryqYHclfRbo/Svzs=
github.com/jesseduffield/gocui v0.3.1-0.20220815095708-156fda5e0419/go.mod h1:znJuCDnF2Ph40YZSlBwdX/4GEofnIoWLGdT4mK5zRAU=
github.com/jesseduffield/gocui v0.3.1-0.20220916034937-22d48fda22d6 h1:FgxhH7++BaLcDwldyNtxkeVUC2z7ur2QYtJ8Msgkgc0=
github.com/jesseduffield/gocui v0.3.1-0.20220916034937-22d48fda22d6/go.mod h1:znJuCDnF2Ph40YZSlBwdX/4GEofnIoWLGdT4mK5zRAU=
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e h1:uw/oo+kg7t/oeMs6sqlAwr85ND/9cpO3up3VxphxY0U=
@ -134,8 +134,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.3.4 h1:3Z3Eu6FGHZWSfNKJTOUiPatWwfc7DzJRU04jFUqJODw=
github.com/rivo/uniseg v0.3.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8=
github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
github.com/samber/lo v1.10.1 h1:0D3h7i0U3hRAbaCeQ82DLe67n0A7Bbl0/cEoWqFGp+U=
@ -194,8 +194,8 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220318055525-2edf467146b5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 h1:ohgcoMbSofXygzo6AD2I1kz3BFmW1QArPYTtwEM3UXc=
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc=
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=

View File

@ -494,8 +494,6 @@ func (gui *Gui) Run(startArgs appTypes.StartArgs) error {
})
deadlock.Opts.Disable = !gui.Debug
gui.handleTestMode(startArgs.IntegrationTest)
gui.g.OnSearchEscape = gui.onSearchEscape
if err := gui.Config.ReloadUserConfig(); err != nil {
return nil
@ -552,6 +550,8 @@ func (gui *Gui) Run(startArgs appTypes.StartArgs) error {
gui.c.Log.Info("starting main loop")
gui.handleTestMode(startArgs.IntegrationTest)
return gui.g.MainLoop()
}

View File

@ -79,3 +79,11 @@ func (self *GuiDriver) MainView() *gocui.View {
func (self *GuiDriver) SecondaryView() *gocui.View {
return self.gui.secondaryView()
}
func (self *GuiDriver) View(viewName string) *gocui.View {
view, err := self.gui.g.View(viewName)
if err != nil {
panic(err)
}
return view
}

View File

@ -53,10 +53,17 @@ func (gui *Gui) modeStatuses() []modeStatus {
{
isActive: gui.State.Modes.CherryPicking.Active,
description: func() string {
copiedCount := len(gui.State.Modes.CherryPicking.CherryPickedCommits)
text := gui.c.Tr.LcCommitsCopied
if copiedCount == 1 {
text = gui.c.Tr.LcCommitCopied
}
return gui.withResetButton(
fmt.Sprintf(
"%d commits copied",
len(gui.State.Modes.CherryPicking.CherryPickedCommits),
"%d %s",
copiedCount,
text,
),
style.FgCyan,
)

View File

@ -42,7 +42,7 @@ func (gui *Gui) handleTestMode(test integrationTypes.IntegrationTest) {
if Replaying() {
gui.g.RecordingConfig = gocui.RecordingConfig{
Speed: GetRecordingSpeed(),
Leeway: 100,
Leeway: 1000,
}
var err error

View File

@ -507,6 +507,8 @@ type TranslationSet struct {
EmptyOutput string
Patch string
CustomPatch string
LcCommitsCopied string
LcCommitCopied string
Actions Actions
Bisect Bisect
}
@ -1147,6 +1149,8 @@ func EnglishTranslationSet() TranslationSet {
EmptyOutput: "<empty output>",
Patch: "Patch",
CustomPatch: "Custom patch",
LcCommitsCopied: "commits copied",
LcCommitCopied: "commit copied",
Actions: Actions{
// TODO: combine this with the original keybinding descriptions (those are all in lowercase atm)
CheckoutCommit: "Checkout commit",

View File

@ -11,7 +11,7 @@ go run cmd/integration_test/main.go tui
or
```sh
go run cmd/integration_test/main.go cli [--slow] [testname or testpath...]
go run cmd/integration_test/main.go cli [--slow or --sandbox] [testname or testpath...]
```
## Writing tests
@ -49,7 +49,7 @@ If you find yourself doing something frequently in a test, consider making it a
There are three ways to invoke a test:
1. go run cmd/integration_test/main.go cli [--slow] [testname or testpath...]
1. go run cmd/integration_test/main.go cli [--slow or --sandbox] [testname or testpath...]
2. go run cmd/integration_test/main.go tui
3. go test pkg/integration/clients/go_test.go
@ -69,7 +69,7 @@ At the moment (this is subject to change) each test has a snapshot repo created
Say you want to do a manual test of how lazygit handles merge-conflicts, but you can't be bothered actually finding a way to create merge conflicts in a repo. To make your life easier, you can simply run a merge-conflicts test in sandbox mode, meaning the setup step is run for you, and then instead of the test driving the lazygit session, you're allowed to drive it yourself.
To run a test in sandbox mode you can press 's' on a test in the test TUI or pass the env var MODE=sandbox to the test runner.
To run a test in sandbox mode you can press 's' on a test in the test TUI or in the test runner pass MODE=sandbox or the --sandbox argument.
## Migration process

View File

@ -23,26 +23,34 @@ import (
// If invoked directly, you can specify tests to run by passing their names as positional arguments
func RunCLI(testNames []string, slow bool) {
func RunCLI(testNames []string, slow bool, sandbox bool) {
keyPressDelay := tryConvert(os.Getenv("KEY_PRESS_DELAY"), 0)
if slow {
keyPressDelay = SLOW_KEY_PRESS_DELAY
}
var mode components.Mode
if sandbox {
mode = components.SANDBOX
} else {
mode = getModeFromEnv()
}
err := components.RunTests(
getTestsToRun(testNames),
log.Printf,
runCmdInTerminal,
runAndPrintError,
getModeFromEnv(),
runAndPrintFatalError,
mode,
keyPressDelay,
1,
)
if err != nil {
log.Print(err.Error())
}
}
func runAndPrintError(test *components.IntegrationTest, f func() error) {
func runAndPrintFatalError(test *components.IntegrationTest, f func() error) {
if err := f(); err != nil {
log.Fatalf(err.Error())
}

View File

@ -7,6 +7,8 @@ package clients
// for an example
import (
"bytes"
"errors"
"io"
"io/ioutil"
"os"
@ -39,12 +41,16 @@ func TestIntegration(t *testing.T) {
}
t.Run(test.Name(), func(t *testing.T) {
t.Parallel()
err := f()
assert.NoError(t, err)
})
},
components.CHECK_SNAPSHOT,
0,
// allowing two attempts at the test. If a test fails intermittently,
// there may be a concurrency issue that we need to resolve.
2,
)
assert.NoError(t, err)
@ -57,12 +63,26 @@ func runCmdHeadless(cmd *exec.Cmd) error {
"TERM=xterm",
)
f, err := pty.StartWithSize(cmd, &pty.Winsize{Rows: 100, Cols: 100})
// not writing stderr to the pty because we want to capture a panic if
// there is one. But some commands will not be in tty mode if stderr is
// not a terminal. We'll need to keep an eye out for that.
stderr := new(bytes.Buffer)
cmd.Stderr = stderr
// these rows and columns are ignored because internally we use tcell's
// simulation screen. However we still need the pty for the sake of
// running other commands in a pty.
f, err := pty.StartWithSize(cmd, &pty.Winsize{Rows: 300, Cols: 300})
if err != nil {
return err
}
_, _ = io.Copy(ioutil.Discard, f)
if cmd.Wait() != nil {
// return an error with the stderr output
return errors.New(stderr.String())
}
return f.Close()
}

View File

@ -375,8 +375,15 @@ func runTuiTest(test *components.IntegrationTest, mode components.Mode, keyPress
runAndPrintError,
mode,
keyPressDelay,
1,
)
if err != nil {
log.Println(err.Error())
}
}
func runAndPrintError(test *components.IntegrationTest, f func() error) {
if err := f(); err != nil {
log.Println(err.Error())
}
}

View File

@ -46,7 +46,13 @@ func (self *matcher) context(prefix string) *matcher {
func Contains(target string) *matcher {
return &matcher{testFn: func(value string) (bool, string) {
return strings.Contains(value, target), fmt.Sprintf("Expected '%s' to contain '%s'", value, target)
return strings.Contains(value, target), fmt.Sprintf("Expected '%s' to be found in '%s'", target, value)
}}
}
func NotContains(target string) *matcher {
return &matcher{testFn: func(value string) (bool, string) {
return !strings.Contains(value, target), fmt.Sprintf("Expected '%s' to NOT be found in '%s'", target, value)
}}
}
@ -78,6 +84,14 @@ func (self *Assert) CommitCount(expectedCount int) {
})
}
func (self *Assert) AtLeastOneCommit() {
self.assertWithRetries(func() (bool, string) {
actualCount := len(self.gui.Model().Commits)
return actualCount > 0, "Expected at least one commit present"
})
}
func (self *Assert) MatchHeadCommitMessage(matcher *matcher) {
self.assertWithRetries(func() (bool, string) {
return len(self.gui.Model().Commits) > 0, "Expected at least one commit to be present"
@ -97,6 +111,13 @@ func (self *Assert) CurrentViewName(expectedViewName string) {
})
}
func (self *Assert) CurrentWindowName(expectedWindowName string) {
self.assertWithRetries(func() (bool, string) {
actual := self.gui.CurrentContext().GetView().Name()
return actual == expectedWindowName, fmt.Sprintf("Expected current window name to be '%s', but got '%s'", expectedWindowName, actual)
})
}
func (self *Assert) CurrentBranchName(expectedViewName string) {
self.assertWithRetries(func() (bool, string) {
actual := self.gui.CheckedOutRef().Name
@ -156,6 +177,22 @@ func (self *Assert) MatchCurrentViewTitle(matcher *matcher) {
)
}
func (self *Assert) MatchViewContent(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) MatchCurrentViewContent(matcher *matcher) {
self.matchString(matcher, "Unexpected content in current view.",
func() string {
return self.gui.CurrentContext().GetView().Buffer()
},
)
}
func (self *Assert) MatchMainViewContent(matcher *matcher) {
self.matchString(matcher, "Unexpected main view content.",
func() string {
@ -180,7 +217,7 @@ func (self *Assert) matchString(matcher *matcher, context string, getValue func(
}
func (self *Assert) assertWithRetries(test func() (bool, string)) {
waitTimes := []int{0, 1, 5, 10, 200, 500, 1000}
waitTimes := []int{0, 1, 5, 10, 200, 500, 1000, 2000, 4000}
var message string
for _, waitTime := range waitTimes {

View File

@ -42,22 +42,27 @@ func (self *Input) pressKey(keyStr string) {
func (self *Input) SwitchToStatusWindow() {
self.pressKey(self.keys.Universal.JumpToBlock[0])
self.assert.CurrentWindowName("status")
}
func (self *Input) SwitchToFilesWindow() {
self.pressKey(self.keys.Universal.JumpToBlock[1])
self.assert.CurrentWindowName("files")
}
func (self *Input) SwitchToBranchesWindow() {
self.pressKey(self.keys.Universal.JumpToBlock[2])
self.assert.CurrentWindowName("localBranches")
}
func (self *Input) SwitchToCommitsWindow() {
self.pressKey(self.keys.Universal.JumpToBlock[3])
self.assert.CurrentWindowName("commits")
}
func (self *Input) SwitchToStashWindow() {
self.pressKey(self.keys.Universal.JumpToBlock[4])
self.assert.CurrentWindowName("stash")
}
func (self *Input) Type(content string) {
@ -71,6 +76,11 @@ func (self *Input) Confirm() {
self.pressKey(self.keys.Universal.Confirm)
}
// i.e. same as Confirm
func (self *Input) Enter() {
self.pressKey(self.keys.Universal.Confirm)
}
// i.e. pressing escape
func (self *Input) Cancel() {
self.pressKey(self.keys.Universal.Return)
@ -132,35 +142,43 @@ func (self *Input) NavigateToListItemContainingText(text string) {
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
}
}
var matchIndex int
self.assert.Fail(fmt.Sprintf("Could not find item containing text: %s", text))
self.assert.assertWithRetries(func() (bool, string) {
matchCount := 0
matchIndex = -1
// first we look for a duplicate on the current screen. We won't bother looking beyond that though.
for i, line := range view.ViewBufferLines() {
if strings.Contains(line, text) {
matchCount++
matchIndex = i
}
}
if matchCount > 1 {
return false, fmt.Sprintf("Found %d matches for %s, expected only a single match", matchCount, text)
} else if matchCount == 0 {
return false, fmt.Sprintf("Could not find item containing text: %s", text)
} else {
return true, ""
}
})
selectedLineIdx := view.SelectedLineIdx()
if selectedLineIdx == matchIndex {
self.assert.MatchSelectedLine(Contains(text))
return
}
if selectedLineIdx < matchIndex {
for i := selectedLineIdx; i < matchIndex; i++ {
self.NextItem()
}
self.assert.MatchSelectedLine(Contains(text))
return
} else {
for i := selectedLineIdx; i > matchIndex; i-- {
self.PreviousItem()
}
self.assert.MatchSelectedLine(Contains(text))
return
}
}

View File

@ -42,6 +42,7 @@ func RunTests(
testWrapper func(test *IntegrationTest, f func() error),
mode Mode,
keyPressDelay int,
maxAttempts int,
) error {
projectRootDir := utils.GetLazygitRootDirectory()
err := os.Chdir(projectRootDir)
@ -58,12 +59,24 @@ func RunTests(
for _, test := range tests {
test := test
paths := NewPaths(
filepath.Join(testDir, test.Name()),
)
testWrapper(test, func() error { //nolint: thelper
return runTest(test, paths, projectRootDir, logf, runCmd, mode, keyPressDelay)
paths := NewPaths(
filepath.Join(testDir, test.Name()),
)
for i := 0; i < maxAttempts; i++ {
err := runTest(test, paths, projectRootDir, logf, runCmd, mode, keyPressDelay)
if err != nil {
if i == maxAttempts-1 {
return err
}
logf("retrying test %s", test.Name())
} else {
break
}
}
return nil
})
}
@ -126,16 +139,7 @@ func buildLazygit() error {
}
func createFixture(test *IntegrationTest, paths Paths) error {
originalDir, err := os.Getwd()
if err != nil {
return err
}
if err := os.Chdir(paths.ActualRepo()); err != nil {
panic(err)
}
shell := NewShell()
shell := NewShell(paths.ActualRepo())
shell.RunCommand("git init -b master")
shell.RunCommand(`git config user.email "CI@example.com"`)
shell.RunCommand(`git config user.name "CI"`)
@ -143,10 +147,6 @@ func createFixture(test *IntegrationTest, paths Paths) error {
test.SetupRepo(shell)
if err := os.Chdir(originalDir); err != nil {
panic(err)
}
return nil
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/jesseduffield/lazygit/pkg/secureexec"
"github.com/mgutz/str"
@ -12,16 +13,20 @@ import (
// this is for running shell commands, mostly for the sake of setting up the repo
// but you can also run the commands from within lazygit to emulate things happening
// in the background.
type Shell struct{}
type Shell struct {
// working directory the shell is invoked in
dir string
}
func NewShell() *Shell {
return &Shell{}
func NewShell(dir string) *Shell {
return &Shell{dir: dir}
}
func (s *Shell) RunCommand(cmdStr string) *Shell {
args := str.ToArgv(cmdStr)
cmd := secureexec.Command(args[0], args[1:]...)
cmd.Env = os.Environ()
cmd.Dir = s.dir
output, err := cmd.CombinedOutput()
if err != nil {
@ -32,9 +37,20 @@ func (s *Shell) RunCommand(cmdStr string) *Shell {
}
func (s *Shell) CreateFile(path string, content string) *Shell {
err := ioutil.WriteFile(path, []byte(content), 0o644)
fullPath := filepath.Join(s.dir, path)
err := ioutil.WriteFile(fullPath, []byte(content), 0o644)
if err != nil {
panic(fmt.Sprintf("error creating file: %s\n%s", path, err))
panic(fmt.Sprintf("error creating file: %s\n%s", fullPath, err))
}
return s
}
func (s *Shell) UpdateFile(path string, content string) *Shell {
fullPath := filepath.Join(s.dir, path)
err := ioutil.WriteFile(fullPath, []byte(content), 0o644)
if err != nil {
panic(fmt.Sprintf("error updating file: %s\n%s", fullPath, err))
}
return s
@ -44,6 +60,10 @@ func (s *Shell) NewBranch(name string) *Shell {
return s.RunCommand("git checkout -b " + name)
}
func (s *Shell) Checkout(name string) *Shell {
return s.RunCommand("git checkout " + name)
}
func (s *Shell) GitAdd(path string) *Shell {
return s.RunCommand(fmt.Sprintf("git add \"%s\"", path))
}
@ -67,6 +87,13 @@ func (s *Shell) CreateFileAndAdd(fileName string, fileContents string) *Shell {
GitAdd(fileName)
}
// convenience method for updating a file and adding it
func (s *Shell) UpdateFileAndAdd(fileName string, fileContents string) *Shell {
return s.
UpdateFile(fileName, fileContents).
GitAdd(fileName)
}
// 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

View File

@ -174,7 +174,7 @@ func (self *Snapshotter) compareSnapshots() error {
}
self.logf("%s", string(bytes))
return errors.New(getDiff(f.Name(), actualRepo, expectedRepo))
return errors.New(getDiff(f.Name(), expectedRepo, actualRepo))
}
}

View File

@ -93,7 +93,7 @@ func (self *IntegrationTest) SetupRepo(shell *Shell) {
// I want access to all contexts, the model, the ability to press a key, the ability to log,
func (self *IntegrationTest) Run(gui integrationTypes.GuiDriver) {
shell := NewShell()
shell := NewShell("/tmp/lazygit-test")
assert := NewAssert(gui)
keys := gui.Keys()
input := NewInput(gui, keys, assert, KeyPressDelay())

View File

@ -56,6 +56,10 @@ func (self *fakeGuiDriver) SecondaryView() *gocui.View {
return nil
}
func (self *fakeGuiDriver) View(viewName string) *gocui.View {
return nil
}
func TestAssertionFailure(t *testing.T) {
test := NewIntegrationTest(NewIntegrationTestArgs{
Description: unitTestDescription,

View File

@ -4,6 +4,8 @@
package deprecated
import (
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
@ -95,6 +97,15 @@ func runCmdHeadless(cmd *exec.Cmd) error {
"TERM=xterm",
)
// not writing stderr to the pty because we want to capture a panic if
// there is one. But some commands will not be in tty mode if stderr is
// not a terminal. We'll need to keep an eye out for that.
stderr := new(bytes.Buffer)
cmd.Stderr = stderr
// these rows and columns are ignored because internally we use tcell's
// simulation screen. However we still need the pty for the sake of
// running other commands in a pty.
f, err := pty.StartWithSize(cmd, &pty.Winsize{Rows: 100, Cols: 100})
if err != nil {
return err
@ -102,5 +113,10 @@ func runCmdHeadless(cmd *exec.Cmd) error {
_, _ = io.Copy(ioutil.Discard, f)
if cmd.Wait() != nil {
// return an error with the stderr output
return errors.New(stderr.String())
}
return f.Close()
}

View File

@ -310,7 +310,7 @@ func getTestSpeeds(testStartSpeed float64, mode Mode, speedStr string) []float64
if startSpeed > 5 {
speeds = append(speeds, 5)
}
speeds = append(speeds, 1, 1)
speeds = append(speeds, 1, 0.5, 0.5)
return speeds
}

View File

@ -0,0 +1,86 @@
package bisect
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var Basic = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Start a git bisect to find a bad commit",
ExtraCmdArgs: "",
Skip: false,
SetupRepo: func(shell *Shell) {
shell.
CreateNCommits(10)
},
SetupConfig: func(cfg *config.AppConfig) {},
Run: func(
shell *Shell,
input *Input,
assert *Assert,
keys config.KeybindingConfig,
) {
viewBisectOptions := func() {
input.PressKeys(keys.Commits.ViewBisectOptions)
assert.InMenu()
}
markCommitAsBad := func() {
viewBisectOptions()
assert.MatchSelectedLine(Contains("bad"))
input.Confirm()
}
markCommitAsGood := func() {
viewBisectOptions()
assert.MatchSelectedLine(Contains("bad"))
input.NextItem()
assert.MatchSelectedLine(Contains("good"))
input.Confirm()
}
assert.AtLeastOneCommit()
input.SwitchToCommitsWindow()
assert.MatchSelectedLine(Contains("commit 10"))
input.NavigateToListItemContainingText("commit 09")
markCommitAsBad()
assert.MatchViewContent("information", Contains("bisecting"))
assert.CurrentViewName("commits")
assert.MatchSelectedLine(Contains("<-- bad"))
input.NavigateToListItemContainingText("commit 02")
markCommitAsGood()
// lazygit will land us in the comit between our good and bad commits.
assert.CurrentViewName("commits")
assert.MatchSelectedLine(Contains("commit 05"))
assert.MatchSelectedLine(Contains("<-- current"))
markCommitAsBad()
assert.CurrentViewName("commits")
assert.MatchSelectedLine(Contains("commit 04"))
assert.MatchSelectedLine(Contains("<-- current"))
markCommitAsGood()
assert.InAlert()
assert.MatchCurrentViewContent(Contains("Bisect complete!"))
// commit 5 is the culprit because we marked 4 as good and 5 as bad.
assert.MatchCurrentViewContent(Contains("commit 05"))
assert.MatchCurrentViewContent(Contains("Do you want to reset"))
input.Confirm()
assert.CurrentViewName("commits")
assert.MatchCurrentViewContent(Contains("commit 04"))
assert.MatchViewContent("information", NotContains("bisecting"))
},
})

View File

@ -0,0 +1,69 @@
package bisect
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var FromOtherBranch = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Opening lazygit when bisect has been started from another branch. There's an issue where we don't reselect the current branch if we mark the current branch as bad so this test side-steps that problem",
ExtraCmdArgs: "",
Skip: false,
SetupRepo: func(shell *Shell) {
shell.
EmptyCommit("only commit on master"). // this'll ensure we have a master branch
NewBranch("other").
CreateNCommits(10).
Checkout("master").
RunCommand("git bisect start other~2 other~5")
},
SetupConfig: func(cfg *config.AppConfig) {},
Run: func(
shell *Shell,
input *Input,
assert *Assert,
keys config.KeybindingConfig,
) {
viewBisectOptions := func() {
input.PressKeys(keys.Commits.ViewBisectOptions)
assert.InMenu()
}
markCommitAsGood := func() {
viewBisectOptions()
assert.MatchSelectedLine(Contains("bad"))
input.NextItem()
assert.MatchSelectedLine(Contains("good"))
input.Confirm()
}
assert.MatchViewContent("information", Contains("bisecting"))
assert.AtLeastOneCommit()
input.SwitchToCommitsWindow()
assert.MatchSelectedLine(Contains("<-- bad"))
assert.MatchSelectedLine(Contains("commit 08"))
input.NextItem()
assert.MatchSelectedLine(Contains("<-- current"))
assert.MatchSelectedLine(Contains("commit 07"))
markCommitAsGood()
assert.InAlert()
assert.MatchCurrentViewContent(Contains("Bisect complete!"))
assert.MatchCurrentViewContent(Contains("commit 08"))
assert.MatchCurrentViewContent(Contains("Do you want to reset"))
input.Confirm()
assert.MatchViewContent("information", NotContains("bisecting"))
// back in master branch which just had the one commit
assert.CurrentViewName("commits")
assert.CommitCount(1)
assert.MatchSelectedLine(Contains("only commit on master"))
},
})

View File

@ -0,0 +1,40 @@
package branch
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var Delete = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Try to delete the checked out branch first (to no avail), and then delete another branch.",
ExtraCmdArgs: "",
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.
EmptyCommit("blah").
NewBranch("branch-one").
NewBranch("branch-two")
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
assert.MatchSelectedLine(Contains("branch-two"))
input.PressKeys(keys.Universal.Remove)
assert.InAlert()
assert.MatchCurrentViewContent(Contains("You cannot delete the checked out branch!"))
input.Confirm()
input.NextItem()
assert.MatchSelectedLine(Contains("branch-one"))
input.PressKeys(keys.Universal.Remove)
assert.InConfirm()
assert.MatchCurrentViewContent(Contains("Are you sure you want to delete the branch 'branch-one'?"))
input.Confirm()
assert.CurrentViewName("localBranches")
assert.MatchSelectedLine(Contains("master"))
assert.MatchCurrentViewContent(NotContains("branch-one"))
},
})

View File

@ -0,0 +1,53 @@
package branch
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
"github.com/jesseduffield/lazygit/pkg/integration/tests/shared"
)
var Rebase = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Rebase onto another branch, deal with the conflicts.",
ExtraCmdArgs: "",
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shared.MergeConflictsSetup(shell)
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
assert.MatchSelectedLine(Contains("first-change-branch"))
input.NextItem()
assert.MatchSelectedLine(Contains("second-change-branch"))
input.PressKeys(keys.Branches.RebaseBranch)
assert.InConfirm()
assert.MatchCurrentViewContent(Contains("Are you sure you want to rebase 'first-change-branch' onto 'second-change-branch'?"))
input.Confirm()
assert.InConfirm()
assert.MatchCurrentViewContent(Contains("Conflicts!"))
input.Confirm()
assert.CurrentViewName("files")
assert.MatchSelectedLine(Contains("file"))
// not using Confirm() convenience method because I suspect we might change this
// keybinding to something more bespoke
input.PressKeys(keys.Universal.Confirm)
assert.CurrentViewName("mergeConflicts")
input.PrimaryAction()
assert.MatchViewContent("information", Contains("rebasing"))
assert.InConfirm()
assert.MatchCurrentViewContent(Contains("all merge conflicts resolved. Continue?"))
input.Confirm()
assert.MatchViewContent("information", NotContains("rebasing"))
// this proves we actually have integrated the changes from second-change-branch
assert.MatchViewContent("commits", Contains("second-change-branch unrelated change"))
},
})

View File

@ -0,0 +1,69 @@
package branch
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
"github.com/jesseduffield/lazygit/pkg/integration/tests/shared"
)
var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Rebase onto another branch, deal with the conflicts. Also mark a commit to be dropped before continuing.",
ExtraCmdArgs: "",
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shared.MergeConflictsSetup(shell)
// addin a couple additional commits so that we can drop one
shell.EmptyCommit("to remove")
shell.EmptyCommit("to keep")
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
assert.MatchSelectedLine(Contains("first-change-branch"))
input.NextItem()
assert.MatchSelectedLine(Contains("second-change-branch"))
input.PressKeys(keys.Branches.RebaseBranch)
assert.InConfirm()
assert.MatchCurrentViewContent(Contains("Are you sure you want to rebase 'first-change-branch' onto 'second-change-branch'?"))
input.Confirm()
assert.MatchViewContent("information", Contains("rebasing"))
assert.InConfirm()
assert.MatchCurrentViewContent(Contains("Conflicts!"))
input.Confirm()
assert.CurrentViewName("files")
assert.MatchSelectedLine(Contains("file"))
input.SwitchToCommitsWindow()
assert.MatchSelectedLine(Contains("pick")) // this means it's a rebasing commit
input.NextItem()
input.PressKeys(keys.Universal.Remove)
assert.MatchSelectedLine(Contains("to remove"))
assert.MatchSelectedLine(Contains("drop"))
input.SwitchToFilesWindow()
// not using Confirm() convenience method because I suspect we might change this
// keybinding to something more bespoke
input.PressKeys(keys.Universal.Confirm)
assert.CurrentViewName("mergeConflicts")
input.PrimaryAction()
assert.InConfirm()
assert.MatchCurrentViewContent(Contains("all merge conflicts resolved. Continue?"))
input.Confirm()
assert.MatchViewContent("information", NotContains("rebasing"))
// this proves we actually have integrated the changes from second-change-branch
assert.MatchViewContent("commits", Contains("second-change-branch unrelated change"))
assert.MatchViewContent("commits", Contains("to keep"))
assert.MatchViewContent("commits", NotContains("to remove"))
},
})

View File

@ -2,15 +2,15 @@ package branch
import (
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/integration/components"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var Suggestions = components.NewIntegrationTest(components.NewIntegrationTestArgs{
var Suggestions = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Checking out a branch with name suggestions",
ExtraCmdArgs: "",
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *components.Shell) {
SetupRepo: func(shell *Shell) {
shell.
EmptyCommit("my commit message").
NewBranch("new-branch").
@ -20,7 +20,7 @@ var Suggestions = components.NewIntegrationTest(components.NewIntegrationTestArg
NewBranch("other-new-branch-2").
NewBranch("other-new-branch-3")
},
Run: func(shell *components.Shell, input *components.Input, assert *components.Assert, keys config.KeybindingConfig) {
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
@ -34,6 +34,7 @@ var Suggestions = components.NewIntegrationTest(components.NewIntegrationTestArg
// we expect the first suggestion to be the branch we want because it most
// closely matches what we typed in
assert.MatchSelectedLine(Contains("branch-to-checkout"))
input.Confirm()
assert.CurrentBranchName("branch-to-checkout")

View File

@ -0,0 +1,66 @@
package cherry_pick
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var CherryPick = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Cherry pick commits from the subcommits view, without conflicts",
ExtraCmdArgs: "",
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.
EmptyCommit("base").
NewBranch("first-branch").
NewBranch("second-branch").
Checkout("first-branch").
EmptyCommit("one").
EmptyCommit("two").
Checkout("second-branch").
EmptyCommit("three").
EmptyCommit("four").
Checkout("first-branch")
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
assert.MatchSelectedLine(Contains("first-branch"))
input.NextItem()
assert.MatchSelectedLine(Contains("second-branch"))
input.Enter()
assert.CurrentViewName("subCommits")
assert.MatchSelectedLine(Contains("four"))
input.PressKeys(keys.Commits.CherryPickCopy)
assert.MatchViewContent("information", Contains("1 commit copied"))
input.NextItem()
assert.MatchSelectedLine(Contains("three"))
input.PressKeys(keys.Commits.CherryPickCopy)
assert.MatchViewContent("information", Contains("2 commits copied"))
input.SwitchToCommitsWindow()
assert.CurrentViewName("commits")
assert.MatchSelectedLine(Contains("two"))
input.PressKeys(keys.Commits.PasteCommits)
assert.InAlert()
assert.MatchCurrentViewContent(Contains("Are you sure you want to cherry-pick the copied commits onto this branch?"))
input.Confirm()
assert.CurrentViewName("commits")
assert.MatchSelectedLine(Contains("four"))
input.NextItem()
assert.MatchSelectedLine(Contains("three"))
input.NextItem()
assert.MatchSelectedLine(Contains("two"))
assert.MatchViewContent("information", Contains("2 commits copied"))
input.PressKeys(keys.Universal.Return)
assert.MatchViewContent("information", NotContains("commits copied"))
},
})

View File

@ -0,0 +1,87 @@
package cherry_pick
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
"github.com/jesseduffield/lazygit/pkg/integration/tests/shared"
)
var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Cherry pick commits from the subcommits view, with conflicts",
ExtraCmdArgs: "",
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shared.MergeConflictsSetup(shell)
},
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
input.SwitchToBranchesWindow()
assert.CurrentViewName("localBranches")
assert.MatchSelectedLine(Contains("first-change-branch"))
input.NextItem()
assert.MatchSelectedLine(Contains("second-change-branch"))
input.Enter()
assert.CurrentViewName("subCommits")
assert.MatchSelectedLine(Contains("second-change-branch unrelated change"))
input.PressKeys(keys.Commits.CherryPickCopy)
assert.MatchViewContent("information", Contains("1 commit copied"))
input.NextItem()
assert.MatchSelectedLine(Contains("second change"))
input.PressKeys(keys.Commits.CherryPickCopy)
assert.MatchViewContent("information", Contains("2 commits copied"))
input.SwitchToCommitsWindow()
assert.CurrentViewName("commits")
assert.MatchSelectedLine(Contains("first change"))
input.PressKeys(keys.Commits.PasteCommits)
assert.InAlert()
assert.MatchCurrentViewContent(Contains("Are you sure you want to cherry-pick the copied commits onto this branch?"))
input.Confirm()
assert.MatchCurrentViewContent(Contains("Conflicts!"))
input.Confirm()
assert.CurrentViewName("files")
assert.MatchSelectedLine(Contains("file"))
// not using Confirm() convenience method because I suspect we might change this
// keybinding to something more bespoke
input.PressKeys(keys.Universal.Confirm)
assert.CurrentViewName("mergeConflicts")
// picking 'Second change'
input.NextItem()
input.PrimaryAction()
assert.InConfirm()
assert.MatchCurrentViewContent(Contains("all merge conflicts resolved. Continue?"))
input.Confirm()
assert.CurrentViewName("files")
assert.WorkingTreeFileCount(0)
input.SwitchToCommitsWindow()
assert.CurrentViewName("commits")
assert.MatchSelectedLine(Contains("second-change-branch unrelated change"))
input.NextItem()
assert.MatchSelectedLine(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.MatchMainViewContent(Contains("-First Change"))
assert.MatchMainViewContent(Contains("+Second Change"))
input.NextItem()
assert.MatchSelectedLine(Contains("first change"))
assert.MatchViewContent("information", Contains("2 commits copied"))
input.PressKeys(keys.Universal.Return)
assert.MatchViewContent("information", NotContains("commits copied"))
},
})

View File

@ -0,0 +1 @@
This package contains shared helper functions for tests. It is not intended to contain any actual tests itself.

View File

@ -0,0 +1,49 @@
package shared
import (
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var OriginalFileContent = `
This
Is
The
Original
File
`
var FirstChangeFileContent = `
This
Is
The
First Change
File
`
var SecondChangeFileContent = `
This
Is
The
Second Change
File
`
// prepares us for a rebase/merge that has conflicts
var MergeConflictsSetup = func(shell *Shell) {
shell.
NewBranch("original-branch").
EmptyCommit("one").
EmptyCommit("two").
EmptyCommit("three").
CreateFileAndAdd("file", OriginalFileContent).
Commit("original").
NewBranch("first-change-branch").
UpdateFileAndAdd("file", FirstChangeFileContent).
Commit("first change").
Checkout("original-branch").
NewBranch("second-change-branch").
UpdateFileAndAdd("file", SecondChangeFileContent).
Commit("second change").
EmptyCommit("second-change-branch unrelated change").
Checkout("first-change-branch")
}

View File

@ -9,7 +9,9 @@ import (
"github.com/jesseduffield/generics/set"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/integration/components"
"github.com/jesseduffield/lazygit/pkg/integration/tests/bisect"
"github.com/jesseduffield/lazygit/pkg/integration/tests/branch"
"github.com/jesseduffield/lazygit/pkg/integration/tests/cherry_pick"
"github.com/jesseduffield/lazygit/pkg/integration/tests/commit"
"github.com/jesseduffield/lazygit/pkg/integration/tests/custom_commands"
"github.com/jesseduffield/lazygit/pkg/integration/tests/interactive_rebase"
@ -23,10 +25,17 @@ var tests = []*components.IntegrationTest{
commit.Commit,
commit.NewBranch,
branch.Suggestions,
branch.Delete,
branch.Rebase,
branch.RebaseAndDrop,
interactive_rebase.One,
custom_commands.Basic,
custom_commands.MultiplePrompts,
custom_commands.MenuFromCommand,
bisect.Basic,
bisect.FromOtherBranch,
cherry_pick.CherryPick,
cherry_pick.CherryPickConflicts,
}
func GetTests() []*components.IntegrationTest {
@ -49,6 +58,11 @@ func GetTests() []*components.IntegrationTest {
return nil
}
// the shared directory won't itself contain tests: only shared helper functions
if filepath.Base(filepath.Dir(path)) == "shared" {
return nil
}
nameFromPath := components.TestNameFromFilePath(path)
if !testNamesSet.Includes(nameFromPath) {
missingTestNames = append(missingTestNames, nameFromPath)

View File

@ -34,4 +34,5 @@ type GuiDriver interface {
// the other view that sometimes appears to the right of the side panel
// e.g. when we're showing both staged and unstaged changes
SecondaryView() *gocui.View
View(viewName string) *gocui.View
}

View File

@ -1 +0,0 @@
e927f0f9467e772eea36f24053c9b534303b106a

View File

@ -1,16 +0,0 @@
git bisect start
# bad: [054bdf969fdcf1f90f1998666f628d40f72fde4f] commit 19
git bisect bad 054bdf969fdcf1f90f1998666f628d40f72fde4f
# good: [39983ea412adebe6c5a3d4451a7673cf0962c472] commit 9
git bisect good 39983ea412adebe6c5a3d4451a7673cf0962c472
# good: [e9d2f825e793bc9ac2be698348dbe669bad34cad] commit 14
git bisect good e9d2f825e793bc9ac2be698348dbe669bad34cad
# skip: [d1f7a85555fe6f10dd44754d35459ae741cb107c] commit 15
git bisect skip d1f7a85555fe6f10dd44754d35459ae741cb107c
# skip: [bc21c8fabc28201fab6c60503168ecda25ad8626] commit 17
git bisect skip bc21c8fabc28201fab6c60503168ecda25ad8626
# good: [67fbfb3b74c2381ad1e058949231f2b4f0c8921f] commit 16
git bisect good 67fbfb3b74c2381ad1e058949231f2b4f0c8921f
# good: [e927f0f9467e772eea36f24053c9b534303b106a] commit 18
git bisect good e927f0f9467e772eea36f24053c9b534303b106a
# first bad commit: [054bdf969fdcf1f90f1998666f628d40f72fde4f] commit 19

View File

@ -1 +0,0 @@
ref: refs/heads/test

View File

@ -1,24 +0,0 @@
0000000000000000000000000000000000000000 005ca78c7fb8157683fa61158235b250d2316004 CI <CI@example.com> 1643185278 +1100 commit (initial): commit 1
005ca78c7fb8157683fa61158235b250d2316004 d9328d9b2c9536fdf01641dd03f4a254d2c86601 CI <CI@example.com> 1643185278 +1100 commit: commit 2
d9328d9b2c9536fdf01641dd03f4a254d2c86601 e59bbaffe94b06acaadab4245f30ff3e11c66e5b CI <CI@example.com> 1643185278 +1100 commit: commit 3
e59bbaffe94b06acaadab4245f30ff3e11c66e5b 32e7b0308424a817ed5aa5bba94b06b72a1b8ce5 CI <CI@example.com> 1643185278 +1100 commit: commit 4
32e7b0308424a817ed5aa5bba94b06b72a1b8ce5 96202a92c1d3bde1b20d6f3dec8e742d09732b4d CI <CI@example.com> 1643185278 +1100 commit: commit 5
96202a92c1d3bde1b20d6f3dec8e742d09732b4d 82d721eb037f7045056023d0904989781ce1f526 CI <CI@example.com> 1643185278 +1100 commit: commit 6
82d721eb037f7045056023d0904989781ce1f526 b97844c9437a4ab69c8165cadd97bc597b43135b CI <CI@example.com> 1643185278 +1100 commit: commit 7
b97844c9437a4ab69c8165cadd97bc597b43135b ebe59a71e9750e75fb983f241687cdf7f0c8ce94 CI <CI@example.com> 1643185278 +1100 commit: commit 8
ebe59a71e9750e75fb983f241687cdf7f0c8ce94 39983ea412adebe6c5a3d4451a7673cf0962c472 CI <CI@example.com> 1643185278 +1100 commit: commit 9
39983ea412adebe6c5a3d4451a7673cf0962c472 dbb21289ee21b2ff0f3de2bc7d00038b30c4e353 CI <CI@example.com> 1643185278 +1100 commit: commit 10
dbb21289ee21b2ff0f3de2bc7d00038b30c4e353 5f9397e5bcee1ac2a3fe6d834d42e36b74ef4ca8 CI <CI@example.com> 1643185278 +1100 commit: commit 11
5f9397e5bcee1ac2a3fe6d834d42e36b74ef4ca8 267465454f74736bbe5b493c7f69dd3d024e26e5 CI <CI@example.com> 1643185278 +1100 commit: commit 12
267465454f74736bbe5b493c7f69dd3d024e26e5 478a007451b33c7a234c60f0d13b164561b29094 CI <CI@example.com> 1643185278 +1100 commit: commit 13
478a007451b33c7a234c60f0d13b164561b29094 e9d2f825e793bc9ac2be698348dbe669bad34cad CI <CI@example.com> 1643185278 +1100 commit: commit 14
e9d2f825e793bc9ac2be698348dbe669bad34cad d1f7a85555fe6f10dd44754d35459ae741cb107c CI <CI@example.com> 1643185278 +1100 commit: commit 15
d1f7a85555fe6f10dd44754d35459ae741cb107c 67fbfb3b74c2381ad1e058949231f2b4f0c8921f CI <CI@example.com> 1643185278 +1100 commit: commit 16
67fbfb3b74c2381ad1e058949231f2b4f0c8921f bc21c8fabc28201fab6c60503168ecda25ad8626 CI <CI@example.com> 1643185278 +1100 commit: commit 17
bc21c8fabc28201fab6c60503168ecda25ad8626 e927f0f9467e772eea36f24053c9b534303b106a CI <CI@example.com> 1643185278 +1100 commit: commit 18
e927f0f9467e772eea36f24053c9b534303b106a 054bdf969fdcf1f90f1998666f628d40f72fde4f CI <CI@example.com> 1643185278 +1100 commit: commit 19
054bdf969fdcf1f90f1998666f628d40f72fde4f 78d41b2abbd2f52c1ebf2f496268a915d59eb27b CI <CI@example.com> 1643185278 +1100 commit: commit 20
78d41b2abbd2f52c1ebf2f496268a915d59eb27b e9d2f825e793bc9ac2be698348dbe669bad34cad CI <CI@example.com> 1643185283 +1100 checkout: moving from master to e9d2f825e793bc9ac2be698348dbe669bad34cad
e9d2f825e793bc9ac2be698348dbe669bad34cad 67fbfb3b74c2381ad1e058949231f2b4f0c8921f CI <CI@example.com> 1643185286 +1100 checkout: moving from e9d2f825e793bc9ac2be698348dbe669bad34cad to 67fbfb3b74c2381ad1e058949231f2b4f0c8921f
67fbfb3b74c2381ad1e058949231f2b4f0c8921f e927f0f9467e772eea36f24053c9b534303b106a CI <CI@example.com> 1643185295 +1100 checkout: moving from 67fbfb3b74c2381ad1e058949231f2b4f0c8921f to e927f0f9467e772eea36f24053c9b534303b106a
e927f0f9467e772eea36f24053c9b534303b106a 78d41b2abbd2f52c1ebf2f496268a915d59eb27b CI <CI@example.com> 1643185301 +1100 checkout: moving from e927f0f9467e772eea36f24053c9b534303b106a to test

View File

@ -1,20 +0,0 @@
0000000000000000000000000000000000000000 005ca78c7fb8157683fa61158235b250d2316004 CI <CI@example.com> 1643185278 +1100 commit (initial): commit 1
005ca78c7fb8157683fa61158235b250d2316004 d9328d9b2c9536fdf01641dd03f4a254d2c86601 CI <CI@example.com> 1643185278 +1100 commit: commit 2
d9328d9b2c9536fdf01641dd03f4a254d2c86601 e59bbaffe94b06acaadab4245f30ff3e11c66e5b CI <CI@example.com> 1643185278 +1100 commit: commit 3
e59bbaffe94b06acaadab4245f30ff3e11c66e5b 32e7b0308424a817ed5aa5bba94b06b72a1b8ce5 CI <CI@example.com> 1643185278 +1100 commit: commit 4
32e7b0308424a817ed5aa5bba94b06b72a1b8ce5 96202a92c1d3bde1b20d6f3dec8e742d09732b4d CI <CI@example.com> 1643185278 +1100 commit: commit 5
96202a92c1d3bde1b20d6f3dec8e742d09732b4d 82d721eb037f7045056023d0904989781ce1f526 CI <CI@example.com> 1643185278 +1100 commit: commit 6
82d721eb037f7045056023d0904989781ce1f526 b97844c9437a4ab69c8165cadd97bc597b43135b CI <CI@example.com> 1643185278 +1100 commit: commit 7
b97844c9437a4ab69c8165cadd97bc597b43135b ebe59a71e9750e75fb983f241687cdf7f0c8ce94 CI <CI@example.com> 1643185278 +1100 commit: commit 8
ebe59a71e9750e75fb983f241687cdf7f0c8ce94 39983ea412adebe6c5a3d4451a7673cf0962c472 CI <CI@example.com> 1643185278 +1100 commit: commit 9
39983ea412adebe6c5a3d4451a7673cf0962c472 dbb21289ee21b2ff0f3de2bc7d00038b30c4e353 CI <CI@example.com> 1643185278 +1100 commit: commit 10
dbb21289ee21b2ff0f3de2bc7d00038b30c4e353 5f9397e5bcee1ac2a3fe6d834d42e36b74ef4ca8 CI <CI@example.com> 1643185278 +1100 commit: commit 11
5f9397e5bcee1ac2a3fe6d834d42e36b74ef4ca8 267465454f74736bbe5b493c7f69dd3d024e26e5 CI <CI@example.com> 1643185278 +1100 commit: commit 12
267465454f74736bbe5b493c7f69dd3d024e26e5 478a007451b33c7a234c60f0d13b164561b29094 CI <CI@example.com> 1643185278 +1100 commit: commit 13
478a007451b33c7a234c60f0d13b164561b29094 e9d2f825e793bc9ac2be698348dbe669bad34cad CI <CI@example.com> 1643185278 +1100 commit: commit 14
e9d2f825e793bc9ac2be698348dbe669bad34cad d1f7a85555fe6f10dd44754d35459ae741cb107c CI <CI@example.com> 1643185278 +1100 commit: commit 15
d1f7a85555fe6f10dd44754d35459ae741cb107c 67fbfb3b74c2381ad1e058949231f2b4f0c8921f CI <CI@example.com> 1643185278 +1100 commit: commit 16
67fbfb3b74c2381ad1e058949231f2b4f0c8921f bc21c8fabc28201fab6c60503168ecda25ad8626 CI <CI@example.com> 1643185278 +1100 commit: commit 17
bc21c8fabc28201fab6c60503168ecda25ad8626 e927f0f9467e772eea36f24053c9b534303b106a CI <CI@example.com> 1643185278 +1100 commit: commit 18
e927f0f9467e772eea36f24053c9b534303b106a 054bdf969fdcf1f90f1998666f628d40f72fde4f CI <CI@example.com> 1643185278 +1100 commit: commit 19
054bdf969fdcf1f90f1998666f628d40f72fde4f 78d41b2abbd2f52c1ebf2f496268a915d59eb27b CI <CI@example.com> 1643185278 +1100 commit: commit 20

View File

@ -1 +0,0 @@
0000000000000000000000000000000000000000 78d41b2abbd2f52c1ebf2f496268a915d59eb27b CI <CI@example.com> 1643185301 +1100 branch: Created from master

View File

@ -1,2 +0,0 @@
x��K
1D]罤?ù‚ˆ0«9FÌtP0Î0Dðøfá¤vÅ{PUÖÖ(ùCßU!‘ø*äÔ%Çh¥’-KÁ…caŒšG–@fË»¾:hâP±&냆ÀªyølÑII7'VPn„>›üî÷u‡i†ó4_õ“ÛöÔSYÛÈ[¡è8D8!šÑŽQ]ÿÄü8a¾©:E

View File

@ -1,2 +0,0 @@
x�ÎM
1 †a×=Eö‚4ý™$ "ÌjŽÑÖë C�oÀíÇÃÇ[ÖÖPâ¡ïªàÕº¢b}àê=OèXsvB.b¬“'fF6[ÚõÕA³FI„*­Ò ¾º€S¹Uª¶ðø &½û}Ýa^à</Wý¤¶=õTÖvœ‚GŽŽŽˆÖš±Ž¨®òŸ1_¥Á9ä

View File

@ -1 +0,0 @@
x+)JMU06b040031QHֻּIe�כ6פLסQ»תא)�¥¹:‹ױ�<…נפ

View File

@ -1,2 +0,0 @@
x�ÎA
1 @Q×=Eö‚4m'm@D˜•Çh›ë C�ï,<€ÛÏ[üºôþ€L‡±µ¡Ð$DÕ&®”ŠfbQuKÕEïcçÍš·ö`§PD™X¥**[EæDDJ.I°�J jò{Ü— æœçÛµ}r_ŸíT—~¤à1M.&8"ZköºO�ö'ÿypÖ|à;’

View File

@ -1 +0,0 @@
x+)JMU06b040031QHклIeь▒■ЦС_ц3и[}ШY╝Кзbf┘k░

View File

@ -1,4 +0,0 @@
x�ÎM
Â@ †a×sŠì™LÒ¤¡«#ó#
Ž-e�ï,<€Û—‡�/­µ>à$‡¶—
K¡DšÑ˜,HœüdÔcÊ!O*ªIÝf{y5`Í{å#QR ÄIüÍg¤ˆÂƒ` }€�½Û}Ýa^à</×ò±º=Ë)­õÝŽCÐŽˆÞ»^û©Vþä?Èî {ò9

Some files were not shown because too many files have changed in this diff Show More