From 2614156b2f289a57d14fd26189ffe7a19387668b Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 15 Jun 2026 11:32:24 +0200 Subject: [PATCH] Add an IsActiveTab assertion for integration tests Side panel tabs share a window, so which tab is shown is decided by view z-order rather than the visibility flag (every tab in a window is 'visible'). Tests had no way to assert which tab is actually drawn in front, which is distinct from which view has keyboard focus. Expose the window's top view and add an IsActiveTab assertion built on it. Co-Authored-By: Claude Opus 4.8 (1M context) --- pkg/gui/gui_driver.go | 6 ++++++ pkg/integration/components/test_test.go | 4 ++++ pkg/integration/components/view_driver.go | 22 ++++++++++++++++++++++ pkg/integration/types/types.go | 2 ++ 4 files changed, 34 insertions(+) diff --git a/pkg/gui/gui_driver.go b/pkg/gui/gui_driver.go index 632e271c3..57425231a 100644 --- a/pkg/gui/gui_driver.go +++ b/pkg/gui/gui_driver.go @@ -153,6 +153,12 @@ func (self *GuiDriver) View(viewName string) *gocui.View { return view } +// TopViewInWindow returns the frontmost visible view in the given window, i.e. +// the tab that is currently shown when a window holds several tabbed views. +func (self *GuiDriver) TopViewInWindow(windowName string) *gocui.View { + return self.gui.helpers.Window.TopViewInWindow(windowName, false) +} + func (self *GuiDriver) SetCaption(caption string) { self.gui.setCaption(caption) self.waitTillIdle() diff --git a/pkg/integration/components/test_test.go b/pkg/integration/components/test_test.go index b00a2a672..e7d03ada9 100644 --- a/pkg/integration/components/test_test.go +++ b/pkg/integration/components/test_test.go @@ -75,6 +75,10 @@ func (self *fakeGuiDriver) View(viewName string) *gocui.View { return nil } +func (self *fakeGuiDriver) TopViewInWindow(windowName string) *gocui.View { + return nil +} + func (self *fakeGuiDriver) SetCaption(string) { } diff --git a/pkg/integration/components/view_driver.go b/pkg/integration/components/view_driver.go index e9e5fbbc7..df4b9d7d8 100644 --- a/pkg/integration/components/view_driver.go +++ b/pkg/integration/components/view_driver.go @@ -408,6 +408,28 @@ func (self *ViewDriver) IsFocused() *ViewDriver { return self } +// asserts that the view is the one currently shown in its window, i.e. it's the +// active tab of its panel (drawn in front of the window's other tabs). Unlike +// IsFocused, this is about what's displayed rather than which view has keyboard +// focus; the two can disagree, e.g. if a config reload reshuffles the tabs. +func (self *ViewDriver) IsActiveTab() *ViewDriver { + self.t.assertWithRetries(func() (bool, string) { + expected := self.getView().Name() + context := self.t.gui.ContextForView(expected) + if context == nil { + return false, fmt.Sprintf("%s: Could not find context for view, so can't determine its window", expected) + } + topView := self.t.gui.TopViewInWindow(context.GetWindowName()) + actual := "" + if topView != nil { + actual = topView.Name() + } + return actual == expected, fmt.Sprintf("%s: Expected view to be the active tab of its window, but it was %s", expected, actual) + }) + + return self +} + func (self *ViewDriver) Press(key config.Keybinding) *ViewDriver { self.IsFocused() diff --git a/pkg/integration/types/types.go b/pkg/integration/types/types.go index 3d87e7d6e..cd6102cdf 100644 --- a/pkg/integration/types/types.go +++ b/pkg/integration/types/types.go @@ -44,6 +44,8 @@ type GuiDriver interface { // e.g. when we're showing both staged and unstaged changes SecondaryView() *gocui.View View(viewName string) *gocui.View + // the frontmost visible view in the given window, i.e. the currently shown tab + TopViewInWindow(windowName string) *gocui.View SetCaption(caption string) SetCaptionPrefix(prefix string) // Pop the next toast that was displayed; returns nil if there was none