package middleware import ( "bytes" "log/slog" "net/http" "net/http/httptest" "strings" "testing" ) func TestLoggingEmitsLineWithStatusAndPath(t *testing.T) { var buf bytes.Buffer logger := slog.New(slog.NewTextHandler(&buf, nil)) h := Logging(logger)(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(201) _, _ = w.Write([]byte("hello")) })) rr := httptest.NewRecorder() h.ServeHTTP(rr, httptest.NewRequestWithContext(t.Context(), "POST", "/widgets", http.NoBody)) logged := buf.String() for _, want := range []string{"http request", "method=POST", "path=/widgets", "status=201", "size=5"} { if !strings.Contains(logged, want) { t.Errorf("log line missing %q\nfull line: %s", want, logged) } } } func TestLoggingDefaultsStatusTo200(t *testing.T) { var buf bytes.Buffer logger := slog.New(slog.NewTextHandler(&buf, nil)) h := Logging(logger)(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { // No explicit WriteHeader: should default to 200 in our log line. _, _ = w.Write([]byte("ok")) })) rr := httptest.NewRecorder() h.ServeHTTP(rr, httptest.NewRequestWithContext(t.Context(), "GET", "/", http.NoBody)) if !strings.Contains(buf.String(), "status=200") { t.Errorf("expected status=200 in log, got %q", buf.String()) } } func TestLoggingIncludesRequestID(t *testing.T) { var buf bytes.Buffer logger := slog.New(slog.NewTextHandler(&buf, nil)) h := RequestID(Logging(logger)(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) }))) req := httptest.NewRequestWithContext(t.Context(), "GET", "/", http.NoBody) req.Header.Set("X-Request-ID", "abc-123") rr := httptest.NewRecorder() h.ServeHTTP(rr, req) if !strings.Contains(buf.String(), "request_id=abc-123") { t.Errorf("expected request_id in log, got %q", buf.String()) } }