text_test.go

  1package text
  2
  3import (
  4	"strings"
  5	"testing"
  6)
  7
  8func TestWrap(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		// Handle chinese
 93		{
 94			"婞一枳郲逴靲屮蜧曀殳,掫乇峔掮傎溒兀緉冘仜。",
 95			"婞一枳郲逴靲屮蜧曀殳,掫\n乇峔掮傎溒兀緉冘仜。",
 96			12,
 97		},
 98		// Handle chinese with colors
 99		{
100			"婞一枳郲逴\x1b[31m靲屮蜧曀殳,掫乇峔掮傎溒\x1b[0m兀緉冘仜。",
101			"婞一枳郲逴\x1b[31m靲屮蜧曀殳,掫\n乇峔掮傎溒\x1b[0m兀緉冘仜。",
102			12,
103		},
104	}
105
106	for i, tc := range cases {
107		actual, lines := Wrap(tc.Input, tc.Lim)
108		if actual != tc.Output {
109			t.Fatalf("Case %d Input:\n\n`%s`\n\nExpected Output:\n\n`%s`\n\nActual Output:\n`\n%s`",
110				i, tc.Input, tc.Output, actual)
111		}
112
113		expected := len(strings.Split(tc.Output, "\n"))
114		if expected != lines {
115			t.Fatalf("Case %d Nb lines mismatch\nExpected:%d\nActual:%d",
116				i, expected, lines)
117		}
118	}
119}
120
121func TestWrapLeftPadded(t *testing.T) {
122	cases := []struct {
123		input, output string
124		lim, pad      int
125	}{
126		{
127			"The Lorem ipsum text is typically composed of pseudo-Latin words. It is commonly used as placeholder text to examine or demonstrate the visual effects of various graphic design.",
128			`    The Lorem ipsum text is typically composed of
129		pseudo-Latin words. It is commonly used as placeholder
130		text to examine or demonstrate the visual effects of
131		various graphic design.`,
132			59, 4,
133		},
134	}
135
136	for i, tc := range cases {
137		actual, lines := WrapLeftPadded(tc.input, tc.lim, tc.pad)
138		if actual != tc.output {
139			t.Fatalf("Case %d Input:\n\n`%s`\n\nExpected Output:\n`\n%s`\n\nActual Output:\n`\n%s\n%s`",
140				i, tc.input, tc.output,
141				"|"+strings.Repeat("-", tc.lim-2)+"|",
142				actual)
143		}
144
145		expected := len(strings.Split(tc.output, "\n"))
146		if expected != lines {
147			t.Fatalf("Case %d Nb lines mismatch\nExpected:%d\nActual:%d",
148				i, expected, lines)
149		}
150	}
151}
152
153func TestWordLen(t *testing.T) {
154	cases := []struct {
155		Input  string
156		Length int
157	}{
158		// A simple word
159		{
160			"foo",
161			3,
162		},
163		// A simple word with colors
164		{
165			"\x1b[31mbar\x1b[0m",
166			3,
167		},
168		// Handle prefix and suffix properly
169		{
170			"foo\x1b[31mfoobarHoy\x1b[0mbaaar",
171			17,
172		},
173		// Handle chinese
174		{
175			"快檢什麼望對",
176			6,
177		},
178		// Handle chinese with colors
179		{
180			"快\x1b[31m檢什麼\x1b[0m望對",
181			6,
182		},
183	}
184
185	for i, tc := range cases {
186		l := wordLen(tc.Input)
187		if l != tc.Length {
188			t.Fatalf("Case %d Input:\n\n`%s`\n\nExpected Output:\n\n`%d`\n\nActual Output:\n\n`%d`",
189				i, tc.Input, tc.Length, l)
190		}
191	}
192}
193
194func TestSplitWord(t *testing.T) {
195	cases := []struct {
196		Input            string
197		Length           int
198		Result, Leftover string
199	}{
200		// A simple word passes through.
201		{
202			"foo",
203			4,
204			"foo", "",
205		},
206		// Cut at the right place
207		{
208			"foobarHoy",
209			4,
210			"foob", "arHoy",
211		},
212		// A simple word passes through with colors
213		{
214			"\x1b[31mbar\x1b[0m",
215			4,
216			"\x1b[31mbar\x1b[0m", "",
217		},
218		// Cut at the right place with colors
219		{
220			"\x1b[31mfoobarHoy\x1b[0m",
221			4,
222			"\x1b[31mfoob", "arHoy\x1b[0m",
223		},
224		// Handle prefix and suffix properly
225		{
226			"foo\x1b[31mfoobarHoy\x1b[0mbaaar",
227			4,
228			"foo\x1b[31mf", "oobarHoy\x1b[0mbaaar",
229		},
230		// Cut properly with length = 0
231		{
232			"foo",
233			0,
234			"", "foo",
235		},
236		// Handle chinese
237		{
238			"快檢什麼望對",
239			2,
240			"快檢", "什麼望對",
241		},
242		// Handle chinese with colors
243		{
244			"快\x1b[31m檢什麼\x1b[0m望對",
245			2,
246			"快\x1b[31m檢", "什麼\x1b[0m望對",
247		},
248	}
249
250	for i, tc := range cases {
251		result, leftover := splitWord(tc.Input, tc.Length)
252		if result != tc.Result || leftover != tc.Leftover {
253			t.Fatalf("Case %d Input:\n\n`%s`\n\nExpected Output:\n\n`%s` - `%s`\n\nActual Output:\n\n`%s` - `%s`",
254				i, tc.Input, tc.Result, tc.Leftover, result, leftover)
255		}
256	}
257}