package server import ( "encoding/json" "io" "log/slog" "maps" "net/http" "net/http/httptest" "testing" ) func TestHealth(t *testing.T) { t.Parallel() logger := slog.New(slog.NewTextHandler(io.Discard, nil)) srv := httptest.NewServer(NewRouter(logger, "1.2.3")) t.Cleanup(srv.Close) resp, err := http.Get(srv.URL + "/health") if err != nil { t.Fatal(err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Errorf("status = %d, want 200", resp.StatusCode) } if ct := resp.Header.Get("Content-Type"); ct != "application/json" { t.Errorf("Content-Type = %q, want application/json", ct) } var got map[string]string if err := json.NewDecoder(resp.Body).Decode(&got); err != nil { t.Fatal(err) } want := map[string]string{"status": "ok", "version": "1.2.3"} if len(got) != len(want) || got["status"] != want["status"] || got["version"] != want["version"] { t.Errorf("body = %v, want %v", got, want) } } func TestHealthRejectsOtherMethods(t *testing.T) { t.Parallel() logger := slog.New(slog.NewTextHandler(io.Discard, nil)) rec := httptest.NewRecorder() NewRouter(logger, "dev").ServeHTTP(rec, httptest.NewRequest(http.MethodPost, "/health", nil)) if rec.Code != http.StatusMethodNotAllowed { t.Errorf("status = %d, want 405", rec.Code) } if ct := rec.Header().Get("Content-Type"); ct != "application/json" { t.Errorf("Content-Type = %q, want application/json", ct) } var got struct { Error map[string]any `json:"error"` } if err := json.NewDecoder(rec.Body).Decode(&got); err != nil { t.Fatal(err) } want := map[string]any{ "code": "method_not_allowed", "message": "method not allowed", "retryable": false, } if !maps.Equal(got.Error, want) { t.Errorf("error body = %v, want %v", got.Error, want) } } func TestUnknownPathNotFound(t *testing.T) { t.Parallel() logger := slog.New(slog.NewTextHandler(io.Discard, nil)) rec := httptest.NewRecorder() NewRouter(logger, "dev").ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/unknown", nil)) if rec.Code != http.StatusNotFound { t.Errorf("status = %d, want 404", rec.Code) } if ct := rec.Header().Get("Content-Type"); ct != "application/json" { t.Errorf("Content-Type = %q, want application/json", ct) } const want = `{"error":{"code":"not_found","message":"not found","retryable":false}}` if got := rec.Body.String(); got != want { t.Errorf("body = %s, want %s", got, want) } }