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 document with a few // levels of nesting is pretty-printed: only deep nesting is shown // as received. 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_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) // 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) }