// Copyright 2026 Beacon Contributors // SPDX-License-Identifier: AGPL-3.0-or-later package handlers import ( "encoding/json" "net/http" "net/http/httptest" "testing" ) func TestRespond_StatusAndContentType(t *testing.T) { w := httptest.NewRecorder() respond(w, http.StatusOK, map[string]string{"hello": "world"}) if w.Code != http.StatusOK { t.Errorf("expected 200, got %d", w.Code) } if ct := w.Header().Get("Content-Type"); ct != "application/json" { t.Errorf("expected application/json, got %s", ct) } } func TestRespond_EncodesJSON(t *testing.T) { w := httptest.NewRecorder() respond(w, http.StatusOK, map[string]string{"key": "value"}) var result map[string]string if err := json.NewDecoder(w.Body).Decode(&result); err != nil { t.Fatalf("failed to decode response: %v", err) } if result["key"] != "value" { t.Errorf("expected value, got %s", result["key"]) } } func TestRespondError_StatusCode(t *testing.T) { w := httptest.NewRecorder() respondError(w, http.StatusBadRequest, "invalid input") if w.Code != http.StatusBadRequest { t.Errorf("expected 400, got %d", w.Code) } } func TestRespondError_Shape(t *testing.T) { w := httptest.NewRecorder() respondError(w, http.StatusBadRequest, "invalid input") var result map[string]APIError if err := json.NewDecoder(w.Body).Decode(&result); err != nil { t.Fatalf("failed to decode error response: %v", err) } e, ok := result["error"] if !ok { t.Fatal("expected 'error' key in response") } if e.Code != "bad_request" { t.Errorf("expected code bad_request, got %s", e.Code) } if e.Message != "invalid input" { t.Errorf("expected message 'invalid input', got %s", e.Message) } } func TestRespondError_CodeDerivation(t *testing.T) { tests := []struct { status int want string }{ {http.StatusBadRequest, "bad_request"}, {http.StatusNotFound, "not_found"}, {http.StatusInternalServerError, "internal_server_error"}, {http.StatusUnauthorized, "unauthorized"}, } for _, tt := range tests { w := httptest.NewRecorder() respondError(w, tt.status, "msg") var result map[string]APIError if err := json.NewDecoder(w.Body).Decode(&result); err != nil { t.Fatalf("status %d: failed to decode: %v", tt.status, err) } if result["error"].Code != tt.want { t.Errorf("status %d: expected code %s, got %s", tt.status, tt.want, result["error"].Code) } } }