package apierror
import (
"encoding/json"
"errors"
"fmt"
"net/http/httptest"
"testing"
)
func TestFromErrorPassesThroughProblem(t *testing.T) {
original := Problem{Title: "Teapot", Status: 418, Code: "TEAPOT"}
got := FromError(original)
if got != original {
t.Errorf("FromError(Problem) lost data: got %+v want %+v", got, original)
}
}
func TestFromErrorWrappedProblem(t *testing.T) {
original := Problem{Title: "Teapot", Status: 418}
wrapped := fmt.Errorf("outer: %w", original)
got := FromError(wrapped)
if got.Status != 418 {
t.Errorf("status = %d, want 418", got.Status)
}
}
func TestFromErrorNotFound(t *testing.T) {
p := FromError(NotFound("widget"))
if p.Status != 404 {
t.Errorf("status = %d, want 404", p.Status)
}
if p.Code != "NOT_FOUND" {
t.Errorf("code = %q", p.Code)
}
if p.Detail != "widget not found" {
t.Errorf("detail = %q", p.Detail)
}
}
func TestFromErrorBadRequest(t *testing.T) {
p := FromError(BadRequest("missing q"))
if p.Status != 400 {
t.Errorf("status = %d, want 400", p.Status)
}
if p.Code != "BAD_REQUEST" {
t.Errorf("code = %q", p.Code)
}
if p.Detail != "missing q" {
t.Errorf("detail = %q", p.Detail)
}
}
func TestFromErrorUnknownCollapsesTo500(t *testing.T) {
p := FromError(errors.New("secret database password leaked"))
if p.Status != 500 {
t.Errorf("status = %d, want 500", p.Status)
}
if p.Detail != "" {
t.Errorf("detail should be empty to avoid leaks, got %q", p.Detail)
}
if p.Title != "Internal Server Error" {
t.Errorf("title = %q", p.Title)
}
}
func TestProblemError(t *testing.T) {
p := Problem{Title: "Bad"}
if p.Error() != "Bad" {
t.Errorf("Error() = %q", p.Error())
}
}
func TestProblemWrite(t *testing.T) {
rr := httptest.NewRecorder()
p := Problem{Title: "Not Found", Status: 404, Detail: "thing missing", Code: "NOT_FOUND"}
p.Write(rr)
if rr.Code != 404 {
t.Errorf("status = %d", rr.Code)
}
if got := rr.Header().Get("Content-Type"); got != "application/problem+json" {
t.Errorf("content-type = %q", got)
}
var decoded Problem
if err := json.Unmarshal(rr.Body.Bytes(), &decoded); err != nil {
t.Fatalf("decode body: %v", err)
}
if decoded != p {
t.Errorf("decoded = %+v, want %+v", decoded, p)
}
}
func TestNotFoundErrorMessage(t *testing.T) {
if got := (NotFoundError{Resource: "thing"}).Error(); got != "thing not found" {
t.Errorf("Error() = %q", got)
}
}
func TestBadRequestErrorMessage(t *testing.T) {
if got := (BadRequestError{Detail: "nope"}).Error(); got != "nope" {
t.Errorf("Error() = %q", got)
}
}