diff --git a/pkg/integration/components/alert_asserter.go b/pkg/integration/components/alert_asserter.go index 8ca027b59..739f44256 100644 --- a/pkg/integration/components/alert_asserter.go +++ b/pkg/integration/components/alert_asserter.go @@ -7,7 +7,7 @@ type AlertAsserter struct { hasCheckedContent bool } -func (self *AlertAsserter) getViewAsserter() *Views { +func (self *AlertAsserter) getViewAsserter() *View { return self.assert.Views().ByName("confirmation") } diff --git a/pkg/integration/components/assert.go b/pkg/integration/components/assert.go index 42ef90d6f..531e4f4dc 100644 --- a/pkg/integration/components/assert.go +++ b/pkg/integration/components/assert.go @@ -7,7 +7,8 @@ import ( // through this struct we assert on the state of the lazygit gui type Assert struct { - gui integrationTypes.GuiDriver + input *Input + gui integrationTypes.GuiDriver *assertionHelper } @@ -16,8 +17,8 @@ func NewAssert(gui integrationTypes.GuiDriver) *Assert { } // for making assertions on lazygit views -func (self *Assert) Views() *ViewAsserterGetter { - return &ViewAsserterGetter{assert: self} +func (self *Assert) Views() *Views { + return &Views{assert: self, input: self.input} } // for making assertions on the lazygit model diff --git a/pkg/integration/components/commit_message_panel_asserter.go b/pkg/integration/components/commit_message_panel_asserter.go index 3a534bd2d..2d9ef834a 100644 --- a/pkg/integration/components/commit_message_panel_asserter.go +++ b/pkg/integration/components/commit_message_panel_asserter.go @@ -5,7 +5,7 @@ type CommitMessagePanelAsserter struct { input *Input } -func (self *CommitMessagePanelAsserter) getViewAsserter() *Views { +func (self *CommitMessagePanelAsserter) getViewAsserter() *View { return self.assert.Views().ByName("commitMessage") } diff --git a/pkg/integration/components/confirmation_asserter.go b/pkg/integration/components/confirmation_asserter.go index 9cf4d653d..4fe64fdb0 100644 --- a/pkg/integration/components/confirmation_asserter.go +++ b/pkg/integration/components/confirmation_asserter.go @@ -7,7 +7,7 @@ type ConfirmationAsserter struct { hasCheckedContent bool } -func (self *ConfirmationAsserter) getViewAsserter() *Views { +func (self *ConfirmationAsserter) getViewAsserter() *View { return self.assert.Views().ByName("confirmation") } diff --git a/pkg/integration/components/input.go b/pkg/integration/components/input.go index 2f1ed18c5..d525c61c6 100644 --- a/pkg/integration/components/input.go +++ b/pkg/integration/components/input.go @@ -18,11 +18,10 @@ type Input struct { pushKeyDelay int } -func NewInput(gui integrationTypes.GuiDriver, keys config.KeybindingConfig, assert *Assert, pushKeyDelay int) *Input { +func NewInput(gui integrationTypes.GuiDriver, keys config.KeybindingConfig, pushKeyDelay int) *Input { return &Input{ gui: gui, keys: keys, - assert: assert, pushKeyDelay: pushKeyDelay, assertionHelper: assert.assertionHelper, } @@ -53,14 +52,14 @@ func (self *Input) SwitchToStatusView() { self.assert.Views().Current().Name("status") } -func (self *Input) SwitchToFilesWindow() { +func (self *Input) switchToFilesWindow() { self.press(self.keys.Universal.JumpToBlock[1]) self.currentWindowName("files") } // switch to files window and assert that the files view is on top func (self *Input) SwitchToFilesView() { - self.SwitchToFilesWindow() + self.switchToFilesWindow() self.assert.Views().Current().Name("files") } diff --git a/pkg/integration/components/menu_asserter.go b/pkg/integration/components/menu_asserter.go index e302c235b..32191ac08 100644 --- a/pkg/integration/components/menu_asserter.go +++ b/pkg/integration/components/menu_asserter.go @@ -6,7 +6,7 @@ type MenuAsserter struct { hasCheckedTitle bool } -func (self *MenuAsserter) getViewAsserter() *Views { +func (self *MenuAsserter) getViewAsserter() *View { return self.assert.Views().ByName("menu") } diff --git a/pkg/integration/components/prompt_asserter.go b/pkg/integration/components/prompt_asserter.go index b03ee85b7..fe7749e14 100644 --- a/pkg/integration/components/prompt_asserter.go +++ b/pkg/integration/components/prompt_asserter.go @@ -6,7 +6,7 @@ type PromptAsserter struct { hasCheckedTitle bool } -func (self *PromptAsserter) getViewAsserter() *Views { +func (self *PromptAsserter) getViewAsserter() *View { return self.assert.Views().ByName("confirmation") } diff --git a/pkg/integration/components/views.go b/pkg/integration/components/views.go index 624d1f66e..0c339dbe9 100644 --- a/pkg/integration/components/views.go +++ b/pkg/integration/components/views.go @@ -7,15 +7,57 @@ import ( ) type Views struct { + assert *Assert + input *Input +} + +func (self *Views) Current() *View { + return &View{ + context: "current view", + getView: func() *gocui.View { return self.assert.gui.CurrentContext().GetView() }, + assert: self.assert, + input: self.input, + } +} + +func (self *Views) Main() *View { + return &View{ + context: "main view", + getView: func() *gocui.View { return self.assert.gui.MainView() }, + assert: self.assert, + input: self.input, + } +} + +func (self *Views) Secondary() *View { + return &View{ + context: "secondary view", + getView: func() *gocui.View { return self.assert.gui.SecondaryView() }, + assert: self.assert, + input: self.input, + } +} + +func (self *Views) ByName(viewName string) *View { + return &View{ + context: fmt.Sprintf("%s view", viewName), + getView: func() *gocui.View { return self.assert.gui.View(viewName) }, + assert: self.assert, + input: self.input, + } +} + +type View struct { // context is prepended to any error messages e.g. 'context: "current view"' context string getView func() *gocui.View assert *Assert + input *Input } // asserts that the view has the expected name. This is typically used in tandem with the CurrentView method i.e.; // assert.CurrentView().Name("commits") to assert that the current view is the commits view. -func (self *Views) Name(expected string) *Views { +func (self *View) Name(expected string) *View { self.assert.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) @@ -25,7 +67,7 @@ func (self *Views) Name(expected string) *Views { } // asserts that the view has the expected title -func (self *Views) Title(expected *matcher) *Views { +func (self *View) Title(expected *matcher) *View { self.assert.assertWithRetries(func() (bool, string) { actual := self.getView().Title return expected.context(fmt.Sprintf("%s title", self.context)).test(actual) @@ -38,7 +80,7 @@ func (self *Views) Title(expected *matcher) *Views { // are passed, we only check the first three lines of the 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 *Views) TopLines(matchers ...*matcher) *Views { +func (self *View) TopLines(matchers ...*matcher) *View { self.assert.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)) @@ -49,7 +91,7 @@ func (self *Views) TopLines(matchers ...*matcher) *Views { // 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 *Views) Lines(matchers ...*matcher) *Views { +func (self *View) Lines(matchers ...*matcher) *View { self.assert.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)) @@ -58,7 +100,7 @@ func (self *Views) Lines(matchers ...*matcher) *Views { return self.assertLines(matchers...) } -func (self *Views) assertLines(matchers ...*matcher) *Views { +func (self *View) assertLines(matchers ...*matcher) *View { view := self.getView() for i, matcher := range matchers { @@ -82,7 +124,7 @@ func (self *Views) assertLines(matchers ...*matcher) *Views { } // asserts on the content of the view i.e. the stuff within the view's frame. -func (self *Views) Content(matcher *matcher) *Views { +func (self *View) Content(matcher *matcher) *View { self.assert.matchString(matcher, fmt.Sprintf("%s: Unexpected content.", self.context), func() string { return self.getView().Buffer() @@ -93,7 +135,7 @@ func (self *Views) Content(matcher *matcher) *Views { } // asserts on the selected line of the view -func (self *Views) SelectedLine(matcher *matcher) *Views { +func (self *View) SelectedLine(matcher *matcher) *View { self.assert.matchString(matcher, fmt.Sprintf("%s: Unexpected selected line.", self.context), func() string { return self.getView().SelectedLine() @@ -104,7 +146,7 @@ func (self *Views) SelectedLine(matcher *matcher) *Views { } // asserts on the index of the selected line. 0 is the first index, representing the line at the top of the view. -func (self *Views) SelectedLineIdx(expected int) *Views { +func (self *View) SelectedLineIdx(expected int) *View { self.assert.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) @@ -113,38 +155,29 @@ func (self *Views) SelectedLineIdx(expected int) *Views { return self } -type ViewAsserterGetter struct { - assert *Assert -} +// func (self *View) Focus() *View { +// // we can easily change focus by switching to the view's window, but this assumes that the desired view +// // is at the top of that window. So for now we'll switch to the window then assert that the desired +// // view is on top (i.e. that it's the current view). +// whitelistedViewNames := []string{"status", "files", "localBranches", "commits", "stash"} -func (self *ViewAsserterGetter) Current() *Views { - return &Views{ - context: "current view", - getView: func() *gocui.View { return self.assert.gui.CurrentContext().GetView() }, - assert: self.assert, - } -} +// viewName := self.getView().Name() -func (self *ViewAsserterGetter) Main() *Views { - return &Views{ - context: "main view", - getView: func() *gocui.View { return self.assert.gui.MainView() }, - assert: self.assert, - } -} +// if !lo.Contains(whitelistedViewNames, self.getView().Name()) { +// self.assert.fail(fmt.Sprintf("Cannot focus view %s: Focus() method not implemented", viewName)) +// } -func (self *ViewAsserterGetter) Secondary() *Views { - return &Views{ - context: "secondary view", - getView: func() *gocui.View { return self.assert.gui.SecondaryView() }, - assert: self.assert, - } -} +// windowIndexMap := map[string]int{ +// "status": 0, +// "files": 1, +// "localBranches": 2, +// "commits": 3, +// "stash": 4, +// } -func (self *ViewAsserterGetter) ByName(viewName string) *Views { - return &Views{ - context: fmt.Sprintf("%s view", viewName), - getView: func() *gocui.View { return self.assert.gui.View(viewName) }, - assert: self.assert, - } -} +// self.input.switchToFilesWindow() +// self.press(self.keys.Universal.JumpToBlock[1]) +// self.assert.Views().Current().Name(viewName) + +// return self +// }