1
0
mirror of https://github.com/volatiletech/authboss.git synced 2025-03-21 21:47:13 +02:00

Add router tests.

- Rename Endpoint to Location in ErrAndRedirect
This commit is contained in:
Aaron 2015-02-24 14:45:37 -08:00
parent e369d626a8
commit 1075149bb8
8 changed files with 244 additions and 55 deletions

View File

@ -22,30 +22,6 @@ func TestAuthBossInit(t *testing.T) {
}
}
func TestAuthBossRouter(t *testing.T) {
NewConfig()
Cfg.Storer = mockStorer{}
Cfg.CookieStoreMaker = func(_ http.ResponseWriter, _ *http.Request) ClientStorer {
return mockClientStore{}
}
Cfg.SessionStoreMaker = SessionStoreMaker(Cfg.CookieStoreMaker)
Cfg.MountPath = "/candycanes"
if err := Init(); err != nil {
t.Error("Unexpected error:", err)
}
router := NewRouter()
r, _ := http.NewRequest("GET", "/candycanes/testroute", nil)
response := httptest.NewRecorder()
router.ServeHTTP(response, r)
if response.Header().Get("testhandler") != "test" {
t.Error("Expected a header to have been set.")
}
}
func TestAuthBossCurrentUser(t *testing.T) {
NewConfig()
Cfg.Storer = mockStorer{"joe": Attributes{"email": "john@john.com", "password": "lies"}}

View File

@ -4,6 +4,7 @@ import (
"html/template"
"io"
"io/ioutil"
"net/http"
"net/smtp"
"time"
@ -32,6 +33,13 @@ type Config struct {
LayoutEmail *template.Template
LayoutDataMaker ViewDataMaker
// ErrorHandler handles would be 500 errors.
ErrorHandler http.Handler
// BadRequestHandler handles would be 400 errors.
BadRequestHandler http.Handler
// NotFoundHandler handles would be 404 errors.
NotFoundHandler http.Handler
AuthLogoutRoute string
AuthLoginSuccessRoute string

View File

@ -149,7 +149,7 @@ func (c *Confirm) confirmHandler(ctx *authboss.Context, w http.ResponseWriter, r
toHash, err := base64.URLEncoding.DecodeString(token)
if err != nil {
return authboss.ErrAndRedirect{
Endpoint: "/", Err: fmt.Errorf("confirm: token failed to decode %q => %v\n", token, err),
Location: "/", Err: fmt.Errorf("confirm: token failed to decode %q => %v\n", token, err),
}
}
@ -158,7 +158,7 @@ func (c *Confirm) confirmHandler(ctx *authboss.Context, w http.ResponseWriter, r
dbTok := base64.StdEncoding.EncodeToString(sum[:])
user, err := authboss.Cfg.Storer.(ConfirmStorer).ConfirmUser(dbTok)
if err == authboss.ErrUserNotFound {
return authboss.ErrAndRedirect{Endpoint: "/", Err: errors.New("confirm: token not found")}
return authboss.ErrAndRedirect{Location: "/", Err: errors.New("confirm: token not found")}
} else if err != nil {
return err
}

View File

@ -141,10 +141,10 @@ func TestConfirm_ConfirmHandlerErrors(t *testing.T) {
}{
{"http://localhost", false, authboss.ClientDataErr{FormValueConfirm}},
{"http://localhost?cnf=c$ats", false,
authboss.ErrAndRedirect{Endpoint: "/", Err: errors.New("confirm: token failed to decode \"c$ats\" => illegal base64 data at input byte 1\n")},
authboss.ErrAndRedirect{Location: "/", Err: errors.New("confirm: token failed to decode \"c$ats\" => illegal base64 data at input byte 1\n")},
},
{"http://localhost?cnf=SGVsbG8sIHBsYXlncm91bmQ=", false,
authboss.ErrAndRedirect{Endpoint: "/", Err: errors.New(`confirm: token not found`)},
authboss.ErrAndRedirect{Location: "/", Err: errors.New(`confirm: token not found`)},
},
}

View File

@ -40,13 +40,13 @@ func (c ClientDataErr) Error() string {
// be to redirect.
type ErrAndRedirect struct {
Err error
Endpoint string
Location string
FlashSuccess string
FlashError string
}
func (e ErrAndRedirect) Error() string {
return fmt.Sprintf("Error: %v, Redirecting to: %s", e.Err, e.Endpoint)
return fmt.Sprintf("Error: %v, Redirecting to: %s", e.Err, e.Location)
}
// RenderErr represents an error that occured during rendering

View File

@ -23,21 +23,11 @@ func testHandler(ctx *Context, w http.ResponseWriter, r *http.Request) error {
return nil
}
func (t *testModule) Initialize() error {
return nil
}
func (t *testModule) Routes() RouteTable {
return t.r
}
func (t *testModule) Storage() StorageOptions {
return t.s
}
func (t *testModule) Initialize() error { return nil }
func (t *testModule) Routes() RouteTable { return t.r }
func (t *testModule) Storage() StorageOptions { return t.s }
func TestRegister(t *testing.T) {
t.Parallel()
// RegisterModule called by TestMain.
if _, ok := modules["testmodule"]; !ok {
@ -50,8 +40,6 @@ func TestRegister(t *testing.T) {
}
func TestLoadedModules(t *testing.T) {
t.Parallel()
// RegisterModule called by TestMain.
loadedMods := LoadedModules()

View File

@ -2,6 +2,7 @@ package authboss
import (
"fmt"
"io"
"net/http"
"path"
)
@ -23,6 +24,15 @@ func NewRouter() http.Handler {
}
}
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if Cfg.NotFoundHandler != nil {
Cfg.NotFoundHandler.ServeHTTP(w, r)
} else {
w.WriteHeader(http.StatusNotFound)
io.WriteString(w, "404 Page not found")
}
})
return mux
}
@ -46,22 +56,29 @@ func (c contextRoute) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
fmt.Fprintf(Cfg.LogWriter, "Error Occurred at %s: %v", r.URL.Path, err)
switch e := err.(type) {
case AttributeErr:
w.WriteHeader(http.StatusInternalServerError)
case ClientDataErr:
w.WriteHeader(http.StatusBadRequest)
case ErrAndRedirect:
if len(e.FlashSuccess) > 0 {
ctx.CookieStorer.Put(FlashSuccessKey, e.FlashSuccess)
ctx.SessionStorer.Put(FlashSuccessKey, e.FlashSuccess)
}
if len(e.FlashError) > 0 {
ctx.CookieStorer.Put(FlashErrorKey, e.FlashError)
ctx.SessionStorer.Put(FlashErrorKey, e.FlashError)
}
http.Redirect(w, r, e.Location, http.StatusFound)
case ClientDataErr:
if Cfg.BadRequestHandler != nil {
Cfg.BadRequestHandler.ServeHTTP(w, r)
} else {
w.WriteHeader(http.StatusBadRequest)
io.WriteString(w, "400 Bad request")
}
http.Redirect(w, r, e.Endpoint, http.StatusTemporaryRedirect)
case RenderErr:
w.WriteHeader(http.StatusInternalServerError)
default:
w.WriteHeader(http.StatusInternalServerError)
if Cfg.ErrorHandler != nil {
Cfg.ErrorHandler.ServeHTTP(w, r)
} else {
w.WriteHeader(http.StatusInternalServerError)
io.WriteString(w, "500 An error has occurred")
}
}
}

200
router_test.go Normal file
View File

@ -0,0 +1,200 @@
package authboss
import (
"bytes"
"errors"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
type testRouterMod struct {
handler HandlerFunc
routes RouteTable
}
func (t testRouterMod) Initialize() error { return nil }
func (t testRouterMod) Routes() RouteTable { return t.routes }
func (t testRouterMod) Storage() StorageOptions { return nil }
func testRouterSetup() (http.Handler, *bytes.Buffer) {
Cfg = NewConfig()
Cfg.MountPath = "/prefix"
Cfg.SessionStoreMaker = func(w http.ResponseWriter, r *http.Request) ClientStorer { return mockClientStore{} }
Cfg.CookieStoreMaker = func(w http.ResponseWriter, r *http.Request) ClientStorer { return mockClientStore{} }
logger := &bytes.Buffer{}
Cfg.LogWriter = logger
return NewRouter(), logger
}
func testRouterCallbackSetup(path string, h HandlerFunc) (w *httptest.ResponseRecorder, r *http.Request) {
modules = map[string]Modularizer{
"test": testRouterMod{
routes: map[string]HandlerFunc{
path: h,
},
},
}
w = httptest.NewRecorder()
r, _ = http.NewRequest("GET", "http://localhost/prefix"+path, nil)
return w, r
}
func TestRouter(t *testing.T) {
called := false
w, r := testRouterCallbackSetup("/called", func(ctx *Context, w http.ResponseWriter, r *http.Request) error {
called = true
return nil
})
router, _ := testRouterSetup()
router.ServeHTTP(w, r)
if !called {
t.Error("Expected handler to be called.")
}
}
func TestRouter_NotFound(t *testing.T) {
router, _ := testRouterSetup()
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "http://localhost/wat", nil)
router.ServeHTTP(w, r)
if w.Code != http.StatusNotFound {
t.Error("Wrong code:", w.Code)
}
if body := w.Body.String(); body != "404 Page not found" {
t.Error("Wrong body:", body)
}
called := false
Cfg.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
called = true
})
router.ServeHTTP(w, r)
if !called {
t.Error("Should be called.")
}
}
func TestRouter_BadRequest(t *testing.T) {
err := ClientDataErr{"what"}
w, r := testRouterCallbackSetup("/badrequest",
func(ctx *Context, w http.ResponseWriter, r *http.Request) error {
return err
},
)
router, logger := testRouterSetup()
logger.Reset()
router.ServeHTTP(w, r)
if w.Code != http.StatusBadRequest {
t.Error("Wrong code:", w.Code)
}
if body := w.Body.String(); body != "400 Bad request" {
t.Error("Wrong body:", body)
}
if str := logger.String(); !strings.Contains(str, err.Error()) {
t.Error(str)
}
called := false
Cfg.BadRequestHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
called = true
})
logger.Reset()
router.ServeHTTP(w, r)
if !called {
t.Error("Should be called.")
}
if str := logger.String(); !strings.Contains(str, err.Error()) {
t.Error(str)
}
}
func TestRouter_Error(t *testing.T) {
err := errors.New("error")
w, r := testRouterCallbackSetup("/error",
func(ctx *Context, w http.ResponseWriter, r *http.Request) error {
return err
},
)
router, logger := testRouterSetup()
logger.Reset()
router.ServeHTTP(w, r)
if w.Code != http.StatusInternalServerError {
t.Error("Wrong code:", w.Code)
}
if body := w.Body.String(); body != "500 An error has occurred" {
t.Error("Wrong body:", body)
}
if str := logger.String(); !strings.Contains(str, err.Error()) {
t.Error(str)
}
called := false
Cfg.ErrorHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
called = true
})
logger.Reset()
router.ServeHTTP(w, r)
if !called {
t.Error("Should be called.")
}
if str := logger.String(); !strings.Contains(str, err.Error()) {
t.Error(str)
}
}
func TestRouter_Redirect(t *testing.T) {
err := ErrAndRedirect{
Err: errors.New("error"),
Location: "/",
FlashSuccess: "yay",
FlashError: "nay",
}
w, r := testRouterCallbackSetup("/error",
func(ctx *Context, w http.ResponseWriter, r *http.Request) error {
return err
},
)
router, logger := testRouterSetup()
session := mockClientStore{}
Cfg.SessionStoreMaker = func(w http.ResponseWriter, r *http.Request) ClientStorer { return session }
logger.Reset()
router.ServeHTTP(w, r)
if w.Code != http.StatusFound {
t.Error("Wrong code:", w.Code)
}
if loc := w.Header().Get("Location"); loc != err.Location {
t.Error("Wrong location:", loc)
}
if succ, ok := session.Get(FlashSuccessKey); !ok || succ != err.FlashSuccess {
t.Error(succ, ok)
}
if fail, ok := session.Get(FlashErrorKey); !ok || fail != err.FlashError {
t.Error(fail, ok)
}
}