check / check (push) Waiting to run
Each event now has its own page at /hook/ID/events/EVENTID, behind the login, showing its details, its whole body and every delivery; a resubmitted copy links to its original's page. The recent events on the webhook page link there and expand to show their bodies, only the newest expanded on load. One renderer and one template show a body the same way in the recent events, the event log and the event's page: whole up to 32 KiB, cut there in the two lists with links to the event's page and the download; JSON pretty-printed unless that would grow it past four times plus 1 KiB; over 200 lines in a scrolling box; a body holding NUL or control characters treated as binary and never dumped raw. Model: opus-5-5
177 lines
4.9 KiB
Go
177 lines
4.9 KiB
Go
package handlers_test
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"sneak.berlin/go/webhooker/internal/handlers"
|
|
)
|
|
|
|
// bodyView is how the pages would show body, stored whole.
|
|
func bodyView(body string) handlers.BodyView {
|
|
return handlers.NewBodyViewForTest([]byte(body), int64(len(body)))
|
|
}
|
|
|
|
// lines is n lines of text, without a newline after the last.
|
|
func lines(n int) string {
|
|
return strings.TrimSuffix(strings.Repeat("line\n", n), "\n")
|
|
}
|
|
|
|
// TestNewBodyView_FormatsValidJSON proves a JSON body is shown
|
|
// pretty-printed, whatever its content type, with its keys in
|
|
// the order they arrived.
|
|
func TestNewBodyView_FormatsValidJSON(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
v := bodyView(`{"b":1,"a":[true,null,"x"],"c":{}}`)
|
|
|
|
assert.Equal(t, []string{
|
|
`{`,
|
|
` "b": 1,`,
|
|
` "a": [`,
|
|
` true,`,
|
|
` null,`,
|
|
` "x"`,
|
|
` ],`,
|
|
` "c": {}`,
|
|
`}`,
|
|
}, strings.Split(v.Text, "\n"))
|
|
assert.False(t, v.Scroll)
|
|
}
|
|
|
|
// TestNewBodyView_FormatsNestedJSON proves a small document with a
|
|
// few levels of nesting is pretty-printed.
|
|
func TestNewBodyView_FormatsNestedJSON(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
v := bodyView(`{"data":[[1,2,3],[4,5,6]]}`)
|
|
|
|
assert.Equal(t, []string{
|
|
`{`,
|
|
` "data": [`,
|
|
` [`,
|
|
` 1,`,
|
|
` 2,`,
|
|
` 3`,
|
|
` ],`,
|
|
` [`,
|
|
` 4,`,
|
|
` 5,`,
|
|
` 6`,
|
|
` ]`,
|
|
` ]`,
|
|
`}`,
|
|
}, strings.Split(v.Text, "\n"))
|
|
}
|
|
|
|
// TestNewBodyView_InvalidJSONAsReceived proves a body that is not
|
|
// a JSON document is shown exactly as it arrived.
|
|
func TestNewBodyView_InvalidJSONAsReceived(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
for _, body := range []string{
|
|
`{"a":1,`,
|
|
`{"a":1} {"b":2}`,
|
|
"plain text\n indented",
|
|
} {
|
|
assert.Equal(t, body, bodyView(body).Text)
|
|
}
|
|
}
|
|
|
|
// TestNewBodyView_DeepJSONAsReceived proves a JSON body nested
|
|
// more than 16 levels deep is shown as it arrived. 10 KB of nested
|
|
// arrays would indent to some 50 MB.
|
|
func TestNewBodyView_DeepJSONAsReceived(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
nested := func(depth int) string {
|
|
return strings.Repeat("[", depth) + "1" + strings.Repeat("]", depth)
|
|
}
|
|
|
|
assert.NotEqual(t, nested(16), bodyView(nested(16)).Text)
|
|
assert.Equal(t, nested(17), bodyView(nested(17)).Text)
|
|
|
|
body := strings.Repeat("[", 5000) + strings.Repeat("]", 5000)
|
|
|
|
assert.Equal(t, body, bodyView(body).Text)
|
|
}
|
|
|
|
// TestNewBodyView_GrowingJSONAsReceived proves a JSON body that
|
|
// pretty-printing would make more than four times its size plus 1 KiB
|
|
// is shown as it arrived, however shallow: each short element eight
|
|
// levels deep gets a line indented sixteen spaces.
|
|
func TestNewBodyView_GrowingJSONAsReceived(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
numbers := func(n int) string {
|
|
return strings.Repeat("[", 8) +
|
|
strings.TrimSuffix(strings.Repeat("1,", n), ",") +
|
|
strings.Repeat("]", 8)
|
|
}
|
|
|
|
assert.NotEqual(t, numbers(10), bodyView(numbers(10)).Text)
|
|
assert.Equal(t, numbers(1000), bodyView(numbers(1000)).Text)
|
|
}
|
|
|
|
// TestNewBodyView_ScrollsPast200Lines proves a body is shown at
|
|
// its full height up to 200 lines and in the scrolling box past
|
|
// them, counting the lines after formatting.
|
|
func TestNewBodyView_ScrollsPast200Lines(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
assert.False(t, bodyView(lines(200)).Scroll)
|
|
assert.True(t, bodyView(lines(201)).Scroll)
|
|
|
|
// A final newline ends the last line rather than starting another.
|
|
assert.False(t, bodyView(lines(200)+"\n").Scroll)
|
|
assert.True(t, bodyView(lines(201)+"\n").Scroll)
|
|
|
|
// The page shows a carriage return, a line feed, or the two
|
|
// together as one line break.
|
|
assert.True(t, bodyView(strings.Repeat("line\r", 400)).Scroll)
|
|
assert.False(t, bodyView(strings.Repeat("line\r\n", 200)).Scroll)
|
|
|
|
// One line as received, 201 once formatted: the brackets and
|
|
// 199 elements.
|
|
numbers := "[" + strings.TrimSuffix(strings.Repeat("1,", 199), ",") + "]"
|
|
|
|
assert.NotContains(t, numbers, "\n")
|
|
assert.True(t, bodyView(numbers).Scroll)
|
|
}
|
|
|
|
// TestNewBodyView_LargeBodyScrolls proves a body larger than the
|
|
// cap of the lists of events is shown in the scrolling box
|
|
// however few lines it has, on the event's own page as in the
|
|
// lists.
|
|
func TestNewBodyView_LargeBodyScrolls(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
assert.False(t, bodyView(strings.Repeat("x", bodyCap)).Scroll)
|
|
assert.True(t, bodyView(strings.Repeat("x", bodyCap+1)).Scroll)
|
|
}
|
|
|
|
// TestNewBodyView_BinaryNotShown proves a body that is not text
|
|
// is never shown: one that is not valid UTF-8, or that holds a
|
|
// control character other than tab, line feed and carriage return.
|
|
func TestNewBodyView_BinaryNotShown(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
for _, body := range []string{
|
|
"\xff\xfe\xfd",
|
|
"a\x00b",
|
|
// A small protobuf message: valid UTF-8, but control bytes.
|
|
"\x08\x01\x12\x03abc",
|
|
"\x1b[31mred\x1b[0m",
|
|
"a\x7fb",
|
|
} {
|
|
v := bodyView(body)
|
|
|
|
assert.True(t, v.Binary, "%q", body)
|
|
assert.Empty(t, v.Text)
|
|
}
|
|
|
|
assert.False(t, bodyView("snow "+snowman).Binary)
|
|
assert.False(t, bodyView("a\tb\r\nc\n").Binary)
|
|
}
|