1package tui
2
3import (
4 "strings"
5 "testing"
6
7 "github.com/bnema/zut/packages/provider"
8)
9
10func userMsg(text string) provider.Message {
11 return provider.Message{
12 Role: provider.RoleUser,
13 Content: []provider.Content{provider.TextBlock{Text: text}},
14 }
15}
16
17// userBubbleRows counts the rows that carry the user gutter bar "▌".
18func userBubbleRows(plain string) int {
19 n := 0
20 for _, l := range strings.Split(plain, "\n") {
21 if strings.Contains(l, "▌") {
22 n++
23 }
24 }
25 return n
26}
27
28// A one-line prompt is a 3-row bubble by default (blank pad, text,
29// blank pad); compact mode collapses it to a single text row.
30func TestCompactUserDropsPaddingRows(t *testing.T) {
31 bubble := View{Theme: Dark, Messages: []provider.Message{userMsg("hello")}}
32 bubblePlain := stripANSI(strings.Join(bubble.Build(80), "\n"))
33 if got := userBubbleRows(bubblePlain); got != 3 {
34 t.Fatalf("default bubble should be 3 gutter rows (pad+text+pad), got %d:\n%s", got, bubblePlain)
35 }
36
37 compact := View{Theme: Dark, CompactUser: true, Messages: []provider.Message{userMsg("hello")}}
38 compactPlain := stripANSI(strings.Join(compact.Build(80), "\n"))
39 if got := userBubbleRows(compactPlain); got != 1 {
40 t.Fatalf("compact user should be a single gutter row, got %d:\n%s", got, compactPlain)
41 }
42 if !strings.Contains(compactPlain, "▌ hello") {
43 t.Fatalf("compact user lost the gutter or text:\n%s", compactPlain)
44 }
45}
46
47// Compact mode must never paint the bubble background tint. The tint
48// is an SGR background sequence (ESC[48;...m); the compact path uses
49// only a foreground-colored gutter, so no 48; should appear on the
50// user rows.
51func TestCompactUserHasNoBackgroundTint(t *testing.T) {
52 compact := View{Theme: Dark, CompactUser: true, Messages: []provider.Message{userMsg("hi there")}}
53 raw := strings.Join(compact.Build(80), "\n")
54 if strings.Contains(raw, "[48;") {
55 t.Fatalf("compact user should not paint a background tint:\n%q", raw)
56 }
57
58 // The default bubble does tint, so this is a meaningful assertion.
59 bubble := View{Theme: Dark, Messages: []provider.Message{userMsg("hi there")}}
60 if rawB := strings.Join(bubble.Build(80), "\n"); !strings.Contains(rawB, "[48;") {
61 t.Fatalf("default bubble was expected to paint a background tint:\n%q", rawB)
62 }
63}
64
65// Multi-line prompts keep every wrapped row in compact mode, just
66// without the surrounding padding rows.
67func TestCompactUserKeepsAllWrappedRows(t *testing.T) {
68 long := strings.Repeat("word ", 60) // forces several wrapped rows
69 compact := View{Theme: Dark, CompactUser: true, Messages: []provider.Message{userMsg(long)}}
70 plain := stripANSI(strings.Join(compact.Build(40), "\n"))
71 rows := userBubbleRows(plain)
72 if rows < 3 {
73 t.Fatalf("expected multiple wrapped gutter rows, got %d:\n%s", rows, plain)
74 }
75 // No empty gutter rows (that would be leftover padding).
76 for _, l := range strings.Split(plain, "\n") {
77 if strings.TrimSpace(strings.TrimPrefix(strings.TrimSpace(l), "▌")) == "" && strings.Contains(l, "▌") {
78 t.Fatalf("compact user emitted an empty padding row:\n%s", plain)
79 }
80 }
81}