fix(bonfire): keep a blank line printed during a live view (IN-11, quick-261028-rqd)

This commit is contained in:
Jakub Zych
2026-10-28 20:34:35 +01:00
parent 795c4f6b29
commit 4d75695582
3 changed files with 41 additions and 1 deletions

View File

@@ -539,8 +539,15 @@ func printAbove(owner *console, s string) bool {
return false
default:
}
block := strings.TrimSuffix(s, "\n")
if block == "" && s != "" {
// A blank line (Println()): bubbletea v2.1.0's insertAbove
// returns early for an empty string, which would drop it, so
// send a single space, which prints as a blank line.
block = " "
}
// One message for the whole block, sent while holding liveMu: blocks
// from different goroutines keep the order of their calls.
v.prog.Send(printLine(strings.TrimSuffix(s, "\n")))
v.prog.Send(printLine(block))
return true
}

View File

@@ -8,6 +8,7 @@ import (
"io"
"os"
"regexp"
"slices"
"strings"
"sync"
"testing"
@@ -712,3 +713,33 @@ func TestPrintAboveAfterCancel(t *testing.T) {
t.Error("a view is still registered after Process returned")
}
}
// insertedLine matches one line bubbletea v2 inserts above the view:
// insert line (CSI L), the text, erase to the end of the line (CSI K).
var insertedLine = regexp.MustCompile(`\x1b\[L(.*?)\x1b\[K`)
// TestPrintAboveBlankLine (IN-11): a blank line printed during a live view
// (out.Println()) prints a blank line above the view instead of being
// dropped. bubbletea writes each line above the view as an inserted line,
// so the test reads those insertions from the raw output: stripping the
// escape sequences would also drop the cursor movement and show a blank
// line that the terminal never gets.
func TestPrintAboveBlankLine(t *testing.T) {
out := &lockedBuffer{}
c := newConsole(strings.NewReader(""), out, io.Discard, noEnv, boolPtr(true), boolPtr(true))
if err := c.Spinner("working", func() error {
c.Println("before-blank")
c.Println()
c.Println("after-blank")
return nil
}); err != nil {
t.Fatal(err)
}
var lines []string
for _, m := range insertedLine.FindAllStringSubmatch(out.String(), -1) {
lines = append(lines, strings.TrimSpace(ansi.Strip(m[1])))
}
if want := []string{"before-blank", "", "after-blank"}; !slices.Equal(lines, want) {
t.Errorf("lines inserted above the view = %q, want %q\nraw: %q", lines, want, out.String())
}
}

View File

@@ -134,6 +134,8 @@ BONFIRE_TESTS=(
# quick 261028-rqd (info findings): IN-03, IN-06, IN-02, IN-04.
TestPluginErrorWordedUnknownCommand TestExecuteKeepsRootHelp
TestErrorBlockUsesParsedGlobals TestFlagBool
# quick 261028-rqd: IN-11.
TestPrintAboveBlankLine
)
DOCSITE_TESTS=(
# Plan 04: the docs checker reads past the global options.