diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2022-08-09 21:27:12 +1000 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2022-08-13 13:55:08 +1000 |
commit | ba96baee32f5d02173312b357327eb7478492f89 (patch) | |
tree | fbd0c91d5799f9519d617f7041518c0c7e14d2bc /pkg/gui | |
parent | d890238c7bcbdd62e7158df0c1f3f0e5c0b05b66 (diff) |
move code from main into app package to allow test to be injected
Diffstat (limited to 'pkg/gui')
-rw-r--r-- | pkg/gui/gui.go | 32 | ||||
-rw-r--r-- | pkg/gui/gui_adapter.go (renamed from pkg/gui/gui_adapter_impl.go) | 21 | ||||
-rw-r--r-- | pkg/gui/gui_test.go | 84 | ||||
-rw-r--r-- | pkg/gui/old_gui_test.go | 76 | ||||
-rw-r--r-- | pkg/gui/recent_repos_panel.go | 3 | ||||
-rw-r--r-- | pkg/gui/test_mode.go | 8 | ||||
-rw-r--r-- | pkg/gui/types/main_args.go | 29 | ||||
-rw-r--r-- | pkg/gui/types/test.go | 27 |
8 files changed, 34 insertions, 246 deletions
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 11c8af78b..8be5a4a4d 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -10,6 +10,7 @@ import ( "time" "github.com/jesseduffield/gocui" + appTypes "github.com/jesseduffield/lazygit/pkg/app/types" "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/git_config" @@ -31,6 +32,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/gui/services/custom_commands" "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/types" + integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types" "github.com/jesseduffield/lazygit/pkg/tasks" "github.com/jesseduffield/lazygit/pkg/theme" "github.com/jesseduffield/lazygit/pkg/updates" @@ -213,7 +215,7 @@ const ( COMPLETE ) -func (gui *Gui) onNewRepo(startArgs types.StartArgs, reuseState bool) error { +func (gui *Gui) onNewRepo(startArgs appTypes.StartArgs, reuseState bool) error { var err error gui.git, err = commands.NewGitCommand( gui.Common, @@ -245,7 +247,7 @@ func (gui *Gui) onNewRepo(startArgs types.StartArgs, reuseState bool) error { // it gets a bit confusing to land back in the status panel when visiting a repo // you've already switched from. There's no doubt some easy way to make the UX // optimal for all cases but I'm too lazy to think about what that is right now -func (gui *Gui) resetState(startArgs types.StartArgs, reuseState bool) { +func (gui *Gui) resetState(startArgs appTypes.StartArgs, reuseState bool) { currentDir, err := os.Getwd() if reuseState { @@ -300,28 +302,28 @@ func (gui *Gui) resetState(startArgs types.StartArgs, reuseState bool) { gui.RepoStateMap[Repo(currentDir)] = gui.State } -func initialScreenMode(startArgs types.StartArgs) WindowMaximisation { - if startArgs.FilterPath != "" || startArgs.GitArg != types.GitArgNone { +func initialScreenMode(startArgs appTypes.StartArgs) WindowMaximisation { + if startArgs.FilterPath != "" || startArgs.GitArg != appTypes.GitArgNone { return SCREEN_HALF } else { return SCREEN_NORMAL } } -func initialContext(contextTree *context.ContextTree, startArgs types.StartArgs) types.IListContext { +func initialContext(contextTree *context.ContextTree, startArgs appTypes.StartArgs) types.IListContext { var initialContext types.IListContext = contextTree.Files if startArgs.FilterPath != "" { initialContext = contextTree.LocalCommits - } else if startArgs.GitArg != types.GitArgNone { + } else if startArgs.GitArg != appTypes.GitArgNone { switch startArgs.GitArg { - case types.GitArgStatus: + case appTypes.GitArgStatus: initialContext = contextTree.Files - case types.GitArgBranch: + case appTypes.GitArgBranch: initialContext = contextTree.Branches - case types.GitArgLog: + case appTypes.GitArgLog: initialContext = contextTree.LocalCommits - case types.GitArgStash: + case appTypes.GitArgStash: initialContext = contextTree.Stash default: panic("unhandled git arg") @@ -417,7 +419,7 @@ var RuneReplacements = map[rune]string{ graph.CommitSymbol: "o", } -func (gui *Gui) initGocui(headless bool, test types.Test) (*gocui.Gui, error) { +func (gui *Gui) initGocui(headless bool, test integrationTypes.IntegrationTest) (*gocui.Gui, error) { recordEvents := RecordingEvents() playMode := gocui.NORMAL if recordEvents { @@ -476,8 +478,8 @@ func (gui *Gui) viewTabMap() map[string][]context.TabView { } // Run: setup the gui with keybindings and start the mainloop -func (gui *Gui) Run(startArgs types.StartArgs) error { - g, err := gui.initGocui(Headless(), startArgs.Test) +func (gui *Gui) Run(startArgs appTypes.StartArgs) error { + g, err := gui.initGocui(Headless(), startArgs.IntegrationTest) if err != nil { return err } @@ -492,7 +494,7 @@ func (gui *Gui) Run(startArgs types.StartArgs) error { }) deadlock.Opts.Disable = !gui.Debug - gui.handleTestMode(startArgs.Test) + gui.handleTestMode(startArgs.IntegrationTest) gui.g.OnSearchEscape = gui.onSearchEscape if err := gui.Config.ReloadUserConfig(); err != nil { @@ -553,7 +555,7 @@ func (gui *Gui) Run(startArgs types.StartArgs) error { return gui.g.MainLoop() } -func (gui *Gui) RunAndHandleError(startArgs types.StartArgs) error { +func (gui *Gui) RunAndHandleError(startArgs appTypes.StartArgs) error { gui.stopChan = make(chan struct{}) return utils.SafeWithError(func() error { if err := gui.Run(startArgs); err != nil { diff --git a/pkg/gui/gui_adapter_impl.go b/pkg/gui/gui_adapter.go index 427b8eb47..5566f8b0f 100644 --- a/pkg/gui/gui_adapter_impl.go +++ b/pkg/gui/gui_adapter.go @@ -9,17 +9,18 @@ import ( "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/gui/keybindings" "github.com/jesseduffield/lazygit/pkg/gui/types" + integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types" ) // this gives our integration test a way of interacting with the gui for sending keypresses // and reading state. -type GuiAdapterImpl struct { +type GuiAdapter struct { gui *Gui } -var _ types.GuiAdapter = &GuiAdapterImpl{} +var _ integrationTypes.GuiAdapter = &GuiAdapter{} -func (self *GuiAdapterImpl) PressKey(keyStr string) { +func (self *GuiAdapter) PressKey(keyStr string) { key := keybindings.GetKey(keyStr) var r rune @@ -38,19 +39,19 @@ func (self *GuiAdapterImpl) PressKey(keyStr string) { ) } -func (self *GuiAdapterImpl) Keys() config.KeybindingConfig { +func (self *GuiAdapter) Keys() config.KeybindingConfig { return self.gui.Config.GetUserConfig().Keybinding } -func (self *GuiAdapterImpl) CurrentContext() types.Context { +func (self *GuiAdapter) CurrentContext() types.Context { return self.gui.c.CurrentContext() } -func (self *GuiAdapterImpl) Model() *types.Model { +func (self *GuiAdapter) Model() *types.Model { return self.gui.State.Model } -func (self *GuiAdapterImpl) Fail(message string) { +func (self *GuiAdapter) Fail(message string) { self.gui.g.Close() // need to give the gui time to close time.Sleep(time.Millisecond * 100) @@ -58,15 +59,15 @@ func (self *GuiAdapterImpl) Fail(message string) { } // logs to the normal place that you log to i.e. viewable with `lazygit --logs` -func (self *GuiAdapterImpl) Log(message string) { +func (self *GuiAdapter) Log(message string) { self.gui.c.Log.Warn(message) } // logs in the actual UI (in the commands panel) -func (self *GuiAdapterImpl) LogUI(message string) { +func (self *GuiAdapter) LogUI(message string) { self.gui.c.LogAction(message) } -func (self *GuiAdapterImpl) CheckedOutRef() *models.Branch { +func (self *GuiAdapter) CheckedOutRef() *models.Branch { return self.gui.helpers.Refs.GetCheckedOutRef() } diff --git a/pkg/gui/gui_test.go b/pkg/gui/gui_test.go deleted file mode 100644 index 2d698d34c..000000000 --- a/pkg/gui/gui_test.go +++ /dev/null @@ -1,84 +0,0 @@ -//go:build !windows -// +build !windows - -package gui - -// this is the new way of running tests. See pkg/integration/integration_tests/commit.go -// for an example - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "strconv" - "testing" - - "github.com/creack/pty" - "github.com/jesseduffield/lazygit/pkg/integration" - "github.com/jesseduffield/lazygit/pkg/integration/types" - "github.com/stretchr/testify/assert" -) - -func Test(t *testing.T) { - if testing.Short() { - t.Skip("Skipping integration tests in short mode") - } - - mode := integration.GetModeFromEnv() - includeSkipped := os.Getenv("INCLUDE_SKIPPED") != "" - - parallelTotal := tryConvert(os.Getenv("PARALLEL_TOTAL"), 1) - parallelIndex := tryConvert(os.Getenv("PARALLEL_INDEX"), 0) - testNumber := 0 - - err := integration.RunTestsNew( - t.Logf, - runCmdHeadless, - func(test types.Test, f func() error) { - defer func() { testNumber += 1 }() - if testNumber%parallelTotal != parallelIndex { - return - } - - t.Run(test.Name(), func(t *testing.T) { - err := f() - assert.NoError(t, err) - }) - }, - mode, - func(expected string, actual string, prefix string) { - 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 runCmdHeadless(cmd *exec.Cmd) error { - cmd.Env = append( - cmd.Env, - "HEADLESS=true", - "TERM=xterm", - ) - - f, err := pty.StartWithSize(cmd, &pty.Winsize{Rows: 100, Cols: 100}) - if err != nil { - return err - } - - _, _ = io.Copy(ioutil.Discard, f) - - return f.Close() -} - -func tryConvert(numStr string, defaultVal int) int { - num, err := strconv.Atoi(numStr) - if err != nil { - return defaultVal - } - - return num -} diff --git a/pkg/gui/old_gui_test.go b/pkg/gui/old_gui_test.go deleted file mode 100644 index 12e33432d..000000000 --- a/pkg/gui/old_gui_test.go +++ /dev/null @@ -1,76 +0,0 @@ -//go:build !windows -// +build !windows - -package gui - -import ( - "fmt" - "os" - "testing" - - "github.com/jesseduffield/lazygit/pkg/integration" - "github.com/stretchr/testify/assert" -) - -// Deprecated: this is the old way of running tests. See pkg/gui/gui_test.go for the new way. - -// 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 TestOld(t *testing.T) { - if testing.Short() { - t.Skip("Skipping integration tests in short mode") - } - - mode := integration.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 := integration.RunTests( - t.Logf, - runCmdHeadless, - func(test *integration.Test, 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) -} diff --git a/pkg/gui/recent_repos_panel.go b/pkg/gui/recent_repos_panel.go index 73d6e54c5..705461726 100644 --- a/pkg/gui/recent_repos_panel.go +++ b/pkg/gui/recent_repos_panel.go @@ -9,6 +9,7 @@ import ( "sync" "github.com/jesseduffield/generics/slices" + appTypes "github.com/jesseduffield/lazygit/pkg/app/types" "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/env" "github.com/jesseduffield/lazygit/pkg/gui/presentation/icons" @@ -152,7 +153,7 @@ func (gui *Gui) dispatchSwitchToRepo(path string, reuse bool) error { gui.Mutexes.RefreshingFilesMutex.Lock() defer gui.Mutexes.RefreshingFilesMutex.Unlock() - return gui.onNewRepo(types.StartArgs{}, reuse) + return gui.onNewRepo(appTypes.StartArgs{}, reuse) } // updateRecentRepoList registers the fact that we opened lazygit in this repo, diff --git a/pkg/gui/test_mode.go b/pkg/gui/test_mode.go index 942e7824e..e9d596e80 100644 --- a/pkg/gui/test_mode.go +++ b/pkg/gui/test_mode.go @@ -9,20 +9,20 @@ import ( "time" "github.com/jesseduffield/gocui" - "github.com/jesseduffield/lazygit/pkg/gui/types" + integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types" "github.com/jesseduffield/lazygit/pkg/utils" ) type IntegrationTest interface { - Run(guiAdapter *GuiAdapterImpl) + Run(guiAdapter *GuiAdapter) } -func (gui *Gui) handleTestMode(test types.Test) { +func (gui *Gui) handleTestMode(test integrationTypes.IntegrationTest) { if test != nil { go func() { time.Sleep(time.Millisecond * 100) - test.Run(&GuiAdapterImpl{gui: gui}) + test.Run(&GuiAdapter{gui: gui}) gui.g.Update(func(*gocui.Gui) error { return gocui.ErrQuit diff --git a/pkg/gui/types/main_args.go b/pkg/gui/types/main_args.go deleted file mode 100644 index 7d9b9fbb7..000000000 --- a/pkg/gui/types/main_args.go +++ /dev/null @@ -1,29 +0,0 @@ -package types - -// StartArgs is the struct that represents some things we want to do on program start -type StartArgs struct { - // FilterPath determines which path we're going to filter on so that we only see commits from that file. - FilterPath string - // GitArg determines what context we open in - GitArg GitArg - // integration test (only relevant when invoking lazygit in the context of an integration test) - Test Test -} - -type GitArg string - -const ( - GitArgNone GitArg = "" - GitArgStatus GitArg = "status" - GitArgBranch GitArg = "branch" - GitArgLog GitArg = "log" - GitArgStash GitArg = "stash" -) - -func NewStartArgs(filterPath string, gitArg GitArg, test Test) StartArgs { - return StartArgs{ - FilterPath: filterPath, - GitArg: gitArg, - Test: test, - } -} diff --git a/pkg/gui/types/test.go b/pkg/gui/types/test.go deleted file mode 100644 index 55c1d50a8..000000000 --- a/pkg/gui/types/test.go +++ /dev/null @@ -1,27 +0,0 @@ -package types - -import ( - "github.com/jesseduffield/lazygit/pkg/commands/models" - "github.com/jesseduffield/lazygit/pkg/config" -) - -type Test interface { - Run(GuiAdapter) - SetupConfig(config *config.AppConfig) -} - -// this is the interface through which our integration tests interact with the lazygit gui -type GuiAdapter interface { - PressKey(string) - Keys() config.KeybindingConfig - CurrentContext() Context - Model() *Model - Fail(message string) - // These two log methods are for the sake of debugging while testing. There's no need to actually - // commit any logging. - // logs to the normal place that you log to i.e. viewable with `lazygit --logs` - Log(message string) - // logs in the actual UI (in the commands panel) - LogUI(message string) - CheckedOutRef() *models.Branch -} |