diff --git a/internal/cli/app_internal_test.go b/internal/cli/app_internal_test.go index 6c5853b..11ddd9a 100644 --- a/internal/cli/app_internal_test.go +++ b/internal/cli/app_internal_test.go @@ -362,7 +362,8 @@ func TestLinesKeepOrder(t *testing.T) { // TestStartUp runs the client's start-up path on a simulation // screen. It fails unless the event loop starts and the status // window gets two lines: first the one that holds "Welcome to -// neoirc-cli", then the /connect hint. +// neoirc-cli", then the /connect hint. The status bar must show +// [disconnected]. func TestStartUp(t *testing.T) { t.Parallel() @@ -429,6 +430,77 @@ func TestStartUp(t *testing.T) { if !strings.Contains(lines[1], "/connect ") { t.Errorf("second status line is %q, want the /connect hint", lines[1]) } + + // run sets the status bar before it adds the welcome lines. + status := statusBarText(ui) + if !strings.Contains(status, "[disconnected]") { + t.Errorf("status bar is %q, want it to show [disconnected]", status) + } +} + +// TestStatusBar checks that the status bar shows [connected], and +// shows a nick, target or window name with square brackets as it +// is. +func TestStatusBar(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + nick string + target string + unread string + want string + }{ + { + name: "plain names", + nick: testNick, + target: testChannel, + unread: testOtherNick, + want: " [connected] erin [1:#chan] #chan [Act: 2:bob(1)]", + }, + { + name: "nicks with brackets", + nick: "erin[away]", + target: "bob[m]", + unread: "dave[afk]", + want: " [connected] erin[away] [1:bob[m]] bob[m] [Act: 2:dave[afk](1)]", + }, + { + name: "nicks with brackets and symbols", + nick: "bob[|[]", + target: "x[^[]", + unread: testOtherNick, + want: " [connected] bob[|[] [1:x[^[]] x[^[] [Act: 2:bob(1)]", + }, + { + // /query takes any text as the target. + name: "query target with brackets", + nick: testNick, + target: "[:::y|z]", + unread: testOtherNick, + want: " [connected] erin [1:[:::y|z]] [:::y|z] [Act: 2:bob(1)]", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + ui := NewUI() + runUI(t, ui) + + // Window 1, the one shown, is the target's. Window 2 + // gets one unread line. + ui.SwitchToBuffer(test.target) + ui.AddLine(test.unread, testText) + ui.SetStatus(test.nick, test.target, "connected") + + got := statusBarText(ui) + if got != test.want { + t.Fatalf("status bar is %q, want %q", got, test.want) + } + }) + } } // TestOwnEventFromOtherClient checks that a message, notice, @@ -513,6 +585,19 @@ func bufferState(ui *UI, name string) (int, int) { return lines, unread } +// statusBarText returns the text the status bar shows. +// GetText(true) leaves out whatever tview reads as a tag, as +// drawing does. +func statusBarText(ui *UI) string { + var text string + + ui.app.QueueUpdate(func() { + text = ui.statusBar.GetText(true) + }) + + return text +} + // handledLines makes app.ui pass each typed line to // app.handleInput, as Run does, and returns a channel that // receives each line once it has been handled. diff --git a/internal/cli/ui.go b/internal/cli/ui.go index 563df0d..f702a8d 100644 --- a/internal/cli/ui.go +++ b/internal/cli/ui.go @@ -226,8 +226,10 @@ func (ui *UI) initMessages() { } func (ui *UI) initStatusBar() { - ui.statusBar = tview.NewTextView(). - SetDynamicColors(true) + // Colour tags stay off. With them on, tview reads text in + // square brackets, such as "[connected]" or part of a nick, + // as a tag and drops it. + ui.statusBar = tview.NewTextView() ui.statusBar.SetBackgroundColor(tcell.ColorNavy) ui.statusBar.SetTextColor(tcell.ColorWhite) }