173 lines
3.8 KiB
Go
173 lines
3.8 KiB
Go
package html_test
|
|
|
|
import (
|
|
"bytes"
|
|
"code.squareroundforest.org/arpio/html"
|
|
. "code.squareroundforest.org/arpio/html/tags"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
type failingWriter struct {
|
|
after int
|
|
}
|
|
|
|
func failWriteAfter(n int) *failingWriter {
|
|
return &failingWriter{n}
|
|
}
|
|
|
|
func (w *failingWriter) Write(p []byte) (int, error) {
|
|
w.after -= len(p)
|
|
if w.after < 0 {
|
|
return len(p) + w.after, errors.New("test error")
|
|
}
|
|
|
|
return len(p), nil
|
|
}
|
|
|
|
func TestRender(t *testing.T) {
|
|
t.Run("merge render guides", func(t *testing.T) {
|
|
foo := html.Inline(html.Verbatim(NewTag("foo")))
|
|
foo = foo("<bar><baz></bar>")
|
|
|
|
var b bytes.Buffer
|
|
if err := html.RenderIndent(&b, "\t", 0, foo); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != "<foo><bar><baz></bar></foo>" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("attribute escaping", func(t *testing.T) {
|
|
span := Span(Attr("foo", "bar=\"&\""))
|
|
|
|
var b bytes.Buffer
|
|
if err := html.Render(&b, span); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != "<span foo=\"bar="&"\"></span>" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("html escape", func(t *testing.T) {
|
|
t.Run("basic escape", func(t *testing.T) {
|
|
span := Span("<foo>bar&baz</foo>")
|
|
|
|
var b bytes.Buffer
|
|
if err := html.Render(&b, span); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != "<span><foo>bar&baz</foo></span>" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("consecutive spaces", func(t *testing.T) {
|
|
span := Span("consecutive spaces: \" \"")
|
|
|
|
var b bytes.Buffer
|
|
if err := html.Render(&b, span); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != "<span>consecutive spaces: \" \"</span>" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("write error", func(t *testing.T) {
|
|
t.Run("fail immediately", func(t *testing.T) {
|
|
div := Div(Span("foo"))
|
|
w := failWriteAfter(0)
|
|
if err := html.Render(w, div); err == nil || !strings.Contains(err.Error(), "test error") {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("fail in tag", func(t *testing.T) {
|
|
div := Div(Span("foo"))
|
|
w := failWriteAfter(6)
|
|
if err := html.Render(w, div); err == nil || !strings.Contains(err.Error(), "test error") {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("partial text children", func(t *testing.T) {
|
|
div := Div("foo", Div("bar"), "baz")
|
|
w := failWriteAfter(5)
|
|
if err := html.RenderIndent(w, "\t", 0, div); err == nil || !strings.Contains(err.Error(), "test error") {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("text children", func(t *testing.T) {
|
|
div := Div("foo", "bar", "baz")
|
|
w := failWriteAfter(5)
|
|
if err := html.RenderIndent(w, "\t", 0, div); err == nil || !strings.Contains(err.Error(), "test error") {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("indent", func(t *testing.T) {
|
|
t.Run("simple tag", func(t *testing.T) {
|
|
div := Div(Span("foo"))
|
|
|
|
var b bytes.Buffer
|
|
if err := html.RenderIndent(&b, "\t", 0, div); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != "<div>\n\t<span>foo</span>\n</div>\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("empty tag", func(t *testing.T) {
|
|
div := Div(Br())
|
|
|
|
var b bytes.Buffer
|
|
if err := html.RenderIndent(&b, "\t", 0, div); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != "<div>\n\t<br>\n</div>\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("inline fragment between blocks", func(t *testing.T) {
|
|
div := Div("foo bar baz", Div("qux quux"), "corge")
|
|
|
|
var b bytes.Buffer
|
|
if err := html.RenderIndent(&b, "\t", 0, div); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != "<div>\n\tfoo bar baz\n\t<div>\n\t\tqux quux\n\t</div>\n\tcorge\n</div>\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("block inside inline", func(t *testing.T) {
|
|
div := Div(Span("foo bar baz", Div("qux quux"), "corge"))
|
|
|
|
var b bytes.Buffer
|
|
if err := html.RenderIndent(&b, "XYZ", 0, div); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != "" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
})
|
|
}
|