This commit is contained in:
Stavros
2026-03-12 16:17:16 +02:00
parent b2a1bfb1f5
commit 8c8a9e93ff
4 changed files with 201 additions and 121 deletions

View File

@@ -2,77 +2,77 @@ package controller_test
import ( import (
"encoding/json" "encoding/json"
"net/http/httptest" "io"
"net/http"
"testing" "testing"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/controller"
"github.com/steveiliop56/tinyauth/internal/utils/tlog"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/steveiliop56/tinyauth/internal/controller"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
) )
var contextControllerCfg = controller.ContextControllerConfig{ func TestUserContextController(t *testing.T) {
Providers: []controller.Provider{ // Controller setup
{ suite := NewControllerTest(func(router *gin.RouterGroup) *controller.ContextController {
Name: "Local", ctrl := controller.NewContextController(contextControllerCfg, router)
ID: "local", ctrl.SetupRoutes()
OAuth: false, return ctrl
})
// Test user context
req, err := http.NewRequest("GET", "/api/context/user", nil)
assert.NilError(t, err)
ctx := testContext
ctx.IsLoggedIn = true
ctx.Provider = "local"
expected, err := json.Marshal(controller.UserContextResponse{
Status: 200,
Message: "Success",
IsLoggedIn: ctx.IsLoggedIn,
Username: ctx.Username,
Name: ctx.Name,
Email: ctx.Email,
Provider: ctx.Provider,
OAuth: ctx.OAuth,
TotpPending: ctx.TotpPending,
OAuthName: ctx.OAuthName,
})
assert.NilError(t, err)
resp := suite.RequestWithMiddleware(req, []gin.HandlerFunc{
func(c *gin.Context) {
c.Set("context", &ctx)
}, },
{ })
Name: "Google",
ID: "google",
OAuth: true,
},
},
Title: "Test App",
AppURL: "http://localhost:8080",
CookieDomain: "localhost",
ForgotPasswordMessage: "Contact admin to reset your password.",
BackgroundImage: "/assets/bg.jpg",
OAuthAutoRedirect: "google",
WarningsEnabled: true,
}
var contextCtrlTestContext = config.UserContext{ assert.Equal(t, http.StatusOK, resp.Code)
Username: "testuser", bytes, err := io.ReadAll(resp.Body)
Name: "testuser", assert.NilError(t, err)
Email: "test@example.com", assert.DeepEqual(t, expected, bytes)
IsLoggedIn: true,
IsBasicAuth: false,
OAuth: false,
Provider: "local",
TotpPending: false,
OAuthGroups: "",
TotpEnabled: false,
OAuthSub: "",
}
func setupContextController(middlewares *[]gin.HandlerFunc) (*gin.Engine, *httptest.ResponseRecorder) { // Ensure user context is not available when not logged in
tlog.NewSimpleLogger().Init() req, err = http.NewRequest("GET", "/api/context/user", nil)
assert.NilError(t, err)
// Setup expected, err = json.Marshal(controller.UserContextResponse{
gin.SetMode(gin.TestMode) Status: http.StatusUnauthorized,
router := gin.Default() Message: "Unauthorized",
recorder := httptest.NewRecorder() })
assert.NilError(t, err)
if middlewares != nil { resp = suite.RequestWithMiddleware(req, nil)
for _, m := range *middlewares { assert.Equal(t, 200, resp.Code)
router.Use(m) bytes, err = io.ReadAll(resp.Body)
} assert.NilError(t, err)
} assert.DeepEqual(t, expected, bytes)
group := router.Group("/api") // Test app context
req, err = http.NewRequest("GET", "/api/context/app", nil)
assert.NilError(t, err)
ctrl := controller.NewContextController(contextControllerCfg, group) expected, err = json.Marshal(controller.AppContextResponse{
ctrl.SetupRoutes()
return router, recorder
}
func TestAppContextHandler(t *testing.T) {
expectedRes := controller.AppContextResponse{
Status: 200, Status: 200,
Message: "Success", Message: "Success",
Providers: contextControllerCfg.Providers, Providers: contextControllerCfg.Providers,
@@ -83,71 +83,13 @@ func TestAppContextHandler(t *testing.T) {
BackgroundImage: contextControllerCfg.BackgroundImage, BackgroundImage: contextControllerCfg.BackgroundImage,
OAuthAutoRedirect: contextControllerCfg.OAuthAutoRedirect, OAuthAutoRedirect: contextControllerCfg.OAuthAutoRedirect,
WarningsEnabled: contextControllerCfg.WarningsEnabled, WarningsEnabled: contextControllerCfg.WarningsEnabled,
}
router, recorder := setupContextController(nil)
req := httptest.NewRequest("GET", "/api/context/app", nil)
router.ServeHTTP(recorder, req)
assert.Equal(t, 200, recorder.Code)
var ctrlRes controller.AppContextResponse
err := json.Unmarshal(recorder.Body.Bytes(), &ctrlRes)
assert.NilError(t, err)
assert.DeepEqual(t, expectedRes, ctrlRes)
}
func TestUserContextHandler(t *testing.T) {
expectedRes := controller.UserContextResponse{
Status: 200,
Message: "Success",
IsLoggedIn: contextCtrlTestContext.IsLoggedIn,
Username: contextCtrlTestContext.Username,
Name: contextCtrlTestContext.Name,
Email: contextCtrlTestContext.Email,
Provider: contextCtrlTestContext.Provider,
OAuth: contextCtrlTestContext.OAuth,
TotpPending: contextCtrlTestContext.TotpPending,
OAuthName: contextCtrlTestContext.OAuthName,
}
// Test with context
router, recorder := setupContextController(&[]gin.HandlerFunc{
func(c *gin.Context) {
c.Set("context", &contextCtrlTestContext)
c.Next()
},
}) })
req := httptest.NewRequest("GET", "/api/context/user", nil)
router.ServeHTTP(recorder, req)
assert.Equal(t, 200, recorder.Code)
var ctrlRes controller.UserContextResponse
err := json.Unmarshal(recorder.Body.Bytes(), &ctrlRes)
assert.NilError(t, err) assert.NilError(t, err)
assert.DeepEqual(t, expectedRes, ctrlRes)
// Test no context resp = suite.RequestWithMiddleware(req, nil)
expectedRes = controller.UserContextResponse{
Status: 401,
Message: "Unauthorized",
IsLoggedIn: false,
}
router, recorder = setupContextController(nil)
req = httptest.NewRequest("GET", "/api/context/user", nil)
router.ServeHTTP(recorder, req)
assert.Equal(t, 200, recorder.Code)
err = json.Unmarshal(recorder.Body.Bytes(), &ctrlRes)
assert.Equal(t, http.StatusOK, resp.Code)
bytes, err = io.ReadAll(resp.Body)
assert.NilError(t, err) assert.NilError(t, err)
assert.DeepEqual(t, expectedRes, ctrlRes) assert.DeepEqual(t, expected, bytes)
} }

