Files
netbird/client/ui/services/windowmanager_test.go
T
Zoltán Papp b1c154dc3d [client] Cover the hidden-window bookkeeping with tests
application.Window carries unexported methods, so the hide/restore paths could
not be faked and the earlier tests could only assert which entries survived a
restore, never which windows were actually shown.

The bookkeeping now goes through hideableWindow, the four methods it needs,
with the window enumeration and the main-window raise behind seams that are nil
in production. That makes the case the owner tag exists for testable end to
end: an install started during SSO login restores only the login popup it hid,
and leaves the main window hidden until the login popup itself closes.
2026-09-15 14:55:14 +02:00

172 lines
4.8 KiB
Go

//go:build !android && !ios && !freebsd && !js
package services
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/wailsapp/wails/v3/pkg/application"
)
type fakeWindow struct {
name string
visible bool
shown int
hidden int
}
func newFakeWindow(name string) *fakeWindow {
return &fakeWindow{name: name, visible: true}
}
func (f *fakeWindow) Show() application.Window {
f.visible = true
f.shown++
return nil
}
func (f *fakeWindow) Hide() application.Window {
f.visible = false
f.hidden++
return nil
}
func (f *fakeWindow) IsVisible() bool { return f.visible }
func (f *fakeWindow) Name() string { return f.name }
func newTestWindowManager(windows ...*fakeWindow) (*WindowManager, *int) {
raised := 0
s := &WindowManager{
generation: map[string]uint64{},
allWindows: func() []hideableWindow {
all := make([]hideableWindow, 0, len(windows))
for _, w := range windows {
all = append(all, w)
}
return all
},
raiseMain: func() { raised++ },
}
return s, &raised
}
func ownersOf(hidden []hiddenWindow) []string {
owners := make([]string, 0, len(hidden))
for _, h := range hidden {
owners = append(owners, h.owner)
}
return owners
}
func TestHideOtherWindowsLockedSkipsKeepNameAndInvisible(t *testing.T) {
main := newFakeWindow("main")
settings := newFakeWindow("settings")
settings.visible = false
popup := newFakeWindow("browser-login")
s, _ := newTestWindowManager(main, settings, popup)
s.hideOtherWindowsLocked("browser-login")
assert.False(t, main.visible)
assert.Equal(t, 1, main.hidden)
assert.Equal(t, 0, settings.hidden, "an already hidden window must not be recorded")
assert.Equal(t, 0, popup.hidden, "the popup itself must stay visible")
assert.Equal(t, []string{"browser-login"}, ownersOf(s.hiddenWindows))
}
func TestInstallDuringLoginKeepsMainHiddenUntilLoginCloses(t *testing.T) {
main := newFakeWindow("main")
login := newFakeWindow("browser-login")
install := newFakeWindow("install-progress")
s, raised := newTestWindowManager(main, login, install)
s.hideOtherWindowsLocked("browser-login")
require.False(t, main.visible)
require.False(t, install.visible)
install.visible = true
s.hideOtherWindowsLocked("install-progress")
assert.False(t, login.visible, "the login popup is hidden by the install popup")
s.restoreHiddenWindowsLocked("install-progress")
assert.True(t, login.visible, "the install popup restores the login popup it hid")
assert.False(t, main.visible, "the main window stays hidden for the login popup")
assert.Equal(t, 0, *raised)
assert.Equal(t, []string{"browser-login", "browser-login"}, ownersOf(s.hiddenWindows))
s.restoreHiddenWindowsLocked("browser-login")
assert.True(t, main.visible)
assert.Equal(t, 1, *raised, "restoring the main window raises it above the SSO browser")
assert.Empty(t, s.hiddenWindows)
}
func TestRestoreHiddenWindowsLockedUnknownOwnerKeepsEverything(t *testing.T) {
main := newFakeWindow("main")
s, raised := newTestWindowManager(main)
s.hideOtherWindowsLocked("browser-login")
s.restoreHiddenWindowsLocked("welcome")
assert.False(t, main.visible)
assert.Equal(t, []string{"browser-login"}, ownersOf(s.hiddenWindows))
assert.Equal(t, 0, *raised)
}
func TestRestoreHiddenWindowsLockedWithoutMainDoesNotRaise(t *testing.T) {
settings := newFakeWindow("settings")
s, raised := newTestWindowManager(settings)
s.hideOtherWindowsLocked("browser-login")
s.restoreHiddenWindowsLocked("browser-login")
assert.True(t, settings.visible)
assert.Equal(t, 0, *raised)
}
func TestRestoreHiddenWindowsLockedEmptyIsNoop(t *testing.T) {
s, _ := newTestWindowManager()
require.NotPanics(t, func() { s.restoreHiddenWindowsLocked("browser-login") })
assert.Empty(t, s.hiddenWindows)
}
func TestStampGenerationTracksLatestPerWindow(t *testing.T) {
s, _ := newTestWindowManager()
first := s.stampGeneration("browser-login", "/#/dialog/browser-login")
assert.Equal(t, "/#/dialog/browser-login?gen=1", first)
assert.True(t, s.matchesGeneration("browser-login", 1))
second := s.stampGeneration("browser-login", "/#/dialog/browser-login?uri=x")
assert.Equal(t, "/#/dialog/browser-login?uri=x&gen=2", second)
assert.False(t, s.matchesGeneration("browser-login", 1))
assert.True(t, s.matchesGeneration("browser-login", 2))
}
func TestMatchesGenerationUntrackedWindowAccepts(t *testing.T) {
s, _ := newTestWindowManager()
assert.True(t, s.matchesGeneration("main", 0))
}
func TestPaintedGeneration(t *testing.T) {
tests := []struct {
name string
data any
want uint64
}{
{"string", "7", 7},
{"float", float64(7), 7},
{"slice", []any{"7"}, 7},
{"empty slice", []any{}, 0},
{"unparsable", "abc", 0},
{"nil", nil, 0},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.want, paintedGeneration(tc.data))
})
}
}