diff --git a/internal/integration/caching_integration_test.go b/internal/integration/caching_integration_test.go index 3ad4cca..2457f0b 100644 --- a/internal/integration/caching_integration_test.go +++ b/internal/integration/caching_integration_test.go @@ -53,25 +53,25 @@ func TestIntegration_Caching(t *testing.T) { router := ctx.Router t.Run("Cache_Hit_On_Repeated_Requests", 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) time.Sleep(10 * time.Millisecond) - 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 code") } - if rec1.Body.String() != rec2.Body.String() { + if firstRecorder.Body.String() != secondRecorder.Body.String() { t.Error("Cached responses should have same body") } - if rec2.Header().Get("X-Cache") != "HIT" { + if secondRecorder.Header().Get("X-Cache") != "HIT" { t.Log("Cache may not be enabled for this path or response may not be cacheable") } }) @@ -80,9 +80,9 @@ func TestIntegration_Caching(t *testing.T) { ctx.Suite.EmailSender.Reset() user := createUserWithCleanup(t, ctx, "cache_post_user", "cache_post@example.com") - 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) time.Sleep(10 * time.Millisecond) @@ -92,12 +92,12 @@ func TestIntegration_Caching(t *testing.T) { "content": "Test content", } body, _ := json.Marshal(postBody) - req2 := httptest.NewRequest("POST", "/api/posts", bytes.NewBuffer(body)) - req2.Header.Set("Content-Type", "application/json") - req2.Header.Set("Authorization", "Bearer "+user.Token) - req2 = testutils.WithUserContext(req2, middleware.UserIDKey, user.User.ID) - rec2 := httptest.NewRecorder() - router.ServeHTTP(rec2, req2) + secondRequest := httptest.NewRequest("POST", "/api/posts", bytes.NewBuffer(body)) + secondRequest.Header.Set("Content-Type", "application/json") + secondRequest.Header.Set("Authorization", "Bearer "+user.Token) + secondRequest = testutils.WithUserContext(secondRequest, middleware.UserIDKey, user.User.ID) + secondRecorder := httptest.NewRecorder() + router.ServeHTTP(secondRecorder, secondRequest) time.Sleep(10 * time.Millisecond) @@ -105,15 +105,15 @@ func TestIntegration_Caching(t *testing.T) { rec3 := httptest.NewRecorder() router.ServeHTTP(rec3, req3) - if rec1.Body.String() == rec3.Body.String() && rec1.Code == http.StatusOK && rec3.Code == http.StatusOK { + if firstRecorder.Body.String() == rec3.Body.String() && firstRecorder.Code == http.StatusOK && rec3.Code == http.StatusOK { t.Log("Cache invalidation may not be working or cache may not be enabled") } }) t.Run("Cache_Headers_Present", func(t *testing.T) { - req := httptest.NewRequest("GET", "/api/posts", nil) + request := httptest.NewRequest("GET", "/api/posts", nil) recorder := httptest.NewRecorder() - router.ServeHTTP(recorder, req) + router.ServeHTTP(recorder, request) if recorder.Header().Get("Cache-Control") == "" && recorder.Header().Get("X-Cache") == "" { t.Log("Cache headers may not be present for all responses") @@ -126,18 +126,18 @@ func TestIntegration_Caching(t *testing.T) { post := testutils.CreatePostWithRepo(t, ctx.Suite.PostRepo, user.User.ID, "Cache Delete Post", "https://example.com/cache-delete") - 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) time.Sleep(10 * time.Millisecond) - req2 := httptest.NewRequest("DELETE", "/api/posts/"+fmt.Sprintf("%d", post.ID), nil) - req2.Header.Set("Authorization", "Bearer "+user.Token) - req2 = testutils.WithUserContext(req2, middleware.UserIDKey, user.User.ID) - req2 = testutils.WithURLParams(req2, map[string]string{"id": fmt.Sprintf("%d", post.ID)}) - rec2 := httptest.NewRecorder() - router.ServeHTTP(rec2, req2) + secondRequest := httptest.NewRequest("DELETE", "/api/posts/"+fmt.Sprintf("%d", post.ID), nil) + secondRequest.Header.Set("Authorization", "Bearer "+user.Token) + secondRequest = testutils.WithUserContext(secondRequest, middleware.UserIDKey, user.User.ID) + secondRequest = testutils.WithURLParams(secondRequest, map[string]string{"id": fmt.Sprintf("%d", post.ID)}) + secondRecorder := httptest.NewRecorder() + router.ServeHTTP(secondRecorder, secondRequest) time.Sleep(10 * time.Millisecond) @@ -145,7 +145,7 @@ func TestIntegration_Caching(t *testing.T) { rec3 := httptest.NewRecorder() router.ServeHTTP(rec3, req3) - if rec1.Body.String() == rec3.Body.String() && rec1.Code == http.StatusOK && rec3.Code == http.StatusOK { + if firstRecorder.Body.String() == rec3.Body.String() && firstRecorder.Code == http.StatusOK && rec3.Code == http.StatusOK { t.Log("Cache invalidation may not be working or cache may not be enabled") } }) diff --git a/internal/integration/complete_api_endpoints_integration_test.go b/internal/integration/complete_api_endpoints_integration_test.go index 55713ee..88990e3 100644 --- a/internal/integration/complete_api_endpoints_integration_test.go +++ b/internal/integration/complete_api_endpoints_integration_test.go @@ -290,10 +290,10 @@ func TestIntegration_CompleteAPIEndpoints(t *testing.T) { } } - rec2 := makeGetRequest(t, ctx.Router, "/api/posts/search?q=Searchable&limit=1&offset=1") + secondRequest := makeGetRequest(t, ctx.Router, "/api/posts/search?q=Searchable&limit=1&offset=1") - response2 := assertJSONResponse(t, rec2, http.StatusOK) - if data, ok := getDataFromResponse(response2); ok { + secondResponse := assertJSONResponse(t, secondRequest, http.StatusOK) + if data, ok := getDataFromResponse(secondResponse); ok { if posts, ok := data["posts"].([]any); ok { if len(posts) > 1 { t.Errorf("Expected at most 1 post with limit=1 and offset=1, got %d", len(posts)) diff --git a/internal/integration/compression_static_metadata_integration_test.go b/internal/integration/compression_static_metadata_integration_test.go index 5c5edc2..a6385bf 100644 --- a/internal/integration/compression_static_metadata_integration_test.go +++ b/internal/integration/compression_static_metadata_integration_test.go @@ -1,17 +1,12 @@ package integration import ( - "bytes" "compress/gzip" - "encoding/json" "io" "net/http" "net/http/httptest" "strings" "testing" - - "goyco/internal/middleware" - "goyco/internal/testutils" ) func TestIntegration_Compression(t *testing.T) { @@ -19,11 +14,11 @@ func TestIntegration_Compression(t *testing.T) { router := ctx.Router t.Run("Response_Compression_Gzip", func(t *testing.T) { - req := httptest.NewRequest("GET", "/api/posts", nil) - req.Header.Set("Accept-Encoding", "gzip") + request := httptest.NewRequest("GET", "/api/posts", nil) + request.Header.Set("Accept-Encoding", "gzip") recorder := httptest.NewRecorder() - router.ServeHTTP(recorder, req) + router.ServeHTTP(recorder, request) contentEncoding := recorder.Header().Get("Content-Encoding") if contentEncoding != "" && strings.Contains(contentEncoding, "gzip") { @@ -48,11 +43,11 @@ func TestIntegration_Compression(t *testing.T) { }) t.Run("Compression_Headers_Present", func(t *testing.T) { - req := httptest.NewRequest("GET", "/api/posts", nil) - req.Header.Set("Accept-Encoding", "gzip, deflate") + request := httptest.NewRequest("GET", "/api/posts", nil) + request.Header.Set("Accept-Encoding", "gzip, deflate") recorder := httptest.NewRecorder() - router.ServeHTTP(recorder, req) + router.ServeHTTP(recorder, request) if recorder.Header().Get("Vary") != "" { assertHeaderContains(t, recorder, "Vary", "Accept-Encoding") @@ -67,25 +62,19 @@ func TestIntegration_StaticFiles(t *testing.T) { router := ctx.Router t.Run("Robots_Txt_Served", func(t *testing.T) { - req := httptest.NewRequest("GET", "/robots.txt", nil) - recorder := httptest.NewRecorder() + request := makeGetRequest(t, router, "/robots.txt") - router.ServeHTTP(recorder, req) + assertStatus(t, request, http.StatusOK) - assertStatus(t, recorder, http.StatusOK) - - if !strings.Contains(recorder.Body.String(), "User-agent") { + if !strings.Contains(request.Body.String(), "User-agent") { t.Error("Expected robots.txt content") } }) t.Run("Static_Files_Security_Headers", func(t *testing.T) { - req := httptest.NewRequest("GET", "/robots.txt", nil) - recorder := httptest.NewRecorder() + request := makeGetRequest(t, router, "/robots.txt") - router.ServeHTTP(recorder, req) - - if recorder.Header().Get("X-Content-Type-Options") == "" { + if request.Header().Get("X-Content-Type-Options") == "" { t.Log("Security headers may not be applied to all static files") } }) @@ -101,32 +90,22 @@ func TestIntegration_URLMetadata(t *testing.T) { ctx.Suite.TitleFetcher.SetTitle("Fetched Title") - postBody := map[string]string{ + postBody := map[string]any{ "title": "Test Post", "url": "https://example.com/metadata-test", "content": "Test content", } - body, _ := json.Marshal(postBody) - req := httptest.NewRequest("POST", "/api/posts", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Authorization", "Bearer "+user.Token) - req = testutils.WithUserContext(req, middleware.UserIDKey, user.User.ID) - recorder := httptest.NewRecorder() + request := makePostRequest(t, router, "/api/posts", postBody, user, nil) - router.ServeHTTP(recorder, req) - - assertStatus(t, recorder, http.StatusCreated) + assertStatus(t, request, http.StatusCreated) }) t.Run("URL_Metadata_Endpoint", func(t *testing.T) { ctx.Suite.TitleFetcher.SetTitle("Endpoint Title") - req := httptest.NewRequest("GET", "/api/posts/title?url=https://example.com/test", nil) - recorder := httptest.NewRecorder() + request := makeGetRequest(t, router, "/api/posts/title?url=https://example.com/test") - router.ServeHTTP(recorder, req) - - response := assertJSONResponse(t, recorder, http.StatusOK) + response := assertJSONResponse(t, request, http.StatusOK) if response != nil { if data, ok := response["data"].(map[string]any); ok { if _, exists := data["title"]; !exists { diff --git a/internal/integration/data_consistency_integration_test.go b/internal/integration/data_consistency_integration_test.go index 739e440..dd3c214 100644 --- a/internal/integration/data_consistency_integration_test.go +++ b/internal/integration/data_consistency_integration_test.go @@ -181,15 +181,9 @@ func TestIntegration_DataConsistency(t *testing.T) { firstPost := testutils.CreatePostWithRepo(t, ctx.Suite.PostRepo, user.User.ID, "Post 1", "https://example.com/post1") secondPost := testutils.CreatePostWithRepo(t, ctx.Suite.PostRepo, user.User.ID, "Post 2", "https://example.com/post2") - request := httptest.NewRequest("GET", fmt.Sprintf("/api/users/%d/posts", user.User.ID), nil) - request.Header.Set("Authorization", "Bearer "+user.Token) - request = testutils.WithUserContext(request, middleware.UserIDKey, user.User.ID) - request = testutils.WithURLParams(request, map[string]string{"id": fmt.Sprintf("%d", user.User.ID)}) - recorder := httptest.NewRecorder() + request := makeAuthenticatedGetRequest(t, ctx.Router, fmt.Sprintf("/api/users/%d/posts", user.User.ID), user, map[string]string{"id": fmt.Sprintf("%d", user.User.ID)}) - ctx.Router.ServeHTTP(recorder, request) - - response := assertJSONResponse(t, recorder, http.StatusOK) + response := assertJSONResponse(t, request, http.StatusOK) if response == nil { return } diff --git a/internal/integration/email_integration_test.go b/internal/integration/email_integration_test.go index 4240845..b1c400c 100644 --- a/internal/integration/email_integration_test.go +++ b/internal/integration/email_integration_test.go @@ -1,14 +1,10 @@ package integration import ( - "bytes" - "encoding/json" "net/http" - "net/http/httptest" "testing" "goyco/internal/database" - "goyco/internal/middleware" "goyco/internal/testutils" ) @@ -19,19 +15,14 @@ func TestIntegration_EmailService(t *testing.T) { t.Run("Registration_Email_Sent", func(t *testing.T) { ctx.Suite.EmailSender.Reset() - reqBody := map[string]string{ + reqBody := map[string]any{ "username": "email_reg_user", "email": "email_reg@example.com", "password": "SecurePass123!", } - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("POST", "/api/auth/register", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() + request := makePostRequestWithJSON(t, router, "/api/auth/register", reqBody) - router.ServeHTTP(rec, req) - - assertStatus(t, rec, http.StatusCreated) + assertStatus(t, request, http.StatusCreated) token := ctx.Suite.EmailSender.VerificationToken() if token == "" { @@ -52,15 +43,10 @@ func TestIntegration_EmailService(t *testing.T) { t.Fatalf("Failed to create user: %v", err) } - reqBody := map[string]string{ + reqBody := map[string]any{ "username_or_email": "email_reset_user", } - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("POST", "/api/auth/forgot-password", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() - - router.ServeHTTP(rec, req) + makePostRequestWithJSON(t, router, "/api/auth/forgot-password", reqBody) token := ctx.Suite.EmailSender.PasswordResetToken() if token == "" { @@ -72,17 +58,9 @@ func TestIntegration_EmailService(t *testing.T) { ctx.Suite.EmailSender.Reset() user := createAuthenticatedUser(t, ctx.AuthService, ctx.Suite.UserRepo, "email_del_user", "email_del@example.com") - reqBody := map[string]string{} - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("DELETE", "/api/auth/account", bytes.NewBuffer(body)) - 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 := makeDeleteRequest(t, router, "/api/auth/account", user, nil) - router.ServeHTTP(rec, req) - - assertStatus(t, rec, http.StatusOK) + assertStatus(t, request, http.StatusOK) token := ctx.Suite.EmailSender.DeletionToken() if token == "" { @@ -94,17 +72,10 @@ func TestIntegration_EmailService(t *testing.T) { ctx.Suite.EmailSender.Reset() user := createAuthenticatedUser(t, ctx.AuthService, ctx.Suite.UserRepo, "email_change_user", "email_change@example.com") - reqBody := map[string]string{ + reqBody := map[string]any{ "email": "newemail@example.com", } - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("PUT", "/api/auth/email", bytes.NewBuffer(body)) - 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() - - router.ServeHTTP(rec, req) + makePutRequest(t, router, "/api/auth/email", reqBody, user, nil) token := ctx.Suite.EmailSender.VerificationToken() if token == "" { @@ -115,17 +86,12 @@ func TestIntegration_EmailService(t *testing.T) { t.Run("Email_Template_Content", func(t *testing.T) { ctx.Suite.EmailSender.Reset() - reqBody := map[string]string{ + reqBody := map[string]any{ "username": "template_user", "email": "template@example.com", "password": "SecurePass123!", } - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("POST", "/api/auth/register", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() - - router.ServeHTTP(rec, req) + makePostRequestWithJSON(t, router, "/api/auth/register", reqBody) token := ctx.Suite.EmailSender.VerificationToken() if token == "" { diff --git a/internal/integration/end_to_end_journeys_integration_test.go b/internal/integration/end_to_end_journeys_integration_test.go index 5183ad8..5969251 100644 --- a/internal/integration/end_to_end_journeys_integration_test.go +++ b/internal/integration/end_to_end_journeys_integration_test.go @@ -152,9 +152,9 @@ func TestIntegration_EndToEndUserJourneys(t *testing.T) { if data, ok := getDataFromResponse(votesResponse); ok { if votes, ok := data["votes"].([]any); ok && len(votes) > 0 { - unvoteRec := makeDeleteRequest(t, ctx.Router, fmt.Sprintf("/api/posts/%d/vote", post.ID), user, map[string]string{"id": fmt.Sprintf("%d", post.ID)}) + unvoteRequest := makeDeleteRequest(t, ctx.Router, fmt.Sprintf("/api/posts/%d/vote", post.ID), user, map[string]string{"id": fmt.Sprintf("%d", post.ID)}) - assertStatus(t, unvoteRec, http.StatusOK) + assertStatus(t, unvoteRequest, http.StatusOK) } } }) diff --git a/internal/integration/error_propagation_integration_test.go b/internal/integration/error_propagation_integration_test.go index bcb289c..2060733 100644 --- a/internal/integration/error_propagation_integration_test.go +++ b/internal/integration/error_propagation_integration_test.go @@ -2,7 +2,6 @@ package integration import ( "bytes" - "encoding/json" "fmt" "net/http" "net/http/httptest" @@ -19,58 +18,46 @@ func TestIntegration_ErrorPropagation(t *testing.T) { ctx.Suite.EmailSender.Reset() user := createAuthenticatedUser(t, ctx.AuthService, ctx.Suite.UserRepo, "json_error_user", "json_error@example.com") - req := httptest.NewRequest("POST", "/api/posts", bytes.NewBuffer([]byte("invalid json{"))) - 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.NewBuffer([]byte("invalid json{"))) + 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() - ctx.Router.ServeHTTP(rec, req) + ctx.Router.ServeHTTP(recorder, request) - assertErrorResponse(t, rec, http.StatusBadRequest) + assertErrorResponse(t, recorder, http.StatusBadRequest) }) t.Run("Validation_Error_Propagation", func(t *testing.T) { ctx.Suite.EmailSender.Reset() - reqBody := map[string]string{ + reqBody := map[string]any{ "username": "", "email": "invalid-email", "password": "weak", } - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("POST", "/api/auth/register", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() + request := makePostRequestWithJSON(t, ctx.Router, "/api/auth/register", reqBody) - ctx.Router.ServeHTTP(rec, req) - - assertErrorResponse(t, rec, http.StatusBadRequest) + assertErrorResponse(t, request, http.StatusBadRequest) }) t.Run("Database_Error_Propagation", func(t *testing.T) { ctx.Suite.EmailSender.Reset() user := createAuthenticatedUser(t, ctx.AuthService, ctx.Suite.UserRepo, "db_error_user", "db_error@example.com") - reqBody := map[string]string{ + reqBody := map[string]any{ "title": "Test Post", "url": "https://example.com/test", "content": "Test content", } - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("POST", "/api/posts", bytes.NewBuffer(body)) - 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 := makePostRequest(t, ctx.Router, "/api/posts", reqBody, user, nil) - ctx.Router.ServeHTTP(rec, req) - - if rec.Code == http.StatusInternalServerError { - assertErrorResponse(t, rec, http.StatusInternalServerError) + if request.Code == http.StatusInternalServerError { + assertErrorResponse(t, request, http.StatusInternalServerError) } else { - assertStatus(t, rec, http.StatusCreated) + assertStatus(t, request, http.StatusCreated) } }) @@ -78,34 +65,23 @@ func TestIntegration_ErrorPropagation(t *testing.T) { ctx.Suite.EmailSender.Reset() user := createAuthenticatedUser(t, ctx.AuthService, ctx.Suite.UserRepo, "notfound_error_user", "notfound_error@example.com") - req := httptest.NewRequest("GET", "/api/posts/999999", nil) - req.Header.Set("Authorization", "Bearer "+user.Token) - req = testutils.WithUserContext(req, middleware.UserIDKey, user.User.ID) - req = testutils.WithURLParams(req, map[string]string{"id": "999999"}) - rec := httptest.NewRecorder() + request := makeAuthenticatedGetRequest(t, ctx.Router, "/api/posts/999999", user, map[string]string{"id": "999999"}) - ctx.Router.ServeHTTP(rec, req) - - assertErrorResponse(t, rec, http.StatusNotFound) + assertErrorResponse(t, request, http.StatusNotFound) }) t.Run("Unauthorized_Error_Propagation", func(t *testing.T) { ctx.Suite.EmailSender.Reset() - reqBody := map[string]string{ + reqBody := map[string]any{ "title": "Test Post", "url": "https://example.com/test", "content": "Test content", } - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("POST", "/api/posts", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() + request := makePostRequestWithJSON(t, ctx.Router, "/api/posts", reqBody) - ctx.Router.ServeHTTP(rec, req) - - assertErrorResponse(t, rec, http.StatusUnauthorized) + assertErrorResponse(t, request, http.StatusUnauthorized) }) t.Run("Forbidden_Error_Propagation", func(t *testing.T) { @@ -115,78 +91,58 @@ func TestIntegration_ErrorPropagation(t *testing.T) { post := testutils.CreatePostWithRepo(t, ctx.Suite.PostRepo, owner.User.ID, "Forbidden Post", "https://example.com/forbidden") - updateBody := map[string]string{ + updateBody := map[string]any{ "title": "Updated Title", "content": "Updated content", } - body, _ := json.Marshal(updateBody) - req := httptest.NewRequest("PUT", fmt.Sprintf("/api/posts/%d", post.ID), bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Authorization", "Bearer "+otherUser.Token) - req = testutils.WithUserContext(req, middleware.UserIDKey, otherUser.User.ID) - req = testutils.WithURLParams(req, map[string]string{"id": fmt.Sprintf("%d", post.ID)}) - rec := httptest.NewRecorder() + request := makePutRequest(t, ctx.Router, fmt.Sprintf("/api/posts/%d", post.ID), updateBody, otherUser, map[string]string{"id": fmt.Sprintf("%d", post.ID)}) - ctx.Router.ServeHTTP(rec, req) - - assertErrorResponse(t, rec, http.StatusForbidden) + assertErrorResponse(t, request, http.StatusForbidden) }) t.Run("Service_Error_Propagation", func(t *testing.T) { ctx.Suite.EmailSender.Reset() - reqBody := map[string]string{ + reqBody := map[string]any{ "username": "existing_user", "email": "existing@example.com", "password": "SecurePass123!", } - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("POST", "/api/auth/register", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() - ctx.Router.ServeHTTP(rec, req) + request := makePostRequestWithJSON(t, ctx.Router, "/api/auth/register", reqBody) - assertStatus(t, rec, http.StatusCreated) + assertStatus(t, request, http.StatusCreated) - req = httptest.NewRequest("POST", "/api/auth/register", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - rec = httptest.NewRecorder() - ctx.Router.ServeHTTP(rec, req) + request = makePostRequestWithJSON(t, ctx.Router, "/api/auth/register", reqBody) - assertStatusRange(t, rec, http.StatusBadRequest, http.StatusConflict) - assertErrorResponse(t, rec, rec.Code) + assertStatusRange(t, request, http.StatusBadRequest, http.StatusConflict) + assertErrorResponse(t, request, request.Code) }) t.Run("Middleware_Error_Propagation", func(t *testing.T) { ctx.Suite.EmailSender.Reset() - req := httptest.NewRequest("POST", "/api/posts", bytes.NewBuffer([]byte("{}"))) - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Authorization", "Bearer expired.invalid.token") - rec := httptest.NewRecorder() + request := httptest.NewRequest("POST", "/api/posts", bytes.NewBuffer([]byte("{}"))) + request.Header.Set("Content-Type", "application/json") + request.Header.Set("Authorization", "Bearer expired.invalid.token") + recorder := httptest.NewRecorder() - ctx.Router.ServeHTTP(rec, req) + ctx.Router.ServeHTTP(recorder, request) - assertErrorResponse(t, rec, http.StatusUnauthorized) + assertErrorResponse(t, recorder, http.StatusUnauthorized) }) t.Run("Handler_Error_Response_Format", func(t *testing.T) { ctx.Suite.EmailSender.Reset() - req := httptest.NewRequest("GET", "/api/nonexistent", nil) - rec := httptest.NewRecorder() + request := makeGetRequest(t, ctx.Router, "/api/nonexistent") - ctx.Router.ServeHTTP(rec, req) - - if rec.Code == http.StatusNotFound { - if rec.Header().Get("Content-Type") == "application/json" { - assertErrorResponse(t, rec, http.StatusNotFound) - } else { - if rec.Body.Len() == 0 { - t.Error("Expected error response body") - } + if request.Code == http.StatusNotFound { + if request.Header().Get("Content-Type") == "application/json" { + assertErrorResponse(t, request, http.StatusNotFound) + } else if request.Body.Len() == 0 { + t.Error("Expected error response body") } } }) diff --git a/internal/integration/password_reset_integration_test.go b/internal/integration/password_reset_integration_test.go index a9b07f9..18440cd 100644 --- a/internal/integration/password_reset_integration_test.go +++ b/internal/integration/password_reset_integration_test.go @@ -1,8 +1,6 @@ package integration import ( - "bytes" - "encoding/json" "net/http" "net/http/httptest" "net/url" @@ -32,17 +30,12 @@ func TestIntegration_PasswordReset_CompleteFlow(t *testing.T) { t.Fatalf("Failed to create user: %v", err) } - reqBody := map[string]string{ + reqBody := map[string]any{ "username_or_email": "reset_user", } - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("POST", "/api/auth/forgot-password", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() + request := makePostRequestWithJSON(t, router, "/api/auth/forgot-password", reqBody) - router.ServeHTTP(rec, req) - - response := assertJSONResponse(t, rec, http.StatusOK) + response := assertJSONResponse(t, request, http.StatusOK) if response != nil { if success, ok := response["success"].(bool); !ok || !success { t.Error("Expected success=true") @@ -77,18 +70,13 @@ func TestIntegration_PasswordReset_CompleteFlow(t *testing.T) { t.Fatal("Expected password reset token") } - reqBody := map[string]string{ + reqBody := map[string]any{ "token": resetToken, "new_password": "NewPassword123!", } - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("POST", "/api/auth/reset-password", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() + request := makePostRequestWithJSON(t, router, "/api/auth/reset-password", reqBody) - router.ServeHTTP(rec, req) - - assertStatus(t, rec, http.StatusOK) + assertStatus(t, request, http.StatusOK) loginResult, err := ctx.AuthService.Login("reset_complete_user", "NewPassword123!") if err != nil { @@ -120,14 +108,14 @@ func TestIntegration_PasswordReset_CompleteFlow(t *testing.T) { reqBody := url.Values{} reqBody.Set("username_or_email", "page_reset_user") reqBody.Set("csrf_token", csrfToken) - req := httptest.NewRequest("POST", "/forgot-password", strings.NewReader(reqBody.Encode())) - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - req.AddCookie(&http.Cookie{Name: "csrf_token", Value: csrfToken}) - rec := httptest.NewRecorder() + request := httptest.NewRequest("POST", "/forgot-password", strings.NewReader(reqBody.Encode())) + request.Header.Set("Content-Type", "application/x-www-form-urlencoded") + request.AddCookie(&http.Cookie{Name: "csrf_token", Value: csrfToken}) + recorder := httptest.NewRecorder() - pageRouter.ServeHTTP(rec, req) + pageRouter.ServeHTTP(recorder, request) - assertStatusRange(t, rec, http.StatusOK, http.StatusSeeOther) + assertStatusRange(t, recorder, http.StatusOK, http.StatusSeeOther) resetToken := pageCtx.Suite.EmailSender.PasswordResetToken() if resetToken == "" { @@ -166,33 +154,23 @@ func TestIntegration_PasswordReset_CompleteFlow(t *testing.T) { t.Fatalf("Failed to update user: %v", err) } - reqBody := map[string]string{ + reqBody := map[string]any{ "token": resetToken, "new_password": "NewPassword123!", } - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("POST", "/api/auth/reset-password", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() + request := makePostRequestWithJSON(t, router, "/api/auth/reset-password", reqBody) - router.ServeHTTP(rec, req) - - assertErrorResponse(t, rec, http.StatusBadRequest) + assertErrorResponse(t, request, http.StatusBadRequest) }) t.Run("PasswordReset_InvalidToken", func(t *testing.T) { - reqBody := map[string]string{ + reqBody := map[string]any{ "token": "invalid-token", "new_password": "NewPassword123!", } - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("POST", "/api/auth/reset-password", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() + request := makePostRequestWithJSON(t, router, "/api/auth/reset-password", reqBody) - router.ServeHTTP(rec, req) - - assertErrorResponse(t, rec, http.StatusBadRequest) + assertErrorResponse(t, request, http.StatusBadRequest) }) t.Run("PasswordReset_WeakPassword", func(t *testing.T) { @@ -214,18 +192,13 @@ func TestIntegration_PasswordReset_CompleteFlow(t *testing.T) { resetToken := ctx.Suite.EmailSender.PasswordResetToken() - reqBody := map[string]string{ + reqBody := map[string]any{ "token": resetToken, "new_password": "123", } - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("POST", "/api/auth/reset-password", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() + request := makePostRequestWithJSON(t, router, "/api/auth/reset-password", reqBody) - router.ServeHTTP(rec, req) - - assertErrorResponse(t, rec, http.StatusBadRequest) + assertErrorResponse(t, request, http.StatusBadRequest) }) t.Run("PasswordReset_EmailIntegration", func(t *testing.T) { @@ -243,17 +216,12 @@ func TestIntegration_PasswordReset_CompleteFlow(t *testing.T) { t.Fatalf("Failed to create user: %v", err) } - reqBody := map[string]string{ + reqBody := map[string]any{ "username_or_email": "email_reset@example.com", } - body, _ := json.Marshal(reqBody) - req := httptest.NewRequest("POST", "/api/auth/forgot-password", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() + request := makePostRequestWithJSON(t, freshCtx.Router, "/api/auth/forgot-password", reqBody) - freshCtx.Router.ServeHTTP(rec, req) - - assertStatus(t, rec, http.StatusOK) + assertStatus(t, request, http.StatusOK) resetToken := freshCtx.Suite.EmailSender.PasswordResetToken() if resetToken == "" { diff --git a/internal/integration/ratelimit_integration_test.go b/internal/integration/ratelimit_integration_test.go index 2a097b4..27d57b6 100644 --- a/internal/integration/ratelimit_integration_test.go +++ b/internal/integration/ratelimit_integration_test.go @@ -51,24 +51,24 @@ func TestIntegration_RateLimiting(t *testing.T) { router, _ := setupRateLimitRouter(t, rateLimitConfig) for i := 0; i < 2; i++ { - req := httptest.NewRequest("POST", "/api/auth/login", bytes.NewBufferString(`{"username":"test","password":"test"}`)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() - router.ServeHTTP(rec, req) + request := httptest.NewRequest("POST", "/api/auth/login", bytes.NewBufferString(`{"username":"test","password":"test"}`)) + request.Header.Set("Content-Type", "application/json") + recorder := httptest.NewRecorder() + router.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() - router.ServeHTTP(rec, req) + router.ServeHTTP(recorder, request) - assertErrorResponse(t, rec, http.StatusTooManyRequests) + assertErrorResponse(t, recorder, http.StatusTooManyRequests) - assertHeader(t, rec, "Retry-After", "") + assertHeader(t, recorder, "Retry-After") 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 _, exists := response["retry_after"]; !exists { t.Error("Expected retry_after in response") } @@ -81,17 +81,17 @@ func TestIntegration_RateLimiting(t *testing.T) { router, _ := setupRateLimitRouter(t, rateLimitConfig) for i := 0; i < 5; i++ { - req := httptest.NewRequest("GET", "/api/posts", nil) - rec := httptest.NewRecorder() - router.ServeHTTP(rec, req) + request := httptest.NewRequest("GET", "/api/posts", nil) + recorder := httptest.NewRecorder() + router.ServeHTTP(recorder, request) } - 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) - assertErrorResponse(t, rec, http.StatusTooManyRequests) + assertErrorResponse(t, recorder, http.StatusTooManyRequests) }) t.Run("Health_RateLimit_Enforced", func(t *testing.T) { @@ -100,17 +100,17 @@ func TestIntegration_RateLimiting(t *testing.T) { router, _ := setupRateLimitRouter(t, rateLimitConfig) for i := 0; i < 3; i++ { - req := httptest.NewRequest("GET", "/health", nil) - rec := httptest.NewRecorder() - router.ServeHTTP(rec, req) + request := httptest.NewRequest("GET", "/health", nil) + recorder := httptest.NewRecorder() + router.ServeHTTP(recorder, request) } - 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) - assertErrorResponse(t, rec, http.StatusTooManyRequests) + assertErrorResponse(t, recorder, http.StatusTooManyRequests) }) t.Run("Metrics_RateLimit_Enforced", func(t *testing.T) { @@ -119,17 +119,17 @@ func TestIntegration_RateLimiting(t *testing.T) { router, _ := setupRateLimitRouter(t, rateLimitConfig) for i := 0; i < 2; i++ { - req := httptest.NewRequest("GET", "/metrics", nil) - rec := httptest.NewRecorder() - router.ServeHTTP(rec, req) + request := httptest.NewRequest("GET", "/metrics", nil) + recorder := httptest.NewRecorder() + router.ServeHTTP(recorder, request) } - 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) - assertErrorResponse(t, rec, http.StatusTooManyRequests) + assertErrorResponse(t, recorder, http.StatusTooManyRequests) }) t.Run("RateLimit_Different_Endpoints_Independent", func(t *testing.T) { @@ -139,17 +139,17 @@ func TestIntegration_RateLimiting(t *testing.T) { router, _ := setupRateLimitRouter(t, rateLimitConfig) for i := 0; i < 2; i++ { - req := httptest.NewRequest("POST", "/api/auth/login", bytes.NewBufferString(`{"username":"test","password":"test"}`)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() - router.ServeHTTP(rec, req) + request := httptest.NewRequest("POST", "/api/auth/login", bytes.NewBufferString(`{"username":"test","password":"test"}`)) + request.Header.Set("Content-Type", "application/json") + recorder := httptest.NewRecorder() + router.ServeHTTP(recorder, request) } - req := httptest.NewRequest("GET", "/api/posts", nil) - rec := httptest.NewRecorder() - router.ServeHTTP(rec, req) + request := httptest.NewRequest("GET", "/api/posts", nil) + recorder := httptest.NewRecorder() + router.ServeHTTP(recorder, request) - assertStatus(t, rec, http.StatusOK) + assertStatus(t, recorder, http.StatusOK) }) t.Run("RateLimit_With_Authentication", func(t *testing.T) { @@ -166,20 +166,20 @@ func TestIntegration_RateLimiting(t *testing.T) { user := createAuthenticatedUser(t, authService, suite.UserRepo, uniqueTestUsername(t, "ratelimit_auth"), uniqueTestEmail(t, "ratelimit_auth")) for i := 0; i < 3; i++ { - 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() - router.ServeHTTP(rec, req) + 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(recorder, request) } - 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) - assertErrorResponse(t, rec, http.StatusTooManyRequests) + assertErrorResponse(t, recorder, http.StatusTooManyRequests) }) } diff --git a/internal/integration/router_integration_test.go b/internal/integration/router_integration_test.go index 3f11e41..6cf644a 100644 --- a/internal/integration/router_integration_test.go +++ b/internal/integration/router_integration_test.go @@ -17,16 +17,13 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { router := ctx.Router t.Run("SecurityHeaders_Present", func(t *testing.T) { - request := httptest.NewRequest("GET", "/health", nil) - recorder := httptest.NewRecorder() + request := makeGetRequest(t, router, "/health") - router.ServeHTTP(recorder, request) + assertStatus(t, request, http.StatusOK) - assertStatus(t, recorder, http.StatusOK) - - assertHeader(t, recorder, "X-Content-Type-Options", "") - assertHeader(t, recorder, "X-Frame-Options", "") - assertHeader(t, recorder, "X-XSS-Protection", "") + assertHeader(t, request, "X-Content-Type-Options") + assertHeader(t, request, "X-Frame-Options") + assertHeader(t, request, "X-XSS-Protection") }) t.Run("CORS_Headers_Present", func(t *testing.T) { @@ -36,16 +33,13 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { router.ServeHTTP(recorder, request) - assertHeader(t, recorder, "Access-Control-Allow-Origin", "") + assertHeader(t, recorder, "Access-Control-Allow-Origin") }) t.Run("Logging_Middleware_Executes", func(t *testing.T) { - request := httptest.NewRequest("GET", "/health", nil) - recorder := httptest.NewRecorder() + request := makeGetRequest(t, router, "/health") - router.ServeHTTP(recorder, request) - - if recorder.Code == 0 { + if request.Code == 0 { t.Error("Expected logging middleware to execute") } }) @@ -67,13 +61,10 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { }) t.Run("DBMonitoring_Active", func(t *testing.T) { - request := httptest.NewRequest("GET", "/health", nil) - recorder := httptest.NewRecorder() - - router.ServeHTTP(recorder, request) + request := makeGetRequest(t, router, "/health") var response map[string]any - if err := json.NewDecoder(recorder.Body).Decode(&response); err == nil { + if err := json.NewDecoder(request.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 +74,9 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { }) t.Run("Metrics_Middleware_Executes", func(t *testing.T) { - request := httptest.NewRequest("GET", "/metrics", nil) - recorder := httptest.NewRecorder() + request := makeGetRequest(t, router, "/metrics") - router.ServeHTTP(recorder, request) - - response := assertJSONResponse(t, recorder, http.StatusOK) + response := assertJSONResponse(t, request, http.StatusOK) if response != nil { if data, ok := response["data"].(map[string]any); ok { if _, exists := data["database"]; !exists { @@ -99,34 +87,25 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { }) t.Run("StaticFiles_Served", func(t *testing.T) { - request := httptest.NewRequest("GET", "/robots.txt", nil) - recorder := httptest.NewRecorder() + request := makeGetRequest(t, router, "/robots.txt") - router.ServeHTTP(recorder, request) + assertStatus(t, request, http.StatusOK) - assertStatus(t, recorder, http.StatusOK) - - if !strings.Contains(recorder.Body.String(), "User-agent") { + if !strings.Contains(request.Body.String(), "User-agent") { t.Error("Expected robots.txt content") } }) t.Run("API_Routes_Accessible", func(t *testing.T) { - request := httptest.NewRequest("GET", "/api/posts", nil) - recorder := httptest.NewRecorder() + request := makeGetRequest(t, router, "/api/posts") - router.ServeHTTP(recorder, request) - - assertStatus(t, recorder, http.StatusOK) + assertStatus(t, request, http.StatusOK) }) t.Run("Health_Endpoint_Accessible", func(t *testing.T) { - request := httptest.NewRequest("GET", "/health", nil) - recorder := httptest.NewRecorder() + request := makeGetRequest(t, router, "/health") - router.ServeHTTP(recorder, request) - - response := assertJSONResponse(t, recorder, http.StatusOK) + response := assertJSONResponse(t, request, http.StatusOK) if response != nil { if success, ok := response["success"].(bool); !ok || !success { t.Error("Expected success=true in health response") @@ -135,14 +114,11 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { }) t.Run("Middleware_Order_Correct", func(t *testing.T) { - request := httptest.NewRequest("GET", "/api/posts", nil) - recorder := httptest.NewRecorder() + request := makeGetRequest(t, router, "/api/posts") - router.ServeHTTP(recorder, request) + assertHeader(t, request, "X-Content-Type-Options") - assertHeader(t, recorder, "X-Content-Type-Options", "") - - if recorder.Code == 0 { + if request.Code == 0 { t.Error("Response should have status code") } }) @@ -160,15 +136,11 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { }) t.Run("Cache_Middleware_Active", func(t *testing.T) { - firstRequest := httptest.NewRequest("GET", "/api/posts", nil) - firstRecorder := httptest.NewRecorder() - router.ServeHTTP(firstRecorder, firstRequest) + firstRequest := makeGetRequest(t, router, "/api/posts") - secondRequest := httptest.NewRequest("GET", "/api/posts", nil) - secondRecorder := httptest.NewRecorder() - router.ServeHTTP(secondRecorder, secondRequest) + secondRequest := makeGetRequest(t, router, "/api/posts") - if firstRecorder.Code != secondRecorder.Code { + if firstRequest.Code != secondRequest.Code { t.Error("Cached responses should have same status") } }) @@ -177,14 +149,9 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { ctx.Suite.EmailSender.Reset() user := createUserWithCleanup(t, ctx, "auth_middleware_user", "auth_middleware@example.com") - 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() + request := makeAuthenticatedGetRequest(t, router, "/api/auth/me", user, nil) - router.ServeHTTP(recorder, request) - - assertStatus(t, recorder, http.StatusOK) + assertStatus(t, request, http.StatusOK) }) t.Run("RateLimit_Middleware_Integration", func(t *testing.T) { @@ -192,20 +159,13 @@ func TestIntegration_Router_FullMiddlewareChain(t *testing.T) { rateLimitRouter := rateLimitCtx.Router 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(recorder, request) + request := makePostRequestWithJSON(t, rateLimitRouter, "/api/auth/login", map[string]any{"username": "test", "password": "test"}) + _ = request } - request := httptest.NewRequest("POST", "/api/auth/login", bytes.NewBufferString(`{"username":"test","password":"test"}`)) - request.Header.Set("Content-Type", "application/json") - recorder := httptest.NewRecorder() + request := makePostRequestWithJSON(t, rateLimitRouter, "/api/auth/login", map[string]any{"username": "test", "password": "test"}) - rateLimitRouter.ServeHTTP(recorder, request) - - if recorder.Code == http.StatusTooManyRequests { + if request.Code == http.StatusTooManyRequests { t.Log("Rate limiting is working") } })