From 349a7d24532a32feaaf40129b3b07b9215b8a625 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sun, 14 Aug 2022 11:24:07 +1000 Subject: [PATCH] even better structure --- pkg/cheatsheet/generate.go | 2 +- pkg/integration/README.md | 2 +- pkg/integration/cmd/injector/main.go | 9 +- pkg/integration/cmd/runner/main.go | 74 ++-- pkg/integration/cmd/tui/main.go | 12 +- pkg/integration/components/paths.go | 43 ++ pkg/integration/components/runner.go | 229 +++++++++++ .../snapshot.go} | 368 +++++------------- pkg/integration/go_test.go | 10 +- 9 files changed, 431 insertions(+), 318 deletions(-) create mode 100644 pkg/integration/components/paths.go create mode 100644 pkg/integration/components/runner.go rename pkg/integration/{integration.go => components/snapshot.go} (52%) diff --git a/pkg/cheatsheet/generate.go b/pkg/cheatsheet/generate.go index ec5c6db0e..73ae07a55 100644 --- a/pkg/cheatsheet/generate.go +++ b/pkg/cheatsheet/generate.go @@ -45,7 +45,7 @@ func CommandToRun() string { } func GetDir() string { - return integration.GetRootDirectory() + "/docs/keybindings" + return integration.GetProjectRootDirectory() + "/docs/keybindings" } func generateAtDir(cheatsheetDir string) { diff --git a/pkg/integration/README.md b/pkg/integration/README.md index 01d5786b1..1bc9d0a85 100644 --- a/pkg/integration/README.md +++ b/pkg/integration/README.md @@ -51,7 +51,7 @@ You can pass the KEY_PRESS_DELAY env var to the test runner in order to set a de ### Snapshots -At the moment (this is subject to change) each test has a snapshot repo created after running for the first time. These snapshots live in `test/integration_new`, in folders named 'expected' (alongside the 'actual' folders which contain the resulting repo from the last test run). Whenever you run a test, the resultant repo will be compared against the snapshot repo and if they're different, you'll be asked whether you want to update the snapshot. If you want to update a snapshot without being prompted you can pass MODE=updateSnapshot to the test runner or the go test command. This is useful when you've made a change to +At the moment (this is subject to change) each test has a snapshot repo created after running for the first time. These snapshots live in `test/integration_new`, in folders named 'expected' (alongside the 'actual' folders which contain the resulting repo from the last test run). Whenever you run a test, the resultant repo will be compared against the snapshot repo and if they're different, you'll be asked whether you want to update the snapshot. If you want to update a snapshot without being prompted you can pass MODE=updateSnapshot to the test runner. ### Sandbox mode diff --git a/pkg/integration/cmd/injector/main.go b/pkg/integration/cmd/injector/main.go index 2f47d04a6..ceb770065 100644 --- a/pkg/integration/cmd/injector/main.go +++ b/pkg/integration/cmd/injector/main.go @@ -6,7 +6,8 @@ import ( "github.com/jesseduffield/lazygit/pkg/app" "github.com/jesseduffield/lazygit/pkg/app/daemon" - "github.com/jesseduffield/lazygit/pkg/integration" + "github.com/jesseduffield/lazygit/pkg/integration/components" + "github.com/jesseduffield/lazygit/pkg/integration/tests" integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types" ) @@ -38,15 +39,15 @@ func getIntegrationTest() integrationTypes.IntegrationTest { return nil } - integrationTestName := os.Getenv(integration.LAZYGIT_TEST_NAME_ENV_VAR) + integrationTestName := os.Getenv(components.LAZYGIT_TEST_NAME_ENV_VAR) if integrationTestName == "" { panic(fmt.Sprintf( "expected %s environment variable to be set, given that we're running an integration test", - integration.LAZYGIT_TEST_NAME_ENV_VAR, + components.LAZYGIT_TEST_NAME_ENV_VAR, )) } - for _, candidateTest := range integration.Tests { + for _, candidateTest := range tests.Tests { if candidateTest.Name() == integrationTestName { return candidateTest } diff --git a/pkg/integration/cmd/runner/main.go b/pkg/integration/cmd/runner/main.go index 1fbde96c5..ba8bc9d75 100644 --- a/pkg/integration/cmd/runner/main.go +++ b/pkg/integration/cmd/runner/main.go @@ -5,9 +5,8 @@ import ( "os" "os/exec" - "github.com/jesseduffield/generics/slices" - "github.com/jesseduffield/lazygit/pkg/integration" "github.com/jesseduffield/lazygit/pkg/integration/components" + "github.com/jesseduffield/lazygit/pkg/integration/tests" ) // see pkg/integration/README.md @@ -21,49 +20,44 @@ import ( // If invoked directly, you can specify tests to run by passing their names as positional arguments func main() { - mode := integration.GetModeFromEnv() - includeSkipped := os.Getenv("INCLUDE_SKIPPED") == "true" - var testsToRun []*components.IntegrationTest - - if len(os.Args) > 1 { - outer: - for _, testName := range os.Args[1:] { - // check if our given test name actually exists - for _, test := range integration.Tests { - if test.Name() == testName { - testsToRun = append(testsToRun, test) - continue outer - } - } - log.Fatalf("test %s not found. Perhaps you forgot to add it to `pkg/integration/integration_tests/tests.go`?", testName) - } - } else { - testsToRun = integration.Tests - } - - testNames := slices.Map(testsToRun, func(test *components.IntegrationTest) string { - return test.Name() - }) - - err := integration.RunTests( + err := components.RunTests( + getTestsToRun(), log.Printf, runCmdInTerminal, func(test *components.IntegrationTest, f func() error) { - if !slices.Contains(testNames, test.Name()) { - return - } if err := f(); err != nil { log.Print(err.Error()) } }, - mode, - includeSkipped, + getModeFromEnv(), ) if err != nil { log.Print(err.Error()) } } +func getTestsToRun() []*components.IntegrationTest { + var testsToRun []*components.IntegrationTest + + if len(os.Args) < 2 { + return tests.Tests + } + +outer: + for _, testName := range os.Args[1:] { + // check if our given test name actually exists + for _, test := range tests.Tests { + if test.Name() == testName { + testsToRun = append(testsToRun, test) + continue outer + } + } + log.Fatalf("test %s not found. Perhaps you forgot to add it to `pkg/integration/integration_tests/tests.go`?", testName) + } + + return testsToRun +} + func runCmdInTerminal(cmd *exec.Cmd) error { cmd.Stdout = os.Stdout cmd.Stdin = os.Stdin @@ -71,3 +65,19 @@ func runCmdInTerminal(cmd *exec.Cmd) error { return cmd.Run() } + +func getModeFromEnv() components.Mode { + switch os.Getenv("MODE") { + case "", "ask": + return components.ASK_TO_UPDATE_SNAPSHOT + case "check": + return components.CHECK_SNAPSHOT + case "updateSnapshot": + return components.UPDATE_SNAPSHOT + case "sandbox": + return components.SANDBOX + default: + log.Fatalf("unknown test mode: %s, must be one of [test, record, updateSnapshot, sandbox]", os.Getenv("MODE")) + panic("unreachable") + } +} diff --git a/pkg/integration/cmd/tui/main.go b/pkg/integration/cmd/tui/main.go index c9e533f61..cabd55210 100644 --- a/pkg/integration/cmd/tui/main.go +++ b/pkg/integration/cmd/tui/main.go @@ -10,8 +10,8 @@ import ( "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/gui" "github.com/jesseduffield/lazygit/pkg/gui/style" - "github.com/jesseduffield/lazygit/pkg/integration" "github.com/jesseduffield/lazygit/pkg/integration/components" + "github.com/jesseduffield/lazygit/pkg/integration/tests" "github.com/jesseduffield/lazygit/pkg/secureexec" ) @@ -33,14 +33,14 @@ func (app *App) getCurrentTest() *components.IntegrationTest { } func (app *App) loadTests() { - app.tests = integration.Tests + app.tests = tests.Tests if app.itemIdx > len(app.tests)-1 { app.itemIdx = len(app.tests) - 1 } } func main() { - rootDir := integration.GetRootDirectory() + rootDir := components.GetProjectRootDirectory() testDir := filepath.Join(rootDir, "test", "integration") app := &App{testDir: testDir} @@ -85,7 +85,7 @@ func main() { return nil } - cmd := secureexec.Command("sh", "-c", fmt.Sprintf("INCLUDE_SKIPPED=true MODE=sandbox go run pkg/integration/cmd/runner/main.go %s", currentTest.Name())) + cmd := secureexec.Command("sh", "-c", fmt.Sprintf("MODE=sandbox go run pkg/integration/cmd/runner/main.go %s", currentTest.Name())) app.runSubprocess(cmd) return nil @@ -99,7 +99,7 @@ func main() { return nil } - cmd := secureexec.Command("sh", "-c", fmt.Sprintf("INCLUDE_SKIPPED=true go run pkg/integration/cmd/runner/main.go %s", currentTest.Name())) + cmd := secureexec.Command("sh", "-c", fmt.Sprintf("go run pkg/integration/cmd/runner/main.go %s", currentTest.Name())) app.runSubprocess(cmd) return nil @@ -113,7 +113,7 @@ func main() { return nil } - cmd := secureexec.Command("sh", "-c", fmt.Sprintf("INCLUDE_SKIPPED=true KEY_PRESS_DELAY=200 go run pkg/integration/cmd/runner/main.go %s", currentTest.Name())) + cmd := secureexec.Command("sh", "-c", fmt.Sprintf("KEY_PRESS_DELAY=200 go run pkg/integration/cmd/runner/main.go %s", currentTest.Name())) app.runSubprocess(cmd) return nil diff --git a/pkg/integration/components/paths.go b/pkg/integration/components/paths.go new file mode 100644 index 000000000..d01b58437 --- /dev/null +++ b/pkg/integration/components/paths.go @@ -0,0 +1,43 @@ +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. +type Paths struct { + // e.g. test/integration/test_name + root string +} + +func NewPaths(root string) Paths { + return Paths{root: root} +} + +// when a test first runs, it's situated in a repo called 'repo' within this +// directory. In its setup step, the test is allowed to create other repos +// alongside the 'repo' repo in this directory, for example, creating remotes +// or repos to add as submodules. +func (self Paths) Actual() string { + return filepath.Join(self.root, "actual") +} + +// this is the 'repo' directory within the 'actual' directory, +// where a lazygit test will start within. +func (self Paths) ActualRepo() string { + return filepath.Join(self.Actual(), "repo") +} + +// When an integration test first runs, we copy everything in the 'actual' directory, +// and copy it into the 'expected' directory so that future runs can be compared +// against what we expect. +func (self Paths) Expected() string { + return filepath.Join(self.root, "expected") +} + +func (self Paths) Config() string { + return filepath.Join(self.root, "used_config") +} + +func (self Paths) Root() string { + return self.root +} diff --git a/pkg/integration/components/runner.go b/pkg/integration/components/runner.go new file mode 100644 index 000000000..1b7fb0a36 --- /dev/null +++ b/pkg/integration/components/runner.go @@ -0,0 +1,229 @@ +package components + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + + "github.com/jesseduffield/lazygit/pkg/commands/oscommands" +) + +// this is the integration runner for the new and improved integration interface + +const LAZYGIT_TEST_NAME_ENV_VAR = "LAZYGIT_TEST_NAME" + +type Mode int + +const ( + // Default: if a snapshot test fails, the we'll be asked whether we want to update it + ASK_TO_UPDATE_SNAPSHOT Mode = iota + // fails the test if the snapshots don't match + CHECK_SNAPSHOT + // runs the test and updates the snapshot + UPDATE_SNAPSHOT + // This just makes use of the setup step of the test to get you into + // a lazygit session. Then you'll be able to do whatever you want. Useful + // when you want to test certain things without needing to manually set + // up the situation yourself. + // fails the test if the snapshots don't match + SANDBOX +) + +func RunTests( + tests []*IntegrationTest, + logf func(format string, formatArgs ...interface{}), + runCmd func(cmd *exec.Cmd) error, + testWrapper func(test *IntegrationTest, f func() error), + mode Mode, +) error { + projectRootDir := GetProjectRootDirectory() + err := os.Chdir(projectRootDir) + if err != nil { + return err + } + + testDir := filepath.Join(projectRootDir, "test", "integration_new") + + if err := buildLazygit(); err != nil { + return err + } + + 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) + }) + } + + return nil +} + +func runTest( + test *IntegrationTest, + paths Paths, + projectRootDir string, + logf func(format string, formatArgs ...interface{}), + runCmd func(cmd *exec.Cmd) error, + mode Mode, +) error { + if test.Skip() { + logf("Skipping test %s", test.Name()) + return nil + } + + logf("path: %s", paths.Root()) + + if err := prepareTestDir(test, paths); err != nil { + return err + } + + cmd, err := getLazygitCommand(test, paths, projectRootDir) + if err != nil { + return err + } + + err = runCmd(cmd) + if err != nil { + return err + } + + return HandleSnapshots(paths, logf, test, mode) +} + +func prepareTestDir( + test *IntegrationTest, + paths Paths, +) error { + findOrCreateDir(paths.Root()) + deleteAndRecreateEmptyDir(paths.Actual()) + + err := os.Mkdir(paths.ActualRepo(), 0o777) + if err != nil { + return err + } + + return createFixture(test, paths) +} + +func buildLazygit() error { + osCommand := oscommands.NewDummyOSCommand() + return osCommand.Cmd.New(fmt.Sprintf( + "go build -o %s pkg/integration/cmd/injector/main.go", tempLazygitPath(), + )).Run() +} + +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.RunCommand("git init") + shell.RunCommand(`git config user.email "CI@example.com"`) + shell.RunCommand(`git config user.name "CI"`) + + test.SetupRepo(shell) + + if err := os.Chdir(originalDir); err != nil { + panic(err) + } + + return nil +} + +func getLazygitCommand(test *IntegrationTest, paths Paths, rootDir string) (*exec.Cmd, error) { + osCommand := oscommands.NewDummyOSCommand() + + templateConfigDir := filepath.Join(rootDir, "test", "default_test_config") + + err := os.RemoveAll(paths.Config()) + if err != nil { + return nil, err + } + err = oscommands.CopyDir(templateConfigDir, paths.Config()) + if err != nil { + return nil, err + } + + cmdStr := fmt.Sprintf("%s -debug --use-config-dir=%s --path=%s %s", tempLazygitPath(), paths.Config(), paths.ActualRepo(), test.ExtraCmdArgs()) + + cmdObj := osCommand.Cmd.New(cmdStr) + + cmdObj.AddEnvVars(fmt.Sprintf("%s=%s", LAZYGIT_TEST_NAME_ENV_VAR, test.Name())) + + return cmdObj.GetCmd(), nil +} + +func GetProjectRootDirectory() string { + path, err := os.Getwd() + if err != nil { + panic(err) + } + + for { + _, err := os.Stat(filepath.Join(path, ".git")) + + if err == nil { + return path + } + + if !os.IsNotExist(err) { + panic(err) + } + + path = filepath.Dir(path) + + if path == "/" { + log.Fatal("must run in lazygit folder or child folder") + } + } +} + +func tempLazygitPath() string { + return filepath.Join("/tmp", "lazygit", "test_lazygit") +} + +func findOrCreateDir(path string) { + _, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + err = os.MkdirAll(path, 0o777) + if err != nil { + panic(err) + } + } else { + panic(err) + } + } +} + +func deleteAndRecreateEmptyDir(path string) { + // remove contents of integration test directory + dir, err := ioutil.ReadDir(path) + if err != nil { + if os.IsNotExist(err) { + err = os.Mkdir(path, 0o777) + if err != nil { + panic(err) + } + } else { + panic(err) + } + } + for _, d := range dir { + os.RemoveAll(filepath.Join(path, d.Name())) + } +} diff --git a/pkg/integration/integration.go b/pkg/integration/components/snapshot.go similarity index 52% rename from pkg/integration/integration.go rename to pkg/integration/components/snapshot.go index ca71241e2..8c87e6727 100644 --- a/pkg/integration/integration.go +++ b/pkg/integration/components/snapshot.go @@ -1,181 +1,129 @@ -package integration +package components import ( "errors" "fmt" "io/ioutil" - "log" "os" - "os/exec" "path/filepath" "strings" "github.com/jesseduffield/generics/slices" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" - "github.com/jesseduffield/lazygit/pkg/integration/components" - "github.com/jesseduffield/lazygit/pkg/integration/tests" "github.com/stretchr/testify/assert" ) -// this is the integration runner for the new and improved integration interface - -var Tests = tests.Tests - -type Mode int - -const ( - // Default: if a snapshot test fails, the we'll be asked whether we want to update it - ASK_TO_UPDATE_SNAPSHOT = iota - // fails the test if the snapshots don't match - CHECK_SNAPSHOT - // runs the test and updates the snapshot - UPDATE_SNAPSHOT - // This just makes use of the setup step of the test to get you into - // a lazygit session. Then you'll be able to do whatever you want. Useful - // when you want to test certain things without needing to manually set - // up the situation yourself. - // fails the test if the snapshots don't match - SANDBOX -) - -const LAZYGIT_TEST_NAME_ENV_VAR = "LAZYGIT_TEST_NAME" +// This creates and compares integration test snapshots. type ( logf func(format string, formatArgs ...interface{}) ) -func RunTests( +func HandleSnapshots(paths Paths, logf logf, test *IntegrationTest, mode Mode) error { + return NewSnapshotter(paths, logf, test, mode). + handleSnapshots() +} + +type Snapshotter struct { + paths Paths + logf logf + test *IntegrationTest + mode Mode +} + +func NewSnapshotter( + paths Paths, logf logf, - runCmd func(cmd *exec.Cmd) error, - fnWrapper func(test *components.IntegrationTest, f func() error), + test *IntegrationTest, mode Mode, - includeSkipped bool, -) error { - rootDir := GetRootDirectory() - err := os.Chdir(rootDir) +) *Snapshotter { + return &Snapshotter{ + paths: paths, + logf: logf, + test: test, + mode: mode, + } +} + +func (self *Snapshotter) handleSnapshots() error { + switch self.mode { + case UPDATE_SNAPSHOT: + return self.handleUpdate() + case CHECK_SNAPSHOT: + return self.handleCheck() + case ASK_TO_UPDATE_SNAPSHOT: + return self.handleAskToUpdate() + case SANDBOX: + self.logf("Session exited") + } + return nil +} + +func (self *Snapshotter) handleUpdate() error { + if err := self.updateSnapshot(); err != nil { + return err + } + self.logf("Test passed: %s", self.test.Name()) + return nil +} + +func (self *Snapshotter) handleCheck() error { + if err := self.compareSnapshots(); err != nil { + return err + } + self.logf("Test passed: %s", self.test.Name()) + return nil +} + +func (self *Snapshotter) handleAskToUpdate() error { + if _, err := os.Stat(self.paths.Expected()); os.IsNotExist(err) { + if err := self.updateSnapshot(); err != nil { + return err + } + self.logf("No existing snapshot found for %s. Created snapshot.", self.test.Name()) + + return nil + } + + if err := self.compareSnapshots(); err != nil { + self.logf("%s", err) + + // prompt user whether to update the snapshot (Y/N) + if promptUserToUpdateSnapshot() { + if err := self.updateSnapshot(); err != nil { + return err + } + self.logf("Snapshot updated: %s", self.test.Name()) + } else { + return err + } + } + + self.logf("Test passed: %s", self.test.Name()) + return nil +} + +func (self *Snapshotter) updateSnapshot() error { + // create/update snapshot + err := oscommands.CopyDir(self.paths.Actual(), self.paths.Expected()) if err != nil { return err } - testDir := filepath.Join(rootDir, "test", "integration_new") - - osCommand := oscommands.NewDummyOSCommand() - err = osCommand.Cmd.New(fmt.Sprintf("go build -o %s pkg/integration/cmd/injector/main.go", tempLazygitPath())).Run() - if err != nil { + if err := renameSpecialPaths(self.paths.Expected()); err != nil { return err } - for _, test := range Tests { - test := test - - fnWrapper(test, func() error { //nolint: thelper - if test.Skip() && !includeSkipped { - logf("skipping test: %s", test.Name()) - return nil - } - - 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) - - findOrCreateDir(testPath) - prepareIntegrationTestDir(actualDir) - findOrCreateDir(actualRepoDir) - err := createFixture(test, actualRepoDir, rootDir) - if err != nil { - return err - } - - configDir := filepath.Join(testPath, "used_config") - - cmd, err := getLazygitCommand(test, testPath, rootDir) - if err != nil { - return err - } - - err = runCmd(cmd) - if err != nil { - return err - } - - switch mode { - case UPDATE_SNAPSHOT: - if err := updateSnapshot(actualDir, expectedDir); err != nil { - return err - } - logf("Test passed: %s", test.Name()) - case CHECK_SNAPSHOT: - if err := compareSnapshots(logf, configDir, actualDir, expectedDir, test.Name()); err != nil { - return err - } - logf("Test passed: %s", test.Name()) - case ASK_TO_UPDATE_SNAPSHOT: - if _, err := os.Stat(expectedDir); os.IsNotExist(err) { - if err := updateSnapshot(actualDir, expectedDir); err != nil { - return err - } - logf("No existing snapshot found for %s. Created snapshot.", test.Name()) - - return nil - } - - if err := compareSnapshots(logf, configDir, actualDir, expectedDir, test.Name()); err != nil { - logf("%s", err) - - // prompt user whether to update the snapshot (Y/N) - if promptUserToUpdateSnapshot() { - if err := updateSnapshot(actualDir, expectedDir); err != nil { - return err - } - logf("Snapshot updated: %s", test.Name()) - } else { - return err - } - } - - logf("Test passed: %s", test.Name()) - case SANDBOX: - logf("Session exited") - } - - return nil - }) - } - return nil } -func promptUserToUpdateSnapshot() bool { - fmt.Println("Test failed. Update snapshot? (y/n)") - var input string - fmt.Scanln(&input) - return input == "y" -} - -func updateSnapshot(actualDir string, expectedDir string) error { - // create/update snapshot - err := oscommands.CopyDir(actualDir, expectedDir) - if err != nil { - return err - } - - if err := renameSpecialPaths(expectedDir); err != nil { - return err - } - - return err -} - -func compareSnapshots(logf logf, configDir string, actualDir string, expectedDir string, testName string) error { +func (self *Snapshotter) compareSnapshots() error { // there are a couple of reasons we're not generating the snapshot in expectedDir directly: // Firstly we don't want to have to revert our .git file back to .git_keep. // Secondly, the act of calling git commands like 'git status' actually changes the index // for some reason, and we don't want to leave your lazygit working tree dirty as a result. - expectedDirCopy := filepath.Join(os.TempDir(), "expected_dir_test", testName) - err := oscommands.CopyDir(expectedDir, expectedDirCopy) + expectedDirCopy := filepath.Join(os.TempDir(), "expected_dir_test", self.test.Name()) + err := oscommands.CopyDir(self.paths.Expected(), expectedDirCopy) if err != nil { return err } @@ -191,7 +139,7 @@ func compareSnapshots(logf logf, configDir string, actualDir string, expectedDir return err } - err = validateSameRepos(expectedDirCopy, actualDir) + err = validateSameRepos(expectedDirCopy, self.paths.Actual()) if err != nil { return err } @@ -208,7 +156,7 @@ func compareSnapshots(logf logf, configDir string, actualDir string, expectedDir } // get corresponding file name from actual dir - actualRepoPath := filepath.Join(actualDir, f.Name()) + actualRepoPath := filepath.Join(self.paths.Actual(), f.Name()) expectedRepoPath := filepath.Join(expectedDirCopy, f.Name()) actualRepo, expectedRepo, err := generateSnapshots(actualRepoPath, expectedRepoPath) @@ -218,11 +166,11 @@ func compareSnapshots(logf logf, configDir string, actualDir string, expectedDir if expectedRepo != actualRepo { // get the log file and print it - bytes, err := ioutil.ReadFile(filepath.Join(configDir, "development.log")) + bytes, err := ioutil.ReadFile(filepath.Join(self.paths.Config(), "development.log")) if err != nil { return err } - logf("%s", string(bytes)) + self.logf("%s", string(bytes)) return errors.New(getDiff(f.Name(), actualRepo, expectedRepo)) } @@ -231,95 +179,11 @@ func compareSnapshots(logf logf, configDir string, actualDir string, expectedDir return nil } -func createFixture(test *components.IntegrationTest, actualDir string, rootDir string) error { - if err := os.Chdir(actualDir); err != nil { - panic(err) - } - - shell := components.NewShell() - shell.RunCommand("git init") - shell.RunCommand(`git config user.email "CI@example.com"`) - shell.RunCommand(`git config user.name "CI"`) - - test.SetupRepo(shell) - - // changing directory back to rootDir after the setup is done - if err := os.Chdir(rootDir); err != nil { - panic(err) - } - - return nil -} - -func getLazygitCommand(test *components.IntegrationTest, testPath string, rootDir string) (*exec.Cmd, error) { - osCommand := oscommands.NewDummyOSCommand() - - templateConfigDir := filepath.Join(rootDir, "test", "default_test_config") - actualRepoDir := filepath.Join(testPath, "actual", "repo") - - configDir := filepath.Join(testPath, "used_config") - - err := os.RemoveAll(configDir) - if err != nil { - return nil, err - } - err = oscommands.CopyDir(templateConfigDir, configDir) - if err != nil { - return nil, err - } - - cmdStr := fmt.Sprintf("%s -debug --use-config-dir=%s --path=%s %s", tempLazygitPath(), configDir, actualRepoDir, test.ExtraCmdArgs()) - - cmdObj := osCommand.Cmd.New(cmdStr) - - cmdObj.AddEnvVars(fmt.Sprintf("%s=%s", LAZYGIT_TEST_NAME_ENV_VAR, test.Name())) - - return cmdObj.GetCmd(), nil -} - -func GetModeFromEnv() Mode { - switch os.Getenv("MODE") { - case "", "ask": - return ASK_TO_UPDATE_SNAPSHOT - case "check": - return CHECK_SNAPSHOT - 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") - } -} - -func GetRootDirectory() string { - path, err := os.Getwd() - if err != nil { - panic(err) - } - - for { - _, err := os.Stat(filepath.Join(path, ".git")) - - if err == nil { - return path - } - - if !os.IsNotExist(err) { - panic(err) - } - - path = filepath.Dir(path) - - if path == "/" { - log.Fatal("must run in lazygit folder or child folder") - } - } -} - -func tempLazygitPath() string { - return filepath.Join("/tmp", "lazygit", "test_lazygit") +func promptUserToUpdateSnapshot() bool { + fmt.Println("Test failed. Update snapshot? (y/n)") + var input string + fmt.Scanln(&input) + return input == "y" } func generateSnapshots(actualDir string, expectedDir string) (string, string, error) { @@ -491,38 +355,6 @@ func getFileName(f os.FileInfo) string { return f.Name() } -func findOrCreateDir(path string) { - _, err := os.Stat(path) - if err != nil { - if os.IsNotExist(err) { - err = os.MkdirAll(path, 0o777) - if err != nil { - panic(err) - } - } else { - panic(err) - } - } -} - -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) - if err != nil { - panic(err) - } - } else { - panic(err) - } - } - for _, d := range dir { - os.RemoveAll(filepath.Join(actualDir, d.Name())) - } -} - func getDiff(prefix string, expected string, actual string) string { mockT := &MockTestingT{} assert.Equal(mockT, expected, actual, fmt.Sprintf("Unexpected %s. Expected:\n%s\nActual:\n%s\n", prefix, expected, actual)) diff --git a/pkg/integration/go_test.go b/pkg/integration/go_test.go index 0e55f9886..3dd03ec56 100644 --- a/pkg/integration/go_test.go +++ b/pkg/integration/go_test.go @@ -16,6 +16,7 @@ import ( "github.com/creack/pty" "github.com/jesseduffield/lazygit/pkg/integration/components" + "github.com/jesseduffield/lazygit/pkg/integration/tests" "github.com/stretchr/testify/assert" ) @@ -24,14 +25,12 @@ func TestIntegration(t *testing.T) { t.Skip("Skipping integration tests in short mode") } - mode := GetModeFromEnv() - includeSkipped := os.Getenv("INCLUDE_SKIPPED") != "" - parallelTotal := tryConvert(os.Getenv("PARALLEL_TOTAL"), 1) parallelIndex := tryConvert(os.Getenv("PARALLEL_INDEX"), 0) testNumber := 0 - err := RunTests( + err := components.RunTests( + tests.Tests, t.Logf, runCmdHeadless, func(test *components.IntegrationTest, f func() error) { @@ -45,8 +44,7 @@ func TestIntegration(t *testing.T) { assert.NoError(t, err) }) }, - mode, - includeSkipped, + components.CHECK_SNAPSHOT, ) assert.NoError(t, err)