mirror of
https://github.com/volatiletech/authboss.git
synced 2025-03-29 22:06:58 +02:00
Add router tests.
- Rename Endpoint to Location in ErrAndRedirect
This commit is contained in:
parent
e369d626a8
commit
1075149bb8
@ -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) {
|
func TestAuthBossCurrentUser(t *testing.T) {
|
||||||
NewConfig()
|
NewConfig()
|
||||||
Cfg.Storer = mockStorer{"joe": Attributes{"email": "john@john.com", "password": "lies"}}
|
Cfg.Storer = mockStorer{"joe": Attributes{"email": "john@john.com", "password": "lies"}}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"net/smtp"
|
"net/smtp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -32,6 +33,13 @@ type Config struct {
|
|||||||
LayoutEmail *template.Template
|
LayoutEmail *template.Template
|
||||||
LayoutDataMaker ViewDataMaker
|
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
|
AuthLogoutRoute string
|
||||||
AuthLoginSuccessRoute string
|
AuthLoginSuccessRoute string
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ func (c *Confirm) confirmHandler(ctx *authboss.Context, w http.ResponseWriter, r
|
|||||||
toHash, err := base64.URLEncoding.DecodeString(token)
|
toHash, err := base64.URLEncoding.DecodeString(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return authboss.ErrAndRedirect{
|
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[:])
|
dbTok := base64.StdEncoding.EncodeToString(sum[:])
|
||||||
user, err := authboss.Cfg.Storer.(ConfirmStorer).ConfirmUser(dbTok)
|
user, err := authboss.Cfg.Storer.(ConfirmStorer).ConfirmUser(dbTok)
|
||||||
if err == authboss.ErrUserNotFound {
|
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 {
|
} else if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -141,10 +141,10 @@ func TestConfirm_ConfirmHandlerErrors(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{"http://localhost", false, authboss.ClientDataErr{FormValueConfirm}},
|
{"http://localhost", false, authboss.ClientDataErr{FormValueConfirm}},
|
||||||
{"http://localhost?cnf=c$ats", false,
|
{"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,
|
{"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`)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,13 +40,13 @@ func (c ClientDataErr) Error() string {
|
|||||||
// be to redirect.
|
// be to redirect.
|
||||||
type ErrAndRedirect struct {
|
type ErrAndRedirect struct {
|
||||||
Err error
|
Err error
|
||||||
Endpoint string
|
Location string
|
||||||
FlashSuccess string
|
FlashSuccess string
|
||||||
FlashError string
|
FlashError string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e ErrAndRedirect) Error() 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
|
// RenderErr represents an error that occured during rendering
|
||||||
|
@ -23,21 +23,11 @@ func testHandler(ctx *Context, w http.ResponseWriter, r *http.Request) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *testModule) Initialize() error {
|
func (t *testModule) Initialize() error { return nil }
|
||||||
return nil
|
func (t *testModule) Routes() RouteTable { return t.r }
|
||||||
}
|
func (t *testModule) Storage() StorageOptions { return t.s }
|
||||||
|
|
||||||
func (t *testModule) Routes() RouteTable {
|
|
||||||
return t.r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *testModule) Storage() StorageOptions {
|
|
||||||
return t.s
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRegister(t *testing.T) {
|
func TestRegister(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// RegisterModule called by TestMain.
|
// RegisterModule called by TestMain.
|
||||||
|
|
||||||
if _, ok := modules["testmodule"]; !ok {
|
if _, ok := modules["testmodule"]; !ok {
|
||||||
@ -50,8 +40,6 @@ func TestRegister(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadedModules(t *testing.T) {
|
func TestLoadedModules(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// RegisterModule called by TestMain.
|
// RegisterModule called by TestMain.
|
||||||
|
|
||||||
loadedMods := LoadedModules()
|
loadedMods := LoadedModules()
|
||||||
|
37
router.go
37
router.go
@ -2,6 +2,7 @@ package authboss
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"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
|
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)
|
fmt.Fprintf(Cfg.LogWriter, "Error Occurred at %s: %v", r.URL.Path, err)
|
||||||
|
|
||||||
switch e := err.(type) {
|
switch e := err.(type) {
|
||||||
case AttributeErr:
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
case ClientDataErr:
|
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
|
||||||
case ErrAndRedirect:
|
case ErrAndRedirect:
|
||||||
if len(e.FlashSuccess) > 0 {
|
if len(e.FlashSuccess) > 0 {
|
||||||
ctx.CookieStorer.Put(FlashSuccessKey, e.FlashSuccess)
|
ctx.SessionStorer.Put(FlashSuccessKey, e.FlashSuccess)
|
||||||
}
|
}
|
||||||
if len(e.FlashError) > 0 {
|
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:
|
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
200
router_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user