mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-09-09 01:46:22 -07:00
554 lines
12 KiB
Go
554 lines
12 KiB
Go
package gctemplates
|
|
|
|
import (
|
|
"bytes"
|
|
"html/template"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/gochan-org/gochan/pkg/config"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestArithmeticTmplFuncs(t *testing.T) {
|
|
testCases := []struct {
|
|
desc string
|
|
tmplStr string
|
|
expected string
|
|
A int
|
|
B int
|
|
}{
|
|
{desc: "addition", tmplStr: "{{add .A .B}}", expected: "-5", A: -2, B: -3},
|
|
{desc: "subtraction", tmplStr: "{{subtract .A .B}}", expected: "1", A: -2, B: -3},
|
|
}
|
|
buf := bytes.NewBuffer(nil)
|
|
var tmpl *template.Template
|
|
for _, tC := range testCases {
|
|
buf.Reset()
|
|
t.Run(tC.desc, func(t *testing.T) {
|
|
tmpl = template.Must(template.New("name").Funcs(funcMap).Parse(tC.tmplStr))
|
|
assert.NoError(t, tmpl.Execute(buf, tC))
|
|
assert.Equal(t, tC.expected, buf.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDereferenceTmplFunc(t *testing.T) {
|
|
const tmplStr = "{{dereference .Val}}"
|
|
testCases := []struct {
|
|
desc string
|
|
Val *int
|
|
expected string
|
|
}{
|
|
{
|
|
desc: "nil int",
|
|
Val: nil,
|
|
expected: "0",
|
|
},
|
|
{
|
|
desc: "non-nil int",
|
|
expected: "32",
|
|
Val: new(int),
|
|
},
|
|
}
|
|
*testCases[1].Val = 32
|
|
tmpl := template.Must(template.New("name").Funcs(funcMap).Parse(tmplStr))
|
|
buf := bytes.NewBuffer(nil)
|
|
for _, tC := range testCases {
|
|
buf.Reset()
|
|
t.Run(tC.desc, func(t *testing.T) {
|
|
assert.NoError(t, tmpl.Execute(buf, tC))
|
|
assert.Equal(t, tC.expected, buf.String())
|
|
})
|
|
}
|
|
}
|
|
func TestIsNilTmplFunc(t *testing.T) {
|
|
const tmplStr = "{{isNil .Val}}"
|
|
testCases := []struct {
|
|
desc string
|
|
Val any
|
|
expected string
|
|
}{
|
|
{
|
|
desc: "nil value",
|
|
Val: nil,
|
|
expected: "true",
|
|
},
|
|
{
|
|
desc: "non-nil value",
|
|
Val: 42,
|
|
expected: "false",
|
|
},
|
|
{
|
|
desc: "non-nil pointer",
|
|
Val: new(int),
|
|
expected: "false",
|
|
},
|
|
}
|
|
tmpl := template.Must(template.New("name").Funcs(funcMap).Parse(tmplStr))
|
|
buf := bytes.NewBuffer(nil)
|
|
for _, tC := range testCases {
|
|
buf.Reset()
|
|
t.Run(tC.desc, func(t *testing.T) {
|
|
assert.NoError(t, tmpl.Execute(buf, tC))
|
|
assert.Equal(t, tC.expected, buf.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetSliceTmplFunc(t *testing.T) {
|
|
testCases := []struct {
|
|
desc string
|
|
tmplStr string
|
|
expected string
|
|
Slice []any
|
|
Start int
|
|
End int
|
|
}{
|
|
{
|
|
desc: "nil slice",
|
|
tmplStr: "{{getSlice .Slice 0 10}}",
|
|
expected: "[]",
|
|
Slice: nil,
|
|
},
|
|
{
|
|
desc: "normalize start and length",
|
|
tmplStr: "{{getSlice .Slice .Start .End}}",
|
|
expected: "[1 2 3 4]",
|
|
Start: -4,
|
|
End: 15,
|
|
Slice: []any{1, 2, 3, 4},
|
|
},
|
|
{
|
|
desc: "regular slice",
|
|
tmplStr: "{{getSlice .Slice .Start .End}}",
|
|
expected: "[2 3]",
|
|
Start: 1,
|
|
End: 3,
|
|
Slice: []any{1, 2, 3, 4},
|
|
},
|
|
}
|
|
var tmpl *template.Template
|
|
buf := bytes.NewBuffer(nil)
|
|
for _, tC := range testCases {
|
|
buf.Reset()
|
|
t.Run(tC.desc, func(t *testing.T) {
|
|
tmpl = template.Must(template.New("name").Funcs(funcMap).Parse(tC.tmplStr))
|
|
assert.NoError(t, tmpl.Execute(buf, tC))
|
|
assert.Equal(t, tC.expected, buf.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFormatFilesizeTmplFunc(t *testing.T) {
|
|
const tmplStr = "{{formatFilesize .Size}}"
|
|
testCases := []struct {
|
|
desc string
|
|
Size int
|
|
expected string
|
|
}{
|
|
{
|
|
desc: "bytes",
|
|
Size: 500,
|
|
expected: "500 B",
|
|
},
|
|
{
|
|
desc: "kilobytes",
|
|
Size: 4096,
|
|
expected: "4.0 KB",
|
|
},
|
|
{
|
|
desc: "megabytes",
|
|
Size: 5242880,
|
|
expected: "5.00 MB",
|
|
},
|
|
{
|
|
desc: "gigabytes",
|
|
Size: 5368709120,
|
|
expected: "5.00 GB",
|
|
},
|
|
}
|
|
tmpl := template.Must(template.New("name").Funcs(funcMap).Parse(tmplStr))
|
|
buf := bytes.NewBuffer(nil)
|
|
|
|
for _, tC := range testCases {
|
|
buf.Reset()
|
|
t.Run(tC.desc, func(t *testing.T) {
|
|
assert.NoError(t, tmpl.Execute(buf, tC))
|
|
assert.Equal(t, tC.expected, buf.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFormatTimestampTmplFunc(t *testing.T) {
|
|
config.InitTestConfig()
|
|
|
|
tmpl := template.Must(template.New("name").Funcs(funcMap).Parse("{{formatTimestamp .Time}}"))
|
|
buf := bytes.NewBuffer(nil)
|
|
timeVal, err := time.Parse("01", "01")
|
|
assert.NoError(t, err)
|
|
tC := struct{ Time time.Time }{timeVal}
|
|
assert.NoError(t, tmpl.Execute(buf, tC))
|
|
assert.Equal(t, "Sat, January 01, 0000 12:00:00 AM", buf.String())
|
|
}
|
|
|
|
func TestStringAppendTmplFunc(t *testing.T) {
|
|
testCases := []struct {
|
|
desc string
|
|
tmplStr string
|
|
expected string
|
|
}{
|
|
{
|
|
desc: "no strings",
|
|
tmplStr: "{{stringAppend}}",
|
|
expected: "",
|
|
},
|
|
{
|
|
desc: "single string",
|
|
tmplStr: `{{stringAppend "a"}}`,
|
|
expected: "a",
|
|
},
|
|
{
|
|
desc: "multiple strings",
|
|
tmplStr: `{{stringAppend "a" "a"}}`,
|
|
expected: "aa",
|
|
},
|
|
}
|
|
var tmpl *template.Template
|
|
buf := bytes.NewBuffer(nil)
|
|
for _, tC := range testCases {
|
|
buf.Reset()
|
|
t.Run(tC.desc, func(t *testing.T) {
|
|
tmpl = template.Must(template.New("name").Funcs(funcMap).Parse(tC.tmplStr))
|
|
assert.NoError(t, tmpl.Execute(buf, nil))
|
|
assert.Equal(t, tC.expected, buf.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTruncateFilenameTmplFunc(t *testing.T) {
|
|
const tmplStr = "{{truncateFilename .Filename}}"
|
|
testCases := []struct {
|
|
desc string
|
|
Filename string
|
|
expected string
|
|
}{
|
|
{
|
|
desc: "empty filename",
|
|
},
|
|
{
|
|
desc: "filename smaller than max",
|
|
Filename: "file.png",
|
|
expected: "file.png",
|
|
},
|
|
{
|
|
desc: "filename larger than max",
|
|
Filename: "filename larger than max.png",
|
|
expected: "filename l.png",
|
|
},
|
|
{
|
|
desc: "filename larger than max (no ext)",
|
|
Filename: "filename larger than max",
|
|
expected: "filename l",
|
|
},
|
|
}
|
|
tmpl := template.Must(template.New("name").Funcs(funcMap).Parse(tmplStr))
|
|
buf := bytes.NewBuffer(nil)
|
|
|
|
for _, tC := range testCases {
|
|
buf.Reset()
|
|
t.Run(tC.desc, func(t *testing.T) {
|
|
assert.NoError(t, tmpl.Execute(buf, tC))
|
|
assert.Equal(t, tC.expected, buf.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTruncateMessageTmplFunc(t *testing.T) {
|
|
const tmplStr = "{{truncateMessage .Message .Limit .MaxLines}}"
|
|
testCases := []struct {
|
|
desc string
|
|
expected string
|
|
Message string
|
|
Limit int
|
|
MaxLines int
|
|
}{
|
|
{
|
|
desc: "empty string",
|
|
},
|
|
{
|
|
desc: "size within limit (single line)",
|
|
expected: "test test",
|
|
Message: "test test",
|
|
Limit: 10,
|
|
MaxLines: 1,
|
|
},
|
|
{
|
|
desc: "size = limit (single line)",
|
|
expected: "0123456789",
|
|
Message: "0123456789",
|
|
Limit: 10,
|
|
MaxLines: 1,
|
|
},
|
|
{
|
|
desc: "size > limit (single line)",
|
|
expected: "blah blah...",
|
|
Message: "blah blah blah",
|
|
Limit: 10,
|
|
MaxLines: 1,
|
|
},
|
|
{
|
|
desc: "lines > max lines",
|
|
expected: "blah\nblah...",
|
|
Message: "blah\nblah\nblah",
|
|
Limit: 999,
|
|
MaxLines: 2,
|
|
},
|
|
}
|
|
tmpl := template.Must(template.New("name").Funcs(funcMap).Parse(tmplStr))
|
|
buf := bytes.NewBuffer(nil)
|
|
for _, tC := range testCases {
|
|
buf.Reset()
|
|
t.Run(tC.desc, func(t *testing.T) {
|
|
assert.NoError(t, tmpl.Execute(buf, tC))
|
|
assert.Equal(t, tC.expected, buf.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTruncateHTMLMessageTmplFunc(t *testing.T) {
|
|
const tmplStr = "{{truncateHTMLMessage .Message .Limit .MaxLines}}"
|
|
testCases := []struct {
|
|
desc string
|
|
expected string
|
|
Message template.HTML
|
|
Limit int
|
|
MaxLines int
|
|
}{
|
|
{
|
|
desc: "empty string",
|
|
},
|
|
{
|
|
desc: "size within limit (single line)",
|
|
expected: "test test",
|
|
Message: "test test",
|
|
Limit: 40,
|
|
MaxLines: 1,
|
|
},
|
|
{
|
|
desc: "size = limit (single line)",
|
|
expected: "0123456789",
|
|
Message: "0123456789",
|
|
Limit: 10,
|
|
MaxLines: 1,
|
|
},
|
|
{
|
|
desc: "size > limit (single line)",
|
|
expected: "blah blah...",
|
|
Message: "blah blah blah",
|
|
Limit: 10,
|
|
MaxLines: 1,
|
|
},
|
|
{
|
|
desc: "lines > max lines",
|
|
expected: "blah<br/>blah<br/>",
|
|
Message: "blah<br/>blah<br/>blah",
|
|
Limit: 999,
|
|
MaxLines: 2,
|
|
},
|
|
{
|
|
desc: "end tag after limit",
|
|
expected: "<div>blah <div>b...</div></div>",
|
|
Message: "<div>blah <div>blah</div></div>",
|
|
Limit: 7,
|
|
MaxLines: 1,
|
|
},
|
|
}
|
|
tmpl := template.Must(template.New("name").Funcs(funcMap).Parse(tmplStr))
|
|
buf := bytes.NewBuffer(nil)
|
|
for _, tC := range testCases {
|
|
buf.Reset()
|
|
t.Run(tC.desc, func(t *testing.T) {
|
|
assert.NoError(t, tmpl.Execute(buf, tC))
|
|
assert.Equal(t, tC.expected, buf.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTruncateStringTmplFunc(t *testing.T) {
|
|
const tmplStr = "{{truncateString .Message .Limit .Ellipsis}}"
|
|
testCases := []struct {
|
|
desc string
|
|
expected string
|
|
Message string
|
|
Limit int
|
|
Ellipsis bool
|
|
}{
|
|
{
|
|
desc: "empty string",
|
|
Ellipsis: true,
|
|
},
|
|
{
|
|
desc: "string within limit",
|
|
expected: "string",
|
|
Message: "string",
|
|
Limit: 50,
|
|
Ellipsis: true,
|
|
},
|
|
{
|
|
desc: "string larger than limit, no ellipses",
|
|
expected: "string ",
|
|
Message: "string string",
|
|
Limit: 7,
|
|
},
|
|
{
|
|
desc: "string larger than limit, ellipses",
|
|
expected: "string ...",
|
|
Message: "string string",
|
|
Limit: 7,
|
|
Ellipsis: true,
|
|
},
|
|
}
|
|
tmpl := template.Must(template.New("name").Funcs(funcMap).Parse(tmplStr))
|
|
buf := bytes.NewBuffer(nil)
|
|
for _, tC := range testCases {
|
|
buf.Reset()
|
|
t.Run(tC.desc, func(t *testing.T) {
|
|
assert.NoError(t, tmpl.Execute(buf, tC))
|
|
assert.Equal(t, tC.expected, buf.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
type vertex struct {
|
|
X, Y int
|
|
}
|
|
|
|
func TestMapTmplFunc(t *testing.T) {
|
|
testCases := []struct {
|
|
desc string
|
|
tmplStr string
|
|
expected string
|
|
err bool
|
|
baseData map[string]any
|
|
}{
|
|
{
|
|
desc: "nil map",
|
|
},
|
|
{
|
|
desc: "map with odd-numbered arguments returns error",
|
|
tmplStr: "{{define `subTmpl`}}x: .x\ny: .y{{end}}{{template `subTmpl` map `x` 1 `y` 2 `z`}}",
|
|
err: true,
|
|
},
|
|
{
|
|
desc: "map only accepts string keys",
|
|
tmplStr: "{{define `subTmpl`}}x: .x\ny: .y{{end}}{{template `subTmpl` map `x` 1 `y` 2 1 1}}",
|
|
err: true,
|
|
},
|
|
{
|
|
desc: "map with data",
|
|
tmplStr: "{{define `subTmpl`}}x: {{.pos.X}}\ny: {{.pos.Y}}\nrotation: {{.rot}}{{end}}{{template `subTmpl` map `pos` .vertex `rot` .rotation}}",
|
|
expected: "x: 32\ny: 34\nrotation: 127",
|
|
baseData: map[string]any{
|
|
"vertex": vertex{32, 34},
|
|
"rotation": 127,
|
|
},
|
|
},
|
|
}
|
|
var tmpl *template.Template
|
|
buf := bytes.NewBuffer(nil)
|
|
var err error
|
|
for _, tC := range testCases {
|
|
buf.Reset()
|
|
t.Run(tC.desc, func(t *testing.T) {
|
|
tmpl = template.Must(template.New("name").Funcs(funcMap).Parse(tC.tmplStr))
|
|
err = tmpl.Execute(buf, tC.baseData)
|
|
if tC.err {
|
|
assert.Error(t, err)
|
|
return
|
|
}
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tC.expected, buf.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWebPathDirTmplFunc(t *testing.T) {
|
|
config.InitTestConfig()
|
|
testCases := []struct {
|
|
desc string
|
|
tmplStr string
|
|
expected string
|
|
}{
|
|
{
|
|
desc: "no input returns slash",
|
|
tmplStr: "{{webPathDir}}",
|
|
expected: "/",
|
|
},
|
|
{
|
|
desc: "empty string returns slash",
|
|
tmplStr: `{{webPathDir ""}}`,
|
|
expected: "/",
|
|
},
|
|
{
|
|
desc: "single slash returns slash",
|
|
tmplStr: `{{webPathDir "/"}}`,
|
|
expected: "/",
|
|
},
|
|
{
|
|
desc: "multiple slashes returns single slash",
|
|
tmplStr: `{{webPathDir "//"}}`,
|
|
expected: "/",
|
|
},
|
|
{
|
|
desc: "multiple multi-slashes returns single slash",
|
|
tmplStr: `{{webPathDir "//" "//"}}`,
|
|
expected: "/",
|
|
},
|
|
{
|
|
desc: "general webpath usage",
|
|
tmplStr: `{{webPathDir "test"}}`,
|
|
expected: "/test/",
|
|
},
|
|
}
|
|
var tmpl *template.Template
|
|
buf := bytes.NewBuffer(nil)
|
|
for _, tC := range testCases {
|
|
buf.Reset()
|
|
t.Run(tC.desc, func(t *testing.T) {
|
|
tmpl = template.Must(template.New("name").Funcs(funcMap).Parse(tC.tmplStr))
|
|
assert.NoError(t, tmpl.Execute(buf, nil))
|
|
assert.Equal(t, tC.expected, buf.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMakeLoopTmplFunc(t *testing.T) {
|
|
config.InitTestConfig()
|
|
testCases := []struct {
|
|
desc string
|
|
tmplStr string
|
|
expected string
|
|
}{
|
|
{
|
|
desc: "makeLoop range",
|
|
tmplStr: "{{range $_,$i := makeLoop 4 1}}{{$i}}\n{{end}}",
|
|
expected: "1\n2\n3\n4\n",
|
|
},
|
|
{
|
|
desc: "makeLoop with n = 0",
|
|
tmplStr: "{{range $_,$i := makeLoop 0 1}}{{$i}}\n{{end}}",
|
|
expected: "",
|
|
},
|
|
}
|
|
var tmpl *template.Template
|
|
buf := bytes.NewBuffer(nil)
|
|
for _, tC := range testCases {
|
|
buf.Reset()
|
|
t.Run(tC.desc, func(t *testing.T) {
|
|
tmpl = template.Must(template.New("name").Funcs(funcMap).Parse(tC.tmplStr))
|
|
assert.NoError(t, tmpl.Execute(buf, nil))
|
|
assert.Equal(t, tC.expected, buf.String())
|
|
})
|
|
}
|
|
}
|