diff options
| -rw-r--r-- | context_test.go | 64 | ||||
| -rw-r--r-- | engine.go (renamed from api.go) | 0 | ||||
| -rw-r--r-- | engine_test.go | 114 | ||||
| -rw-r--r-- | router_test.go | 79 | ||||
| -rw-r--r-- | test/main.go | 79 |
5 files changed, 257 insertions, 79 deletions
diff --git a/context_test.go b/context_test.go new file mode 100644 index 0000000..560d9f5 --- /dev/null +++ b/context_test.go @@ -0,0 +1,64 @@ +package growel + +import ( + "net/http" + "net/http/httptest" + "strings" + "testing" +) + +func TestContextPlain(t *testing.T) { + w := httptest.NewRecorder() + c := &Context{W: w} + + c.Plain(201, "ok") + + if w.Code != 201 { + t.Fatalf("expected 201, got %d", w.Code) + } + if ct := w.Header().Get("Content-Type"); !strings.Contains(ct, "text/plain") { + t.Fatalf("wrong content-type: %s", ct) + } + if w.Body.String() != "ok" { + t.Fatalf("wrong body: %s", w.Body.String()) + } +} + +func TestContextJSON(t *testing.T) { + w := httptest.NewRecorder() + c := &Context{W: w} + + c.JSON(200, map[string]string{"x": "y"}) + + if w.Code != 200 { + t.Fatalf("expected 200, got %d", w.Code) + } + if ct := w.Header().Get("Content-Type"); !strings.Contains(ct, "application/json") { + t.Fatalf("unexpected content-type: %s", ct) + } + if !strings.Contains(w.Body.String(), `"x":"y"`) { + t.Fatalf("wrong json: %s", w.Body.String()) + } +} + +func TestContextError(t *testing.T) { + w := httptest.NewRecorder() + c := &Context{W: w} + + c.Error(http.StatusBadRequest, "bad input") + + if w.Code != 400 { + t.Fatalf("expected 400, got %d", w.Code) + } + + body := w.Body.String() + if !strings.Contains(body, `"error":"Bad Request"`) { + t.Fatalf("missing human readable status: %s", body) + } + if !strings.Contains(body, `"message":"bad input"`) { + t.Fatalf("missing message: %s", body) + } + if !strings.Contains(body, `"status":"400"`) { + t.Fatalf("missing status field: %s", body) + } +} diff --git a/engine_test.go b/engine_test.go new file mode 100644 index 0000000..12ec2c6 --- /dev/null +++ b/engine_test.go @@ -0,0 +1,114 @@ +package growel + +import ( + "net/http/httptest" + "strings" + "testing" +) + +func setupEngine() *Engine { + e := New() + + e.GET("/", func(c *Context) { + c.Plain(200, "home") + }) + + e.GET("/hello", func(c *Context) { + c.JSON(200, map[string]string{"msg": "hi"}) + }) + + e.GET("/user/:id", func(c *Context) { + c.JSON(200, map[string]string{"id": c.Params["id"]}) + }) + + e.GET("/error", func(c *Context) { + c.BadRequest("bad") + }) + + return e +} + +func TestEngineStaticRoute(t *testing.T) { + e := setupEngine() + + req := httptest.NewRequest("GET", "/", nil) + w := httptest.NewRecorder() + e.ServeHTTP(w, req) + + if w.Code != 200 { + t.Fatalf("expected 200, got %d", w.Code) + } + + if w.Body.String() != "home" { + t.Fatalf("expected body 'home', got %q", w.Body.String()) + } +} + +func TestEngineJSONRoute(t *testing.T) { + e := setupEngine() + + req := httptest.NewRequest("GET", "/hello", nil) + w := httptest.NewRecorder() + e.ServeHTTP(w, req) + + if w.Code != 200 { + t.Fatalf("expected 200, got %d", w.Code) + } + + if !strings.Contains(w.Body.String(), `"msg":"hi"`) { + t.Fatalf("unexpected json: %s", w.Body.String()) + } +} + +func TestEngineParamRoute(t *testing.T) { + e := setupEngine() + + req := httptest.NewRequest("GET", "/user/99", nil) + w := httptest.NewRecorder() + e.ServeHTTP(w, req) + + if w.Code != 200 { + t.Fatalf("expected 200, got %d", w.Code) + } + + if !strings.Contains(w.Body.String(), `"id":"99"`) { + t.Fatalf("unexpected json: %s", w.Body.String()) + } +} + +func TestEngineNotFound(t *testing.T) { + e := setupEngine() + + req := httptest.NewRequest("GET", "/doesnotexist", nil) + w := httptest.NewRecorder() + e.ServeHTTP(w, req) + + if w.Code != 404 { + t.Fatalf("expected 404, got %d", w.Code) + } +} + +func TestEngineErrorResponse(t *testing.T) { + e := setupEngine() + + req := httptest.NewRequest("GET", "/error", nil) + w := httptest.NewRecorder() + e.ServeHTTP(w, req) + + if w.Code != 400 { + t.Fatalf("expected 400, got %d", w.Code) + } + + body := w.Body.String() + if !strings.Contains(body, `"error":"Bad Request"`) { + t.Fatalf("missing error text: %s", body) + } + + if !strings.Contains(body, `"message":"bad"`) { + t.Fatalf("missing message: %s", body) + } + + if !strings.Contains(body, `"status":"400"`) { + t.Fatalf("missing status code: %s", body) + } +} diff --git a/router_test.go b/router_test.go new file mode 100644 index 0000000..24a2faa --- /dev/null +++ b/router_test.go @@ -0,0 +1,79 @@ +package growel + +import ( + "testing" +) + +func dummy(c *Context) {} + +func TestRouterStaticMatch(t *testing.T) { + r := NewRouter() + r.Add("GET", "/hello", dummy) + + h, params := r.Find("GET", "/hello") + if h == nil { + t.Fatal("expected handler, got nil") + } + if len(params) != 0 { + t.Fatalf("expected no params, got %v", params) + } +} + +func TestRouterStaticNoMatch(t *testing.T) { + r := NewRouter() + r.Add("GET", "/hello", dummy) + + h, _ := r.Find("GET", "/nothello") + if h != nil { + t.Fatal("expected nil handler, got non-nil") + } +} + +func TestRouterParamMatch(t *testing.T) { + r := NewRouter() + r.Add("GET", "/user/:id", dummy) + + h, params := r.Find("GET", "/user/42") + if h == nil { + t.Fatal("expected handler, got nil") + } + if params["id"] != "42" { + t.Fatalf("expected id=42, got %v", params) + } +} + +func TestRouterParamMismatch(t *testing.T) { + r := NewRouter() + r.Add("GET", "/user/:id", dummy) + + h, _ := r.Find("GET", "/user") + if h != nil { + t.Fatal("expected nil handler, got non-nil") + } +} + +func TestRouterSplitPath(t *testing.T) { + r := NewRouter() + + tests := []struct { + input string + want []string + }{ + {"/", []string{""}}, + {"/hello", []string{"hello"}}, + {"/hello/world", []string{"hello", "world"}}, + {"//hello//world//", []string{"hello", "", "world"}}, + } + + for _, tt := range tests { + got := r.splitPath(tt.input) + if len(got) != len(tt.want) { + t.Fatalf("splitPath(%q) length mismatch: got %v want %v", tt.input, got, tt.want) + } + for i := range got { + if got[i] != tt.want[i] { + t.Fatalf("splitPath(%q) mismatch: got %v want %v", tt.input, got, tt.want) + } + } + } +} diff --git a/test/main.go b/test/main.go deleted file mode 100644 index 1f6c36b..0000000 --- a/test/main.go +++ /dev/null @@ -1,79 +0,0 @@ -package main - -import ( - "github.com/bigcoke233/growel/v2" - "strconv" -) - -type User struct { - ID int `json:"id"` - Name string `json:"name"` - Group string `json:"group"` -} - -var Users = []User{ - {ID: 1, Name: "Alice Chen", Group: "admin"}, - {ID: 2, Name: "Bob Wu", Group: "admin"}, - - {ID: 3, Name: "Cynthia Lin", Group: "staff"}, - {ID: 4, Name: "Daniel Zhao", Group: "staff"}, - {ID: 5, Name: "Emma Huang", Group: "staff"}, - - {ID: 6, Name: "Felix Sun", Group: "editor"}, - {ID: 7, Name: "Grace Liu", Group: "editor"}, - - {ID: 8, Name: "Henry Qiu", Group: "guest"}, - {ID: 9, Name: "Ivy Xu", Group: "guest"}, - {ID: 10, Name: "Jack Ma", Group: "guest"}, - - {ID: 11, Name: "Karen He", Group: "beta"}, - {ID: 12, Name: "Leo Fang", Group: "beta"}, - - {ID: 13, Name: "Mia Tang", Group: "test"}, - {ID: 14, Name: "Noah Jin", Group: "test"}, - {ID: 15, Name: "Olivia Ding", Group: "test"}, - - {ID: 16, Name: "Peter Yan", Group: "ops"}, - {ID: 17, Name: "Queena Zhou", Group: "ops"}, - {ID: 18, Name: "Ryan Li", Group: "ops"}, - - {ID: 19, Name: "Sophia Wang", Group: "support"}, - {ID: 20, Name: "Tony Du", Group: "support"}, -} - -func main() { - api := growel.New() - - api.GET("/", func(c *growel.Context) { - c.Plain(200, "This is home.") - }) - - api.GET("/hello", func(c *growel.Context) { - c.JSON(200, map[string]string{ - "message": "Hello Growel!", - }) - }) - - api.GET("/user/", func(c *growel.Context) { - c.JSON(200, Users) - }) - - api.GET("/user/:uid", func(c *growel.Context) { - uid, err := strconv.Atoi(c.Params["uid"]) - if err != nil { - c.BadRequest("Invalid user ID") - return - } - - for _, user := range Users { - if user.ID == uid { - c.JSON(200, user) - return - } - } - - c.NotFound("User not found") - }) - - api.Start(":8080") -} |
