1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
package ansi
import (
"testing"
)
var cases = []struct {
name string
input string
stripped string
width int
}{
{"empty", "", "", 0},
{"ascii", "hello", "hello", 5},
{"emoji", "๐", "๐", 2},
{"wideemoji", "๐ซง", "๐ซง", 2},
{"combining", "a\u0300", "aฬ", 1},
{"control", "\x1b[31mhello\x1b[0m", "hello", 5},
{"csi8", "\x9b38;5;1mhello\x9bm", "hello", 5},
{"osc", "\x9d2;charmbracelet: ~/Source/bubbletea\x9c", "", 0},
{"controlemoji", "\x1b[31m๐\x1b[0m", "๐", 2},
{"oscwideemoji", "\x1b]2;title๐จโ๐ฉโ๐ฆ\x07", "", 0},
{"oscwideemoji", "\x1b[31m๐จโ๐ฉโ๐ฆ\x1b[m", "๐จ\u200d๐ฉ\u200d๐ฆ", 2},
{"multiemojicsi", "๐จโ๐ฉโ๐ฆ\x9b38;5;1mhello\x9bm", "๐จโ๐ฉโ๐ฆhello", 7},
{"osc8eastasianlink", "\x9d8;id=1;https://example.com/\x9cๆ่ฑ่ฑ\x9d8;id=1;\x07", "ๆ่ฑ่ฑ", 6},
{"dcsarabic", "\x1bP?123$pุณูุงู
\x1b\\ุงููุง", "ุงููุง", 4},
{"newline", "hello\nworld", "hello\nworld", 10},
{"tab", "hello\tworld", "hello\tworld", 10},
{"controlnewline", "\x1b[31mhello\x1b[0m\nworld", "hello\nworld", 10},
{"style", "\x1B[38;2;249;38;114mfoo", "foo", 3},
{"unicode", "\x1b[35mโboxโ\x1b[0m", "โboxโ", 5},
{"just_unicode", "Claireโs Boutique", "Claireโs Boutique", 17},
{"unclosed_ansi", "Hey, \x1b[7m\n็ด", "Hey, \n็ด", 7},
}
func TestStrip(t *testing.T) {
for i, c := range cases {
t.Run(c.name, func(t *testing.T) {
if res := Strip(c.input); res != c.stripped {
t.Errorf("test case %d (%s) failed:\nexpected %q, got %q", i, c.name, c.stripped, res)
}
})
}
}
func TestStringWidth(t *testing.T) {
for i, c := range cases {
t.Run(c.name, func(t *testing.T) {
if width := StringWidth(c.input); width != c.width {
t.Errorf("test case %d failed: expected %d, got %d", i+1, c.width, width)
}
})
}
}
func BenchmarkStringWidth(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
b.ReportAllocs()
b.ResetTimer()
for pb.Next() {
StringWidth("foo")
}
})
}
|