summaryrefslogtreecommitdiffstats
path: root/pkg/integration
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2023-02-26 11:23:36 +1100
committerJesse Duffield <jessedduffield@gmail.com>2023-02-26 11:34:18 +1100
commit8b5d59c2380c9d4c78d148d8ee0cecdfa556f1f5 (patch)
tree87642ceeba0771b3080e9428fdf8d8e9648ccc5c /pkg/integration
parentf82f4f6dbcae4c6f46c8c39bbceda526ab92ee11 (diff)
remove legacy integration tests
Diffstat (limited to 'pkg/integration')
-rw-r--r--pkg/integration/README.md22
-rw-r--r--pkg/integration/clients/go_test.go4
-rw-r--r--pkg/integration/clients/tui.go2
-rw-r--r--pkg/integration/components/paths.go2
-rw-r--r--pkg/integration/deprecated/cmd/runner/main.go65
-rw-r--r--pkg/integration/deprecated/cmd/tui/main.go422
-rw-r--r--pkg/integration/deprecated/go_test.go122
-rw-r--r--pkg/integration/deprecated/integration.go564
8 files changed, 6 insertions, 1197 deletions
diff --git a/pkg/integration/README.md b/pkg/integration/README.md
index 413f2d71a..598810a82 100644
--- a/pkg/integration/README.md
+++ b/pkg/integration/README.md
@@ -52,7 +52,7 @@ There are three ways to invoke a test:
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
+3. go test pkg/integration/clients/*.go
The first, the test runner, is for directly running a test from the command line. If you pass no arguments, it runs all tests.
The second, the TUI, is for running tests from a terminal UI where it's easier to find a test and run it without having to copy it's name and paste it into the terminal. This is the easiest approach by far.
@@ -62,7 +62,7 @@ The name of a test is based on its path, so the name of the test at `pkg/integra
You can pass the KEY_PRESS_DELAY env var to the test runner in order to set a delay in milliseconds between keypresses, which helps for watching a test at a realistic speed to understand what it's doing. Or you can pass the '--slow' flag which sets a pre-set 'slow' key delay. In the tui you can press 't' to run the test in slow mode.
-The resultant repo will be stored in `test/integration_new`, so if you're not sure what went wrong you can go there and inspect the repo.
+The resultant repo will be stored in `test/integration`, so if you're not sure what went wrong you can go there and inspect the repo.
### Running tests in VSCode
@@ -78,21 +78,3 @@ The test will run in a VSCode terminal:
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 in the test runner pass the --sandbox argument.
-
-## Migration process
-
-You can watch how to migrate tests in this youtube [video](https://youtu.be/cJtOJu6-HcA).
-
-At the time of writing, most tests are created under an old approach, where you would record yourself in a lazygit session and then the test would replay the keybindings with the same timestamps. This old approach is great for writing tests quickly, but is much harder to maintain. It has to rely on snapshots to determining if a test passes or fails, and can't do assertions along the way. It's also harder to grok what's the intention behind certain actions that take place within the test (e.g. was the recorder intentionally switching to another panel or was that just a misclick?).
-
-At the moment, all the deprecated test code lives in pkg/integration/deprecated. Hopefully in the very near future we migrate everything across so that we don't need to maintain two systems.
-
-We should never write any new tests under the old method, and if a given test breaks because of new functionality, it's best to simply rewrite it under the new approach. If you want to run a test for the sake of watching what it does so that you can transcribe it into the new approach, you can run:
-
-```
-go run pkg/integration/deprecated/cmd/tui/main.go
-```
-
-The tests in the old format live in test/integration. In the old format, test definitions are co-located with snapshots. The setup step is done in a `setup.sh` shell script and the `recording.json` file contains the recorded keypresses to be replayed during the test.
-
-If you have rewritten an integration test under the new pattern, be sure to delete the old integration test directory.
diff --git a/pkg/integration/clients/go_test.go b/pkg/integration/clients/go_test.go
index 201d9bbfa..29d914708 100644
--- a/pkg/integration/clients/go_test.go
+++ b/pkg/integration/clients/go_test.go
@@ -3,8 +3,8 @@
package clients
-// this is the new way of running tests. See pkg/integration/integration_tests/commit.go
-// for an example
+// This file allows you to use `go test` to run integration tests.
+// See See pkg/integration/README.md for more info.
import (
"bytes"
diff --git a/pkg/integration/clients/tui.go b/pkg/integration/clients/tui.go
index dc4e1b5b0..10bfcf748 100644
--- a/pkg/integration/clients/tui.go
+++ b/pkg/integration/clients/tui.go
@@ -137,7 +137,7 @@ func RunTUI() {
return nil
}
- cmd := secureexec.Command("sh", "-c", fmt.Sprintf("code test/integration_new/%s", currentTest.Name()))
+ cmd := secureexec.Command("sh", "-c", fmt.Sprintf("code test/integration/%s", currentTest.Name()))
if err := cmd.Run(); err != nil {
return err
}
diff --git a/pkg/integration/components/paths.go b/pkg/integration/components/paths.go
index d01b58437..43468f509 100644
--- a/pkg/integration/components/paths.go
+++ b/pkg/integration/components/paths.go
@@ -3,7 +3,7 @@ package components
import "path/filepath"
// convenience struct for easily getting directories within our test directory.
-// We have one test directory for each test, found in test/integration_new.
+// We have one test directory for each test, found in test/integration.
type Paths struct {
// e.g. test/integration/test_name
root string
diff --git a/pkg/integration/deprecated/cmd/runner/main.go b/pkg/integration/deprecated/cmd/runner/main.go
deleted file mode 100644
index 86f3c1f14..000000000
--- a/pkg/integration/deprecated/cmd/runner/main.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package main
-
-import (
- "fmt"
- "log"
- "os"
- "os/exec"
- "testing"
-
- "github.com/jesseduffield/lazygit/pkg/integration/deprecated"
- "github.com/stretchr/testify/assert"
-)
-
-// Deprecated: This file is part of the old way of doing things.
-
-// see https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md
-// This file can be invoked directly, but you might find it easier to go through
-// test/lazyintegration/main.go, which provides a convenient gui wrapper to integration tests.
-//
-// If invoked directly, you can specify a test by passing it as the first argument.
-// You can also specify that you want to record a test by passing MODE=record
-// as an env var.
-
-func main() {
- mode := deprecated.GetModeFromEnv()
- speedEnv := os.Getenv("SPEED")
- includeSkipped := os.Getenv("INCLUDE_SKIPPED") == "true"
- selectedTestName := os.Args[1]
-
- err := deprecated.RunTests(
- log.Printf,
- runCmdInTerminal,
- func(test *deprecated.IntegrationTest, f func(*testing.T) error) {
- if selectedTestName != "" && test.Name != selectedTestName {
- return
- }
- if err := f(nil); err != nil {
- log.Print(err.Error())
- }
- },
- mode,
- speedEnv,
- func(_t *testing.T, expected string, actual string, prefix string) { //nolint:thelper
- assert.Equal(MockTestingT{}, expected, actual, fmt.Sprintf("Unexpected %s. Expected:\n%s\nActual:\n%s\n", prefix, expected, actual))
- },
- includeSkipped,
- )
- if err != nil {
- log.Print(err.Error())
- }
-}
-
-type MockTestingT struct{}
-
-func (t MockTestingT) Errorf(format string, args ...interface{}) {
- fmt.Printf(format, args...)
-}
-
-func runCmdInTerminal(cmd *exec.Cmd) error {
- cmd.Stdout = os.Stdout
- cmd.Stdin = os.Stdin
- cmd.Stderr = os.Stderr
-
- return cmd.Run()
-}
diff --git a/pkg/integration/deprecated/cmd/tui/main.go b/pkg/integration/deprecated/cmd/tui/main.go
deleted file mode 100644
index b7fc45d5c..000000000
--- a/pkg/integration/deprecated/cmd/tui/main.go
+++ /dev/null
@@ -1,422 +0,0 @@
-package main
-
-import (
- "fmt"
- "log"
- "os"
- "os/exec"
- "path/filepath"
-
- "github.com/jesseduffield/gocui"
- "github.com/jesseduffield/lazygit/pkg/gui"
- "github.com/jesseduffield/lazygit/pkg/gui/style"
- "github.com/jesseduffield/lazygit/pkg/integration/deprecated"
- "github.com/jesseduffield/lazygit/pkg/secureexec"
-)
-
-// Deprecated. See lazy_integration for the new approach.
-
-// this program lets you manage integration tests in a TUI. See https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md for more info.
-
-type App struct {
- tests []*deprecated.IntegrationTest
- itemIdx int
- testDir string
- editing bool
- g *gocui.Gui
-}
-
-func (app *App) getCurrentTest() *deprecated.IntegrationTest {
- if len(app.tests) > 0 {
- return app.tests[app.itemIdx]
- }
- return nil
-}
-
-func (app *App) refreshTests() {
- app.loadTests()
- app.g.Update(func(*gocui.Gui) error {
- listView, err := app.g.View("list")
- if err != nil {
- return err
- }
-
- listView.Clear()
- for _, test := range app.tests {
- fmt.Fprintln(listView, test.Name)
- }
-
- return nil
- })
-}
-
-func (app *App) loadTests() {
- tests, err := deprecated.LoadTests(app.testDir)
- if err != nil {
- log.Panicln(err)
- }
-
- app.tests = tests
- if app.itemIdx > len(app.tests)-1 {
- app.itemIdx = len(app.tests) - 1
- }
-}
-
-func main() {
- rootDir := deprecated.GetRootDirectory()
- testDir := filepath.Join(rootDir, "test", "integration")
-
- app := &App{testDir: testDir}
- app.loadTests()
-
- g, err := gocui.NewGui(gocui.OutputTrue, false, gocui.NORMAL, false, gui.RuneReplacements)
- if err != nil {
- log.Panicln(err)
- }
-
- g.Cursor = false
-
- app.g = g
-
- g.SetManagerFunc(app.layout)
-
- if err := g.SetKeybinding("list", gocui.KeyArrowUp, gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
- if app.itemIdx > 0 {
- app.itemIdx--
- }
- listView, err := g.View("list")
- if err != nil {
- return err
- }
- listView.FocusPoint(0, app.itemIdx)
- return nil
- }); err != nil {
- log.Panicln(err)
- }
-
- if err := g.SetKeybinding("list", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
- log.Panicln(err)
- }
-
- if err := g.SetKeybinding("list", 'q', gocui.ModNone, quit); err != nil {
- log.Panicln(err)
- }
-
- if err := g.SetKeybinding("list", 'r', gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
- currentTest := app.getCurrentTest()
- if currentTest == nil {
- return nil
- }
-
- cmd := secureexec.Command("sh", "-c", fmt.Sprintf("INCLUDE_SKIPPED=true MODE=record go run pkg/integration/deprecated/cmd/runner/main.go %s", currentTest.Name))
- app.runSubprocess(cmd)
-
- return nil
- }); err != nil {
- log.Panicln(err)
- }
-
- if err := g.SetKeybinding("list", 's', gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
- currentTest := app.getCurrentTest()
- if currentTest == nil {
- return nil
- }
-
- cmd := secureexec.Command("sh", "-c", fmt.Sprintf("INCLUDE_SKIPPED=true MODE=sandbox go run pkg/integration/deprecated/cmd/runner/main.go %s", currentTest.Name))
- app.runSubprocess(cmd)
-
- return nil
- }); err != nil {
- log.Panicln(err)
- }
-
- if err := g.SetKeybinding("list", gocui.KeyEnter, gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
- currentTest := app.getCurrentTest()
- if currentTest == nil {
- return nil
- }
-
- cmd := secureexec.Command("sh", "-c", fmt.Sprintf("INCLUDE_SKIPPED=true go run pkg/integration/deprecated/cmd/runner/main.go %s", currentTest.Name))
- app.runSubprocess(cmd)
-
- return nil
- }); err != nil {
- log.Panicln(err)
- }
-
- if err := g.SetKeybinding("list", 'u', gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
- currentTest := app.getCurrentTest()
- if currentTest == nil {
- return nil
- }
-
- cmd := secureexec.Command("sh", "-c", fmt.Sprintf("INCLUDE_SKIPPED=true MODE=updateSnapshot go run pkg/integration/deprecated/cmd/runner/main.go %s", currentTest.Name))
- app.runSubprocess(cmd)
-
- return nil
- }); err != nil {
- log.Panicln(err)
- }
-
- if err := g.SetKeybinding("list", 't', gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
- currentTest := app.getCurrentTest()
- if currentTest == nil {
- return nil
- }
-
- cmd := secureexec.Command("sh", "-c", fmt.Sprintf("INCLUDE_SKIPPED=true SPEED=1 go run pkg/integration/deprecated/cmd/runner/main.go %s", currentTest.Name))
- app.runSubprocess(cmd)
-
- return nil
- }); err != nil {
- log.Panicln(err)
- }
-
- if err := g.SetKeybinding("list", 'o', gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
- currentTest := app.getCurrentTest()
- if currentTest == nil {
- return nil
- }
-
- cmd := secureexec.Command("sh", "-c", fmt.Sprintf("code -r %s/%s/test.json", app.testDir, currentTest.Name))
- if err := cmd.Run(); err != nil {
- return err
- }
-
- return nil
- }); err != nil {
- log.Panicln(err)
- }
-
- if err := g.SetKeybinding("list", 'n', gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
- currentTest := app.getCurrentTest()
- if currentTest == nil {
- return nil
- }
-
- // need to duplicate that folder and then re-fetch our tests.
- dir := app.testDir + "/" + app.getCurrentTest().Name
- newDir := dir + "_Copy"
-
- cmd := secureexec.Command("sh", "-c", fmt.Sprintf("cp -r %s %s", dir, newDir))
- if err := cmd.Run(); err != nil {
- return err
- }
-
- app.loadTests()
-
- app.refreshTests()
- return nil
- }); err != nil {
- log.Panicln(err)
- }
-
- if err := g.SetKeybinding("list", 'm', gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
- currentTest := app.getCurrentTest()
- if currentTest == nil {
- return nil
- }
-
- app.editing = true
- if _, err := g.SetCurrentView("editor"); err != nil {
- return err
- }
- editorView, err := g.View("editor")
- if err != nil {
- return err
- }
- editorView.Clear()
- fmt.Fprint(editorView, currentTest.Name)
-
- return nil
- }); err != nil {
- log.Panicln(err)
- }
-
- if err := g.SetKeybinding("list", 'd', gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
- currentTest := app.getCurrentTest()
- if currentTest == nil {
- return nil
- }
-
- dir := app.testDir + "/" + app.getCurrentTest().Name
-
- cmd := secureexec.Command("sh", "-c", fmt.Sprintf("rm -rf %s", dir))
- if err := cmd.Run(); err != nil {
- return err
- }
-
- app.refreshTests()
-
- return nil
- }); err != nil {
- log.Panicln(err)
- }
-
- if err := g.SetKeybinding("editor", gocui.KeyEnter, gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
- currentTest := app.getCurrentTest()
- if currentTest == nil {
- return nil
- }
-
- app.editing = false
- if _, err := g.SetCurrentView("list"); err != nil {
- return err
- }
-
- editorView, err := g.View("editor")
- if err != nil {
- return err
- }
-
- dir := app.testDir + "/" + app.getCurrentTest().Name
- newDir := app.testDir + "/" + editorView.Buffer()
-
- cmd := secureexec.Command("sh", "-c", fmt.Sprintf("mv %s %s", dir, newDir))
- if err := cmd.Run(); err != nil {
- return err
- }
-
- editorView.Clear()
-
- app.refreshTests()
- return nil
- }); err != nil {
- log.Panicln(err)
- }
-
- if err := g.SetKeybinding("editor", gocui.KeyEsc, gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
- app.editing = false
- if _, err := g.SetCurrentView("list"); err != nil {
- return err
- }
-
- return nil
- }); err != nil {
- log.Panicln(err)
- }
-
- err = g.MainLoop()
- g.Close()
- switch err {
- case gocui.ErrQuit:
- return
- default:
- log.Panicln(err)
- }
-}
-
-func (app *App) runSubprocess(cmd *exec.Cmd) {
- if err := gocui.Screen.Suspend(); err != nil {
- panic(err)
- }
-
- cmd.Stdin = os.Stdin
- cmd.Stderr = os.Stderr
- cmd.Stdout = os.Stdout
- if err := cmd.Run(); err != nil {
- log.Println(err.Error())
- }
- cmd.Stdin = nil
- cmd.Stderr = nil
- cmd.Stdout = nil
-
- fmt.Fprintf(os.Stdout, "\n%s", style.FgGreen.Sprint("press enter to return"))
- fmt.Scanln() // wait for enter press
-
- if err := gocui.Screen.Resume(); err != nil {
- panic(err)
- }
-}
-
-func (app *App) layout(g *gocui.Gui) error {
- maxX, maxY := g.Size()
- descriptionViewHeight := 7
- keybindingsViewHeight := 3
- editorViewHeight := 3
- if !app.editing {
- editorViewHeight = 0
- } else {
- descriptionViewHeight = 0
- keybindingsViewHeight = 0
- }
- g.Cursor = app.editing
- g.FgColor = gocui.ColorGreen
- listView, err := g.SetView("list", 0, 0, maxX-1, maxY-descriptionViewHeight-keybindingsViewHeight-editorViewHeight-1, 0)
- if err != nil {
- if !gocui.IsUnknownView(err) {
- return err
- }
- listView.Highlight = true
- listView.SelBgColor = gocui.ColorBlue
- listView.Clear()
- for _, test := range app.tests {
- fmt.Fprintln(listView, test.Name)
- }
- listView.Title = "Tests"
- listView.FgColor = gocui.ColorDefault
- if _, err := g.SetCurrentView("list"); err != nil {
- return err
- }
- }
-
- descriptionView, err := g.SetViewBeneath("description", "list", descriptionViewHeight)
- if err != nil {
- if !gocui.IsUnknownView(err) {
- return err
- }
- descriptionView.Title = "Test description"
- descriptionView.Wrap = true
- descriptionView.FgColor = gocui.ColorDefault
- }
-
- keybindingsView, err := g.SetViewBeneath("keybindings", "description", keybindingsViewHeight)
- if err != nil {
- if !gocui.IsUnknownView(err) {
- return err
- }
- keybindingsView.Title = "Keybindings"
- keybindingsView.Wrap = true
- keybindingsView.FgColor = gocui.ColorDefault
- fmt.Fprintln(keybindingsView, "up/down: navigate, enter: run test, u: run test and update snapshots, r: record test, s: sandbox, o: open test config, n: duplicate test, m: rename test, d: delete test, t: run test at original speed")
- }
-
- editorView, err := g.SetViewBeneath("editor", "keybindings", editorViewHeight)
- if err != nil {
- if !gocui.IsUnknownView(err) {
- return err
- }
- editorView.Title = "Enter Name"
- editorView.FgColor = gocui.ColorDefault
- editorView.Editable = true
- }
-
- currentTest := app.getCurrentTest()
- if currentTest == nil {
- return nil
- }
-
- descriptionView.Clear()
- fmt.Fprintf(descriptionView, "Speed: %f. %s", currentTest.Speed, currentTest.Description)
-
- if err := g.SetKeybinding("list", gocui.KeyArrowDown, gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
- if app.itemIdx < len(app.tests)-1 {
- app.itemIdx++
- }
-
- listView, err := g.View("list")
- if err != nil {
- return err
- }
- listView.FocusPoint(0, app.itemIdx)
- return nil
- }); err != nil {
- log.Panicln(err)
- }
-
- return nil
-}
-
-func quit(g *gocui.Gui, v *gocui.View) error {
- return gocui.ErrQuit
-}
diff --git a/pkg/integration/deprecated/go_test.go b/pkg/integration/deprecated/go_test.go
deleted file mode 100644
index af7f6a8eb..000000000
--- a/pkg/integration/deprecated/go_test.go
+++ /dev/null
@@ -1,122 +0,0 @@
-//go:build !windows
-// +build !windows
-
-package deprecated
-
-import (
- "bytes"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "os/exec"
- "strconv"
- "testing"
-
- "github.com/creack/pty"
- "github.com/stretchr/testify/assert"
-)
-
-// Deprecated.
-
-// This file is quite similar to integration/main.go. The main difference is that this file is
-// run via `go test` whereas the other is run via `test/lazyintegration/main.go` which provides
-// a convenient gui wrapper around our integration tests. The `go test` approach is better
-// for CI and for running locally in the background to ensure you haven't broken
-// anything while making changes. If you want to visually see what's happening when a test is run,
-// you'll need to take the other approach
-//
-// As for this file, to run an integration test, e.g. for test 'commit', go:
-// go test pkg/gui/old_gui_test.go -run /commit
-//
-// To update a snapshot for an integration test, pass UPDATE_SNAPSHOTS=true
-// UPDATE_SNAPSHOTS=true go test pkg/gui/old_gui_test.go -run /commit
-//
-// integration tests are run in test/integration/<test_name>/actual and the final test does
-// not clean up that directory so you can cd into it to see for yourself what
-// happened when a test fails.
-//
-// To override speed, pass e.g. `SPEED=1` as an env var. Otherwise we start each test
-// at a high speed and then drop down to lower speeds upon each failure until finally
-// trying at the original playback speed (speed 1). A speed of 2 represents twice the
-// original playback speed. Speed may be a decimal.
-
-func Test(t *testing.T) {
- if testing.Short() {
- t.Skip("Skipping integration tests in short mode")
- }
-
- mode := GetModeFromEnv()
- speedEnv := os.Getenv("SPEED")
- includeSkipped := os.Getenv("INCLUDE_SKIPPED") != ""
-
- parallelTotal := tryConvert(os.Getenv("PARALLEL_TOTAL"), 1)
- parallelIndex := tryConvert(os.Getenv("PARALLEL_INDEX"), 0)
- testNumber := 0
-
- err := RunTests(
- t.Logf,
- runCmdHeadless,
- func(test *IntegrationTest, f func(*testing.T) error) {
- defer func() { testNumber += 1 }()
- if testNumber%parallelTotal != parallelIndex {
- return
- }
-
- t.Run(test.Name, func(t *testing.T) {
- err := f(t)
- assert.NoError(t, err)
- })
- },
- mode,
- speedEnv,
- func(t *testing.T, expected string, actual string, prefix string) {
- t.Helper()
- assert.Equal(t, expected, actual, fmt.Sprintf("Unexpected %s. Expected:\n%s\nActual:\n%s\n", prefix, expected, actual))
- },
- includeSkipped,
- )
-
- assert.NoError(t, err)
-}
-
-func tryConvert(numStr string, defaultVal int) int {
- num, err := strconv.Atoi(numStr)
- if err != nil {
- return defaultVal
- }
-
- return num
-}
-
-func runCmdHeadless(cmd *exec.Cmd) error {
- cmd.Env = append(
- cmd.Env,
- "HEADLESS=true",
- "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
- }
-
- _, _ = io.Copy(ioutil.Discard, f)
-
- if cmd.Wait() != nil {
- // return an error with the stderr output
- return errors.New(stderr.String())
- }
-
- return f.Close()
-}
diff --git a/pkg/integration/deprecated/integration.go b/pkg/integration/deprecated/integration.go
deleted file mode 100644
index b292809c9..000000000
--- a/pkg/integration/deprecated/integration.go
+++ /dev/null
@@ -1,564 +0,0 @@
-package deprecated
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "io/ioutil"
- "log"
- "os"
- "os/exec"
- "path/filepath"
- "strconv"
- "strings"
- "testing"
-
- "github.com/jesseduffield/generics/slices"
- "github.com/jesseduffield/lazygit/pkg/commands/oscommands"
- "github.com/jesseduffield/lazygit/pkg/secureexec"
-)
-
-// Deprecated: This file is part of the old way of doing things. See pkg/integration/integration.go for the new way
-
-// This package is for running our integration test suite. See https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md for more info.
-
-type IntegrationTest struct {
- Name string `json:"name"`
- Speed float64 `json:"speed"`
- Description string `json:"description"`
- ExtraCmdArgs string `json:"extraCmdArgs"`
- Skip bool `json:"skip"`
-}
-
-type Mode int
-
-const (
- // default: for when we're just running a test and comparing to the snapshot
- TEST = iota
- // for when we want to record a test and set the snapshot based on the result
- RECORD
- // when we just want to use the setup of the test for our own sandboxing purposes.
- // This does not record the session and does not create/update snapshots
- SANDBOX
- // running a test but updating the snapshot
- UPDATE_SNAPSHOT
-)
-
-func GetModeFromEnv() Mode {
- switch os.Getenv("MODE") {
- case "record":
- return RECORD
- case "", "test":
- return TEST
- case "updateSnapshot":
- return UPDATE_SNAPSHOT
- case "sandbox":
- return SANDBOX
- default:
- log.Fatalf("unknown test mode: %s, must be one of [test, record, updateSnapshot, sandbox]", os.Getenv("MODE"))
- panic("unreachable")
- }
-}
-
-// this function is used by both `go test` and from our lazyintegration gui, but
-// errors need to be handled differently in each (for example go test is always
-// working with *testing.T) so we pass in any differences as args here.
-func RunTests(
- logf func(format string, formatArgs ...interface{}),
- runCmd func(cmd *exec.Cmd) error,
- fnWrapper func(test *IntegrationTest, f func(*testing.T) error),
- mode Mode,
- speedEnv string,
- onFail func(t *testing.T, expected string, actual string, prefix string),
- includeSkipped bool,
-) error {
- rootDir := GetRootDirectory()
- err := os.Chdir(rootDir)
- if err != nil {
- return err
- }
-
- testDir := filepath.Join(rootDir, "test", "integration")
-
- osCommand := oscommands.NewDummyOSCommand()
- err = osCommand.Cmd.New("go build -o " + tempLazygitPath()).Run()
- if err != nil {
- return err
- }
-
- tests, err := LoadTests(testDir)
- if err != nil {
- return err
- }
-
- for _, test := range tests {
- test := test
-
- fnWrapper(test, func(t *testing.T) error { //nolint: thelper
- if test.Skip && !includeSkipped {
- logf("skipping test: %s", test.Name)
- return nil
- }
-
- speeds := getTestSpeeds(test.Speed, mode, speedEnv)
- testPath := filepath.Join(testDir, test.Name)
- actualDir := filepath.Join(testPath, "actual")
- expectedDir := filepath.Join(testPath, "expected")
- actualRepoDir := filepath.Join(actualDir, "repo")
- logf("path: %s", testPath)
-
- for i, speed := range speeds {
- if mode != SANDBOX && mode != RECORD {
- logf("%s: attempting test at speed %f\n", test.Name, speed)
- }
-
- findOrCreateDir(testPath)
- prepareIntegrationTestDir(actualDir)
- findOrCreateDir(actualRepoDir)
- err := createFixture(testPath, actualRepoDir)
- if err != nil {
- return err
- }
-
- configDir := filepath.Join(testPath, "used_config")
-
- cmd, err := getLazygitCommand(testPath, rootDir, mode, speed, test.ExtraCmdArgs)
- if err != nil {
- return err
- }
-
- err = runCmd(cmd)
- if err != nil {
- return err
- }
-
- if mode == UPDATE_SNAPSHOT || mode == RECORD {
- // create/update snapshot
- err = oscommands.CopyDir(actualDir, expectedDir)
- if err != nil {
- return err
- }
-
- if err := renameSpecialPaths(expectedDir); err != nil {
- return err
- }
-
- logf("%s", "updated snapshot")
- } else {
- if err := validateSameRepos(expectedDir, actualDir); err != nil {
- return err
- }
-
- // iterate through each repo in the expected dir and comparet to the corresponding repo in the actual dir
- expectedFiles, err := ioutil.ReadDir(expectedDir)
- if err != nil {
- return err
- }
-
- success := true
- for _, f := range expectedFiles {
- if !f.IsDir() {
- return errors.New("unexpected file (as opposed to directory) in integration test 'expected' directory")
- }
-
- // get corresponding file name from actual dir
- actualRepoPath := filepath.Join(actualDir, f.Name())
- expectedRepoPath := filepath.Join(expectedDir, f.Name())
-
- actualRepo, expectedRepo, err := generateSnapshots(actualRepoPath, expectedRepoPath)
- if err != nil {
- return err
- }
-
- if expectedRepo != actualRepo {
- success = false
- // if the snapshot doesn't match and we haven't tried all playback speeds different we'll retry at a slower speed
- if i < len(speeds)-1 {
- break
- }
-
- // get the log file and print it
- bytes, err := os.ReadFile(filepath.Join(configDir, "development.log"))
- if err != nil {
- return err
- }
- logf("%s", string(bytes))
-
- onFail(t, expectedRepo, actualRepo, f.Name())
- }
- }
-
- if success {
- logf("%s: success at speed %f\n", test.Name, speed)
- break
- }
- }
- }
-
- return nil
- })
- }
-
- return nil
-}
-
-// validates that the actual and expected dirs have the same repo names (doesn't actually check the contents of the repos)
-func validateSameRepos(expectedDir string, actualDir string) error {
- // iterate through each repo in the expected dir and compare to the corresponding repo in the actual dir
- expectedFiles, err := ioutil.ReadDir(expectedDir)
- if err != nil {
- return err
- }
-
- var actualFiles []os.FileInfo
- actualFiles, err = ioutil.ReadDir(actualDir)
- if err != nil {
- return err
- }
-
- expectedFileNames := slices.Map(expectedFiles, getFileName)
- actualFileNames := slices.Map(actualFiles, getFileName)
- if !slices.Equal(expectedFileNames, actualFileNames) {
- return fmt.Errorf("expected and actual repo dirs do not match: expected: %s, actual: %s", expectedFileNames, actualFileNames)
- }
-
- return nil
-}
-
-func getFileName(f os.FileInfo) string {
- return f.Name()
-}
-
-func prepareIntegrationTestDir(actualDir string) {
- // remove contents of integration test directory
- dir, err := ioutil.ReadDir(actualDir)
- if err != nil {
- if os.IsNotExist(err) {
- err = os.Mkdir(actualDir, 0o777)