1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-07-30 03:23:08 +03:00

rename input to t

This commit is contained in:
Jesse Duffield
2022-12-27 21:35:36 +11:00
parent 53e06b71ae
commit 78b495f50a
45 changed files with 376 additions and 399 deletions

View File

@ -1,13 +1,13 @@
package components
type AlertAsserter struct {
input *Input
t *TestDriver
hasCheckedTitle bool
hasCheckedContent bool
}
func (self *AlertAsserter) getViewAsserter() *View {
return self.input.Views().Confirmation()
return self.t.Views().Confirmation()
}
// asserts that the alert view has the expected title
@ -42,6 +42,6 @@ func (self *AlertAsserter) Cancel() {
func (self *AlertAsserter) checkNecessaryChecksCompleted() {
if !self.hasCheckedContent || !self.hasCheckedTitle {
self.input.Fail("You must both check the content and title of a confirmation popup by calling Title()/Content() before calling Confirm()/Cancel().")
self.t.Fail("You must both check the content and title of a confirmation popup by calling Title()/Content() before calling Confirm()/Cancel().")
}
}

View File

@ -1,11 +1,11 @@
package components
type CommitMessagePanelAsserter struct {
input *Input
t *TestDriver
}
func (self *CommitMessagePanelAsserter) getViewAsserter() *View {
return self.input.Views().CommitMessage()
return self.t.Views().CommitMessage()
}
// asserts on the text initially present in the prompt
@ -16,13 +16,13 @@ func (self *CommitMessagePanelAsserter) InitialText(expected *matcher) *CommitMe
}
func (self *CommitMessagePanelAsserter) Type(value string) *CommitMessagePanelAsserter {
self.input.typeContent(value)
self.t.typeContent(value)
return self
}
func (self *CommitMessagePanelAsserter) AddNewline() *CommitMessagePanelAsserter {
self.input.press(self.input.keys.Universal.AppendNewline)
self.t.press(self.t.keys.Universal.AppendNewline)
return self
}

View File

