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