fix tests and improvements

This commit is contained in:
Pedro Pérez 2024-11-20 10:56:06 +01:00
parent 7eec729f87
commit 774d1d28a0
2 changed files with 76 additions and 64 deletions

13
ron.go
View File

@ -42,6 +42,13 @@ type (
} }
) )
const (
contentType string = "Content-Type"
headerJSON string = "application/json"
headerHTML_UTF8 string = "text/html; charset=utf-8"
headerPlain_UTF8 string = "text/plain; charset=utf-8"
)
func defaultEngine() *Engine { func defaultEngine() *Engine {
return &Engine{ return &Engine{
mux: http.NewServeMux(), mux: http.NewServeMux(),
@ -165,21 +172,23 @@ func (e *Engine) Static(path, dir string) {
} }
func (c *Context) JSON(code int, data any) { func (c *Context) JSON(code int, data any) {
c.W.WriteHeader(code)
c.W.Header().Set("Content-Type", "application/json") c.W.Header().Set("Content-Type", "application/json")
encoder := json.NewEncoder(c.W) encoder := json.NewEncoder(c.W)
if err := encoder.Encode(data); err != nil { if err := encoder.Encode(data); err != nil {
http.Error(c.W, err.Error(), http.StatusInternalServerError) http.Error(c.W, err.Error(), http.StatusInternalServerError)
return
} }
c.W.WriteHeader(code)
} }
func (c *Context) HTML(code int, name string, td *TemplateData) { func (c *Context) HTML(code int, name string, td *TemplateData) {
c.W.WriteHeader(code)
c.W.Header().Set("Content-Type", "text/html; charset=utf-8") c.W.Header().Set("Content-Type", "text/html; charset=utf-8")
err := c.E.Render.Template(c.W, name, td) err := c.E.Render.Template(c.W, name, td)
if err != nil { if err != nil {
http.Error(c.W, err.Error(), http.StatusInternalServerError) http.Error(c.W, err.Error(), http.StatusInternalServerError)
return
} }
c.W.WriteHeader(code)
} }
func newLogger(level slog.Level) { func newLogger(level slog.Level) {

View File

@ -8,6 +8,18 @@ import (
"testing" "testing"
) )
func TestMain(m *testing.M) {
os.Mkdir("templates", os.ModePerm)
f, _ := os.Create("templates/page.index.gohtml")
f.WriteString("<h1>{{.Data.heading1}}</h1><h2>{{.Data.heading2}}</h2>")
f.Close()
code := m.Run()
os.RemoveAll("templates")
os.Exit(code)
}
func Test_defaultEngine(t *testing.T) { func Test_defaultEngine(t *testing.T) {
e := defaultEngine() e := defaultEngine()
if e == nil { if e == nil {
@ -268,7 +280,7 @@ func Test_Static(t *testing.T) {
f, _ := os.Create("assets/style.css") f, _ := os.Create("assets/style.css")
f.WriteString("body { background-color: red; }") f.WriteString("body { background-color: red; }")
f.Close() f.Close()
defer os.Remove("assets/style.css") defer os.RemoveAll("assets")
e := New() e := New()
e.Static("assets", "assets") e.Static("assets", "assets")
@ -289,47 +301,45 @@ type Foo struct {
} }
func Test_JSON(t *testing.T) { func Test_JSON(t *testing.T) {
tests := []struct { tests := map[string]struct {
name string givenCode int
code int givenData any
data any expectedCode int
expectedStatus int
expectedBody string
expectedHeader string expectedHeader string
expectedBody string
}{ }{
{ "valid JSON": {
name: "valid JSON", givenCode: http.StatusOK,
code: http.StatusOK, givenData: Foo{Bar: "bar", Taz: 30, Car: nil},
data: Foo{Bar: "bar", Taz: 30, Car: nil}, expectedCode: http.StatusOK,
expectedStatus: http.StatusOK, expectedHeader: headerJSON,
expectedBody: `{"bar":"bar","something":30,"car":null}` + "\n", expectedBody: `{"bar":"bar","something":30,"car":null}` + "\n",
expectedHeader: "application/json",
}, },
{ "invalid JSON": {
name: "invalid JSON", givenCode: http.StatusOK,
code: http.StatusOK, givenData: make(chan int),
data: make(chan int), expectedCode: http.StatusInternalServerError,
expectedStatus: http.StatusInternalServerError, expectedHeader: headerPlain_UTF8,
expectedBody: "json: unsupported type: chan int\n", expectedBody: "json: unsupported type: chan int\n",
expectedHeader: "application/json",
}, },
} }
for _, tt := range tests { for name, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel()
rr := httptest.NewRecorder() rr := httptest.NewRecorder()
c := &Context{ c := &Context{
W: rr, W: rr,
} }
c.JSON(tt.code, tt.data) c.JSON(tt.givenCode, tt.givenData)
if status := rr.Code; status != tt.expectedStatus { if status := rr.Code; status != tt.expectedCode {
t.Errorf("Expected status code: %d, Actual: %d", tt.expectedStatus, status) t.Errorf("Expected status code: %d, Actual: %d", tt.expectedCode, status)
} }
if rr.Header().Get("Content-Type") != tt.expectedHeader { if rr.Header().Get(contentType) != tt.expectedHeader {
t.Errorf("Expected Content-Type: %s, Actual: %s", tt.expectedHeader, rr.Header().Get("Content-Type")) t.Errorf("Expected Content-Type: %s, Actual: %s", tt.expectedHeader, rr.Header().Get(contentType))
} }
if rr.Body.String() != tt.expectedBody { if rr.Body.String() != tt.expectedBody {
@ -340,43 +350,35 @@ func Test_JSON(t *testing.T) {
} }
func Test_HTML(t *testing.T) { func Test_HTML(t *testing.T) {
os.Mkdir("templates", os.ModePerm) tests := map[string]struct {
f, _ := os.Create("templates/page.index.gohtml") givenCode int
f.WriteString("<h1>{{.Data.heading1}}</h1><h2>{{.Data.heading2}}</h2>") givenTemplate string
f.Close() givenData *TemplateData
defer os.RemoveAll("templates") expectedCode int
tests := []struct {
name string
code int
templateName string
templateData *TemplateData
expectedStatus int
expectedBody string
expectedHeader string expectedHeader string
expectedBody string
}{ }{
{ "valid HTML": {
name: "valid HTML", givenCode: http.StatusOK,
code: http.StatusOK, givenTemplate: "page.index.gohtml",
templateName: "page.index.gohtml", givenData: &TemplateData{Data: Data{"heading1": "foo", "heading2": "bar"}},
templateData: &TemplateData{Data: Data{"heading1": "foo", "heading2": "bar"}}, expectedCode: http.StatusOK,
expectedStatus: http.StatusOK, expectedHeader: headerHTML_UTF8,
expectedBody: `<h1>foo</h1><h2>bar</h2>`, expectedBody: "<h1>foo</h1><h2>bar</h2>",
expectedHeader: "text/html; charset=utf-8",
}, },
{ "template not found": {
name: "template not found", givenCode: http.StatusOK,
code: http.StatusOK, givenTemplate: "nonexistent.gohtml",
templateName: "nonexistent.gohtml", givenData: &TemplateData{Data: Data{"heading1": "foo", "heading2": "bar"}},
templateData: &TemplateData{Data: Data{"heading1": "foo", "heading2": "bar"}}, expectedCode: http.StatusInternalServerError,
expectedStatus: http.StatusInternalServerError, expectedHeader: headerPlain_UTF8,
expectedBody: "open templates/nonexistent.gohtml: no such file or directory\n", expectedBody: "can't get template from cache\n",
expectedHeader: "text/html; charset=utf-8",
}, },
} }
for _, tt := range tests { for name, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel()
rr := httptest.NewRecorder() rr := httptest.NewRecorder()
c := &Context{ c := &Context{
W: rr, W: rr,
@ -385,14 +387,14 @@ func Test_HTML(t *testing.T) {
}, },
} }
c.HTML(tt.code, tt.templateName, tt.templateData) c.HTML(tt.givenCode, tt.givenTemplate, tt.givenData)
if status := rr.Code; status != tt.expectedStatus { if status := rr.Code; status != tt.expectedCode {
t.Errorf("Expected status code: %d, Actual: %d", tt.expectedStatus, status) t.Errorf("Expected status code: %d, Actual: %d", tt.expectedCode, status)
} }
if rr.Header().Get("Content-Type") != tt.expectedHeader { if rr.Header().Get(contentType) != tt.expectedHeader {
t.Errorf("Expected Content-Type: %s, Actual: %s", tt.expectedHeader, rr.Header().Get("Content-Type")) t.Errorf("Expected Content-Type: %s, Actual: %s", tt.expectedHeader, rr.Header().Get(contentType))
} }
if rr.Body.String() != tt.expectedBody { if rr.Body.String() != tt.expectedBody {
@ -400,6 +402,7 @@ func Test_HTML(t *testing.T) {
} }
}) })
} }
} }
func Test_newLogger(t *testing.T) { func Test_newLogger(t *testing.T) {