all repos — gomponents @ v1.8.1

HTML components in pure Go

http/handler_test.go (view raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package http_test

import (
	"errors"
	"io"
	"net/http"
	"net/http/httptest"
	"testing"

	g "alin.ovh/gomponents"
	ghttp "alin.ovh/gomponents/http"
)

func TestAdapt(t *testing.T) {
	t.Run("renders a node to the response writer", func(t *testing.T) {
		h := ghttp.Adapt(func(w http.ResponseWriter, r *http.Request) (g.Node, error) {
			return g.El("div"), nil
		})
		code, body := get(t, h)
		if code != http.StatusOK {
			t.Fatal("status code is", code)
		}
		if body != "<div></div>" {
			t.Fatal("body is", body)
		}
	})

	t.Run("renders nothing when returning nil node", func(t *testing.T) {
		h := ghttp.Adapt(func(w http.ResponseWriter, r *http.Request) (g.Node, error) {
			return nil, nil
		})
		code, body := get(t, h)
		if code != http.StatusOK {
			t.Fatal("status code is", code)
		}
		if body != "" {
			t.Fatal(`body is`, body)
		}
	})

	t.Run("errors with 500 if node cannot render", func(t *testing.T) {
		h := ghttp.Adapt(func(w http.ResponseWriter, r *http.Request) (g.Node, error) {
			return erroringNode{}, nil
		})
		code, body := get(t, h)
		if code != http.StatusInternalServerError {
			t.Fatal("status code is", code)
		}
		if body != "error rendering node: don't want to\n" {
			t.Fatal(`body is`, body)
		}
	})

	t.Run(
		"errors with status code if error implements StatusCode method and renders node",
		func(t *testing.T) {
			h := ghttp.Adapt(func(w http.ResponseWriter, r *http.Request) (g.Node, error) {
				return g.El("div"), statusCodeError{http.StatusTeapot}
			})
			code, body := get(t, h)
			if code != http.StatusTeapot {
				t.Fatal("status code is", code)
			}
			if body != "<div></div>" {
				t.Fatal(`body is`, body)
			}
		},
	)

	t.Run("errors with 500 if other error and renders node", func(t *testing.T) {
		h := ghttp.Adapt(func(w http.ResponseWriter, r *http.Request) (g.Node, error) {
			return g.El("div"), errors.New("")
		})
		code, body := get(t, h)
		if code != http.StatusInternalServerError {
			t.Fatal("status code is", code)
		}
		if body != "<div></div>" {
			t.Fatal(`body is`, body)
		}
	})
}

type erroringNode struct{}

func (n erroringNode) WriteTo(io.Writer) (int64, error) {
	return 0, errors.New("don't want to")
}

func (n erroringNode) Render(io.Writer) error {
	return errors.New("don't want to")
}

type statusCodeError struct {
	code int
}

func (e statusCodeError) Error() string {
	return http.StatusText(e.code)
}

func (e statusCodeError) StatusCode() int {
	return e.code
}

func get(t *testing.T, h http.Handler) (int, string) {
	t.Helper()

	recorder := httptest.NewRecorder()
	request, err := http.NewRequest(http.MethodGet, "/", nil)
	if err != nil {
		t.Fatal(err)
	}
	h.ServeHTTP(recorder, request)
	result := recorder.Result()
	body, err := io.ReadAll(result.Body)
	if err != nil {
		t.Fatal(err)
	}
	return result.StatusCode, string(body)
}

func ExampleAdapt() {
	h := ghttp.Adapt(func(w http.ResponseWriter, r *http.Request) (g.Node, error) {
		return g.El("div"), nil
	})
	mux := http.NewServeMux()
	mux.Handle("/", h)
}