mirror of
https://github.com/jimeh/go-render.git
synced 2026-02-19 03:16:39 +00:00
This is yet another drastic refactor of public API and concepts. Hopefully the last one, as I'm now fairly happy with things.
225 lines
4.7 KiB
Go
225 lines
4.7 KiB
Go
package render
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
type mockStringer struct {
|
|
value string
|
|
}
|
|
|
|
var _ fmt.Stringer = (*mockStringer)(nil)
|
|
|
|
func (ms *mockStringer) String() string {
|
|
return ms.value
|
|
}
|
|
|
|
type mockWriterTo struct {
|
|
value string
|
|
err error
|
|
}
|
|
|
|
var _ io.WriterTo = (*mockWriterTo)(nil)
|
|
|
|
func (m *mockWriterTo) WriteTo(w io.Writer) (int64, error) {
|
|
n, err := w.Write([]byte(m.value))
|
|
|
|
if m.err != nil {
|
|
return int64(n), m.err
|
|
}
|
|
|
|
return int64(n), err
|
|
}
|
|
|
|
type mockReader struct {
|
|
value string
|
|
cursor int
|
|
err error
|
|
}
|
|
|
|
var _ io.Reader = (*mockReader)(nil)
|
|
|
|
func (m *mockReader) Read(p []byte) (n int, err error) {
|
|
if m.err != nil {
|
|
return 0, m.err
|
|
}
|
|
|
|
if len(m.value) == 0 {
|
|
return 0, io.EOF
|
|
}
|
|
|
|
n = copy(p, m.value[m.cursor:])
|
|
m.cursor += n
|
|
|
|
if m.cursor >= len(m.value) {
|
|
return n, io.EOF
|
|
}
|
|
|
|
return n, nil
|
|
}
|
|
|
|
func Test_mockReader_Read(t *testing.T) {
|
|
mr := &mockReader{value: "test string"}
|
|
|
|
b1 := make([]byte, 5)
|
|
n1, err := mr.Read(b1)
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 5, n1)
|
|
assert.Equal(t, "test ", string(b1))
|
|
|
|
b2 := make([]byte, 5)
|
|
n2, err := mr.Read(b2)
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 5, n2)
|
|
assert.Equal(t, "strin", string(b2))
|
|
|
|
b3 := make([]byte, 5)
|
|
n3, err := mr.Read(b3)
|
|
|
|
assert.Equal(t, io.EOF, err)
|
|
assert.Equal(t, 1, n3)
|
|
assert.Equal(t, []byte{byte('g'), 0, 0, 0, 0}, b3)
|
|
}
|
|
|
|
func TestText_Render(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
writeErr error
|
|
value any
|
|
want string
|
|
wantErr string
|
|
wantErrIs []error
|
|
}{
|
|
{
|
|
name: "nil",
|
|
value: nil,
|
|
wantErr: "render: cannot render: <nil>",
|
|
wantErrIs: []error{Err, ErrCannotRender},
|
|
},
|
|
{
|
|
name: "byte slice",
|
|
value: []byte("test byte slice"),
|
|
want: "test byte slice",
|
|
},
|
|
{
|
|
name: "nil byte slice",
|
|
value: []byte(nil),
|
|
want: "",
|
|
},
|
|
{
|
|
name: "empty byte slice",
|
|
value: []byte{},
|
|
want: "",
|
|
},
|
|
{
|
|
name: "rune slice",
|
|
value: []rune{'r', 'u', 'n', 'e', 's', '!', ' ', 'y', 'e', 's'},
|
|
want: "runes! yes",
|
|
},
|
|
{
|
|
name: "string",
|
|
value: "test string",
|
|
want: "test string",
|
|
},
|
|
{name: "int", value: int(42), want: "42"},
|
|
{name: "int8", value: int8(43), want: "43"},
|
|
{name: "int16", value: int16(44), want: "44"},
|
|
{name: "int32", value: int32(45), want: "45"},
|
|
{name: "int64", value: int64(46), want: "46"},
|
|
{name: "uint", value: uint(47), want: "47"},
|
|
{name: "uint8", value: uint8(48), want: "48"},
|
|
{name: "uint16", value: uint16(49), want: "49"},
|
|
{name: "uint32", value: uint32(50), want: "50"},
|
|
{name: "uint64", value: uint64(51), want: "51"},
|
|
{name: "float32", value: float32(3.14), want: "3.14"},
|
|
{name: "float64", value: float64(3.14159), want: "3.14159"},
|
|
{name: "bool true", value: true, want: "true"},
|
|
{name: "bool false", value: false, want: "false"},
|
|
{
|
|
name: "implements fmt.Stringer",
|
|
value: &mockStringer{value: "test string"},
|
|
want: "test string",
|
|
},
|
|
{
|
|
name: "error writing to writer with fmt.Stringer",
|
|
writeErr: errors.New("write error!!1"),
|
|
value: &mockStringer{value: "test string"},
|
|
wantErr: "render: failed: write error!!1",
|
|
wantErrIs: []error{Err, ErrFailed},
|
|
},
|
|
{
|
|
name: "implements io.WriterTo",
|
|
value: &mockWriterTo{value: "test string"},
|
|
want: "test string",
|
|
},
|
|
{
|
|
name: "io.WriterTo error",
|
|
value: &mockWriterTo{
|
|
value: "test string",
|
|
err: errors.New("WriteTo error!!1"),
|
|
},
|
|
wantErr: "render: failed: WriteTo error!!1",
|
|
wantErrIs: []error{Err, ErrFailed},
|
|
},
|
|
{
|
|
name: "implements io.Reader",
|
|
value: &mockReader{value: "reader string"},
|
|
want: "reader string",
|
|
},
|
|
{
|
|
name: "io.Reader error",
|
|
value: &mockReader{
|
|
value: "reader string",
|
|
err: errors.New("Read error!!1"),
|
|
},
|
|
wantErr: "render: failed: Read error!!1",
|
|
wantErrIs: []error{Err, ErrFailed},
|
|
},
|
|
{
|
|
name: "error",
|
|
value: errors.New("this is an error"),
|
|
want: "this is an error",
|
|
},
|
|
{
|
|
name: "does not implement any supported type/interface",
|
|
value: struct{}{},
|
|
wantErr: "render: cannot render: struct {}",
|
|
wantErrIs: []error{Err, ErrCannotRender},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
s := &Text{}
|
|
w := &mockWriter{WriteErr: tt.writeErr}
|
|
|
|
err := s.Render(w, tt.value)
|
|
got := w.String()
|
|
|
|
if tt.wantErr != "" {
|
|
assert.EqualError(t, err, tt.wantErr)
|
|
}
|
|
for _, e := range tt.wantErrIs {
|
|
assert.ErrorIs(t, err, e)
|
|
}
|
|
|
|
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tt.want, got)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestText_Formats(t *testing.T) {
|
|
h := &Text{}
|
|
|
|
assert.Equal(t, []string{"text", "txt", "plain"}, h.Formats())
|
|
}
|