package middleware import ( "context" "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "go.uber.org/zap" ) type mockCaptchaVerifier struct { enabled bool err error } func (m *mockCaptchaVerifier) Verify(_ context.Context, _, _ string) error { return m.err } func (m *mockCaptchaVerifier) IsEnabled() bool { return m.enabled } func TestRequireCaptcha_Disabled_PassesThrough(t *testing.T) { gin.SetMode(gin.TestMode) router := gin.New() router.Use(RequireCaptcha(&mockCaptchaVerifier{enabled: false}, zap.NewNop())) router.POST("/register", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) }) req := httptest.NewRequest("POST", "/register", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code, "disabled CAPTCHA should pass through") } func TestRequireCaptcha_Enabled_MissingToken(t *testing.T) { gin.SetMode(gin.TestMode) router := gin.New() router.Use(RequireCaptcha(&mockCaptchaVerifier{enabled: true}, zap.NewNop())) router.POST("/register", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) }) req := httptest.NewRequest("POST", "/register", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) } func TestRequireCaptcha_Enabled_ValidToken(t *testing.T) { gin.SetMode(gin.TestMode) router := gin.New() router.Use(RequireCaptcha(&mockCaptchaVerifier{enabled: true}, zap.NewNop())) router.POST("/register", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) }) req := httptest.NewRequest("POST", "/register", nil) req.Header.Set("X-Captcha-Token", "valid-token") w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) } func TestRequireCaptcha_Enabled_InvalidToken(t *testing.T) { gin.SetMode(gin.TestMode) router := gin.New() router.Use(RequireCaptcha(&mockCaptchaVerifier{ enabled: true, err: assert.AnError, }, zap.NewNop())) router.POST("/login", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) }) req := httptest.NewRequest("POST", "/login", nil) req.Header.Set("X-Captcha-Token", "bad-token") w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusForbidden, w.Code) } func TestRequireCaptcha_NilVerifier(t *testing.T) { gin.SetMode(gin.TestMode) router := gin.New() router.Use(RequireCaptcha(nil, zap.NewNop())) router.POST("/register", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) }) req := httptest.NewRequest("POST", "/register", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code, "nil verifier should pass through") }