[🤖] Add Unit-Tests
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m34s

This commit is contained in:
2026-04-27 10:46:08 +02:00
parent dad0e3240d
commit 02d6894ec6
116 changed files with 18795 additions and 1 deletions
+174
View File
@@ -0,0 +1,174 @@
package ginext
import (
"net/http"
"net/http/httptest"
"testing"
"time"
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
"github.com/gin-gonic/gin"
)
func TestNewEngine_DefaultsApplied(t *testing.T) {
w := NewEngine(Options{})
if w == nil {
t.Fatalf("expected non-nil wrapper")
}
if w.engine == nil {
t.Fatalf("expected gin engine")
}
if w.allowCors {
t.Fatalf("expected allowCors default false")
}
if w.bufferBody {
t.Fatalf("expected bufferBody default false")
}
if !w.ginDebug {
t.Fatalf("expected ginDebug default true")
}
if w.requestTimeout != 24*time.Hour {
t.Fatalf("expected default 24h timeout, got %s", w.requestTimeout)
}
}
func TestNewEngine_OptionsHonored(t *testing.T) {
allowCors := true
bufferBody := true
suppress := true
debug := false
timeout := 5 * time.Second
w := NewEngine(Options{
AllowCors: &allowCors,
BufferBody: &bufferBody,
SuppressGinLogs: &suppress,
GinDebug: &debug,
Timeout: &timeout,
CorsAllowHeader: &[]string{"X-Custom"},
})
if !w.allowCors {
t.Fatalf("allowCors")
}
if !w.bufferBody {
t.Fatalf("bufferBody")
}
if !w.suppressGinLogs {
t.Fatalf("suppressGinLogs")
}
if w.ginDebug {
t.Fatalf("ginDebug should be false")
}
if w.requestTimeout != timeout {
t.Fatalf("timeout mismatch")
}
if !langext.ArrEqualsExact(w.corsAllowHeader, []string{"X-Custom"}) {
t.Fatalf("expected custom allow header")
}
}
func TestNewEngine_BuildRequestBindError_DefaultIsErrorWrapper(t *testing.T) {
w := NewEngine(Options{})
if w.buildRequestBindError == nil {
t.Fatalf("expected default builder")
}
resp := w.buildRequestBindError(nil, "URI", http.ErrAbortHandler)
if resp == nil {
t.Fatalf("expected response")
}
if resp.IsSuccess() {
t.Fatalf("expected error response, not success")
}
}
func TestNewEngine_BuildRequestBindError_Custom(t *testing.T) {
called := false
custom := func(c *gin.Context, fieldtype string, err error) HTTPResponse {
called = true
return Status(http.StatusTeapot)
}
_ = custom // referenced below to avoid unused warning if signature mismatch
w := NewEngine(Options{BuildRequestBindError: custom})
resp := w.buildRequestBindError(nil, "URI", http.ErrAbortHandler)
if !called {
t.Fatalf("expected custom builder to be invoked")
}
if resp.(InspectableHTTPResponse).Statuscode() != http.StatusTeapot {
t.Fatalf("expected 418 from custom builder")
}
}
func TestServeHTTP_RoundTrip(t *testing.T) {
w := NewEngine(Options{})
w.Routes().GET("/hello").Handle(func(p PreContext) HTTPResponse {
return Text(http.StatusOK, "world")
})
req := httptest.NewRequest(http.MethodGet, "/hello", nil)
rec := w.ServeHTTP(req)
if rec.Code != http.StatusOK {
t.Fatalf("expected 200, got %d", rec.Code)
}
if rec.Body.String() != "world" {
t.Fatalf("expected world, got %q", rec.Body.String())
}
}
func TestForwardRequest(t *testing.T) {
w := NewEngine(Options{})
w.Routes().GET("/fwd").Handle(func(p PreContext) HTTPResponse {
return Text(http.StatusOK, "ok")
})
req := httptest.NewRequest(http.MethodGet, "/fwd", nil)
rec := httptest.NewRecorder()
w.ForwardRequest(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected 200, got %d", rec.Code)
}
}
func TestListRoutes(t *testing.T) {
w := NewEngine(Options{})
w.Routes().GET("/a").Handle(func(p PreContext) HTTPResponse { return Status(200) })
w.Routes().POST("/b").Handle(func(p PreContext) HTTPResponse { return Status(200) })
rs := w.ListRoutes()
if len(rs) < 2 {
t.Fatalf("expected at least 2 routes, got %d", len(rs))
}
}
func TestDebugPrintRoutes_NoPanic(t *testing.T) {
w := NewEngine(Options{})
w.Routes().GET("/x").Handle(func(p PreContext) HTTPResponse { return Status(200) })
// just verify it doesn't panic
w.DebugPrintRoutes()
}
func TestCleanMiddlewareName(t *testing.T) {
w := NewEngine(Options{
DebugTrimHandlerPrefixes: []string{"customprefix."},
DebugReplaceHandlerNames: map[string]string{"BadName": "GoodName"},
})
cases := []struct {
in, want string
}{
{"ginext.BodyBuffer", "[BodyBuffer]"},
{"foo.(*GinRoutesWrapper).WithJSONFilter", "[JSONFilter]"},
{"ginext.someThing", "someThing"},
{"api.someThing", "someThing"},
{"customprefix.thing", "thing"},
{"BadName", "GoodName"},
{"badname", "GoodName"},
{"some.pkg.Func.func1", "some.pkg.Func"},
{"some.pkg.Func.func1.2", "some.pkg.Func"},
}
for _, tc := range cases {
if got := w.cleanMiddlewareName(tc.in); got != tc.want {
t.Errorf("cleanMiddlewareName(%q) = %q, want %q", tc.in, got, tc.want)
}
}
}