1 package table
2
3 import (
4 "fmt"
5 "testing"
6
7 "github.com/jedib0t/go-pretty/v6/text"
8 "github.com/stretchr/testify/assert"
9 )
10
11 func TestTable_RenderHTML(t *testing.T) {
12 tw := NewWriter()
13 tw.AppendHeader(testHeader)
14 tw.AppendRows(testRows)
15 tw.AppendRow(testRowMultiLine)
16 tw.AppendFooter(testFooter)
17 tw.SetColumnConfigs([]ColumnConfig{
18 {Name: "Salary", VAlign: text.VAlignBottom},
19 {Number: 5, VAlign: text.VAlignBottom},
20 })
21 tw.SetTitle(testTitle1)
22 tw.SetCaption(testCaption)
23 tw.Style().Title = TitleOptions{
24 Align: text.AlignLeft,
25 Colors: text.Colors{text.BgBlack, text.Bold, text.FgHiBlue},
26 Format: text.FormatTitle,
27 }
28
29 compareOutput(t, tw.RenderHTML(), `<table class="go-pretty-table">
30 <caption class="title" align="left" class="bg-black bold fg-hi-blue">Game Of Thrones</caption>
31 <thead>
32 <tr>
33 <th align="right">#</th>
34 <th>First Name</th>
35 <th>Last Name</th>
36 <th align="right">Salary</th>
37 <th> </th>
38 </tr>
39 </thead>
40 <tbody>
41 <tr>
42 <td align="right">1</td>
43 <td>Arya</td>
44 <td>Stark</td>
45 <td align="right" valign="bottom">3000</td>
46 <td valign="bottom"> </td>
47 </tr>
48 <tr>
49 <td align="right">20</td>
50 <td>Jon</td>
51 <td>Snow</td>
52 <td align="right" valign="bottom">2000</td>
53 <td valign="bottom">You know nothing, Jon Snow!</td>
54 </tr>
55 <tr>
56 <td align="right">300</td>
57 <td>Tyrion</td>
58 <td>Lannister</td>
59 <td align="right" valign="bottom">5000</td>
60 <td valign="bottom"> </td>
61 </tr>
62 <tr>
63 <td align="right">0</td>
64 <td>Winter</td>
65 <td>Is</td>
66 <td align="right" valign="bottom">0</td>
67 <td valign="bottom">Coming.<br/>The North Remembers!<br/>This is known.</td>
68 </tr>
69 </tbody>
70 <tfoot>
71 <tr>
72 <td align="right"> </td>
73 <td> </td>
74 <td>Total</td>
75 <td align="right">10000</td>
76 <td> </td>
77 </tr>
78 </tfoot>
79 <caption class="caption" style="caption-side: bottom;">A Song of Ice and Fire</caption>
80 </table>`)
81 }
82
83 func TestTable_RenderHTML_AutoIndex(t *testing.T) {
84 tw := NewWriter()
85 for rowIdx := 0; rowIdx < 3; rowIdx++ {
86 row := make(Row, 3)
87 for colIdx := 0; colIdx < 3; colIdx++ {
88 row[colIdx] = fmt.Sprintf("%s%d", AutoIndexColumnID(colIdx), rowIdx+1)
89 }
90 tw.AppendRow(row)
91 }
92 for rowIdx := 0; rowIdx < 1; rowIdx++ {
93 row := make(Row, 3)
94 for colIdx := 0; colIdx < 3; colIdx++ {
95 row[colIdx] = AutoIndexColumnID(colIdx) + "F"
96 }
97 tw.AppendFooter(row)
98 }
99 tw.SetOutputMirror(nil)
100 tw.SetAutoIndex(true)
101 tw.SetStyle(StyleLight)
102
103 compareOutput(t, tw.RenderHTML(), `<table class="go-pretty-table">
104 <thead>
105 <tr>
106 <th> </th>
107 <th align="center">A</th>
108 <th align="center">B</th>
109 <th align="center">C</th>
110 </tr>
111 </thead>
112 <tbody>
113 <tr>
114 <td align="right">1</td>
115 <td>A1</td>
116 <td>B1</td>
117 <td>C1</td>
118 </tr>
119 <tr>
120 <td align="right">2</td>
121 <td>A2</td>
122 <td>B2</td>
123 <td>C2</td>
124 </tr>
125 <tr>
126 <td align="right">3</td>
127 <td>A3</td>
128 <td>B3</td>
129 <td>C3</td>
130 </tr>
131 </tbody>
132 <tfoot>
133 <tr>
134 <td> </td>
135 <td>AF</td>
136 <td>BF</td>
137 <td>CF</td>
138 </tr>
139 </tfoot>
140 </table>`)
141 }
142
143 func TestTable_RenderHTML_Colored(t *testing.T) {
144 tw := NewWriter()
145 tw.AppendHeader(testHeader)
146 tw.AppendRows(testRows)
147 tw.AppendRow(testRowMultiLine)
148 tw.AppendFooter(testFooter)
149 tw.SetCaption(testCaption)
150 tw.SetTitle(testTitle1)
151 tw.Style().HTML.CSSClass = "go-pretty-table-colored"
152 colorsBlackOnWhite := text.Colors{text.BgWhite, text.FgBlack}
153 tw.SetColumnConfigs([]ColumnConfig{
154 {
155 Name: "#",
156 Colors: text.Colors{text.Bold},
157 ColorsHeader: colorsBlackOnWhite,
158 }, {
159 Name: "First Name",
160 Colors: text.Colors{text.FgCyan},
161 ColorsHeader: colorsBlackOnWhite,
162 }, {
163 Name: "Last Name",
164 Colors: text.Colors{text.FgMagenta},
165 ColorsHeader: colorsBlackOnWhite,
166 ColorsFooter: colorsBlackOnWhite,
167 }, {
168 Name: "Salary",
169 Colors: text.Colors{text.FgYellow},
170 ColorsHeader: colorsBlackOnWhite,
171 ColorsFooter: colorsBlackOnWhite,
172 VAlign: text.VAlignBottom,
173 }, {
174 Number: 5,
175 Colors: text.Colors{text.FgBlack},
176 ColorsHeader: colorsBlackOnWhite,
177 VAlign: text.VAlignBottom,
178 },
179 })
180
181 compareOutput(t, tw.RenderHTML(), `<table class="go-pretty-table-colored">
182 <caption class="title">Game of Thrones</caption>
183 <thead>
184 <tr>
185 <th align="right" class="bg-white fg-black">#</th>
186 <th class="bg-white fg-black">First Name</th>
187 <th class="bg-white fg-black">Last Name</th>
188 <th align="right" class="bg-white fg-black">Salary</th>
189 <th class="bg-white fg-black"> </th>
190 </tr>
191 </thead>
192 <tbody>
193 <tr>
194 <td align="right" class="bold">1</td>
195 <td class="fg-cyan">Arya</td>
196 <td class="fg-magenta">Stark</td>
197 <td align="right" class="fg-yellow" valign="bottom">3000</td>
198 <td class="fg-black" valign="bottom"> </td>
199 </tr>
200 <tr>
201 <td align="right" class="bold">20</td>
202 <td class="fg-cyan">Jon</td>
203 <td class="fg-magenta">Snow</td>
204 <td align="right" class="fg-yellow" valign="bottom">2000</td>
205 <td class="fg-black" valign="bottom">You know nothing, Jon Snow!</td>
206 </tr>
207 <tr>
208 <td align="right" class="bold">300</td>
209 <td class="fg-cyan">Tyrion</td>
210 <td class="fg-magenta">Lannister</td>
211 <td align="right" class="fg-yellow" valign="bottom">5000</td>
212 <td class="fg-black" valign="bottom"> </td>
213 </tr>
214 <tr>
215 <td align="right" class="bold">0</td>
216 <td class="fg-cyan">Winter</td>
217 <td class="fg-magenta">Is</td>
218 <td align="right" class="fg-yellow" valign="bottom">0</td>
219 <td class="fg-black" valign="bottom">Coming.<br/>The North Remembers!<br/>This is known.</td>
220 </tr>
221 </tbody>
222 <tfoot>
223 <tr>
224 <td align="right"> </td>
225 <td> </td>
226 <td class="bg-white fg-black">Total</td>
227 <td align="right" class="bg-white fg-black">10000</td>
228 <td> </td>
229 </tr>
230 </tfoot>
231 <caption class="caption" style="caption-side: bottom;">A Song of Ice and Fire</caption>
232 </table>`)
233 }
234
235 func TestTable_RenderHTML_CustomStyle(t *testing.T) {
236 tw := NewWriter()
237 tw.AppendHeader(testHeader)
238 tw.AppendRow(Row{1, "Arya", "Stark", 3000, "<a href=\"https://duckduckgo.com/?q=arya+stark+not+today\">Not today.</a>"})
239 tw.AppendRow(Row{1, "Jon", "Snow", 2000, "You know\nnothing,\nJon Snow!"})
240 tw.AppendRow(Row{300, "Tyrion", "Lannister", 5000})
241 tw.AppendFooter(testFooter)
242 tw.SetAutoIndex(true)
243 tw.Style().HTML = HTMLOptions{
244 CSSClass: "game-of-thrones",
245 EmptyColumn: "<!-- test --> ",
246 EscapeText: false,
247 Newline: "<!-- newline -->",
248 }
249 tw.SetOutputMirror(nil)
250
251 compareOutput(t, tw.RenderHTML(), `<table class="game-of-thrones">
252 <thead>
253 <tr>
254 <th><!-- test --> </th>
255 <th align="right">#</th>
256 <th>First Name</th>
257 <th>Last Name</th>
258 <th align="right">Salary</th>
259 <th><!-- test --> </th>
260 </tr>
261 </thead>
262 <tbody>
263 <tr>
264 <td align="right">1</td>
265 <td align="right">1</td>
266 <td>Arya</td>
267 <td>Stark</td>
268 <td align="right">3000</td>
269 <td><a href="https://duckduckgo.com/?q=arya+stark+not+today">Not today.</a></td>
270 </tr>
271 <tr>
272 <td align="right">2</td>
273 <td align="right">1</td>
274 <td>Jon</td>
275 <td>Snow</td>
276 <td align="right">2000</td>
277 <td>You know<!-- newline -->nothing,<!-- newline -->Jon Snow!</td>
278 </tr>
279 <tr>
280 <td align="right">3</td>
281 <td align="right">300</td>
282 <td>Tyrion</td>
283 <td>Lannister</td>
284 <td align="right">5000</td>
285 <td><!-- test --> </td>
286 </tr>
287 </tbody>
288 <tfoot>
289 <tr>
290 <td><!-- test --> </td>
291 <td align="right"><!-- test --> </td>
292 <td><!-- test --> </td>
293 <td>Total</td>
294 <td align="right">10000</td>
295 <td><!-- test --> </td>
296 </tr>
297 </tfoot>
298 </table>`)
299 }
300
301 func TestTable_RenderHTML_Empty(t *testing.T) {
302 tw := NewWriter()
303 assert.Empty(t, tw.RenderHTML())
304 }
305
306 func TestTable_RenderHTML_HiddenColumns(t *testing.T) {
307 tw := NewWriter()
308 tw.AppendHeader(testHeader)
309 tw.AppendRows(testRows)
310 tw.AppendFooter(testFooter)
311
312
313 tw.SortBy([]SortBy{
314 {Name: "Salary", Mode: DscNumeric},
315 })
316
317 t.Run("every column hidden", func(t *testing.T) {
318 tw.SetColumnConfigs(generateColumnConfigsWithHiddenColumns([]int{0, 1, 2, 3, 4}))
319
320 compareOutput(t, tw.RenderHTML(), "")
321 })
322
323 t.Run("first column hidden", func(t *testing.T) {
324 tw.SetColumnConfigs(generateColumnConfigsWithHiddenColumns([]int{0}))
325
326 compareOutput(t, tw.RenderHTML(), `<table class="go-pretty-table">
327 <thead>
328 <tr>
329 <th>First Name</th>
330 <th>Last Name</th>
331 <th align="right">Salary</th>
332 <th> </th>
333 </tr>
334 </thead>
335 <tbody>
336 <tr>
337 <td>>>Tyrion</td>
338 <td>Lannister<<</td>
339 <td align="right">5013</td>
340 <td> </td>
341 </tr>
342 <tr>
343 <td>>>Arya</td>
344 <td>Stark<<</td>
345 <td align="right">3013</td>
346 <td> </td>
347 </tr>
348 <tr>
349 <td>>>Jon</td>
350 <td>Snow<<</td>
351 <td align="right">2013</td>
352 <td>~You know nothing, Jon Snow!~</td>
353 </tr>
354 </tbody>
355 <tfoot>
356 <tr>
357 <td> </td>
358 <td>Total</td>
359 <td align="right">10000</td>
360 <td> </td>
361 </tr>
362 </tfoot>
363 </table>`)
364 })
365
366 t.Run("column hidden in the middle", func(t *testing.T) {
367 tw.SetColumnConfigs(generateColumnConfigsWithHiddenColumns([]int{1}))
368
369 compareOutput(t, tw.RenderHTML(), `<table class="go-pretty-table">
370 <thead>
371 <tr>
372 <th align="right">#</th>
373 <th>Last Name</th>
374 <th align="right">Salary</th>
375 <th> </th>
376 </tr>
377 </thead>
378 <tbody>
379 <tr>
380 <td align="right">307</td>
381 <td>Lannister<<</td>
382 <td align="right">5013</td>
383 <td> </td>
384 </tr>
385 <tr>
386 <td align="right">8</td>
387 <td>Stark<<</td>
388 <td align="right">3013</td>
389 <td> </td>
390 </tr>
391 <tr>
392 <td align="right">27</td>
393 <td>Snow<<</td>
394 <td align="right">2013</td>
395 <td>~You know nothing, Jon Snow!~</td>
396 </tr>
397 </tbody>
398 <tfoot>
399 <tr>
400 <td align="right"> </td>
401 <td>Total</td>
402 <td align="right">10000</td>
403 <td> </td>
404 </tr>
405 </tfoot>
406 </table>`)
407 })
408
409 t.Run("last column hidden", func(t *testing.T) {
410 tw.SetColumnConfigs(generateColumnConfigsWithHiddenColumns([]int{4}))
411
412 compareOutput(t, tw.RenderHTML(), `<table class="go-pretty-table">
413 <thead>
414 <tr>
415 <th align="right">#</th>
416 <th>First Name</th>
417 <th>Last Name</th>
418 <th align="right">Salary</th>
419 </tr>
420 </thead>
421 <tbody>
422 <tr>
423 <td align="right">307</td>
424 <td>>>Tyrion</td>
425 <td>Lannister<<</td>
426 <td align="right">5013</td>
427 </tr>
428 <tr>
429 <td align="right">8</td>
430 <td>>>Arya</td>
431 <td>Stark<<</td>
432 <td align="right">3013</td>
433 </tr>
434 <tr>
435 <td align="right">27</td>
436 <td>>>Jon</td>
437 <td>Snow<<</td>
438 <td align="right">2013</td>
439 </tr>
440 </tbody>
441 <tfoot>
442 <tr>
443 <td align="right"> </td>
444 <td> </td>
445 <td>Total</td>
446 <td align="right">10000</td>
447 </tr>
448 </tfoot>
449 </table>`)
450 })
451 }
452
453 func TestTable_RenderHTML_Sorted(t *testing.T) {
454 tw := NewWriter()
455 tw.AppendHeader(testHeader)
456 tw.AppendRows(testRows)
457 tw.AppendRow(Row{11, "Sansa", "Stark", 6000})
458 tw.AppendFooter(testFooter)
459 tw.SortBy([]SortBy{{Name: "Last Name", Mode: Asc}, {Name: "First Name", Mode: Asc}})
460
461 compareOutput(t, tw.RenderHTML(), `<table class="go-pretty-table">
462 <thead>
463 <tr>
464 <th align="right">#</th>
465 <th>First Name</th>
466 <th>Last Name</th>
467 <th align="right">Salary</th>
468 <th> </th>
469 </tr>
470 </thead>
471 <tbody>
472 <tr>
473 <td align="right">300</td>
474 <td>Tyrion</td>
475 <td>Lannister</td>
476 <td align="right">5000</td>
477 <td> </td>
478 </tr>
479 <tr>
480 <td align="right">20</td>
481 <td>Jon</td>
482 <td>Snow</td>
483 <td align="right">2000</td>
484 <td>You know nothing, Jon Snow!</td>
485 </tr>
486 <tr>
487 <td align="right">1</td>
488 <td>Arya</td>
489 <td>Stark</td>
490 <td align="right">3000</td>
491 <td> </td>
492 </tr>
493 <tr>
494 <td align="right">11</td>
495 <td>Sansa</td>
496 <td>Stark</td>
497 <td align="right">6000</td>
498 <td> </td>
499 </tr>
500 </tbody>
501 <tfoot>
502 <tr>
503 <td align="right"> </td>
504 <td> </td>
505 <td>Total</td>
506 <td align="right">10000</td>
507 <td> </td>
508 </tr>
509 </tfoot>
510 </table>`)
511 }
512
View as plain text