mirror of
https://github.com/jimeh/go-render.git
synced 2026-02-19 11:26:39 +00:00
test(render): improve test coverage
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
package render_test
|
package render_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding"
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jimeh/go-render"
|
"github.com/jimeh/go-render"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type mockBinaryMarshaler struct {
|
type mockBinaryMarshaler struct {
|
||||||
@@ -14,6 +14,8 @@ type mockBinaryMarshaler struct {
|
|||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ encoding.BinaryMarshaler = (*mockBinaryMarshaler)(nil)
|
||||||
|
|
||||||
func (mbm *mockBinaryMarshaler) MarshalBinary() ([]byte, error) {
|
func (mbm *mockBinaryMarshaler) MarshalBinary() ([]byte, error) {
|
||||||
return mbm.data, mbm.err
|
return mbm.data, mbm.err
|
||||||
}
|
}
|
||||||
@@ -57,16 +59,12 @@ func TestBinary_Render(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
b := &render.Binary{}
|
b := &render.Binary{}
|
||||||
|
|
||||||
var err error
|
|
||||||
var got string
|
|
||||||
w := &mockWriter{WriteErr: tt.writeErr}
|
w := &mockWriter{WriteErr: tt.writeErr}
|
||||||
|
|
||||||
err = b.Render(w, tt.value)
|
err := b.Render(w, tt.value)
|
||||||
got = w.String()
|
got := w.String()
|
||||||
|
|
||||||
if tt.wantErr != "" {
|
if tt.wantErr != "" {
|
||||||
require.Error(t, err)
|
|
||||||
assert.EqualError(t, err, tt.wantErr)
|
assert.EqualError(t, err, tt.wantErr)
|
||||||
}
|
}
|
||||||
for _, e := range tt.wantErrIs {
|
for _, e := range tt.wantErrIs {
|
||||||
@@ -74,7 +72,7 @@ func TestBinary_Render(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,17 +1,22 @@
|
|||||||
package render
|
package render
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ErrUnsupportedFormat = fmt.Errorf("%w: unsupported format", Err)
|
||||||
|
|
||||||
// FormatRenderer is a renderer that delegates rendering to another renderer
|
// FormatRenderer is a renderer that delegates rendering to another renderer
|
||||||
// based on a format value.
|
// based on a format value.
|
||||||
type FormatRenderer struct {
|
type FormatRenderer struct {
|
||||||
|
// Renderers is a map of format names to renderers. When Render is called,
|
||||||
|
// the format is used to look up the renderer to use.
|
||||||
Renderers map[string]Renderer
|
Renderers map[string]Renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render renders a value to an io.Writer using the specified format. If the
|
// Render renders a value to an io.Writer using the specified format. If the
|
||||||
// format is not supported, ErrCannotRender is returned.
|
// format is not supported, ErrUnsupportedFormat is returned.
|
||||||
//
|
//
|
||||||
// If the format is supported, but the value cannot be rendered to the format,
|
// If the format is supported, but the value cannot be rendered to the format,
|
||||||
// the error returned by the renderer is returned. In most cases this will be
|
// the error returned by the renderer is returned. In most cases this will be
|
||||||
@@ -23,5 +28,5 @@ func (r *FormatRenderer) Render(w io.Writer, format string, v any) error {
|
|||||||
return renderer.Render(w, v)
|
return renderer.Render(w, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrCannotRender
|
return ErrUnsupportedFormat
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
"github.com/jimeh/go-render"
|
"github.com/jimeh/go-render"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFormatRenderer_Render(t *testing.T) {
|
func TestFormatRenderer_Render(t *testing.T) {
|
||||||
@@ -46,7 +45,7 @@ func TestFormatRenderer_Render(t *testing.T) {
|
|||||||
renderers: map[string]render.Renderer{},
|
renderers: map[string]render.Renderer{},
|
||||||
format: "unknown",
|
format: "unknown",
|
||||||
value: struct{}{},
|
value: struct{}{},
|
||||||
wantErrIs: []error{render.Err, render.ErrCannotRender},
|
wantErrIs: []error{render.Err, render.ErrUnsupportedFormat},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@@ -54,13 +53,12 @@ func TestFormatRenderer_Render(t *testing.T) {
|
|||||||
fr := &render.FormatRenderer{
|
fr := &render.FormatRenderer{
|
||||||
Renderers: tt.renderers,
|
Renderers: tt.renderers,
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
err := fr.Render(&buf, tt.format, tt.value)
|
err := fr.Render(&buf, tt.format, tt.value)
|
||||||
got := buf.String()
|
got := buf.String()
|
||||||
|
|
||||||
if tt.wantErr != "" {
|
if tt.wantErr != "" {
|
||||||
require.Error(t, err)
|
|
||||||
assert.EqualError(t, err, tt.wantErr)
|
assert.EqualError(t, err, tt.wantErr)
|
||||||
}
|
}
|
||||||
for _, e := range tt.wantErrIs {
|
for _, e := range tt.wantErrIs {
|
||||||
@@ -68,7 +66,7 @@ func TestFormatRenderer_Render(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
39
json_test.go
39
json_test.go
@@ -2,6 +2,8 @@ package render_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jimeh/go-render"
|
"github.com/jimeh/go-render"
|
||||||
@@ -9,6 +11,17 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type mockJSONMarshaler struct {
|
||||||
|
data []byte
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ json.Marshaler = (*mockJSONMarshaler)(nil)
|
||||||
|
|
||||||
|
func (mjm *mockJSONMarshaler) MarshalJSON() ([]byte, error) {
|
||||||
|
return mjm.data, mjm.err
|
||||||
|
}
|
||||||
|
|
||||||
func TestJSON_Render(t *testing.T) {
|
func TestJSON_Render(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -29,18 +42,35 @@ func TestJSON_Render(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "simple object with pretty",
|
name: "simple object with pretty",
|
||||||
pretty: true,
|
pretty: true,
|
||||||
indent: " ",
|
|
||||||
value: map[string]int{"age": 30},
|
value: map[string]int{"age": 30},
|
||||||
want: "{\n \"age\": 30\n}\n",
|
want: "{\n \"age\": 30\n}\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with prefix and indent",
|
name: "pretty with prefix and indent",
|
||||||
pretty: true,
|
pretty: true,
|
||||||
prefix: "// ",
|
prefix: "// ",
|
||||||
indent: "\t",
|
indent: "\t",
|
||||||
value: map[string]int{"age": 30},
|
value: map[string]int{"age": 30},
|
||||||
want: "{\n// \t\"age\": 30\n// }\n",
|
want: "{\n// \t\"age\": 30\n// }\n",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "prefix and indent without pretty",
|
||||||
|
pretty: false,
|
||||||
|
prefix: "// ",
|
||||||
|
indent: "\t",
|
||||||
|
value: map[string]int{"age": 30},
|
||||||
|
want: "{\"age\":30}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "implements json.Marshaler",
|
||||||
|
value: &mockJSONMarshaler{data: []byte(`{"age":30}`)},
|
||||||
|
want: "{\"age\":30}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "error from json.Marshaler",
|
||||||
|
value: &mockJSONMarshaler{err: errors.New("marshal error!!1")},
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "invalid value",
|
name: "invalid value",
|
||||||
pretty: false,
|
pretty: false,
|
||||||
@@ -49,7 +79,6 @@ func TestJSON_Render(t *testing.T) {
|
|||||||
wantErrIs: []error{render.Err},
|
wantErrIs: []error{render.Err},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
j := &render.JSON{
|
j := &render.JSON{
|
||||||
@@ -57,9 +86,10 @@ func TestJSON_Render(t *testing.T) {
|
|||||||
Prefix: tt.prefix,
|
Prefix: tt.prefix,
|
||||||
Indent: tt.indent,
|
Indent: tt.indent,
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
err := j.Render(&buf, tt.value)
|
err := j.Render(&buf, tt.value)
|
||||||
|
got := buf.String()
|
||||||
|
|
||||||
if tt.wantErr != "" {
|
if tt.wantErr != "" {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
@@ -71,7 +101,6 @@ func TestJSON_Render(t *testing.T) {
|
|||||||
|
|
||||||
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
got := buf.String()
|
|
||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
"github.com/jimeh/go-render"
|
"github.com/jimeh/go-render"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMultiRenderer_Render(t *testing.T) {
|
func TestMultiRenderer_Render(t *testing.T) {
|
||||||
@@ -88,13 +87,12 @@ func TestMultiRenderer_Render(t *testing.T) {
|
|||||||
mr := &render.MultiRenderer{
|
mr := &render.MultiRenderer{
|
||||||
Renderers: tt.renderers,
|
Renderers: tt.renderers,
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
err := mr.Render(&buf, tt.value)
|
err := mr.Render(&buf, tt.value)
|
||||||
got := buf.String()
|
got := buf.String()
|
||||||
|
|
||||||
if tt.wantErr != "" {
|
if tt.wantErr != "" {
|
||||||
require.Error(t, err)
|
|
||||||
assert.EqualError(t, err, tt.wantErr)
|
assert.EqualError(t, err, tt.wantErr)
|
||||||
}
|
}
|
||||||
for _, e := range tt.wantErrIs {
|
for _, e := range tt.wantErrIs {
|
||||||
@@ -102,7 +100,7 @@ func TestMultiRenderer_Render(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
20
render.go
20
render.go
@@ -48,21 +48,22 @@ var (
|
|||||||
Renderers: []Renderer{DefaultStringer, DefaultWriterTo},
|
Renderers: []Renderer{DefaultStringer, DefaultWriterTo},
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultBinaryMarshaler is the default binary marshaler renderer. It
|
// DefaultBinary is the default binary marshaler renderer. It
|
||||||
// renders values using the encoding.BinaryMarshaler interface.
|
// renders values using the encoding.BinaryMarshaler interface.
|
||||||
DefaultBinaryMarshaler = &Binary{}
|
DefaultBinary = &Binary{}
|
||||||
|
|
||||||
// DefaultRenderer is the default renderer, used by the package level Render
|
// DefaultRenderer is the default renderer, used by the package level Render
|
||||||
// function. It supports the "json", "xml", "yaml", "text", "binary"
|
// function.
|
||||||
// formats.
|
|
||||||
DefaultRenderer = &FormatRenderer{map[string]Renderer{
|
DefaultRenderer = &FormatRenderer{map[string]Renderer{
|
||||||
|
"bin": DefaultBinary,
|
||||||
|
"binary": DefaultBinary,
|
||||||
"json": DefaultJSON,
|
"json": DefaultJSON,
|
||||||
|
"plain": DefaultText,
|
||||||
|
"text": DefaultText,
|
||||||
|
"txt": DefaultText,
|
||||||
"xml": DefaultXML,
|
"xml": DefaultXML,
|
||||||
"yaml": DefaultYAML,
|
"yaml": DefaultYAML,
|
||||||
"yml": DefaultYAML,
|
"yml": DefaultYAML,
|
||||||
"text": DefaultText,
|
|
||||||
"binary": DefaultBinaryMarshaler,
|
|
||||||
"bin": DefaultBinaryMarshaler,
|
|
||||||
}}
|
}}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -81,10 +82,13 @@ var (
|
|||||||
// - "text": Renders values using the fmt.Stringer and io.WriterTo interfaces.
|
// - "text": Renders values using the fmt.Stringer and io.WriterTo interfaces.
|
||||||
// This means a value must implement either the fmt.Stringer or io.WriterTo
|
// This means a value must implement either the fmt.Stringer or io.WriterTo
|
||||||
// interfaces to be rendered.
|
// interfaces to be rendered.
|
||||||
|
// - "txt": Alias for "text".
|
||||||
|
// - "plain": Alias for "text".
|
||||||
// - "binary": Renders values using the encoding.BinaryMarshaler interface.
|
// - "binary": Renders values using the encoding.BinaryMarshaler interface.
|
||||||
// - "bin": Alias for "binary".
|
// - "bin": Alias for "binary".
|
||||||
//
|
//
|
||||||
// If the format is not supported, a ErrCannotRender error will be returned.
|
// If the format is not supported, a ErrUnsupportedFormat error will be
|
||||||
|
// returned.
|
||||||
func Render(w io.Writer, format string, v any) error {
|
func Render(w io.Writer, format string, v any) error {
|
||||||
return DefaultRenderer.Render(w, format, v)
|
return DefaultRenderer.Render(w, format, v)
|
||||||
}
|
}
|
||||||
|
|||||||
485
render_test.go
485
render_test.go
@@ -2,7 +2,13 @@ package render_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/xml"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jimeh/go-render"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
type mockWriter struct {
|
type mockWriter struct {
|
||||||
@@ -10,6 +16,8 @@ type mockWriter struct {
|
|||||||
buf bytes.Buffer
|
buf bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ io.Writer = (*mockWriter)(nil)
|
||||||
|
|
||||||
func (mw *mockWriter) Write(p []byte) (n int, err error) {
|
func (mw *mockWriter) Write(p []byte) (n int, err error) {
|
||||||
if mw.WriteErr != nil {
|
if mw.WriteErr != nil {
|
||||||
return 0, mw.WriteErr
|
return 0, mw.WriteErr
|
||||||
@@ -27,6 +35,8 @@ type mockRenderer struct {
|
|||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ render.Renderer = (*mockRenderer)(nil)
|
||||||
|
|
||||||
func (m *mockRenderer) Render(w io.Writer, _ any) error {
|
func (m *mockRenderer) Render(w io.Writer, _ any) error {
|
||||||
_, err := w.Write([]byte(m.output))
|
_, err := w.Write([]byte(m.output))
|
||||||
|
|
||||||
@@ -36,3 +46,478 @@ func (m *mockRenderer) Render(w io.Writer, _ any) error {
|
|||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDefaultJSON(t *testing.T) {
|
||||||
|
assert.Equal(t, &render.JSON{Pretty: true}, render.DefaultJSON)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultXML(t *testing.T) {
|
||||||
|
assert.Equal(t, &render.XML{Pretty: true}, render.DefaultXML)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultYAML(t *testing.T) {
|
||||||
|
assert.Equal(t, &render.YAML{Indent: 2}, render.DefaultYAML)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultWriterTo(t *testing.T) {
|
||||||
|
assert.Equal(t, &render.WriterTo{}, render.DefaultWriterTo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultStringer(t *testing.T) {
|
||||||
|
assert.Equal(t, &render.Stringer{}, render.DefaultStringer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultText(t *testing.T) {
|
||||||
|
want := &render.MultiRenderer{
|
||||||
|
Renderers: []render.Renderer{
|
||||||
|
&render.Stringer{},
|
||||||
|
&render.WriterTo{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, want, render.DefaultText)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultBinary(t *testing.T) {
|
||||||
|
assert.Equal(t, &render.Binary{}, render.DefaultBinary)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultRenderer(t *testing.T) {
|
||||||
|
want := &render.FormatRenderer{
|
||||||
|
Renderers: map[string]render.Renderer{
|
||||||
|
"bin": render.DefaultBinary,
|
||||||
|
"binary": render.DefaultBinary,
|
||||||
|
"json": render.DefaultJSON,
|
||||||
|
"plain": render.DefaultText,
|
||||||
|
"text": render.DefaultText,
|
||||||
|
"txt": render.DefaultText,
|
||||||
|
"xml": render.DefaultXML,
|
||||||
|
"yaml": render.DefaultYAML,
|
||||||
|
"yml": render.DefaultYAML,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, want, render.DefaultRenderer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRender(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
writeErr error
|
||||||
|
format string
|
||||||
|
value any
|
||||||
|
want string
|
||||||
|
wantErr string
|
||||||
|
wantErrIs []error
|
||||||
|
wantPanic string
|
||||||
|
}{
|
||||||
|
// "bin" format.
|
||||||
|
{
|
||||||
|
name: "bin format with binary marshaler",
|
||||||
|
format: "bin",
|
||||||
|
value: &mockBinaryMarshaler{data: []byte("test string")},
|
||||||
|
want: "test string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "bin format without binary marshaler",
|
||||||
|
format: "bin",
|
||||||
|
value: struct{}{},
|
||||||
|
wantErrIs: []error{render.Err, render.ErrCannotRender},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "bin format with error marshaling",
|
||||||
|
format: "bin",
|
||||||
|
value: &mockBinaryMarshaler{
|
||||||
|
data: []byte("test string"),
|
||||||
|
err: errors.New("marshal error!!1"),
|
||||||
|
},
|
||||||
|
wantErr: "render: marshal error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "bin format with error writing to writer",
|
||||||
|
format: "bin",
|
||||||
|
writeErr: errors.New("write error!!1"),
|
||||||
|
value: &mockBinaryMarshaler{data: []byte("test string")},
|
||||||
|
wantErr: "render: write error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "bin format with invalid type",
|
||||||
|
format: "bin",
|
||||||
|
value: make(chan int),
|
||||||
|
wantErr: "render: cannot render",
|
||||||
|
wantErrIs: []error{render.Err, render.ErrCannotRender},
|
||||||
|
},
|
||||||
|
// "binary" format.
|
||||||
|
{
|
||||||
|
name: "binary format with binary marshaler",
|
||||||
|
format: "binary",
|
||||||
|
value: &mockBinaryMarshaler{data: []byte("test string")},
|
||||||
|
want: "test string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "binary format without binary marshaler",
|
||||||
|
format: "binary",
|
||||||
|
value: struct{}{},
|
||||||
|
wantErrIs: []error{render.Err, render.ErrCannotRender},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "binary format with error marshaling",
|
||||||
|
format: "binary",
|
||||||
|
value: &mockBinaryMarshaler{
|
||||||
|
data: []byte("test string"),
|
||||||
|
err: errors.New("marshal error!!1"),
|
||||||
|
},
|
||||||
|
wantErr: "render: marshal error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "binary format with error writing to writer",
|
||||||
|
format: "binary",
|
||||||
|
writeErr: errors.New("write error!!1"),
|
||||||
|
value: &mockBinaryMarshaler{data: []byte("test string")},
|
||||||
|
wantErr: "render: write error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "binary format with invalid type",
|
||||||
|
format: "binary",
|
||||||
|
value: make(chan int),
|
||||||
|
wantErr: "render: cannot render",
|
||||||
|
wantErrIs: []error{render.Err, render.ErrCannotRender},
|
||||||
|
},
|
||||||
|
// "json" format.
|
||||||
|
{
|
||||||
|
name: "json format",
|
||||||
|
format: "json",
|
||||||
|
value: map[string]int{"age": 30},
|
||||||
|
want: "{\n \"age\": 30\n}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "json format with json marshaler",
|
||||||
|
format: "json",
|
||||||
|
value: &mockJSONMarshaler{data: []byte(`{"age":30}`)},
|
||||||
|
want: "{\n \"age\": 30\n}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "json format with error from json marshaler",
|
||||||
|
format: "json",
|
||||||
|
value: &mockJSONMarshaler{err: errors.New("marshal error!!1")},
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "json format with error writing to writer",
|
||||||
|
format: "json",
|
||||||
|
writeErr: errors.New("write error!!1"),
|
||||||
|
value: map[string]int{"age": 30},
|
||||||
|
wantErr: "render: write error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "json format with invalid type",
|
||||||
|
format: "json",
|
||||||
|
value: make(chan int),
|
||||||
|
wantErr: "render: json: unsupported type: chan int",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
// "plain" format.
|
||||||
|
{
|
||||||
|
name: "plain format with fmt.Stringer",
|
||||||
|
format: "plain",
|
||||||
|
value: &mockStringer{value: "test string"},
|
||||||
|
want: "test string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "plain format with io.WriterTo",
|
||||||
|
format: "plain",
|
||||||
|
value: &mockWriterTo{value: "test string"},
|
||||||
|
want: "test string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "plain format without fmt.Stringer or io.WriterTo",
|
||||||
|
format: "plain",
|
||||||
|
value: struct{}{},
|
||||||
|
wantErrIs: []error{render.Err, render.ErrCannotRender},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "plain format with error writing to writer",
|
||||||
|
format: "plain",
|
||||||
|
writeErr: errors.New("write error!!1"),
|
||||||
|
value: &mockStringer{value: "test string"},
|
||||||
|
wantErr: "render: write error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "plain format with error from io.WriterTo",
|
||||||
|
format: "plain",
|
||||||
|
value: &mockWriterTo{
|
||||||
|
value: "test string",
|
||||||
|
err: errors.New("WriteTo error!!1"),
|
||||||
|
},
|
||||||
|
wantErr: "render: WriteTo error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "plain format with invalid type",
|
||||||
|
format: "plain",
|
||||||
|
value: make(chan int),
|
||||||
|
wantErr: "render: cannot render",
|
||||||
|
wantErrIs: []error{render.Err, render.ErrCannotRender},
|
||||||
|
},
|
||||||
|
// "text" format.
|
||||||
|
{
|
||||||
|
name: "text format with fmt.Stringer",
|
||||||
|
format: "text",
|
||||||
|
value: &mockStringer{value: "test string"},
|
||||||
|
want: "test string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "text format with io.WriterTo",
|
||||||
|
format: "text",
|
||||||
|
value: &mockWriterTo{value: "test string"},
|
||||||
|
want: "test string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "text format without fmt.Stringer or io.WriterTo",
|
||||||
|
format: "text",
|
||||||
|
value: struct{}{},
|
||||||
|
wantErrIs: []error{render.Err, render.ErrCannotRender},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "text format with error writing to writer",
|
||||||
|
format: "text",
|
||||||
|
writeErr: errors.New("write error!!1"),
|
||||||
|
value: &mockStringer{value: "test string"},
|
||||||
|
wantErr: "render: write error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "text format with error from io.WriterTo",
|
||||||
|
format: "text",
|
||||||
|
value: &mockWriterTo{
|
||||||
|
value: "test string",
|
||||||
|
err: errors.New("WriteTo error!!1"),
|
||||||
|
},
|
||||||
|
wantErr: "render: WriteTo error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "text format with invalid type",
|
||||||
|
format: "text",
|
||||||
|
value: make(chan int),
|
||||||
|
wantErr: "render: cannot render",
|
||||||
|
wantErrIs: []error{render.Err, render.ErrCannotRender},
|
||||||
|
},
|
||||||
|
// "txt" format.
|
||||||
|
{
|
||||||
|
name: "txt format with fmt.Stringer",
|
||||||
|
format: "txt",
|
||||||
|
value: &mockStringer{value: "test string"},
|
||||||
|
want: "test string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "txt format with io.WriterTo",
|
||||||
|
format: "txt",
|
||||||
|
value: &mockWriterTo{value: "test string"},
|
||||||
|
want: "test string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "txt format without fmt.Stringer or io.WriterTo",
|
||||||
|
format: "txt",
|
||||||
|
value: struct{}{},
|
||||||
|
wantErrIs: []error{render.Err, render.ErrCannotRender},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "txt format with error writing to writer",
|
||||||
|
format: "txt",
|
||||||
|
writeErr: errors.New("write error!!1"),
|
||||||
|
value: &mockStringer{value: "test string"},
|
||||||
|
wantErr: "render: write error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "txt format with error from io.WriterTo",
|
||||||
|
format: "txt",
|
||||||
|
value: &mockWriterTo{
|
||||||
|
value: "test string",
|
||||||
|
err: errors.New("WriteTo error!!1"),
|
||||||
|
},
|
||||||
|
wantErr: "render: WriteTo error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "txt format with invalid type",
|
||||||
|
format: "txt",
|
||||||
|
value: make(chan int),
|
||||||
|
wantErr: "render: cannot render",
|
||||||
|
wantErrIs: []error{render.Err, render.ErrCannotRender},
|
||||||
|
},
|
||||||
|
// "xml" format.
|
||||||
|
{
|
||||||
|
name: "xml format",
|
||||||
|
format: "xml",
|
||||||
|
value: struct {
|
||||||
|
XMLName xml.Name `xml:"user"`
|
||||||
|
Age int `xml:"age"`
|
||||||
|
}{Age: 30},
|
||||||
|
want: "<user>\n <age>30</age>\n</user>",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "xml format with xml.Marshaler",
|
||||||
|
format: "xml",
|
||||||
|
value: &mockXMLMarshaler{elm: "test string"},
|
||||||
|
want: "<mockXMLMarshaler>test string</mockXMLMarshaler>",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "xml format with error from xml.Marshaler",
|
||||||
|
format: "xml",
|
||||||
|
value: &mockXMLMarshaler{err: errors.New("marshal error!!1")},
|
||||||
|
wantErr: "render: marshal error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "xml format with error writing to writer",
|
||||||
|
format: "xml",
|
||||||
|
writeErr: errors.New("write error!!1"),
|
||||||
|
value: struct {
|
||||||
|
XMLName xml.Name `xml:"user"`
|
||||||
|
Age int `xml:"age"`
|
||||||
|
}{Age: 30},
|
||||||
|
wantErr: "render: write error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "xml format with invalid value",
|
||||||
|
format: "xml",
|
||||||
|
value: make(chan int),
|
||||||
|
wantErr: "render: xml: unsupported type: chan int",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
// "yaml" format.
|
||||||
|
{
|
||||||
|
name: "yaml format",
|
||||||
|
format: "yaml",
|
||||||
|
value: map[string]int{"age": 30},
|
||||||
|
want: "age: 30\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "yaml format with nested structure",
|
||||||
|
format: "yaml",
|
||||||
|
value: map[string]any{
|
||||||
|
"user": map[string]any{
|
||||||
|
"age": 30,
|
||||||
|
"name": "John Doe",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: "user:\n age: 30\n name: John Doe\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "yaml format with yaml.Marshaler",
|
||||||
|
format: "yaml",
|
||||||
|
value: &mockYAMLMarshaler{val: map[string]int{"age": 30}},
|
||||||
|
want: "age: 30\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "yaml format with error from yaml.Marshaler",
|
||||||
|
format: "yaml",
|
||||||
|
value: &mockYAMLMarshaler{err: errors.New("mock error")},
|
||||||
|
wantErr: "render: mock error",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "yaml format with error writing to writer",
|
||||||
|
format: "yaml",
|
||||||
|
writeErr: errors.New("write error!!1"),
|
||||||
|
value: map[string]int{"age": 30},
|
||||||
|
wantErr: "render: yaml: write error: write error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "yaml format with invalid type",
|
||||||
|
format: "yaml",
|
||||||
|
value: make(chan int),
|
||||||
|
wantPanic: "cannot marshal type: chan int",
|
||||||
|
},
|
||||||
|
// "yml" format.
|
||||||
|
{
|
||||||
|
name: "yml format",
|
||||||
|
format: "yml",
|
||||||
|
value: map[string]int{"age": 30},
|
||||||
|
want: "age: 30\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "yml format with nested structure",
|
||||||
|
format: "yml",
|
||||||
|
value: map[string]any{
|
||||||
|
"user": map[string]any{
|
||||||
|
"age": 30,
|
||||||
|
"name": "John Doe",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: "user:\n age: 30\n name: John Doe\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "yml format with yaml.Marshaler",
|
||||||
|
format: "yml",
|
||||||
|
value: &mockYAMLMarshaler{val: map[string]int{"age": 30}},
|
||||||
|
want: "age: 30\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "yml format with error from yaml.Marshaler",
|
||||||
|
format: "yml",
|
||||||
|
value: &mockYAMLMarshaler{err: errors.New("mock error")},
|
||||||
|
wantErr: "render: mock error",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "yml format with error writing to writer",
|
||||||
|
format: "yml",
|
||||||
|
writeErr: errors.New("write error!!1"),
|
||||||
|
value: map[string]int{"age": 30},
|
||||||
|
wantErr: "render: yaml: write error: write error!!1",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "yml format with invalid type",
|
||||||
|
format: "yml",
|
||||||
|
value: make(chan int),
|
||||||
|
wantPanic: "cannot marshal type: chan int",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
w := &mockWriter{WriteErr: tt.writeErr}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var panicRes any
|
||||||
|
func() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
panicRes = r
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
err = render.Render(w, tt.format, tt.value)
|
||||||
|
}()
|
||||||
|
|
||||||
|
got := w.String()
|
||||||
|
|
||||||
|
if tt.wantPanic != "" {
|
||||||
|
assert.Equal(t, tt.wantPanic, panicRes)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantErr != "" {
|
||||||
|
assert.EqualError(t, err, tt.wantErr)
|
||||||
|
}
|
||||||
|
for _, e := range tt.wantErrIs {
|
||||||
|
assert.ErrorIs(t, err, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantPanic == "" &&
|
||||||
|
tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func (s *Stringer) Render(w io.Writer, v any) error {
|
|||||||
return ErrCannotRender
|
return ErrCannotRender
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := fmt.Fprint(w, x.String())
|
_, err := w.Write([]byte(x.String()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%w: %w", Err, err)
|
return fmt.Errorf("%w: %w", Err, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,17 +2,19 @@ package render_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jimeh/go-render"
|
"github.com/jimeh/go-render"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type mockStringer struct {
|
type mockStringer struct {
|
||||||
value string
|
value string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ fmt.Stringer = (*mockStringer)(nil)
|
||||||
|
|
||||||
func (ms *mockStringer) String() string {
|
func (ms *mockStringer) String() string {
|
||||||
return ms.value
|
return ms.value
|
||||||
}
|
}
|
||||||
@@ -47,16 +49,12 @@ func TestStringer_Render(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
s := &render.Stringer{}
|
s := &render.Stringer{}
|
||||||
|
|
||||||
var err error
|
|
||||||
var got string
|
|
||||||
w := &mockWriter{WriteErr: tt.writeErr}
|
w := &mockWriter{WriteErr: tt.writeErr}
|
||||||
|
|
||||||
err = s.Render(w, tt.value)
|
err := s.Render(w, tt.value)
|
||||||
got = w.String()
|
got := w.String()
|
||||||
|
|
||||||
if tt.wantErr != "" {
|
if tt.wantErr != "" {
|
||||||
require.Error(t, err)
|
|
||||||
assert.EqualError(t, err, tt.wantErr)
|
assert.EqualError(t, err, tt.wantErr)
|
||||||
}
|
}
|
||||||
for _, e := range tt.wantErrIs {
|
for _, e := range tt.wantErrIs {
|
||||||
@@ -64,7 +62,7 @@ func TestStringer_Render(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
"github.com/jimeh/go-render"
|
"github.com/jimeh/go-render"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type mockWriterTo struct {
|
type mockWriterTo struct {
|
||||||
@@ -16,6 +15,8 @@ type mockWriterTo struct {
|
|||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ io.WriterTo = (*mockWriterTo)(nil)
|
||||||
|
|
||||||
func (m *mockWriterTo) WriteTo(w io.Writer) (int64, error) {
|
func (m *mockWriterTo) WriteTo(w io.Writer) (int64, error) {
|
||||||
n, err := w.Write([]byte(m.value))
|
n, err := w.Write([]byte(m.value))
|
||||||
|
|
||||||
@@ -59,16 +60,12 @@ func TestWriterTo_Render(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
wt := &render.WriterTo{}
|
wt := &render.WriterTo{}
|
||||||
|
|
||||||
var err error
|
|
||||||
var got string
|
|
||||||
w := &bytes.Buffer{}
|
w := &bytes.Buffer{}
|
||||||
|
|
||||||
err = wt.Render(w, tt.value)
|
err := wt.Render(w, tt.value)
|
||||||
got = w.String()
|
got := w.String()
|
||||||
|
|
||||||
if tt.wantErr != "" {
|
if tt.wantErr != "" {
|
||||||
require.Error(t, err)
|
|
||||||
assert.EqualError(t, err, tt.wantErr)
|
assert.EqualError(t, err, tt.wantErr)
|
||||||
}
|
}
|
||||||
for _, e := range tt.wantErrIs {
|
for _, e := range tt.wantErrIs {
|
||||||
@@ -76,7 +73,7 @@ func TestWriterTo_Render(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
56
xml_test.go
56
xml_test.go
@@ -3,13 +3,33 @@ package render_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jimeh/go-render"
|
"github.com/jimeh/go-render"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type mockXMLMarshaler struct {
|
||||||
|
elm string
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ xml.Marshaler = (*mockXMLMarshaler)(nil)
|
||||||
|
|
||||||
|
func (mxm *mockXMLMarshaler) MarshalXML(
|
||||||
|
e *xml.Encoder,
|
||||||
|
start xml.StartElement,
|
||||||
|
) error {
|
||||||
|
err := e.EncodeElement(mxm.elm, start)
|
||||||
|
|
||||||
|
if mxm.err != nil {
|
||||||
|
return mxm.err
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func TestXML_Render(t *testing.T) {
|
func TestXML_Render(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -33,15 +53,14 @@ func TestXML_Render(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "simple object with pretty",
|
name: "simple object with pretty",
|
||||||
pretty: true,
|
pretty: true,
|
||||||
indent: " ",
|
|
||||||
value: struct {
|
value: struct {
|
||||||
XMLName xml.Name `xml:"user"`
|
XMLName xml.Name `xml:"user"`
|
||||||
Age int `xml:"age"`
|
Age int `xml:"age"`
|
||||||
}{Age: 30},
|
}{Age: 30},
|
||||||
want: "<user>\n <age>30</age>\n</user>",
|
want: "<user>\n <age>30</age>\n</user>",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with prefix and indent",
|
name: "pretty with prefix and indent",
|
||||||
pretty: true,
|
pretty: true,
|
||||||
prefix: "//",
|
prefix: "//",
|
||||||
indent: "\t",
|
indent: "\t",
|
||||||
@@ -51,6 +70,28 @@ func TestXML_Render(t *testing.T) {
|
|||||||
}{Age: 30},
|
}{Age: 30},
|
||||||
want: "//<user>\n//\t<age>30</age>\n//</user>",
|
want: "//<user>\n//\t<age>30</age>\n//</user>",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "prefix and indent without pretty",
|
||||||
|
pretty: false,
|
||||||
|
prefix: "//",
|
||||||
|
indent: "\t",
|
||||||
|
value: struct {
|
||||||
|
XMLName xml.Name `xml:"user"`
|
||||||
|
Age int `xml:"age"`
|
||||||
|
}{Age: 30},
|
||||||
|
want: `<user><age>30</age></user>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "implements xml.Marshaler",
|
||||||
|
value: &mockXMLMarshaler{elm: "test string"},
|
||||||
|
want: "<mockXMLMarshaler>test string</mockXMLMarshaler>",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "error from xml.Marshaler",
|
||||||
|
value: &mockXMLMarshaler{err: errors.New("mock error")},
|
||||||
|
wantErr: "render: mock error",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "invalid value",
|
name: "invalid value",
|
||||||
pretty: false,
|
pretty: false,
|
||||||
@@ -67,12 +108,12 @@ func TestXML_Render(t *testing.T) {
|
|||||||
Prefix: tt.prefix,
|
Prefix: tt.prefix,
|
||||||
Indent: tt.indent,
|
Indent: tt.indent,
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
err := x.Render(&buf, tt.value)
|
err := x.Render(&buf, tt.value)
|
||||||
|
got := buf.String()
|
||||||
|
|
||||||
if tt.wantErr != "" {
|
if tt.wantErr != "" {
|
||||||
require.Error(t, err)
|
|
||||||
assert.EqualError(t, err, tt.wantErr)
|
assert.EqualError(t, err, tt.wantErr)
|
||||||
}
|
}
|
||||||
for _, e := range tt.wantErrIs {
|
for _, e := range tt.wantErrIs {
|
||||||
@@ -80,8 +121,7 @@ func TestXML_Render(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
if tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
got := buf.String()
|
|
||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
44
yaml_test.go
44
yaml_test.go
@@ -2,19 +2,33 @@ package render_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jimeh/go-render"
|
"github.com/jimeh/go-render"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type mockYAMLMarshaler struct {
|
||||||
|
val any
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ yaml.Marshaler = (*mockYAMLMarshaler)(nil)
|
||||||
|
|
||||||
|
func (m *mockYAMLMarshaler) MarshalYAML() (any, error) {
|
||||||
|
return m.val, m.err
|
||||||
|
}
|
||||||
|
|
||||||
func TestYAML_Render(t *testing.T) {
|
func TestYAML_Render(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
indent int
|
indent int
|
||||||
value interface{}
|
value interface{}
|
||||||
want string
|
want string
|
||||||
|
wantErr string
|
||||||
|
wantErrIs []error
|
||||||
wantPanic string
|
wantPanic string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@@ -44,6 +58,17 @@ func TestYAML_Render(t *testing.T) {
|
|||||||
},
|
},
|
||||||
want: "user:\n age: 30\n name: John Doe\n",
|
want: "user:\n age: 30\n name: John Doe\n",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "implements yaml.Marshaler",
|
||||||
|
value: &mockYAMLMarshaler{val: map[string]int{"age": 30}},
|
||||||
|
want: "age: 30\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "error from yaml.Marshaler",
|
||||||
|
value: &mockYAMLMarshaler{err: errors.New("mock error")},
|
||||||
|
wantErr: "render: mock error",
|
||||||
|
wantErrIs: []error{render.Err},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "invalid value",
|
name: "invalid value",
|
||||||
indent: 0,
|
indent: 0,
|
||||||
@@ -51,7 +76,6 @@ func TestYAML_Render(t *testing.T) {
|
|||||||
wantPanic: "cannot marshal type: chan int",
|
wantPanic: "cannot marshal type: chan int",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
j := &render.YAML{
|
j := &render.YAML{
|
||||||
@@ -70,11 +94,21 @@ func TestYAML_Render(t *testing.T) {
|
|||||||
err = j.Render(&buf, tt.value)
|
err = j.Render(&buf, tt.value)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
got := buf.String()
|
||||||
|
|
||||||
if tt.wantPanic != "" {
|
if tt.wantPanic != "" {
|
||||||
assert.Equal(t, tt.wantPanic, panicRes)
|
assert.Equal(t, tt.wantPanic, panicRes)
|
||||||
} else {
|
}
|
||||||
require.NoError(t, err)
|
if tt.wantErr != "" {
|
||||||
got := buf.String()
|
assert.EqualError(t, err, tt.wantErr)
|
||||||
|
}
|
||||||
|
for _, e := range tt.wantErrIs {
|
||||||
|
assert.ErrorIs(t, err, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantPanic == "" &&
|
||||||
|
tt.wantErr == "" && len(tt.wantErrIs) == 0 {
|
||||||
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user