package text import ( "testing" "time" "github.com/stretchr/testify/assert" ) func TestRelativeTimeAgo(t *testing.T) { const form = "2006-Jan-02 15:04:05" now, _ := time.Parse(form, "2020-Nov-22 14:00:00") cases := map[string]string{ "2020-Nov-22 14:00:00": "less than a minute ago", "2020-Nov-22 13:59:30": "less than a minute ago", "2020-Nov-22 13:59:00": "about 1 minute ago", "2020-Nov-22 13:30:00": "about 30 minutes ago", "2020-Nov-22 13:00:00": "about 1 hour ago", "2020-Nov-22 02:00:00": "about 12 hours ago", "2020-Nov-21 14:00:00": "about 1 day ago", "2020-Nov-07 14:00:00": "about 15 days ago", "2020-Oct-24 14:00:00": "about 29 days ago", "2020-Oct-23 14:00:00": "about 1 month ago", "2020-Sep-23 14:00:00": "about 2 months ago", "2019-Nov-22 14:00:00": "about 1 year ago", "2018-Nov-22 14:00:00": "about 2 years ago", } for createdAt, expected := range cases { d, err := time.Parse(form, createdAt) assert.NoError(t, err) relative := RelativeTimeAgo(now, d) assert.Equal(t, expected, relative) } } func TestTruncate(t *testing.T) { type args struct { max int s string } tests := []struct { name string args args want string }{ { name: "empty", args: args{ s: "", max: 10, }, want: "", }, { name: "short", args: args{ s: "hello", max: 3, }, want: "hel", }, { name: "long", args: args{ s: "hello world", max: 5, }, want: "he...", }, { name: "no truncate", args: args{ s: "hello world", max: 11, }, want: "hello world", }, { name: "Short enough", args: args{ max: 5, s: "short", }, want: "short", }, { name: "Too short", args: args{ max: 4, s: "short", }, want: "shor", }, { name: "Japanese", args: args{ max: 11, s: "テストテストテストテスト", }, want: "テストテ...", }, { name: "Japanese filled", args: args{ max: 11, s: "aテストテストテストテスト", }, want: "aテスト... ", }, { name: "Chinese", args: args{ max: 11, s: "幫新舉報違章工廠新增編號", }, want: "幫新舉報...", }, { name: "Chinese filled", args: args{ max: 11, s: "a幫新舉報違章工廠新增編號", }, want: "a幫新舉... ", }, { name: "Korean", args: args{ max: 11, s: "프로젝트 내의", }, want: "프로젝트...", }, { name: "Korean filled", args: args{ max: 11, s: "a프로젝트 내의", }, want: "a프로젝... ", }, { name: "Emoji", args: args{ max: 11, s: "💡💡💡💡💡💡💡💡💡💡💡💡", }, want: "💡💡💡💡...", }, { name: "Accented characters", args: args{ max: 11, s: "é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́", }, want: "é́́é́́é́́é́́é́́é́́é́́é́́...", }, { name: "Red accented characters", args: args{ max: 11, s: "\x1b[0;31mé́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́\x1b[0m", }, want: "\x1b[0;31mé́́é́́é́́é́́é́́é́́é́́é́́...\x1b[0m", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := Truncate(tt.args.max, tt.args.s) assert.Equal(t, tt.want, got) }) } } func TestPadRight(t *testing.T) { type args struct { max int s string } tests := []struct { name string args args want string }{ { name: "empty", args: args{ s: "", max: 5, }, want: " ", }, { name: "short", args: args{ s: "hello", max: 7, }, want: "hello ", }, { name: "long", args: args{ s: "hello world", max: 5, }, want: "hello world", }, { name: "exact", args: args{ s: "hello world", max: 11, }, want: "hello world", }, { name: "Japanese", args: args{ s: "テストテスト", max: 13, }, want: "テストテスト ", }, { name: "Japanese filled", args: args{ s: "aテスト", max: 9, }, want: "aテスト ", }, { name: "Chinese", args: args{ s: "幫新舉報違章工廠新增編號", max: 26, }, want: "幫新舉報違章工廠新增編號 ", }, { name: "Chinese filled", args: args{ s: "a幫新舉報違章工廠新增編號", max: 26, }, want: "a幫新舉報違章工廠新增編號 ", }, { name: "Korean", args: args{ s: "프로젝트 내의", max: 15, }, want: "프로젝트 내의 ", }, { name: "Korean filled", args: args{ s: "a프로젝트 내의", max: 15, }, want: "a프로젝트 내의 ", }, { name: "Emoji", args: args{ s: "💡💡💡💡", max: 10, }, want: "💡💡💡💡 ", }, { name: "Accented characters", args: args{ s: "é́́é́́é́́é́́é́́", max: 7, }, want: "é́́é́́é́́é́́é́́ ", }, { name: "Red accented characters", args: args{ s: "\x1b[0;31mé́́é́́é́́é́́é́́\x1b[0m", max: 7, }, want: "\x1b[0;31mé́́é́́é́́é́́é́́\x1b[0m ", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := PadRight(tt.args.max, tt.args.s) assert.Equal(t, tt.want, got) }) } } func TestDisplayWidth(t *testing.T) { tests := []struct { name string text string want int }{ { name: "check mark", text: `✓`, want: 1, }, { name: "bullet icon", text: `•`, want: 1, }, { name: "middle dot", text: `·`, want: 1, }, { name: "ellipsis", text: `…`, want: 1, }, { name: "right arrow", text: `→`, want: 1, }, { name: "smart double quotes", text: `“”`, want: 2, }, { name: "smart single quotes", text: `‘’`, want: 2, }, { name: "em dash", text: `—`, want: 1, }, { name: "en dash", text: `–`, want: 1, }, { name: "emoji", text: `👍`, want: 2, }, { name: "multi-byte emoji", text: `👨‍💻`, want: 2, }, { name: "accent character", text: `é́́`, want: 1, }, { name: "color codes", text: "\x1b[0;31mred\x1b[0m", want: 3, }, { name: "empty", text: "", want: 0, }, { name: "Latin", text: "hello world 123$#!", want: 18, }, { name: "Asian", text: "つのだ☆HIRO", want: 11, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := DisplayWidth(tt.text) assert.Equal(t, tt.want, got) }) } } func TestIndent(t *testing.T) { type args struct { s string indent string } tests := []struct { name string args args want string }{ { name: "empty", args: args{ s: "", indent: "--", }, want: "", }, { name: "blank", args: args{ s: "\n", indent: "--", }, want: "\n", }, { name: "indent", args: args{ s: "one\ntwo\nthree", indent: "--", }, want: "--one\n--two\n--three", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := Indent(tt.args.s, tt.args.indent) assert.Equal(t, tt.want, got) }) } } func TestRemoveDiacritics(t *testing.T) { tests := [][]string{ // no diacritics {"e", "e"}, {"و", "و"}, {"И", "И"}, {"ж", "ж"}, {"私", "私"}, {"万", "万"}, // diacritics test sets {"à", "a"}, {"é", "e"}, {"è", "e"}, {"ô", "o"}, {"ᾳ", "α"}, {"εͅ", "ε"}, {"ῃ", "η"}, {"ιͅ", "ι"}, {"ؤ", "و"}, {"ā", "a"}, {"č", "c"}, {"ģ", "g"}, {"ķ", "k"}, {"ņ", "n"}, {"š", "s"}, {"ž", "z"}, {"ŵ", "w"}, {"ŷ", "y"}, {"ä", "a"}, {"ÿ", "y"}, {"á", "a"}, {"ẁ", "w"}, {"ỳ", "y"}, {"ō", "o"}, // full words {"Miķelis", "Mikelis"}, {"François", "Francois"}, {"žluťoučký", "zlutoucky"}, {"învățătorița", "invatatorita"}, {"Kękę przy łóżku", "Keke przy łozku"}, } for _, tt := range tests { t.Run(RemoveDiacritics(tt[0]), func(t *testing.T) { assert.Equal(t, tt[1], RemoveDiacritics(tt[0])) }) } }