add middlewares and grouping routes
This commit is contained in:
parent
8e9f348150
commit
c4983ee36d
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
logs/
|
logs/
|
||||||
|
.idea/
|
||||||
79
ron.go
79
ron.go
@ -17,6 +17,8 @@ type (
|
|||||||
|
|
||||||
Data map[string]any
|
Data map[string]any
|
||||||
|
|
||||||
|
Middleware func(http.Handler) http.Handler
|
||||||
|
|
||||||
Context struct {
|
Context struct {
|
||||||
C context.Context
|
C context.Context
|
||||||
W http.ResponseWriter
|
W http.ResponseWriter
|
||||||
@ -26,14 +28,24 @@ type (
|
|||||||
|
|
||||||
Engine struct {
|
Engine struct {
|
||||||
mux *http.ServeMux
|
mux *http.ServeMux
|
||||||
|
middleware []Middleware
|
||||||
|
groupMux map[string]*groupMux
|
||||||
LogLevel slog.Level
|
LogLevel slog.Level
|
||||||
Render *Render
|
Render *Render
|
||||||
}
|
}
|
||||||
|
|
||||||
|
groupMux struct {
|
||||||
|
prefix string
|
||||||
|
mux *http.ServeMux
|
||||||
|
middleware []Middleware
|
||||||
|
engine *Engine
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func defaultEngine() *Engine {
|
func defaultEngine() *Engine {
|
||||||
return &Engine{
|
return &Engine{
|
||||||
mux: http.NewServeMux(),
|
mux: http.NewServeMux(),
|
||||||
|
groupMux: make(map[string]*groupMux),
|
||||||
LogLevel: slog.LevelInfo,
|
LogLevel: slog.LevelInfo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,7 +66,16 @@ func (e *Engine) apply(opts ...EngineOptions) *Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
e.handleRequest(w, r)
|
var handler http.Handler = e.mux
|
||||||
|
for prefix, group := range e.groupMux {
|
||||||
|
if strings.HasPrefix(r.URL.Path, prefix) {
|
||||||
|
handler = createStack(group.middleware...)(handler)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler = createStack(e.middleware...)(handler)
|
||||||
|
handler.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) Run(addr string) error {
|
func (e *Engine) Run(addr string) error {
|
||||||
@ -62,30 +83,62 @@ func (e *Engine) Run(addr string) error {
|
|||||||
return http.ListenAndServe(addr, e)
|
return http.ListenAndServe(addr, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) handleRequest(w http.ResponseWriter, r *http.Request) {
|
func createStack(xs ...Middleware) Middleware {
|
||||||
e.mux.ServeHTTP(w, r)
|
return func(next http.Handler) http.Handler {
|
||||||
|
for i := len(xs) - 1; i >= 0; i-- {
|
||||||
|
x := xs[i]
|
||||||
|
next = x(next)
|
||||||
|
}
|
||||||
|
return next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Engine) USE(middleware Middleware) {
|
||||||
|
e.middleware = append(e.middleware, middleware)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) GET(path string, handler func(*Context)) {
|
func (e *Engine) GET(path string, handler func(*Context)) {
|
||||||
e.mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
|
e.mux.HandleFunc(fmt.Sprintf("GET %s", path), func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != http.MethodGet {
|
|
||||||
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
handler(&Context{W: w, R: r, E: e})
|
handler(&Context{W: w, R: r, E: e})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) POST(path string, handler func(*Context)) {
|
func (e *Engine) POST(path string, handler func(*Context)) {
|
||||||
e.mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
|
e.mux.HandleFunc(fmt.Sprintf("POST %s", path), func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != http.MethodPost {
|
|
||||||
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
handler(&Context{W: w, R: r, E: e})
|
handler(&Context{W: w, R: r, E: e})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Engine) GROUP(prefix string) *groupMux {
|
||||||
|
if _, ok := e.groupMux[prefix]; !ok {
|
||||||
|
e.groupMux[prefix] = &groupMux{
|
||||||
|
prefix: prefix,
|
||||||
|
mux: http.NewServeMux(),
|
||||||
|
engine: e,
|
||||||
|
}
|
||||||
|
|
||||||
|
e.mux.Handle(prefix+"/", http.StripPrefix(prefix, e.groupMux[prefix].mux))
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.groupMux[prefix]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *groupMux) USE(middleware Middleware) {
|
||||||
|
g.middleware = append(g.middleware, middleware)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *groupMux) GET(path string, handler func(*Context)) {
|
||||||
|
g.mux.HandleFunc(fmt.Sprintf("GET %s", path), func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
handler(&Context{W: w, R: r, E: g.engine})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *groupMux) POST(path string, handler func(*Context)) {
|
||||||
|
g.mux.HandleFunc(fmt.Sprintf("POST %s", path), func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
handler(&Context{W: w, R: r, E: g.engine})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Static serves static files from a specified directory, accessible through a defined URL path.
|
// Static serves static files from a specified directory, accessible through a defined URL path.
|
||||||
//
|
//
|
||||||
// The `path` parameter represents the URL prefix to access the static files.
|
// The `path` parameter represents the URL prefix to access the static files.
|
||||||
|
|||||||
339
ron_test.go
339
ron_test.go
@ -1,6 +1,7 @@
|
|||||||
package ron
|
package ron
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
@ -39,32 +40,126 @@ func Test_applyEngineConfig(t *testing.T) {
|
|||||||
|
|
||||||
func Test_ServeHTTP(t *testing.T) {
|
func Test_ServeHTTP(t *testing.T) {
|
||||||
e := New()
|
e := New()
|
||||||
rr := httptest.NewRecorder()
|
api := e.GROUP("/api")
|
||||||
req, _ := http.NewRequest("GET", "/", nil)
|
api.GET("/index", func(c *Context) {
|
||||||
e.ServeHTTP(rr, req)
|
|
||||||
|
|
||||||
if status := rr.Code; status != http.StatusNotFound {
|
|
||||||
t.Errorf("Expected status code: %d, Actual: %d", http.StatusNotFound, status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_GET(t *testing.T) {
|
|
||||||
e := New()
|
|
||||||
e.GET("/", func(c *Context) {
|
|
||||||
c.W.WriteHeader(http.StatusOK)
|
c.W.WriteHeader(http.StatusOK)
|
||||||
c.W.Write([]byte("GET"))
|
c.W.Write([]byte("GET API"))
|
||||||
})
|
})
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
req, _ := http.NewRequest("GET", "/", nil)
|
req, _ := http.NewRequest("GET", "/api/index", nil)
|
||||||
e.ServeHTTP(rr, req)
|
e.ServeHTTP(rr, req)
|
||||||
|
|
||||||
if status := rr.Code; status != http.StatusOK {
|
if status := rr.Code; status != http.StatusOK {
|
||||||
t.Errorf("Expected status code: %d, Actual: %d", http.StatusOK, status)
|
t.Errorf("Expected status code: %d, Actual: %d", http.StatusOK, status)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if rr.Body.String() != "GET" {
|
func Test_RUN(t *testing.T) {
|
||||||
t.Errorf("Expected: GET, Actual: %s", rr.Body.String())
|
e := New()
|
||||||
|
go func() {
|
||||||
|
e.Run(":8080")
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_createStack(t *testing.T) {
|
||||||
|
m1 := func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("Middleware 1"))
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
m2 := func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("Middleware 2"))
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
stack := createStack(m1, m2)
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
req, _ := http.NewRequest("GET", "/", nil)
|
||||||
|
stack(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("Handler"))
|
||||||
|
})).ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
if rr.Body.String() != "Middleware 1Middleware 2Handler" {
|
||||||
|
t.Errorf("Expected: Middleware 1Middleware 2Handler, Actual: %s", rr.Body.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_USE(t *testing.T) {
|
||||||
|
e := New()
|
||||||
|
m1 := func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("Middleware 1"))
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
m2 := func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("Middleware 2"))
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
e.USE(m1)
|
||||||
|
e.USE(m2)
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
req, _ := http.NewRequest("GET", "/", nil)
|
||||||
|
e.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
if rr.Body.String() != "Middleware 1Middleware 2404 page not found\n" {
|
||||||
|
t.Errorf("Expected: Middleware 1Middleware 2Handler, Actual: %s", rr.Body.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_GET(t *testing.T) {
|
||||||
|
e := New()
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
method string
|
||||||
|
path string
|
||||||
|
expectedStatus int
|
||||||
|
expectedBody string
|
||||||
|
}{
|
||||||
|
{"root endpoint", "GET", "/", http.StatusOK, "GET Root"},
|
||||||
|
{"api endpoint", "GET", "/api", http.StatusOK, "GET API"},
|
||||||
|
{"api endpoint with version", "GET", "/api/v1", http.StatusOK, "GET API v1"},
|
||||||
|
{"resource with param", "GET", "/api/v1/resource/1", http.StatusOK, "GET Resource"},
|
||||||
|
}
|
||||||
|
|
||||||
|
e.GET("/", func(c *Context) {
|
||||||
|
c.W.WriteHeader(http.StatusOK)
|
||||||
|
c.W.Write([]byte("GET Root"))
|
||||||
|
})
|
||||||
|
e.GET("/api", func(c *Context) {
|
||||||
|
c.W.WriteHeader(http.StatusOK)
|
||||||
|
c.W.Write([]byte("GET API"))
|
||||||
|
})
|
||||||
|
e.GET("/api/v1", func(c *Context) {
|
||||||
|
c.W.WriteHeader(http.StatusOK)
|
||||||
|
c.W.Write([]byte("GET API v1"))
|
||||||
|
})
|
||||||
|
e.GET("/api/v1/resource/{id}", func(c *Context) {
|
||||||
|
c.W.WriteHeader(http.StatusOK)
|
||||||
|
c.W.Write([]byte("GET Resource"))
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
req, _ := http.NewRequest(tt.method, tt.path, nil)
|
||||||
|
e.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
if rr.Code != tt.expectedStatus {
|
||||||
|
t.Errorf("Expected status code: %d, Actual: %d", tt.expectedStatus, rr.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rr.Body.String() != tt.expectedBody {
|
||||||
|
t.Errorf("Expected body: %q, Actual: %q", tt.expectedBody, rr.Body.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,6 +183,86 @@ func Test_POST(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_GROUP(t *testing.T) {
|
||||||
|
e := New()
|
||||||
|
api := e.GROUP("/api")
|
||||||
|
api.GET("/index", func(c *Context) {
|
||||||
|
c.W.WriteHeader(http.StatusOK)
|
||||||
|
c.W.Write([]byte("GET API"))
|
||||||
|
})
|
||||||
|
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
req, _ := http.NewRequest("GET", "/api/index", nil)
|
||||||
|
e.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
if status := rr.Code; status != http.StatusOK {
|
||||||
|
t.Errorf("Expected status code: %d, Actual: %d", http.StatusOK, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rr.Body.String() != "GET API" {
|
||||||
|
t.Errorf("Expected: GET API, Actual: %s", rr.Body.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_GROUPWithMiddleware(t *testing.T) {
|
||||||
|
e := New()
|
||||||
|
e.GET("/index", func(c *Context) {
|
||||||
|
c.W.WriteHeader(http.StatusOK)
|
||||||
|
c.W.Write([]byte("GET Root"))
|
||||||
|
})
|
||||||
|
e.USE(func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("Middleware 1"))
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
api := e.GROUP("/api")
|
||||||
|
api.USE(func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("Middleware 2"))
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
api.GET("/index", func(c *Context) {
|
||||||
|
c.W.WriteHeader(http.StatusOK)
|
||||||
|
c.W.Write([]byte("GET API"))
|
||||||
|
})
|
||||||
|
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
req, _ := http.NewRequest("GET", "/api/index", nil)
|
||||||
|
e.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
if status := rr.Code; status != http.StatusOK {
|
||||||
|
t.Errorf("Expected status code: %d, Actual: %d", http.StatusOK, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rr.Body.String() != "Middleware 1Middleware 2GET API" {
|
||||||
|
t.Errorf("Expected: Middleware 1Middleware 2GET API, Actual: %s", rr.Body.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_GROUPPOST(t *testing.T) {
|
||||||
|
e := New()
|
||||||
|
api := e.GROUP("/api")
|
||||||
|
api.POST("/index", func(c *Context) {
|
||||||
|
c.W.WriteHeader(http.StatusOK)
|
||||||
|
c.W.Write([]byte("POST API"))
|
||||||
|
})
|
||||||
|
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
req, _ := http.NewRequest("POST", "/api/index", nil)
|
||||||
|
e.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
if status := rr.Code; status != http.StatusOK {
|
||||||
|
t.Errorf("Expected status code: %d, Actual: %d", http.StatusOK, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rr.Body.String() != "POST API" {
|
||||||
|
t.Errorf("Expected: POST API, Actual: %s", rr.Body.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Test_Static(t *testing.T) {
|
func Test_Static(t *testing.T) {
|
||||||
os.Mkdir("assets", os.ModePerm)
|
os.Mkdir("assets", os.ModePerm)
|
||||||
f, _ := os.Create("assets/style.css")
|
f, _ := os.Create("assets/style.css")
|
||||||
@ -114,29 +289,53 @@ type Foo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_JSON(t *testing.T) {
|
func Test_JSON(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
code int
|
||||||
|
data any
|
||||||
|
expectedStatus int
|
||||||
|
expectedBody string
|
||||||
|
expectedHeader string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "valid JSON",
|
||||||
|
code: http.StatusOK,
|
||||||
|
data: Foo{Bar: "bar", Taz: 30, Car: nil},
|
||||||
|
expectedStatus: http.StatusOK,
|
||||||
|
expectedBody: `{"bar":"bar","something":30,"car":null}` + "\n",
|
||||||
|
expectedHeader: "application/json",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid JSON",
|
||||||
|
code: http.StatusOK,
|
||||||
|
data: make(chan int),
|
||||||
|
expectedStatus: http.StatusInternalServerError,
|
||||||
|
expectedBody: "json: unsupported type: chan int\n",
|
||||||
|
expectedHeader: "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
c := &Context{
|
c := &Context{
|
||||||
W: rr,
|
W: rr,
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := `{"bar":"bar","something":30,"car":null}`
|
c.JSON(tt.code, tt.data)
|
||||||
|
|
||||||
c.JSON(http.StatusOK, Foo{
|
if status := rr.Code; status != tt.expectedStatus {
|
||||||
Bar: "bar",
|
t.Errorf("Expected status code: %d, Actual: %d", tt.expectedStatus, status)
|
||||||
Taz: 30,
|
}
|
||||||
Car: nil,
|
|
||||||
|
if rr.Header().Get("Content-Type") != tt.expectedHeader {
|
||||||
|
t.Errorf("Expected Content-Type: %s, Actual: %s", tt.expectedHeader, rr.Header().Get("Content-Type"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if rr.Body.String() != tt.expectedBody {
|
||||||
|
t.Errorf("Expected body: %q, Actual: %q", tt.expectedBody, rr.Body.String())
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if status := rr.Code; status != http.StatusOK {
|
|
||||||
t.Errorf("Expected status code: %d, Actual: %d", http.StatusOK, status)
|
|
||||||
}
|
|
||||||
|
|
||||||
if rr.Header().Get("Content-Type") != "application/json" {
|
|
||||||
t.Errorf("Expected Content-Type: application/json, Actual: %s", c.W.Header().Get("Content-Type"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if rr.Body.String() != string(expected)+"\n" {
|
|
||||||
t.Errorf("Expected: %s, Actual: %s", string(expected), rr.Body.String())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,6 +346,37 @@ func Test_HTML(t *testing.T) {
|
|||||||
f.Close()
|
f.Close()
|
||||||
defer os.RemoveAll("templates")
|
defer os.RemoveAll("templates")
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
code int
|
||||||
|
templateName string
|
||||||
|
templateData *TemplateData
|
||||||
|
expectedStatus int
|
||||||
|
expectedBody string
|
||||||
|
expectedHeader string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "valid HTML",
|
||||||
|
code: http.StatusOK,
|
||||||
|
templateName: "page.index.gohtml",
|
||||||
|
templateData: &TemplateData{Data: Data{"heading1": "foo", "heading2": "bar"}},
|
||||||
|
expectedStatus: http.StatusOK,
|
||||||
|
expectedBody: `<h1>foo</h1><h2>bar</h2>`,
|
||||||
|
expectedHeader: "text/html; charset=utf-8",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "template not found",
|
||||||
|
code: http.StatusOK,
|
||||||
|
templateName: "nonexistent.gohtml",
|
||||||
|
templateData: &TemplateData{Data: Data{"heading1": "foo", "heading2": "bar"}},
|
||||||
|
expectedStatus: http.StatusInternalServerError,
|
||||||
|
expectedBody: "open templates/nonexistent.gohtml: no such file or directory\n",
|
||||||
|
expectedHeader: "text/html; charset=utf-8",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
c := &Context{
|
c := &Context{
|
||||||
W: rr,
|
W: rr,
|
||||||
@ -155,24 +385,43 @@ func Test_HTML(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := `<h1>foo</h1><h2>bar</h2>`
|
c.HTML(tt.code, tt.templateName, tt.templateData)
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "page.index.gohtml", &TemplateData{
|
if status := rr.Code; status != tt.expectedStatus {
|
||||||
Data: Data{
|
t.Errorf("Expected status code: %d, Actual: %d", tt.expectedStatus, status)
|
||||||
"heading1": "foo",
|
}
|
||||||
"heading2": "bar",
|
|
||||||
},
|
if rr.Header().Get("Content-Type") != tt.expectedHeader {
|
||||||
|
t.Errorf("Expected Content-Type: %s, Actual: %s", tt.expectedHeader, rr.Header().Get("Content-Type"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if rr.Body.String() != tt.expectedBody {
|
||||||
|
t.Errorf("Expected body: %q, Actual: %q", tt.expectedBody, rr.Body.String())
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
if status := rr.Code; status != http.StatusOK {
|
|
||||||
t.Errorf("Expected status code: %d, Actual: %d", http.StatusOK, status)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if rr.Header().Get("Content-Type") != "text/html; charset=utf-8" {
|
func Test_newLogger(t *testing.T) {
|
||||||
t.Errorf("Expected Content-Type: text/html; charset=utf-8, Actual: %s", c.W.Header().Get("Content-Type"))
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
level slog.Level
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"valid level", 1, false},
|
||||||
|
{"invalid level", -1, true},
|
||||||
}
|
}
|
||||||
|
|
||||||
if rr.Body.String() != string(expected) {
|
for _, tt := range tests {
|
||||||
t.Errorf("Expected: %s, Actual: %s", string(expected), rr.Body.String())
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
if !tt.wantErr {
|
||||||
|
t.Errorf("newLogger() panicked: %v", r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
newLogger(tt.level)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user