diff --git a/internal/integration/router_integration_test.go b/internal/integration/router_integration_test.go index 43278cc..3f11e41 100644 --- a/internal/integration/router_integration_test.go +++ b/internal/integration/router_integration_test.go @@ -17,35 +17,35 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { router := ctx.Router t.Run("SecurityHeaders_Present", func(t *testing.T) { - req := httptest.NewRequest("GET", "/health", nil) - rec := httptest.NewRecorder() + request := httptest.NewRequest("GET", "/health", nil) + recorder := httptest.NewRecorder() - router.ServeHTTP(rec, req) + router.ServeHTTP(recorder, request) - assertStatus(t, rec, http.StatusOK) + assertStatus(t, recorder, http.StatusOK) - assertHeader(t, rec, "X-Content-Type-Options", "") - assertHeader(t, rec, "X-Frame-Options", "") - assertHeader(t, rec, "X-XSS-Protection", "") + assertHeader(t, recorder, "X-Content-Type-Options", "") + assertHeader(t, recorder, "X-Frame-Options", "") + assertHeader(t, recorder, "X-XSS-Protection", "") }) t.Run("CORS_Headers_Present", func(t *testing.T) { - req := httptest.NewRequest("OPTIONS", "/api/posts", nil) - req.Header.Set("Origin", "http://localhost:3000") - rec := httptest.NewRecorder() + request := httptest.NewRequest("OPTIONS", "/api/posts", nil) + request.Header.Set("Origin", "http://localhost:3000") + recorder := httptest.NewRecorder() - router.ServeHTTP(rec, req) + router.ServeHTTP(recorder, request) - assertHeader(t, rec, "Access-Control-Allow-Origin", "") + assertHeader(t, recorder, "Access-Control-Allow-Origin", "") }) t.Run("Logging_Middleware_Executes", func(t *testing.T) { - req := httptest.NewRequest("GET", "/health", nil) - rec := httptest.NewRecorder() + request := httptest.NewRequest("GET", "/health", nil) + recorder := httptest.NewRecorder() - router.ServeHTTP(rec, req) + router.ServeHTTP(recorder, request) - if rec.Code == 0 { + if recorder.Code == 0 { t.Error("Expected logging middleware to execute") } }) @@ -53,27 +53,27 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { t.Run("RequestSizeLimit_Enforced", func(t *testing.T) { user := createUserWithCleanup(t, ctx, "size_limit_user", "size_limit@example.com") largeBody := strings.Repeat("a", 10*1024*1024) - req := httptest.NewRequest("POST", "/api/posts", bytes.NewBufferString(largeBody)) - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Authorization", "Bearer "+user.Token) - req = testutils.WithUserContext(req, middleware.UserIDKey, user.User.ID) - rec := httptest.NewRecorder() + request := httptest.NewRequest("POST", "/api/posts", bytes.NewBufferString(largeBody)) + request.Header.Set("Content-Type", "application/json") + request.Header.Set("Authorization", "Bearer "+user.Token) + request = testutils.WithUserContext(request, middleware.UserIDKey, user.User.ID) + recorder := httptest.NewRecorder() - router.ServeHTTP(rec, req) + router.ServeHTTP(recorder, request) - if rec.Code != http.StatusRequestEntityTooLarge && rec.Code != http.StatusBadRequest { - t.Errorf("Expected status 413 or 400 for oversized request, got %d. Body: %s", rec.Code, rec.Body.String()) + if recorder.Code != http.StatusRequestEntityTooLarge && recorder.Code != http.StatusBadRequest { + t.Errorf("Expected status 413 or 400 for oversized request, got %d. Body: %s", recorder.Code, recorder.Body.String()) } }) t.Run("DBMonitoring_Active", func(t *testing.T) { - req := httptest.NewRequest("GET", "/health", nil) - rec := httptest.NewRecorder() + request := httptest.NewRequest("GET", "/health", nil) + recorder := httptest.NewRecorder() - router.ServeHTTP(rec, req) + router.ServeHTTP(recorder, request) var response map[string]any - if err := json.NewDecoder(rec.Body).Decode(&response); err == nil { + if err := json.NewDecoder(recorder.Body).Decode(&response); err == nil { if data, ok := response["data"].(map[string]any); ok { if _, exists := data["database_stats"]; !exists { t.Error("Expected database_stats in health response") @@ -83,12 +83,12 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { }) t.Run("Metrics_Middleware_Executes", func(t *testing.T) { - req := httptest.NewRequest("GET", "/metrics", nil) - rec := httptest.NewRecorder() + request := httptest.NewRequest("GET", "/metrics", nil) + recorder := httptest.NewRecorder() - router.ServeHTTP(rec, req) + router.ServeHTTP(recorder, request) - response := assertJSONResponse(t, rec, http.StatusOK) + response := assertJSONResponse(t, recorder, http.StatusOK) if response != nil { if data, ok := response["data"].(map[string]any); ok { if _, exists := data["database"]; !exists { @@ -99,34 +99,34 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { }) t.Run("StaticFiles_Served", func(t *testing.T) { - req := httptest.NewRequest("GET", "/robots.txt", nil) - rec := httptest.NewRecorder() + request := httptest.NewRequest("GET", "/robots.txt", nil) + recorder := httptest.NewRecorder() - router.ServeHTTP(rec, req) + router.ServeHTTP(recorder, request) - assertStatus(t, rec, http.StatusOK) + assertStatus(t, recorder, http.StatusOK) - if !strings.Contains(rec.Body.String(), "User-agent") { + if !strings.Contains(recorder.Body.String(), "User-agent") { t.Error("Expected robots.txt content") } }) t.Run("API_Routes_Accessible", func(t *testing.T) { - req := httptest.NewRequest("GET", "/api/posts", nil) - rec := httptest.NewRecorder() + request := httptest.NewRequest("GET", "/api/posts", nil) + recorder := httptest.NewRecorder() - router.ServeHTTP(rec, req) + router.ServeHTTP(recorder, request) - assertStatus(t, rec, http.StatusOK) + assertStatus(t, recorder, http.StatusOK) }) t.Run("Health_Endpoint_Accessible", func(t *testing.T) { - req := httptest.NewRequest("GET", "/health", nil) - rec := httptest.NewRecorder() + request := httptest.NewRequest("GET", "/health", nil) + recorder := httptest.NewRecorder() - router.ServeHTTP(rec, req) + router.ServeHTTP(recorder, request) - response := assertJSONResponse(t, rec, http.StatusOK) + response := assertJSONResponse(t, recorder, http.StatusOK) if response != nil { if success, ok := response["success"].(bool); !ok || !success { t.Error("Expected success=true in health response") @@ -135,40 +135,40 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { }) t.Run("Middleware_Order_Correct", func(t *testing.T) { - req := httptest.NewRequest("GET", "/api/posts", nil) - rec := httptest.NewRecorder() + request := httptest.NewRequest("GET", "/api/posts", nil) + recorder := httptest.NewRecorder() - router.ServeHTTP(rec, req) + router.ServeHTTP(recorder, request) - assertHeader(t, rec, "X-Content-Type-Options", "") + assertHeader(t, recorder, "X-Content-Type-Options", "") - if rec.Code == 0 { + if recorder.Code == 0 { t.Error("Response should have status code") } }) t.Run("Compression_Middleware_Active", func(t *testing.T) { - req := httptest.NewRequest("GET", "/api/posts", nil) - req.Header.Set("Accept-Encoding", "gzip") - rec := httptest.NewRecorder() + request := httptest.NewRequest("GET", "/api/posts", nil) + request.Header.Set("Accept-Encoding", "gzip") + recorder := httptest.NewRecorder() - router.ServeHTTP(rec, req) + router.ServeHTTP(recorder, request) - if rec.Header().Get("Content-Encoding") == "" { + if recorder.Header().Get("Content-Encoding") == "" { t.Log("Compression may not be applied to small responses") } }) t.Run("Cache_Middleware_Active", func(t *testing.T) { - req1 := httptest.NewRequest("GET", "/api/posts", nil) - rec1 := httptest.NewRecorder() - router.ServeHTTP(rec1, req1) + firstRequest := httptest.NewRequest("GET", "/api/posts", nil) + firstRecorder := httptest.NewRecorder() + router.ServeHTTP(firstRecorder, firstRequest) - req2 := httptest.NewRequest("GET", "/api/posts", nil) - rec2 := httptest.NewRecorder() - router.ServeHTTP(rec2, req2) + secondRequest := httptest.NewRequest("GET", "/api/posts", nil) + secondRecorder := httptest.NewRecorder() + router.ServeHTTP(secondRecorder, secondRequest) - if rec1.Code != rec2.Code { + if firstRecorder.Code != secondRecorder.Code { t.Error("Cached responses should have same status") } }) @@ -177,35 +177,35 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { ctx.Suite.EmailSender.Reset() user := createUserWithCleanup(t, ctx, "auth_middleware_user", "auth_middleware@example.com") - req := httptest.NewRequest("GET", "/api/auth/me", nil) - req.Header.Set("Authorization", "Bearer "+user.Token) - req = testutils.WithUserContext(req, middleware.UserIDKey, user.User.ID) - rec := httptest.NewRecorder() + request := httptest.NewRequest("GET", "/api/auth/me", nil) + request.Header.Set("Authorization", "Bearer "+user.Token) + request = testutils.WithUserContext(request, middleware.UserIDKey, user.User.ID) + recorder := httptest.NewRecorder() - router.ServeHTTP(rec, req) + router.ServeHTTP(recorder, request) - assertStatus(t, rec, http.StatusOK) + assertStatus(t, recorder, http.StatusOK) }) t.Run("RateLimit_Middleware_Integration", func(t *testing.T) { rateLimitCtx := setupTestContext(t) rateLimitRouter := rateLimitCtx.Router - for i := 0; i < 3; i++ { - req := httptest.NewRequest("POST", "/api/auth/login", bytes.NewBufferString(`{"username":"test","password":"test"}`)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() + for range 3 { + request := httptest.NewRequest("POST", "/api/auth/login", bytes.NewBufferString(`{"username":"test","password":"test"}`)) + request.Header.Set("Content-Type", "application/json") + recorder := httptest.NewRecorder() - rateLimitRouter.ServeHTTP(rec, req) + rateLimitRouter.ServeHTTP(recorder, request) } - req := httptest.NewRequest("POST", "/api/auth/login", bytes.NewBufferString(`{"username":"test","password":"test"}`)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() + request := httptest.NewRequest("POST", "/api/auth/login", bytes.NewBufferString(`{"username":"test","password":"test"}`)) + request.Header.Set("Content-Type", "application/json") + recorder := httptest.NewRecorder() - rateLimitRouter.ServeHTTP(rec, req) + rateLimitRouter.ServeHTTP(recorder, request) - if rec.Code == http.StatusTooManyRequests { + if recorder.Code == http.StatusTooManyRequests { t.Log("Rate limiting is working") } })