package editor import ( "regexp" "strings" "testing" "github.com/charmbracelet/lipgloss" ) var ansiRe = regexp.MustCompile("\x1b\\[[0-9;:]*m") func stripANSI(s string) string { return ansiRe.ReplaceAllString(s, "") } const undercurlSGR = "\x1b[4:3m" // curly underline func TestWavySpanEmitsUndercurl(t *testing.T) { sp := []Span{{Text: "teh", Style: lipgloss.NewStyle().Foreground(lipgloss.Color("#CECDC3")), Wavy: true, UnderColor: lipgloss.Color("#D14D41")}} out := renderSpans(sp) if !strings.Contains(out, undercurlSGR) { t.Errorf("wavy span missing undercurl SGR %q in %q", undercurlSGR, out) } // Underline-color SGR: 58:2::R:G:B (D14D41 = 209,77,65). if !strings.Contains(out, "58:2::209:77:65") { t.Errorf("wavy span missing underline-color SGR in %q", out) } if got := stripANSI(out); got != "teh" { t.Errorf("invariant broken: stripped %q != %q", got, "teh") } } func TestNonWavySpanHasNoUndercurl(t *testing.T) { sp := []Span{{Text: "the", Style: lipgloss.NewStyle().Foreground(lipgloss.Color("#CECDC3"))}} out := renderSpans(sp) if strings.Contains(out, undercurlSGR) { t.Errorf("non-wavy span unexpectedly emitted undercurl: %q", out) } if got := stripANSI(out); got != "the" { t.Errorf("stripped %q != %q", got, "the") } } func TestWavySpanCursorRenderKeepsText(t *testing.T) { sp := []Span{{Text: "teh", Style: lipgloss.NewStyle().Foreground(lipgloss.Color("#CECDC3")), Wavy: true, UnderColor: lipgloss.Color("#D14D41")}} cur := lipgloss.NewStyle().Foreground(lipgloss.Color("#100F0F")).Background(lipgloss.Color("#CE5D97")) out := renderSpansCursor(sp, 1, cur) if got := stripANSI(out); got != "teh" { t.Errorf("cursor render invariant broken: stripped %q != %q", got, "teh") } if !strings.Contains(out, undercurlSGR) { t.Errorf("wavy cursor render missing undercurl on non-cursor runes: %q", out) } }