iris/policy_test.go
Gerasimos (Makis) Maropoulos 57e5b77853 add white box tests for transaction, response writer and some of the context's method
Former-commit-id: 67ea92337f120f03e8bb96d3daa43529b10af2f2
2017-02-17 02:14:46 +02:00

190 lines
5.7 KiB
Go

package iris_test
import (
"net/http"
"testing"
. "gopkg.in/kataras/iris.v6"
"gopkg.in/kataras/iris.v6/httptest"
)
// This will be removed at the final release
// it's here just for my tests
// it will may transfered to the (advanced) examples repository
// in order to show the users how they can adapt any third-party router.
// They can also view the ./adaptors/httprouter and ./adaptors/gorillamux.
func newTestNativeRouter() Policies {
fireMethodNotAllowed := false
return Policies{
EventPolicy: EventPolicy{
Boot: func(s *Framework) {
fireMethodNotAllowed = s.Config.FireMethodNotAllowed
},
},
RouterReversionPolicy: RouterReversionPolicy{
// path normalization done on iris' side
StaticPath: func(path string) string { return path },
WildcardPath: func(requestPath string, paramName string) string { return requestPath },
URLPath: func(r RouteInfo, args ...string) string {
if r == nil {
return ""
}
// note:
// as we already know, net/http servemux doesn't provides parameterized paths so we will
// use the passed args(if any) to build the url query
path := r.Path()
if len(args) > 0 {
if len(args)%2 != 0 {
// key=value
// so the result of len args should be %2==0.
// if not return just the path.
return path
}
path += "?"
for i := 0; i < len(args)-1; i++ {
path += args[i] + "=" + args[i+1]
i++
if i != len(args)-1 {
path += "&"
}
}
}
return path
},
RouteContextLinker: func(r RouteInfo, ctx *Context) {
if r == nil {
return
}
ctx.Middleware = r.Middleware()
},
},
RouterBuilderPolicy: func(repo RouteRepository, context ContextPool) http.Handler {
servemux := http.NewServeMux()
noIndexRegistered := true
repo.Visit(func(route RouteInfo) {
path := route.Path()
if path == "/" {
noIndexRegistered = false // this goes before the handlefunc("/")
}
if path[len(path)-1] != '/' { // append a slash (net/http works this way)
path += "/"
repo.ChangePath(route, path)
}
servemux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
ctx := context.Acquire(w, r)
if ctx.Method() == route.Method() || ctx.Method() == MethodOptions && route.HasCors() {
ctx.Middleware = route.Middleware()
recorder := ctx.Recorder()
ctx.Do()
statusCode := recorder.StatusCode()
if statusCode >= 400 { // if we have an error status code try to find a custom error handler
errorHandler := ctx.Framework().Errors.Get(statusCode)
if errorHandler != nil {
// it will reset the response and write its own response by the user's handler
errorHandler.Serve(ctx)
}
}
} else if fireMethodNotAllowed {
ctx.EmitError(StatusMethodNotAllowed) // fire method not allowed if enabled
} else { // else fire not found
ctx.EmitError(StatusNotFound)
}
context.Release(ctx)
})
})
// ok, we can't bypass the net/http server.go's err handlers
// we have two options:
// - create the mux by ourselve, not an ideal because we already done two of them.
// - create a new response writer which will check once if user has registered error handler,if yes write that response instead.
// - on "/" path(which net/http fallbacks if no any registered route handler found) make if requested_path != "/" or ""
// and emit the 404 error, but for the rest of the custom errors...?
// - use our custom context's recorder to record the status code, this will be a bit slower solution(maybe not)
// but it covers all our scenarios.
if noIndexRegistered {
servemux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
context.Run(w, r, func(ctx *Context) {
ctx.EmitError(StatusNotFound)
})
})
}
return servemux
},
}
}
func h(ctx *Context) {
ctx.WriteString("hello from " + ctx.Path())
}
type testNativeRoute struct {
method, path, body string
status int
}
func TestRouterPolicyAdaptor(t *testing.T) {
expectedWrongMethodStatus := StatusNotFound
app := New(Configuration{FireMethodNotAllowed: true})
app.Adapt(newTestNativeRouter())
// 404 or 405
if app.Config.FireMethodNotAllowed {
expectedWrongMethodStatus = StatusMethodNotAllowed
}
var testRoutes = []testNativeRoute{
{"GET", "/hi", "Should be /hi/ \nhello from /hi/", StatusOK},
{"GET", "/other", "Should be /other/ \nhello from /other/", StatusOK},
{"GET", "/hi/you", "Should be /hi/you/ \nhello from /hi/you/", StatusOK},
{"POST", "/hey", "hello from /hey/", StatusOK},
{"GET", "/hey", "Method Not Allowed", expectedWrongMethodStatus},
{"GET", "/doesntexists", "<b>Custom 404 page</b>", StatusNotFound},
}
app.OnError(404, func(ctx *Context) {
ctx.HTML(404, "<b>Custom 404 page</b>")
})
app.Get("/hi", func(ctx *Context) {
ctx.Writef("Should be /hi/ \n")
ctx.Next()
}, h)
app.Get("/other", func(ctx *Context) {
ctx.Writef("Should be /other/ \n")
ctx.Next()
}, h)
app.Get("/hi/you", func(ctx *Context) {
ctx.Writef("Should be /hi/you/ \n")
ctx.Next()
}, h)
app.Post("/hey", h)
app.None("/profile", func(ctx *Context) {
userid, _ := ctx.URLParamInt("user_id")
ref := ctx.URLParam("ref")
ctx.Writef("%s\n%d", userid, ref)
}).ChangeName("profile")
e := httptest.New(app, t)
expected := "/profile/?user_id=42&ref=iris-go&something=anything"
if got := app.Path("profile", "user_id", 42, "ref", "iris-go", "something", "anything"); got != expected {
t.Fatalf("URLPath expected %s but got %s", expected, got)
}
for _, r := range testRoutes {
// post should be passed with ending / here, it's not iris-specific.
if r.method == "POST" {
r.path += "/"
}
e.Request(r.method, r.path).Expect().Status(r.status).Body().Equal(r.body).Raw()
}
}