View File

@@ -0,0 +1,89 @@
package controller_test
import (
"net/http"
"net/http/httptest"
"github.com/gin-gonic/gin"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/controller"
)
// Testing suite
type ControllerTest[T any] struct {
ctrlSetup func(router *gin.RouterGroup) T
}
func NewControllerTest[T any](setup func(router *gin.RouterGroup) T) *ControllerTest[T] {
return &ControllerTest[T]{ctrlSetup: setup}
}
func (ctrlt *ControllerTest[T]) newEngine(middlewares []gin.HandlerFunc) *gin.Engine {
gin.SetMode(gin.TestMode)
engine := gin.New()
for _, mw := range middlewares {
engine.Use(mw)
}
return engine
}
func (ctrlrt *ControllerTest[T]) newControllerInstance(engine *gin.Engine) T {
ctrl := ctrlrt.ctrlSetup(engine.Group("/api"))
return ctrl
}
func (ctrlt *ControllerTest[T]) RequestWithMiddleware(http *http.Request, middlewares []gin.HandlerFunc) *httptest.ResponseRecorder {
engine := ctrlt.newEngine(middlewares)
ctrlt.newControllerInstance(engine)
recorder := httptest.NewRecorder()
engine.ServeHTTP(recorder, http)
return recorder
}
func (ctrlt *ControllerTest[T]) Request(http *http.Request) *httptest.ResponseRecorder {
return ctrlt.RequestWithMiddleware(http, nil)
}
// Controller configs
var contextControllerCfg = controller.ContextControllerConfig{
Providers: []controller.Provider{
{
Name: "Local",
ID: "local",
OAuth: false,
},
{
Name: "Google",
ID: "google",
OAuth: true,
},
},
Title: "Tinyauth Testing",
AppURL: "http://tinyauth.example.com:3000",
CookieDomain: "example.com",
ForgotPasswordMessage: "Foo bar",
BackgroundImage: "/background.jpg",
OAuthAutoRedirect: "google",
WarningsEnabled: true,
}
var testContext = config.UserContext{
Username: "user",
Name: "User",
Email: "user@example.com",
IsLoggedIn: false,
IsBasicAuth: false,
OAuth: false,
Provider: "",
TotpPending: false,
OAuthGroups: "group1,group2",
TotpEnabled: false,
OAuthName: "test",
OAuthSub: "test",
LdapGroups: "group1,group2",
}

View File

@@ -19,7 +19,7 @@ func (controller *HealthController) SetupRoutes() {
func (controller *HealthController) healthHandler(c *gin.Context) { func (controller *HealthController) healthHandler(c *gin.Context) {
c.JSON(200, gin.H{ c.JSON(200, gin.H{
"status": "ok", "status": 200,
"message": "Healthy", "message": "Healthy",
}) })
} }

View File

@@ -0,0 +1,49 @@
package controller_test
import (
"encoding/json"
"io"
"net/http"
"testing"
"github.com/gin-gonic/gin"
"github.com/steveiliop56/tinyauth/internal/controller"
"gotest.tools/v3/assert"
)
func TestHealthController(t *testing.T) {
// Controller setup
suite := NewControllerTest(func(router *gin.RouterGroup) *controller.HealthController {
ctrl := controller.NewHealthController(router)
ctrl.SetupRoutes()
return ctrl
})
expected, err := json.Marshal(map[string]any{
"status": 200,
"message": "Healthy",
})
assert.NilError(t, err)
// Test we are healthy with GET
req, err := http.NewRequest("GET", "/api/healthz", nil)
assert.NilError(t, err)
resp := suite.Request(req)
assert.Equal(t, http.StatusOK, resp.Code)
bytes, err := io.ReadAll(resp.Body)
assert.NilError(t, err)
assert.DeepEqual(t, bytes, expected)
// Test we are healthy with HEAD
req, err = http.NewRequest("HEAD", "/api/healthz", nil)
assert.NilError(t, err)
resp = suite.Request(req)
assert.Equal(t, http.StatusOK, resp.Code)
bytes, err = io.ReadAll(resp.Body)
assert.NilError(t, err)
assert.DeepEqual(t, expected, bytes)
}