Add server WriteJSON and WriteError response helpers
Eliminates repeated marshal-set-header-write boilerplate in handlers.
WriteError produces consistent {"error": "..."} JSON responses.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
72
server/respond_test.go
Normal file
72
server/respond_test.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package server_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"git.codelab.vc/pkg/httpx/server"
|
||||
)
|
||||
|
||||
func TestWriteJSON(t *testing.T) {
|
||||
t.Run("writes JSON with status and content type", func(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
type resp struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
err := server.WriteJSON(w, 201, resp{ID: 1, Name: "Alice"})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if w.Code != 201 {
|
||||
t.Fatalf("got status %d, want %d", w.Code, 201)
|
||||
}
|
||||
if ct := w.Header().Get("Content-Type"); ct != "application/json" {
|
||||
t.Fatalf("Content-Type = %q, want %q", ct, "application/json")
|
||||
}
|
||||
|
||||
var decoded resp
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &decoded); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if decoded.ID != 1 || decoded.Name != "Alice" {
|
||||
t.Fatalf("got %+v, want {ID:1 Name:Alice}", decoded)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("returns error for unmarshalable input", func(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
err := server.WriteJSON(w, 200, make(chan int))
|
||||
if err == nil {
|
||||
t.Fatal("expected error for channel type")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestWriteError(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
err := server.WriteError(w, 404, "not found")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if w.Code != 404 {
|
||||
t.Fatalf("got status %d, want %d", w.Code, 404)
|
||||
}
|
||||
|
||||
var body struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &body); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if body.Error != "not found" {
|
||||
t.Fatalf("error = %q, want %q", body.Error, "not found")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user