package main import ( "net/http" "net/http/httptest" "testing" "time" "github.com/labstack/echo/v4" "github.com/stretchr/testify/assert" ) // TestUsernameWhitespaceValidation tests that whitespace-only usernames are rejected func TestUsernameWhitespaceValidation(t *testing.T) { // This would require integration testing with actual handler t.Skip("Requires integration test with real handler") } // TestRoleCaseNormalization tests that roles are normalized to lowercase func TestRoleCaseNormalization(t *testing.T) { // This would require integration testing with actual handler t.Skip("Requires integration test with real handler") } // TestPaginationMaxLimit tests that pagination has a maximum limit func TestPaginationMaxLimit(t *testing.T) { // This is tested in ebook_test.go t.Skip("Already tested in TestPaginationAndFiltering") } // TestPaginationNegativeOffset tests that negative offset is rejected func TestPaginationNegativeOffset(t *testing.T) { // This is tested in ebook_test.go t.Skip("Already tested in TestPaginationAndFiltering") } // TestRateLimiter tests the rate limiting middleware func TestRateLimiter(t *testing.T) { e := echo.New() // Create a simple handler handler := func(c echo.Context) error { return c.String(http.StatusOK, "ok") } // Create rate limiter: 3 requests per minute config := ratelimitConfig{ RequestsPerMinute: 3, CleanupInterval: 1 * time.Minute, } rl := newRateLimiter(config) rateLimitMiddleware := rateLimiterMiddleware(rl) // Wrap handler wrappedHandler := rateLimitMiddleware(handler) // Make 3 successful requests for i := 0; i < 3; i++ { req := httptest.NewRequest("GET", "/test", nil) req.RemoteAddr = "192.168.1.1:1234" rec := httptest.NewRecorder() c := e.NewContext(req, rec) err := wrappedHandler(c) assert.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) } // 4th request should be rate limited req := httptest.NewRequest("GET", "/test", nil) req.RemoteAddr = "192.168.1.1:1234" rec := httptest.NewRecorder() c := e.NewContext(req, rec) err := wrappedHandler(c) assert.NoError(t, err) assert.Equal(t, http.StatusTooManyRequests, rec.Code) } // Mock rate limiter types for testing type ratelimitConfig struct { RequestsPerMinute int CleanupInterval time.Duration } func newRateLimiter(config ratelimitConfig) *mockRateLimiter { return &mockRateLimiter{ config: config, requests: make(map[string]int), } } type mockRateLimiter struct { requests map[string]int config ratelimitConfig } func (m *mockRateLimiter) Allow(ip string) bool { count := m.requests[ip] if count >= m.config.RequestsPerMinute { return false } m.requests[ip]++ return true } func rateLimiterMiddleware(rl *mockRateLimiter) echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { ip := c.RealIP() if ip == "" { ip = c.Request().RemoteAddr } if !rl.Allow(ip) { return c.JSON(http.StatusTooManyRequests, map[string]string{ "error": "too many requests", }) } return next(c) } } }