package testutil import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" "time" ) // NewRequest creates a test HTTP request with JSON body. func NewRequest(t *testing.T, method, path string, body any) *http.Request { t.Helper() var buf bytes.Buffer if body != nil { if err := json.NewEncoder(&buf).Encode(body); err != nil { t.Fatalf("encode request body: %v", err) } } req := httptest.NewRequest(method, path, &buf) req.Header.Set("Content-Type", "application/json") return req } // NewRequestWithAuth creates a test request with API Key auth. func NewRequestWithAuth(t *testing.T, method, path, apiKey string, body any) *http.Request { t.Helper() req := NewRequest(t, method, path, body) req.Header.Set("Authorization", "Bearer "+apiKey) return req } // AssertStatus checks the response status code. func AssertStatus(t *testing.T, rr *httptest.ResponseRecorder, want int) { t.Helper() if rr.Code != want { t.Errorf("expected status %d, got %d", want, rr.Code) } } // AssertJSON checks the response body contains expected JSON fields. func AssertJSON(t *testing.T, rr *httptest.ResponseRecorder, expected map[string]any) { t.Helper() var actual map[string]any if err := json.Unmarshal(rr.Body.Bytes(), &actual); err != nil { t.Fatalf("unmarshal response: %v\nbody: %s", err, rr.Body.String()) } for k, v := range expected { got, ok := actual[k] if !ok { t.Errorf("expected key %q in response, not found", k) continue } if got != v { t.Errorf("expected %q = %v, got %v", k, v, got) } } } // AssertErrorCode checks the error code in the response. func AssertErrorCode(t *testing.T, rr *httptest.ResponseRecorder, code string) { t.Helper() var resp map[string]any if err := json.Unmarshal(rr.Body.Bytes(), &resp); err != nil { t.Fatalf("unmarshal error response: %v", err) } errBody, ok := resp["error"].(map[string]any) if !ok { t.Fatal("expected error object in response") } if errBody["code"] != code { t.Errorf("expected error code %q, got %v", code, errBody["code"]) } } // RandomID generates a random ID string for testing. func RandomID() string { return "test-" + randHex(8) } func randHex(n int) string { const hexChars = "0123456789abcdef" b := make([]byte, n) for i := range b { b[i] = hexChars[time.Now().UnixNano()%int64(len(hexChars))] } return string(b) } // ExecuteRequest executes a request against a handler and returns the response. func ExecuteRequest(handler http.Handler, req *http.Request) *httptest.ResponseRecorder { rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) return rr }