1package util
2
3import (
4 "strings"
5 "testing"
6)
7
8func TestTextWrap(t *testing.T) {
9 cases := []struct {
10 Input, Output string
11 Lim int
12 }{
13 // A simple word passes through.
14 {
15 "foo",
16 "foo",
17 4,
18 },
19 // Word breaking
20 {
21 "foobarbaz",
22 "foob\narba\nz",
23 4,
24 },
25 // Lines are broken at whitespace.
26 {
27 "foo bar baz",
28 "foo\nbar\nbaz",
29 4,
30 },
31 // Word breaking
32 {
33 "foo bars bazzes",
34 "foo\nbars\nbazz\nes",
35 4,
36 },
37 // A word that would run beyond the width is wrapped.
38 {
39 "fo sop",
40 "fo\nsop",
41 4,
42 },
43 // A tab counts as 4 characters.
44 {
45 "foo\nb\t r\n baz",
46 "foo\nb\n r\n baz",
47 4,
48 },
49 // Trailing whitespace is removed after used for wrapping.
50 // Runs of whitespace on which a line is broken are removed.
51 {
52 "foo \nb ar ",
53 "foo\n\nb\nar\n",
54 4,
55 },
56 // An explicit line break at the end of the input is preserved.
57 {
58 "foo bar baz\n",
59 "foo\nbar\nbaz\n",
60 4,
61 },
62 // Explicit break are always preserved.
63 {
64 "\nfoo bar\n\n\nbaz\n",
65 "\nfoo\nbar\n\n\nbaz\n",
66 4,
67 },
68 // Ignore complete words with terminal color sequence
69 {
70 "foo \x1b[31mbar\x1b[0m baz",
71 "foo\n\x1b[31mbar\x1b[0m\nbaz",
72 4,
73 },
74 // Handle words with colors sequence inside the word
75 {
76 "foo b\x1b[31mbar\x1b[0mr baz",
77 "foo\nb\x1b[31mbar\n\x1b[0mr\nbaz",
78 4,
79 },
80 // Break words with colors sequence inside the word
81 {
82 "foo bb\x1b[31mbar\x1b[0mr baz",
83 "foo\nbb\x1b[31mba\nr\x1b[0mr\nbaz",
84 4,
85 },
86 // Complete example:
87 {
88 " This is a list: \n\n\t* foo\n\t* bar\n\n\n\t* baz \nBAM ",
89 " This\nis a\nlist:\n\n\n *\nfoo\n *\nbar\n\n\n *\nbaz\nBAM\n",
90 6,
91 },
92 }
93
94 for i, tc := range cases {
95 actual, lines := TextWrap(tc.Input, tc.Lim)
96 if actual != tc.Output {
97 t.Fatalf("Case %d Input:\n\n`%s`\n\nExpected Output:\n\n`%s`\n\nActual Output:\n\n`%s`",
98 i, tc.Input, tc.Output, actual)
99 }
100
101 expected := len(strings.Split(tc.Output, "\n"))
102 if expected != lines {
103 t.Fatalf("Case %d Nb lines mismatch\nExpected:%d\nActual:%d",
104 i, expected, lines)
105 }
106 }
107}
108
109func TestWordLen(t *testing.T) {
110 cases := []struct {
111 Input string
112 Length int
113 }{
114 // A simple word
115 {
116 "foo",
117 3,
118 },
119 // A simple word with colors
120 {
121 "\x1b[31mbar\x1b[0m",
122 3,
123 },
124 // Handle prefix and suffix properly
125 {
126 "foo\x1b[31mfoobarHoy\x1b[0mbaaar",
127 17,
128 },
129 }
130
131 for i, tc := range cases {
132 l := wordLen(tc.Input)
133 if l != tc.Length {
134 t.Fatalf("Case %d Input:\n\n`%s`\n\nExpected Output:\n\n`%d`\n\nActual Output:\n\n`%d`",
135 i, tc.Input, tc.Length, l)
136 }
137 }
138}
139
140func TestSplitWord(t *testing.T) {
141 cases := []struct {
142 Input string
143 Length int
144 Result, Leftover string
145 }{
146 // A simple word passes through.
147 {
148 "foo",
149 4,
150 "foo", "",
151 },
152 // Cut at the right place
153 {
154 "foobarHoy",
155 4,
156 "foob", "arHoy",
157 },
158 // A simple word passes through with colors
159 {
160 "\x1b[31mbar\x1b[0m",
161 4,
162 "\x1b[31mbar\x1b[0m", "",
163 },
164 // Cut at the right place with colors
165 {
166 "\x1b[31mfoobarHoy\x1b[0m",
167 4,
168 "\x1b[31mfoob", "arHoy\x1b[0m",
169 },
170 // Handle prefix and suffix properly
171 {
172 "foo\x1b[31mfoobarHoy\x1b[0mbaaar",
173 4,
174 "foo\x1b[31mf", "oobarHoy\x1b[0mbaaar",
175 },
176 // Cut properly with length = 0
177 {
178 "foo",
179 0,
180 "", "foo",
181 },
182 }
183
184 for i, tc := range cases {
185 result, leftover := splitWord(tc.Input, tc.Length)
186 if result != tc.Result || leftover != tc.Leftover {
187 t.Fatalf("Case %d Input:\n\n`%s`\n\nExpected Output:\n\n`%s` - `%s`\n\nActual Output:\n\n`%s` - `%s`",
188 i, tc.Input, tc.Result, tc.Leftover, result, leftover)
189 }
190 }
191}