Skip to content

Commit

Permalink
various changes to improve integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jesseduffield committed Sep 16, 2022
1 parent 7b757d1 commit 7af7af2
Show file tree
Hide file tree
Showing 103 changed files with 2,879 additions and 1,521 deletions.
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
16 changes: 8 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down Expand Up @@ -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=
Expand Down Expand Up @@ -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=
Expand Down Expand Up @@ -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=
Expand Down
4 changes: 2 additions & 2 deletions pkg/gui/gui.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
}

Expand Down
19 changes: 18 additions & 1 deletion pkg/integration/clients/go_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ package clients
// for an example

import (
"bytes"
"errors"
"io"
"io/ioutil"
"os"
Expand Down Expand Up @@ -39,6 +41,7 @@ func TestIntegration(t *testing.T) {
}

t.Run(test.Name(), func(t *testing.T) {
t.Parallel()
err := f()
assert.NoError(t, err)
})
Expand All @@ -57,12 +60,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()
}
9 changes: 8 additions & 1 deletion pkg/integration/components/assert.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,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
Expand Down Expand Up @@ -210,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}

var message string
for _, waitTime := range waitTimes {
Expand Down
68 changes: 39 additions & 29 deletions pkg/integration/components/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -132,38 +137,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
var matchIndex int

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 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 {
self.assert.MatchSelectedLine(Contains(text))
return
if selectedLineIdx < matchIndex {
for i := selectedLineIdx; i < matchIndex; i++ {
self.NextItem()
}
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
self.assert.MatchSelectedLine(Contains(text))
return
} else {
for i := selectedLineIdx; i > matchIndex; i-- {
self.PreviousItem()
}
self.assert.MatchSelectedLine(Contains(text))
return
}

self.assert.Fail(fmt.Sprintf("Could not find item containing text: %s", text))
}
23 changes: 5 additions & 18 deletions pkg/integration/components/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ func RunTests(
for _, test := range tests {
test := test

paths := NewPaths(
filepath.Join(testDir, test.Name()),
)

testWrapper(test, func() error { //nolint: thelper
paths := NewPaths(
filepath.Join(testDir, test.Name()),
)

return runTest(test, paths, projectRootDir, logf, runCmd, mode, keyPressDelay)
})
}
Expand Down Expand Up @@ -126,27 +126,14 @@ 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 "[email protected]"`)
shell.RunCommand(`git config user.name "CI"`)
shell.RunCommand(`git config commit.gpgSign false`)

test.SetupRepo(shell)

if err := os.Chdir(originalDir); err != nil {
panic(err)
}

return nil
}

Expand Down
21 changes: 14 additions & 7 deletions pkg/integration/components/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"io/ioutil"
"os"
"path/filepath"

"github.com/jesseduffield/lazygit/pkg/secureexec"
"github.com/mgutz/str"
Expand All @@ -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 {
Expand All @@ -32,18 +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 {
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 updating file: %s\n%s", path, err))
panic(fmt.Sprintf("error updating file: %s\n%s", fullPath, err))
}

return s
Expand Down
2 changes: 1 addition & 1 deletion pkg/integration/components/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/integration/components/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
4 changes: 4 additions & 0 deletions pkg/integration/components/test_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading

0 comments on commit 7af7af2

Please sign in to comment.