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())
}
}