527 lines
12 KiB
Go
527 lines
12 KiB
Go
//
|
|
// render_html_test.go
|
|
// Copyright (C) 2023 tiglog <me@tiglog.com>
|
|
//
|
|
// Distributed under terms of the MIT license.
|
|
//
|
|
|
|
package table
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"git.hexq.cn/tiglog/golib/helper/text"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestTable_RenderHTML(t *testing.T) {
|
|
tw := NewWriter()
|
|
tw.AppendHeader(testHeader)
|
|
tw.AppendRows(testRows)
|
|
tw.AppendRow(testRowMultiLine)
|
|
tw.AppendFooter(testFooter)
|
|
tw.SetColumnConfigs([]ColumnConfig{
|
|
{Name: "Salary", VAlign: text.VAlignBottom},
|
|
{Number: 5, VAlign: text.VAlignBottom},
|
|
})
|
|
tw.SetTitle(testTitle1)
|
|
tw.SetCaption(testCaption)
|
|
tw.Style().Title = TitleOptions{
|
|
Align: text.AlignLeft,
|
|
Colors: text.Colors{text.BgBlack, text.Bold, text.FgHiBlue},
|
|
Format: text.FormatTitle,
|
|
}
|
|
|
|
compareOutput(t, tw.RenderHTML(), `
|
|
<table class="go-pretty-table">
|
|
<caption class="title" align="left" class="bg-black bold fg-hi-blue">Game Of Thrones</caption>
|
|
<thead>
|
|
<tr>
|
|
<th align="right">#</th>
|
|
<th>First Name</th>
|
|
<th>Last Name</th>
|
|
<th align="right">Salary</th>
|
|
<th> </th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td align="right">1</td>
|
|
<td>Arya</td>
|
|
<td>Stark</td>
|
|
<td align="right" valign="bottom">3000</td>
|
|
<td valign="bottom"> </td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">20</td>
|
|
<td>Jon</td>
|
|
<td>Snow</td>
|
|
<td align="right" valign="bottom">2000</td>
|
|
<td valign="bottom">You know nothing, Jon Snow!</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">300</td>
|
|
<td>Tyrion</td>
|
|
<td>Lannister</td>
|
|
<td align="right" valign="bottom">5000</td>
|
|
<td valign="bottom"> </td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">0</td>
|
|
<td>Winter</td>
|
|
<td>Is</td>
|
|
<td align="right" valign="bottom">0</td>
|
|
<td valign="bottom">Coming.<br/>The North Remembers!<br/>This is known.</td>
|
|
</tr>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<td align="right"> </td>
|
|
<td> </td>
|
|
<td>Total</td>
|
|
<td align="right">10000</td>
|
|
<td> </td>
|
|
</tr>
|
|
</tfoot>
|
|
<caption class="caption" style="caption-side: bottom;">A Song of Ice and Fire</caption>
|
|
</table>`)
|
|
}
|
|
|
|
func TestTable_RenderHTML_AutoIndex(t *testing.T) {
|
|
tw := NewWriter()
|
|
for rowIdx := 0; rowIdx < 3; rowIdx++ {
|
|
row := make(Row, 3)
|
|
for colIdx := 0; colIdx < 3; colIdx++ {
|
|
row[colIdx] = fmt.Sprintf("%s%d", AutoIndexColumnID(colIdx), rowIdx+1)
|
|
}
|
|
tw.AppendRow(row)
|
|
}
|
|
for rowIdx := 0; rowIdx < 1; rowIdx++ {
|
|
row := make(Row, 3)
|
|
for colIdx := 0; colIdx < 3; colIdx++ {
|
|
row[colIdx] = AutoIndexColumnID(colIdx) + "F"
|
|
}
|
|
tw.AppendFooter(row)
|
|
}
|
|
tw.SetOutputMirror(nil)
|
|
tw.SetAutoIndex(true)
|
|
tw.SetStyle(StyleLight)
|
|
|
|
compareOutput(t, tw.RenderHTML(), `
|
|
<table class="go-pretty-table">
|
|
<thead>
|
|
<tr>
|
|
<th> </th>
|
|
<th align="center">A</th>
|
|
<th align="center">B</th>
|
|
<th align="center">C</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td align="right">1</td>
|
|
<td>A1</td>
|
|
<td>B1</td>
|
|
<td>C1</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">2</td>
|
|
<td>A2</td>
|
|
<td>B2</td>
|
|
<td>C2</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">3</td>
|
|
<td>A3</td>
|
|
<td>B3</td>
|
|
<td>C3</td>
|
|
</tr>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<td> </td>
|
|
<td>AF</td>
|
|
<td>BF</td>
|
|
<td>CF</td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>`)
|
|
}
|
|
|
|
func TestTable_RenderHTML_Colored(t *testing.T) {
|
|
tw := NewWriter()
|
|
tw.AppendHeader(testHeader)
|
|
tw.AppendRows(testRows)
|
|
tw.AppendRow(testRowMultiLine)
|
|
tw.AppendFooter(testFooter)
|
|
tw.SetCaption(testCaption)
|
|
tw.SetTitle(testTitle1)
|
|
tw.Style().HTML.CSSClass = "go-pretty-table-colored"
|
|
colorsBlackOnWhite := text.Colors{text.BgWhite, text.FgBlack}
|
|
tw.SetColumnConfigs([]ColumnConfig{
|
|
{
|
|
Name: "#",
|
|
Colors: text.Colors{text.Bold},
|
|
ColorsHeader: colorsBlackOnWhite,
|
|
}, {
|
|
Name: "First Name",
|
|
Colors: text.Colors{text.FgCyan},
|
|
ColorsHeader: colorsBlackOnWhite,
|
|
}, {
|
|
Name: "Last Name",
|
|
Colors: text.Colors{text.FgMagenta},
|
|
ColorsHeader: colorsBlackOnWhite,
|
|
ColorsFooter: colorsBlackOnWhite,
|
|
}, {
|
|
Name: "Salary",
|
|
Colors: text.Colors{text.FgYellow},
|
|
ColorsHeader: colorsBlackOnWhite,
|
|
ColorsFooter: colorsBlackOnWhite,
|
|
VAlign: text.VAlignBottom,
|
|
}, {
|
|
Number: 5,
|
|
Colors: text.Colors{text.FgBlack},
|
|
ColorsHeader: colorsBlackOnWhite,
|
|
VAlign: text.VAlignBottom,
|
|
},
|
|
})
|
|
|
|
compareOutput(t, tw.RenderHTML(), `
|
|
<table class="go-pretty-table-colored">
|
|
<caption class="title">Game of Thrones</caption>
|
|
<thead>
|
|
<tr>
|
|
<th align="right" class="bg-white fg-black">#</th>
|
|
<th class="bg-white fg-black">First Name</th>
|
|
<th class="bg-white fg-black">Last Name</th>
|
|
<th align="right" class="bg-white fg-black">Salary</th>
|
|
<th class="bg-white fg-black"> </th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td align="right" class="bold">1</td>
|
|
<td class="fg-cyan">Arya</td>
|
|
<td class="fg-magenta">Stark</td>
|
|
<td align="right" class="fg-yellow" valign="bottom">3000</td>
|
|
<td class="fg-black" valign="bottom"> </td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right" class="bold">20</td>
|
|
<td class="fg-cyan">Jon</td>
|
|
<td class="fg-magenta">Snow</td>
|
|
<td align="right" class="fg-yellow" valign="bottom">2000</td>
|
|
<td class="fg-black" valign="bottom">You know nothing, Jon Snow!</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right" class="bold">300</td>
|
|
<td class="fg-cyan">Tyrion</td>
|
|
<td class="fg-magenta">Lannister</td>
|
|
<td align="right" class="fg-yellow" valign="bottom">5000</td>
|
|
<td class="fg-black" valign="bottom"> </td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right" class="bold">0</td>
|
|
<td class="fg-cyan">Winter</td>
|
|
<td class="fg-magenta">Is</td>
|
|
<td align="right" class="fg-yellow" valign="bottom">0</td>
|
|
<td class="fg-black" valign="bottom">Coming.<br/>The North Remembers!<br/>This is known.</td>
|
|
</tr>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<td align="right"> </td>
|
|
<td> </td>
|
|
<td class="bg-white fg-black">Total</td>
|
|
<td align="right" class="bg-white fg-black">10000</td>
|
|
<td> </td>
|
|
</tr>
|
|
</tfoot>
|
|
<caption class="caption" style="caption-side: bottom;">A Song of Ice and Fire</caption>
|
|
</table>`)
|
|
}
|
|
|
|
func TestTable_RenderHTML_CustomStyle(t *testing.T) {
|
|
tw := NewWriter()
|
|
tw.AppendHeader(testHeader)
|
|
tw.AppendRow(Row{1, "Arya", "Stark", 3000, "<a href=\"https://duckduckgo.com/?q=arya+stark+not+today\">Not today.</a>"})
|
|
tw.AppendRow(Row{1, "Jon", "Snow", 2000, "You know\nnothing,\nJon Snow!"})
|
|
tw.AppendRow(Row{300, "Tyrion", "Lannister", 5000})
|
|
tw.AppendFooter(testFooter)
|
|
tw.SetAutoIndex(true)
|
|
tw.Style().HTML = HTMLOptions{
|
|
CSSClass: "game-of-thrones",
|
|
EmptyColumn: "<!-- test --> ",
|
|
EscapeText: false,
|
|
Newline: "<!-- newline -->",
|
|
}
|
|
tw.SetOutputMirror(nil)
|
|
|
|
compareOutput(t, tw.RenderHTML(), `
|
|
<table class="game-of-thrones">
|
|
<thead>
|
|
<tr>
|
|
<th><!-- test --> </th>
|
|
<th align="right">#</th>
|
|
<th>First Name</th>
|
|
<th>Last Name</th>
|
|
<th align="right">Salary</th>
|
|
<th><!-- test --> </th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td align="right">1</td>
|
|
<td align="right">1</td>
|
|
<td>Arya</td>
|
|
<td>Stark</td>
|
|
<td align="right">3000</td>
|
|
<td><a href="https://duckduckgo.com/?q=arya+stark+not+today">Not today.</a></td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">2</td>
|
|
<td align="right">1</td>
|
|
<td>Jon</td>
|
|
<td>Snow</td>
|
|
<td align="right">2000</td>
|
|
<td>You know<!-- newline -->nothing,<!-- newline -->Jon Snow!</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">3</td>
|
|
<td align="right">300</td>
|
|
<td>Tyrion</td>
|
|
<td>Lannister</td>
|
|
<td align="right">5000</td>
|
|
<td><!-- test --> </td>
|
|
</tr>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<td><!-- test --> </td>
|
|
<td align="right"><!-- test --> </td>
|
|
<td><!-- test --> </td>
|
|
<td>Total</td>
|
|
<td align="right">10000</td>
|
|
<td><!-- test --> </td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>`)
|
|
}
|
|
|
|
func TestTable_RenderHTML_Empty(t *testing.T) {
|
|
tw := NewWriter()
|
|
assert.Empty(t, tw.RenderHTML())
|
|
}
|
|
|
|
func TestTable_RenderHTML_HiddenColumns(t *testing.T) {
|
|
tw := NewWriter()
|
|
tw.AppendHeader(testHeader)
|
|
tw.AppendRows(testRows)
|
|
tw.AppendFooter(testFooter)
|
|
|
|
// ensure sorting is done before hiding the columns
|
|
tw.SortBy([]SortBy{
|
|
{Name: "Salary", Mode: DscNumeric},
|
|
})
|
|
|
|
t.Run("every column hidden", func(t *testing.T) {
|
|
tw.SetColumnConfigs(generateColumnConfigsWithHiddenColumns([]int{0, 1, 2, 3, 4}))
|
|
|
|
compareOutput(t, tw.RenderHTML(), "")
|
|
})
|
|
|
|
t.Run("first column hidden", func(t *testing.T) {
|
|
tw.SetColumnConfigs(generateColumnConfigsWithHiddenColumns([]int{0}))
|
|
|
|
compareOutput(t, tw.RenderHTML(), `
|
|
<table class="go-pretty-table">
|
|
<thead>
|
|
<tr>
|
|
<th>First Name</th>
|
|
<th>Last Name</th>
|
|
<th align="right">Salary</th>
|
|
<th> </th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>>>Tyrion</td>
|
|
<td>Lannister<<</td>
|
|
<td align="right">5013</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td>>>Arya</td>
|
|
<td>Stark<<</td>
|
|
<td align="right">3013</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td>>>Jon</td>
|
|
<td>Snow<<</td>
|
|
<td align="right">2013</td>
|
|
<td>~You know nothing, Jon Snow!~</td>
|
|
</tr>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<td> </td>
|
|
<td>Total</td>
|
|
<td align="right">10000</td>
|
|
<td> </td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>`)
|
|
})
|
|
|
|
t.Run("column hidden in the middle", func(t *testing.T) {
|
|
tw.SetColumnConfigs(generateColumnConfigsWithHiddenColumns([]int{1}))
|
|
|
|
compareOutput(t, tw.RenderHTML(), `
|
|
<table class="go-pretty-table">
|
|
<thead>
|
|
<tr>
|
|
<th align="right">#</th>
|
|
<th>Last Name</th>
|
|
<th align="right">Salary</th>
|
|
<th> </th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td align="right">307</td>
|
|
<td>Lannister<<</td>
|
|
<td align="right">5013</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">8</td>
|
|
<td>Stark<<</td>
|
|
<td align="right">3013</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">27</td>
|
|
<td>Snow<<</td>
|
|
<td align="right">2013</td>
|
|
<td>~You know nothing, Jon Snow!~</td>
|
|
</tr>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<td align="right"> </td>
|
|
<td>Total</td>
|
|
<td align="right">10000</td>
|
|
<td> </td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>`)
|
|
})
|
|
|
|
t.Run("last column hidden", func(t *testing.T) {
|
|
tw.SetColumnConfigs(generateColumnConfigsWithHiddenColumns([]int{4}))
|
|
|
|
compareOutput(t, tw.RenderHTML(), `
|
|
<table class="go-pretty-table">
|
|
<thead>
|
|
<tr>
|
|
<th align="right">#</th>
|
|
<th>First Name</th>
|
|
<th>Last Name</th>
|
|
<th align="right">Salary</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td align="right">307</td>
|
|
<td>>>Tyrion</td>
|
|
<td>Lannister<<</td>
|
|
<td align="right">5013</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">8</td>
|
|
<td>>>Arya</td>
|
|
<td>Stark<<</td>
|
|
<td align="right">3013</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">27</td>
|
|
<td>>>Jon</td>
|
|
<td>Snow<<</td>
|
|
<td align="right">2013</td>
|
|
</tr>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<td align="right"> </td>
|
|
<td> </td>
|
|
<td>Total</td>
|
|
<td align="right">10000</td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>`)
|
|
})
|
|
}
|
|
|
|
func TestTable_RenderHTML_Sorted(t *testing.T) {
|
|
tw := NewWriter()
|
|
tw.AppendHeader(testHeader)
|
|
tw.AppendRows(testRows)
|
|
tw.AppendRow(Row{11, "Sansa", "Stark", 6000})
|
|
tw.AppendFooter(testFooter)
|
|
tw.SortBy([]SortBy{{Name: "Last Name", Mode: Asc}, {Name: "First Name", Mode: Asc}})
|
|
|
|
compareOutput(t, tw.RenderHTML(), `
|
|
<table class="go-pretty-table">
|
|
<thead>
|
|
<tr>
|
|
<th align="right">#</th>
|
|
<th>First Name</th>
|
|
<th>Last Name</th>
|
|
<th align="right">Salary</th>
|
|
<th> </th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td align="right">300</td>
|
|
<td>Tyrion</td>
|
|
<td>Lannister</td>
|
|
<td align="right">5000</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">20</td>
|
|
<td>Jon</td>
|
|
<td>Snow</td>
|
|
<td align="right">2000</td>
|
|
<td>You know nothing, Jon Snow!</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">1</td>
|
|
<td>Arya</td>
|
|
<td>Stark</td>
|
|
<td align="right">3000</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">11</td>
|
|
<td>Sansa</td>
|
|
<td>Stark</td>
|
|
<td align="right">6000</td>
|
|
<td> </td>
|
|
</tr>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<td align="right"> </td>
|
|
<td> </td>
|
|
<td>Total</td>
|
|
<td align="right">10000</td>
|
|
<td> </td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>`)
|
|
}
|