cli/pkg/export/template_test.go
2021-08-25 12:41:30 +02:00

280 lines
6.5 KiB
Go

package export
import (
"fmt"
"io"
"strings"
"testing"
"time"
"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/v2/pkg/iostreams"
)
func Test_jsonScalarToString(t *testing.T) {
tests := []struct {
name string
input interface{}
want string
wantErr bool
}{
{
name: "string",
input: "hello",
want: "hello",
},
{
name: "int",
input: float64(1234),
want: "1234",
},
{
name: "float",
input: float64(12.34),
want: "12.34",
},
{
name: "null",
input: nil,
want: "",
},
{
name: "true",
input: true,
want: "true",
},
{
name: "false",
input: false,
want: "false",
},
{
name: "object",
input: map[string]interface{}{},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := jsonScalarToString(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("jsonScalarToString() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("jsonScalarToString() = %v, want %v", got, tt.want)
}
})
}
}
func Test_executeTemplate(t *testing.T) {
type args struct {
json io.Reader
template string
colorize bool
}
tests := []struct {
name string
args args
wantW string
wantErr bool
}{
{
name: "color",
args: args{
json: strings.NewReader(`{}`),
template: `{{color "blue+h" "songs are like tattoos"}}`,
},
wantW: "\x1b[0;94msongs are like tattoos\x1b[0m",
},
{
name: "autocolor enabled",
args: args{
json: strings.NewReader(`{}`),
template: `{{autocolor "red" "stop"}}`,
colorize: true,
},
wantW: "\x1b[0;31mstop\x1b[0m",
},
{
name: "autocolor disabled",
args: args{
json: strings.NewReader(`{}`),
template: `{{autocolor "red" "go"}}`,
},
wantW: "go",
},
{
name: "timefmt",
args: args{
json: strings.NewReader(`{"created_at":"2008-02-25T20:18:33Z"}`),
template: `{{.created_at | timefmt "Mon Jan 2, 2006"}}`,
},
wantW: "Mon Feb 25, 2008",
},
{
name: "timeago",
args: args{
json: strings.NewReader(fmt.Sprintf(`{"created_at":"%s"}`, time.Now().Add(-5*time.Minute).Format(time.RFC3339))),
template: `{{.created_at | timeago}}`,
},
wantW: "5 minutes ago",
},
{
name: "pluck",
args: args{
json: strings.NewReader(heredoc.Doc(`[
{"name": "bug"},
{"name": "feature request"},
{"name": "chore"}
]`)),
template: `{{range(pluck "name" .)}}{{. | printf "%s\n"}}{{end}}`,
},
wantW: "bug\nfeature request\nchore\n",
},
{
name: "join",
args: args{
json: strings.NewReader(`[ "bug", "feature request", "chore" ]`),
template: `{{join "\t" .}}`,
},
wantW: "bug\tfeature request\tchore",
},
{
name: "table",
args: args{
json: strings.NewReader(heredoc.Doc(`[
{"number": 1, "title": "One"},
{"number": 20, "title": "Twenty"},
{"number": 3000, "title": "Three thousand"}
]`)),
template: `{{range .}}{{tablerow (.number | printf "#%v") .title}}{{end}}`,
},
wantW: heredoc.Doc(`#1 One
#20 Twenty
#3000 Three thousand
`),
},
{
name: "table with multiline text",
args: args{
json: strings.NewReader(heredoc.Doc(`[
{"number": 1, "title": "One\ranother line of text"},
{"number": 20, "title": "Twenty\nanother line of text"},
{"number": 3000, "title": "Three thousand\r\nanother line of text"}
]`)),
template: `{{range .}}{{tablerow (.number | printf "#%v") .title}}{{end}}`,
},
wantW: heredoc.Doc(`#1 One...
#20 Twenty...
#3000 Three thousand...
`),
},
{
name: "table with mixed value types",
args: args{
json: strings.NewReader(heredoc.Doc(`[
{"number": 1, "title": null, "float": false},
{"number": 20.1, "title": "Twenty-ish", "float": true},
{"number": 3000, "title": "Three thousand", "float": false}
]`)),
template: `{{range .}}{{tablerow .number .title .float}}{{end}}`,
},
wantW: heredoc.Doc(`1 false
20.10 Twenty-ish true
3000 Three thousand false
`),
},
{
name: "table with color",
args: args{
json: strings.NewReader(heredoc.Doc(`[
{"number": 1, "title": "One"}
]`)),
template: `{{range .}}{{tablerow (.number | color "green") .title}}{{end}}`,
},
wantW: "\x1b[0;32m1\x1b[0m One\n",
},
{
name: "table with header and footer",
args: args{
json: strings.NewReader(heredoc.Doc(`[
{"number": 1, "title": "One"},
{"number": 2, "title": "Two"}
]`)),
template: heredoc.Doc(`HEADER
{{range .}}{{tablerow .number .title}}{{end}}FOOTER
`),
},
wantW: heredoc.Doc(`HEADER
FOOTER
1 One
2 Two
`),
},
{
name: "table with header and footer using endtable",
args: args{
json: strings.NewReader(heredoc.Doc(`[
{"number": 1, "title": "One"},
{"number": 2, "title": "Two"}
]`)),
template: heredoc.Doc(`HEADER
{{range .}}{{tablerow .number .title}}{{end}}{{tablerender}}FOOTER
`),
},
wantW: heredoc.Doc(`HEADER
1 One
2 Two
FOOTER
`),
},
{
name: "multiple tables with different columns",
args: args{
json: strings.NewReader(heredoc.Doc(`{
"issues": [
{"number": 1, "title": "One"},
{"number": 2, "title": "Two"}
],
"prs": [
{"number": 3, "title": "Three", "reviewDecision": "REVIEW_REQUESTED"},
{"number": 4, "title": "Four", "reviewDecision": "CHANGES_REQUESTED"}
]
}`)),
template: heredoc.Doc(`{{tablerow "ISSUE" "TITLE"}}{{range .issues}}{{tablerow .number .title}}{{end}}{{tablerender}}
{{tablerow "PR" "TITLE" "DECISION"}}{{range .prs}}{{tablerow .number .title .reviewDecision}}{{end}}`),
},
wantW: heredoc.Docf(`ISSUE TITLE
1 One
2 Two
PR TITLE DECISION
3 Three REVIEW_REQUESTED
4 Four CHANGES_REQUESTED
`),
},
{
name: "truncate",
args: args{
json: strings.NewReader(`{"title": "This is a long title"}`),
template: `{{truncate 13 .title}}`,
},
wantW: "This is a ...",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
io, _, w, _ := iostreams.Test()
io.SetColorEnabled(tt.args.colorize)
if err := ExecuteTemplate(io, tt.args.json, tt.args.template); (err != nil) != tt.wantErr {
t.Errorf("executeTemplate() error = %v, wantErr %v", err, tt.wantErr)
return
}
if gotW := w.String(); gotW != tt.wantW {
t.Errorf("executeTemplate() = %q, want %q", gotW, tt.wantW)
}
})
}
}