TestWidthChangeSuppressesView: any width change (narrow OR widen) flips suppressView so nothing commits between SIGWINCH and the settle. View() returns "" while suppressed; bubbletea expands that to one blank row + EraseScreenBelow, leaving nothing for soft-wrap reflow to orphan. The streaming buffe
(t *testing.T)
| 58 | // EraseScreenBelow, leaving nothing for soft-wrap reflow to orphan. The |
| 59 | // streaming buffer survives (re-wrapped on resume). |
| 60 | func TestWidthChangeSuppressesView(t *testing.T) { |
| 61 | cfg, _, _ := config.Bootstrap(t.TempDir()) |
| 62 | m := New(cfg, llm.New("http://x", cfg.ActiveProfile().LLM, ""), t.TempDir(), "test") |
| 63 | var mm tea.Model = m |
| 64 | |
| 65 | mm, _ = mm.Update(tea.WindowSizeMsg{Width: 80, Height: 24}) |
| 66 | |
| 67 | mx := mm.(Model) |
| 68 | mx.streaming.WriteString("partial reply line one\nline two\nline three\n") |
| 69 | mx.phase = phaseStreaming |
| 70 | mm = mx |
| 71 | |
| 72 | for _, next := range []int{60, 100} { // narrow then widen, both must suppress |
| 73 | mm2, cmd := mm.Update(tea.WindowSizeMsg{Width: next, Height: 24}) |
| 74 | nm := mm2.(Model) |
| 75 | |
| 76 | if !nm.suppressView { |
| 77 | t.Errorf("width change to %d must enable suppressView", next) |
| 78 | } |
| 79 | if got := nm.View(); got != "" { |
| 80 | t.Errorf("View() must return \"\" while suppressed (width=%d), got %q", next, got) |
| 81 | } |
| 82 | if nm.streaming.Len() == 0 { |
| 83 | t.Errorf("streaming buffer must survive width change to %d", next) |
| 84 | } |
| 85 | if cmd == nil { |
| 86 | t.Errorf("width change to %d must schedule a settle tick, got nil cmd", next) |
| 87 | } |
| 88 | mm = nm |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | // TestResizeSettleReplaysScrollbackAtNewWidth: a matching settle returns a |
| 93 | // tea.Sequence that wipes viewport + scrollback and re-emits splash and the |