@ -1,13 +1,13 @@
package components
type ConfirmationAsserter struct {
input *Input
t *TestDriver
hasCheckedTitle bool
hasCheckedContent bool
}
func (self *ConfirmationAsserter) getViewAsserter() *View {
return self.input.Views().Confirmation()
return self.t.Views().Confirmation()
}
// asserts that the confirmation view has the expected title
@ -42,6 +42,6 @@ func (self *ConfirmationAsserter) Cancel() {
func (self *ConfirmationAsserter) checkNecessaryChecksCompleted() {
if !self.hasCheckedContent || !self.hasCheckedTitle {
self.input.Fail("You must both check the content and title of a confirmation popup by calling Title()/Content() before calling Confirm()/Cancel().")
self.t.Fail("You must both check the content and title of a confirmation popup by calling Title()/Content() before calling Confirm()/Cancel().")
}
}

View File

@ -1,12 +1,12 @@
package components
type MenuAsserter struct {
input *Input
t *TestDriver
hasCheckedTitle bool
}
func (self *MenuAsserter) getViewAsserter() *View {
return self.input.Views().Menu()
return self.t.Views().Menu()
}
// asserts that the popup has the expected title
@ -38,6 +38,6 @@ func (self *MenuAsserter) Select(option *matcher) *MenuAsserter {
func (self *MenuAsserter) checkNecessaryChecksCompleted() {
if !self.hasCheckedTitle {
self.input.Fail("You must check the title of a menu popup by calling Title() before calling Confirm()/Cancel().")
self.t.Fail("You must check the title of a menu popup by calling Title() before calling Confirm()/Cancel().")
}
}

View File

@ -1,12 +1,12 @@
package components
type PromptAsserter struct {
input *Input
t *TestDriver
hasCheckedTitle bool
}
func (self *PromptAsserter) getViewAsserter() *View {
return self.input.Views().Confirmation()
return self.t.Views().Confirmation()
}
// asserts that the popup has the expected title
@ -26,7 +26,7 @@ func (self *PromptAsserter) InitialText(expected *matcher) *PromptAsserter {
}
func (self *PromptAsserter) Type(value string) *PromptAsserter {
self.input.typeContent(value)
self.t.typeContent(value)
return self
}
@ -49,25 +49,25 @@ func (self *PromptAsserter) Cancel() {
func (self *PromptAsserter) checkNecessaryChecksCompleted() {
if !self.hasCheckedTitle {
self.input.Fail("You must check the title of a prompt popup by calling Title() before calling Confirm()/Cancel().")
self.t.Fail("You must check the title of a prompt popup by calling Title() before calling Confirm()/Cancel().")
}
}
func (self *PromptAsserter) SuggestionLines(matchers ...*matcher) *PromptAsserter {
self.input.Views().Suggestions().Lines(matchers...)
self.t.Views().Suggestions().Lines(matchers...)
return self
}
func (self *PromptAsserter) SuggestionTopLines(matchers ...*matcher) *PromptAsserter {
self.input.Views().Suggestions().TopLines(matchers...)
self.t.Views().Suggestions().TopLines(matchers...)
return self
}
func (self *PromptAsserter) SelectFirstSuggestion() *PromptAsserter {
self.input.press(self.input.keys.Universal.TogglePanel)
self.input.Views().Suggestions().
self.t.press(self.t.keys.Universal.TogglePanel)
self.t.Views().Suggestions().
IsFocused().
SelectedLineIdx(0)
@ -75,8 +75,8 @@ func (self *PromptAsserter) SelectFirstSuggestion() *PromptAsserter {
}
func (self *PromptAsserter) SelectSuggestion(matcher *matcher) *PromptAsserter {
self.input.press(self.input.keys.Universal.TogglePanel)
self.input.Views().Suggestions().
self.t.press(self.t.keys.Universal.TogglePanel)
self.t.Views().Suggestions().
IsFocused().
NavigateToListItem(matcher)

View File

@ -25,7 +25,7 @@ type IntegrationTest struct {
setupConfig func(config *config.AppConfig)
run func(
shell *Shell,
input *Input,
testController *TestDriver,
keys config.KeybindingConfig,
)
}
@ -40,7 +40,7 @@ type NewIntegrationTestArgs struct {
// takes a config and mutates. The mutated context will end up being passed to the gui
SetupConfig func(config *config.AppConfig)
// runs the test
Run func(shell *Shell, input *Input, keys config.KeybindingConfig)
Run func(shell *Shell, t *TestDriver, keys config.KeybindingConfig)
// additional args passed to lazygit
ExtraCmdArgs string
// for when a test is flakey
@ -94,13 +94,13 @@ func (self *IntegrationTest) SetupRepo(shell *Shell) {
func (self *IntegrationTest) Run(gui integrationTypes.GuiDriver) {
shell := NewShell("/tmp/lazygit-test")
keys := gui.Keys()
input := NewInput(gui, keys, KeyPressDelay())
testController := NewTestController(gui, keys, KeyPressDelay())
self.run(shell, input, keys)
self.run(shell, testController, keys)
if KeyPressDelay() > 0 {
// the dev would want to see the final state if they're running in slow mode
input.Wait(2000)
testController.Wait(2000)
}
}

View File

@ -11,15 +11,15 @@ import (
"github.com/samber/lo"
)
type Input struct {
type TestDriver struct {
gui integrationTypes.GuiDriver
keys config.KeybindingConfig
pushKeyDelay int
*assertionHelper
}
func NewInput(gui integrationTypes.GuiDriver, keys config.KeybindingConfig, pushKeyDelay int) *Input {
return &Input{
func NewTestController(gui integrationTypes.GuiDriver, keys config.KeybindingConfig, pushKeyDelay int) *TestDriver {
return &TestDriver{
gui: gui,
keys: keys,
pushKeyDelay: pushKeyDelay,
@ -29,19 +29,19 @@ func NewInput(gui integrationTypes.GuiDriver, keys config.KeybindingConfig, push
// key is something like 'w' or '<space>'. It's best not to pass a direct value,
// but instead to go through the default user config to get a more meaningful key name
func (self *Input) press(keyStr string) {
func (self *TestDriver) press(keyStr string) {
self.Wait(self.pushKeyDelay)
self.gui.PressKey(keyStr)
}
func (self *Input) typeContent(content string) {
func (self *TestDriver) typeContent(content string) {
for _, char := range content {
self.press(string(char))
}
}
func (self *Input) ContinueMerge() {
func (self *TestDriver) ContinueMerge() {
self.Views().current().Press(self.keys.Universal.CreateRebaseOptionsMenu)
self.ExpectMenu().
@ -50,20 +50,20 @@ func (self *Input) ContinueMerge() {
Confirm()
}
func (self *Input) ContinueRebase() {
func (self *TestDriver) ContinueRebase() {
self.ContinueMerge()
}
// for when you want to allow lazygit to process something before continuing
func (self *Input) Wait(milliseconds int) {
func (self *TestDriver) Wait(milliseconds int) {
time.Sleep(time.Duration(milliseconds) * time.Millisecond)
}
func (self *Input) LogUI(message string) {
func (self *TestDriver) LogUI(message string) {
self.gui.LogUI(message)
}
func (self *Input) Log(message string) {
func (self *TestDriver) Log(message string) {
self.gui.LogUI(message)
}
@ -78,7 +78,7 @@ func (self *Input) Log(message string) {
// If this changes in future, we'll need to update this code to first attempt to find the item
// in the current page and failing that, jump to the top of the view and iterate through all of it,
// looking for the item.
func (self *Input) navigateToListItem(matcher *matcher) {
func (self *TestDriver) navigateToListItem(matcher *matcher) {
self.inListContext()
currentContext := self.gui.CurrentContext().(types.IListContext)
@ -128,7 +128,7 @@ func (self *Input) navigateToListItem(matcher *matcher) {
}
}
func (self *Input) inListContext() {
func (self *TestDriver) inListContext() {
self.assertWithRetries(func() (bool, string) {
currentContext := self.gui.CurrentContext()
_, ok := currentContext.(types.IListContext)
@ -136,39 +136,39 @@ func (self *Input) inListContext() {
})
}
func (self *Input) ExpectConfirmation() *ConfirmationAsserter {
func (self *TestDriver) ExpectConfirmation() *ConfirmationAsserter {
self.inConfirm()
return &ConfirmationAsserter{input: self}
return &ConfirmationAsserter{t: self}
}
func (self *Input) inConfirm() {
func (self *TestDriver) inConfirm() {
self.assertWithRetries(func() (bool, string) {
currentView := self.gui.CurrentContext().GetView()
return currentView.Name() == "confirmation" && !currentView.Editable, "Expected confirmation popup to be focused"
})
}
func (self *Input) ExpectPrompt() *PromptAsserter {
func (self *TestDriver) ExpectPrompt() *PromptAsserter {
self.inPrompt()
return &PromptAsserter{input: self}
return &PromptAsserter{t: self}
}
func (self *Input) inPrompt() {
func (self *TestDriver) inPrompt() {
self.assertWithRetries(func() (bool, string) {
currentView := self.gui.CurrentContext().GetView()
return currentView.Name() == "confirmation" && currentView.Editable, "Expected prompt popup to be focused"
})
}
func (self *Input) ExpectAlert() *AlertAsserter {
func (self *TestDriver) ExpectAlert() *AlertAsserter {
self.inAlert()
return &AlertAsserter{input: self}
return &AlertAsserter{t: self}
}
func (self *Input) inAlert() {
func (self *TestDriver) inAlert() {
// basically the same thing as a confirmation popup with the current implementation
self.assertWithRetries(func() (bool, string) {
currentView := self.gui.CurrentContext().GetView()
@ -176,32 +176,32 @@ func (self *Input) inAlert() {
})
}
func (self *Input) ExpectMenu() *MenuAsserter {
func (self *TestDriver) ExpectMenu() *MenuAsserter {
self.inMenu()
return &MenuAsserter{input: self}
return &MenuAsserter{t: self}
}
func (self *Input) inMenu() {
func (self *TestDriver) inMenu() {
self.assertWithRetries(func() (bool, string) {
return self.gui.CurrentContext().GetView().Name() == "menu", "Expected popup menu to be focused"
})
}
func (self *Input) ExpectCommitMessagePanel() *CommitMessagePanelAsserter {
func (self *TestDriver) ExpectCommitMessagePanel() *CommitMessagePanelAsserter {
self.inCommitMessagePanel()
return &CommitMessagePanelAsserter{input: self}
return &CommitMessagePanelAsserter{t: self}
}
func (self *Input) inCommitMessagePanel() {
func (self *TestDriver) inCommitMessagePanel() {
self.assertWithRetries(func() (bool, string) {
currentView := self.gui.CurrentContext().GetView()
return currentView.Name() == "commitMessage", "Expected commit message panel to be focused"
})
}
func (self *Input) currentWindowName(expectedWindowName string) {
func (self *TestDriver) 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)
@ -209,27 +209,27 @@ func (self *Input) currentWindowName(expectedWindowName string) {
}
// for making assertions on lazygit views
func (self *Input) Views() *Views {
return &Views{input: self}
func (self *TestDriver) Views() *Views {
return &Views{t: self}
}
// for making assertions on the lazygit model
func (self *Input) Model() *Model {
func (self *TestDriver) Model() *Model {
return &Model{assertionHelper: self.assertionHelper, gui: self.gui}
}
// for making assertions on the file system
func (self *Input) FileSystem() *FileSystem {
func (self *TestDriver) FileSystem() *FileSystem {
return &FileSystem{assertionHelper: self.assertionHelper}
}
// for when you just want to fail the test yourself.
// This runs callbacks to ensure we render the error after closing the gui.
func (self *Input) Fail(message string) {
func (self *TestDriver) Fail(message string) {
self.assertionHelper.fail(message)
}
func (self *Input) NotInPopup() {
func (self *TestDriver) NotInPopup() {
self.assertWithRetries(func() (bool, string) {
viewName := self.gui.CurrentContext().GetView().Name()
return !lo.Contains([]string{"menu", "confirmation", "commitMessage"}, viewName), fmt.Sprintf("Unexpected popup view present: %s view", viewName)

View File

@ -63,10 +63,10 @@ func (self *fakeGuiDriver) View(viewName string) *gocui.View {
func TestAssertionFailure(t *testing.T) {
test := NewIntegrationTest(NewIntegrationTestArgs{
Description: unitTestDescription,
Run: func(shell *Shell, input *Input, keys config.KeybindingConfig) {
input.press("a")
input.press("b")
input.Model().CommitCount(2)
Run: func(shell *Shell, t *TestDriver, keys config.KeybindingConfig) {
t.press("a")
t.press("b")
t.Model().CommitCount(2)
},
})
driver := &fakeGuiDriver{}
@ -78,8 +78,8 @@ func TestAssertionFailure(t *testing.T) {
func TestManualFailure(t *testing.T) {
test := NewIntegrationTest(NewIntegrationTestArgs{
Description: unitTestDescription,
Run: func(shell *Shell, input *Input, keys config.KeybindingConfig) {
input.Fail("blah")
Run: func(shell *Shell, t *TestDriver, keys config.KeybindingConfig) {
t.Fail("blah")
},
})
driver := &fakeGuiDriver{}
@ -90,10 +90,10 @@ func TestManualFailure(t *testing.T) {
func TestSuccess(t *testing.T) {
test := NewIntegrationTest(NewIntegrationTestArgs{
Description: unitTestDescription,
Run: func(shell *Shell, input *Input, keys config.KeybindingConfig) {
input.press("a")
input.press("b")
input.Model().CommitCount(0)
Run: func(shell *Shell, t *TestDriver, keys config.KeybindingConfig) {
t.press("a")
t.press("b")
t.Model().CommitCount(0)
},
})
driver := &fakeGuiDriver{}

View File

@ -10,23 +10,12 @@ type View struct {
// context is prepended to any error messages e.g. 'context: "current view"'
context string
getView func() *gocui.View
input *Input
}
// asserts that the view has the expected name. This is typically used in tandem with the CurrentView method i.e.;
// input.CurrentView().Name("commits") to assert that the current view is the commits view.
func (self *View) Name(expected string) *View {
self.input.assertWithRetries(func() (bool, string) {
actual := self.getView().Name()
return actual == expected, fmt.Sprintf("%s: Expected view name to be '%s', but got '%s'", self.context, expected, actual)
})
return self
t *TestDriver
}
// asserts that the view has the expected title
func (self *View) Title(expected *matcher) *View {
self.input.assertWithRetries(func() (bool, string) {
self.t.assertWithRetries(func() (bool, string) {
actual := self.getView().Title
return expected.context(fmt.Sprintf("%s title", self.context)).test(actual)
})
@ -39,7 +28,7 @@ func (self *View) Title(expected *matcher) *View {
// This method is convenient when you have a list of commits but you only want to
// assert on the first couple of commits.
func (self *View) TopLines(matchers ...*matcher) *View {
self.input.assertWithRetries(func() (bool, string) {
self.t.assertWithRetries(func() (bool, string) {
lines := self.getView().BufferLines()
return len(lines) >= len(matchers), fmt.Sprintf("unexpected number of lines in view. Expected at least %d, got %d", len(matchers), len(lines))
})
@ -50,7 +39,7 @@ func (self *View) TopLines(matchers ...*matcher) *View {
// asserts that the view has lines matching the given matchers. One matcher must be passed for each line.
// If you only care about the top n lines, use the TopLines method instead.
func (self *View) Lines(matchers ...*matcher) *View {
self.input.assertWithRetries(func() (bool, string) {
self.t.assertWithRetries(func() (bool, string) {
lines := self.getView().BufferLines()
return len(lines) == len(matchers), fmt.Sprintf("unexpected number of lines in view. Expected %d, got %d", len(matchers), len(lines))
})
@ -64,14 +53,14 @@ func (self *View) assertLines(matchers ...*matcher) *View {
for i, matcher := range matchers {
checkIsSelected, matcher := matcher.checkIsSelected()
self.input.matchString(matcher, fmt.Sprintf("Unexpected content in view '%s'.", view.Name()),
self.t.matchString(matcher, fmt.Sprintf("Unexpected content in view '%s'.", view.Name()),
func() string {
return view.BufferLines()[i]
},
)
if checkIsSelected {
self.input.assertWithRetries(func() (bool, string) {
self.t.assertWithRetries(func() (bool, string) {
lineIdx := view.SelectedLineIdx()
return lineIdx == i, fmt.Sprintf("Unexpected selected line index in view '%s'. Expected %d, got %d", view.Name(), i, lineIdx)
})
@ -83,7 +72,7 @@ func (self *View) assertLines(matchers ...*matcher) *View {
// asserts on the content of the view i.e. the stuff within the view's frame.
func (self *View) Content(matcher *matcher) *View {
self.input.matchString(matcher, fmt.Sprintf("%s: Unexpected content.", self.context),
self.t.matchString(matcher, fmt.Sprintf("%s: Unexpected content.", self.context),
func() string {
return self.getView().Buffer()
},
@ -94,7 +83,7 @@ func (self *View) Content(matcher *matcher) *View {
// asserts on the selected line of the view
func (self *View) SelectedLine(matcher *matcher) *View {
self.input.matchString(matcher, fmt.Sprintf("%s: Unexpected selected line.", self.context),
self.t.matchString(matcher, fmt.Sprintf("%s: Unexpected selected line.", self.context),
func() string {
return self.getView().SelectedLine()
},
@ -105,7 +94,7 @@ func (self *View) SelectedLine(matcher *matcher) *View {
// asserts on the index of the selected line. 0 is the first index, representing the line at the top of the view.
func (self *View) SelectedLineIdx(expected int) *View {
self.input.assertWithRetries(func() (bool, string) {
self.t.assertWithRetries(func() (bool, string) {
actual := self.getView().SelectedLineIdx()
return expected == actual, fmt.Sprintf("%s: Expected selected line index to be %d, got %d", self.context, expected, actual)
})
@ -132,10 +121,10 @@ func (self *View) Focus() *View {
index, ok := windowIndexMap[viewName]
if !ok {
self.input.fail(fmt.Sprintf("Cannot focus view %s: Focus() method not implemented", viewName))
self.t.fail(fmt.Sprintf("Cannot focus view %s: Focus() method not implemented", viewName))
}
self.input.press(self.input.keys.Universal.JumpToBlock[index])
self.t.press(self.t.keys.Universal.JumpToBlock[index])
// assert that we land in the expected view
self.IsFocused()
@ -145,9 +134,9 @@ func (self *View) Focus() *View {
// asserts that the view is focused
func (self *View) IsFocused() *View {
self.input.assertWithRetries(func() (bool, string) {
self.t.assertWithRetries(func() (bool, string) {
expected := self.getView().Name()
actual := self.input.gui.CurrentContext().GetView().Name()
actual := self.t.gui.CurrentContext().GetView().Name()
return actual == expected, fmt.Sprintf("%s: Unexpected view focused. Expected %s, got %s", self.context, expected, actual)
})
@ -157,40 +146,40 @@ func (self *View) IsFocused() *View {
func (self *View) Press(keyStr string) *View {
self.IsFocused()
self.input.press(keyStr)
self.t.press(keyStr)
return self
}
// i.e. pressing down arrow
func (self *View) SelectNextItem() *View {
return self.Press(self.input.keys.Universal.NextItem)
return self.Press(self.t.keys.Universal.NextItem)
}
// i.e. pressing up arrow
func (self *View) SelectPreviousItem() *View {
return self.Press(self.input.keys.Universal.PrevItem)
return self.Press(self.t.keys.Universal.PrevItem)
}
// i.e. pressing space
func (self *View) PressPrimaryAction() *View {
return self.Press(self.input.keys.Universal.Select)
return self.Press(self.t.keys.Universal.Select)
}
// i.e. pressing space
func (self *View) PressEnter() *View {
return self.Press(self.input.keys.Universal.Confirm)
return self.Press(self.t.keys.Universal.Confirm)
}
// i.e. pressing escape
func (self *View) PressEscape() *View {
return self.Press(self.input.keys.Universal.Return)
return self.Press(self.t.keys.Universal.Return)
}
func (self *View) NavigateToListItem(matcher *matcher) *View {
self.IsFocused()
self.input.navigateToListItem(matcher)
self.t.navigateToListItem(matcher)
return self
}

View File

@ -7,7 +7,7 @@ import (
)
type Views struct {
input *Input
t *TestDriver
}
// not exporting this because I want the test to always be explicit about what
@ -15,32 +15,32 @@ type Views struct {
func (self *Views) current() *View {
return &View{
context: "current view",
getView: func() *gocui.View { return self.input.gui.CurrentContext().GetView() },
input: self.input,
getView: func() *gocui.View { return self.t.gui.CurrentContext().GetView() },
t: self.t,
}
}
func (self *Views) Main() *View {
return &View{
context: "main view",
getView: func() *gocui.View { return self.input.gui.MainView() },
input: self.input,
getView: func() *gocui.View { return self.t.gui.MainView() },
t: self.t,
}
}
func (self *Views) Secondary() *View {
return &View{
context: "secondary view",
getView: func() *gocui.View { return self.input.gui.SecondaryView() },
input: self.input,
getView: func() *gocui.View { return self.t.gui.SecondaryView() },
t: self.t,
}
}
func (self *Views) ByName(viewName string) *View {
return &View{
context: fmt.Sprintf("%s view", viewName),
getView: func() *gocui.View { return self.input.gui.View(viewName) },
input: self.input,
getView: func() *gocui.View { return self.t.gui.View(viewName) },
t: self.t,
}
}