diff --git a/api4/post_test.go b/api4/post_test.go index b119715df5..34f96b69bd 100644 --- a/api4/post_test.go +++ b/api4/post_test.go @@ -928,7 +928,7 @@ func TestPatchPost(t *testing.T) { t.Run("invalid requests", func(t *testing.T) { r, err := client.DoAPIPut("/posts/"+post.Id+"/patch", "garbage") - require.EqualError(t, err, ": Invalid or missing post in request body.") + require.EqualError(t, err, ": Invalid or missing post in request body., invalid character 'g' looking for beginning of value") require.Equal(t, http.StatusBadRequest, r.StatusCode, "wrong status code") patch := &model.PostPatch{} diff --git a/model/utils.go b/model/utils.go index 968d0f9c3d..1565503088 100644 --- a/model/utils.go +++ b/model/utils.go @@ -265,10 +265,30 @@ func (er *AppError) SystemMessage(T i18n.TranslateFunc) string { } func (er *AppError) ToJSON() string { + // turn the wrapped error into a detailed message + detailed := er.DetailedError + defer func() { + er.DetailedError = detailed + }() + + er.wrappedToDetailed() + b, _ := json.Marshal(er) return string(b) } +func (er *AppError) wrappedToDetailed() { + if er.wrapped == nil { + return + } + + if er.DetailedError != "" { + er.DetailedError += ", " + } + + er.DetailedError += er.wrapped.Error() +} + func (er *AppError) Unwrap() error { return er.wrapped } diff --git a/model/utils_test.go b/model/utils_test.go index e02c38dc1f..2d878ef470 100644 --- a/model/utils_test.go +++ b/model/utils_test.go @@ -5,6 +5,7 @@ package model import ( "bytes" + "errors" "fmt" "net/http" "reflect" @@ -112,6 +113,52 @@ func TestAppErrorRender(t *testing.T) { }) } +func TestAppErrorSerialize(t *testing.T) { + t.Run("Normal", func(t *testing.T) { + aerr := NewAppError("", "message", nil, "", http.StatusTeapot) + js := aerr.ToJSON() + berr := AppErrorFromJSON(strings.NewReader(js)) + require.Equal(t, "message", berr.Id) + require.Empty(t, berr.DetailedError) + require.Equal(t, http.StatusTeapot, berr.StatusCode) + + require.EqualError(t, berr, aerr.Error()) + }) + + t.Run("Detailed", func(t *testing.T) { + aerr := NewAppError("", "message", nil, "detail", http.StatusTeapot) + js := aerr.ToJSON() + berr := AppErrorFromJSON(strings.NewReader(js)) + require.Equal(t, "message", berr.Id) + require.Equal(t, "detail", berr.DetailedError) + require.Equal(t, http.StatusTeapot, berr.StatusCode) + + require.EqualError(t, berr, aerr.Error()) + }) + + t.Run("Wrapped", func(t *testing.T) { + aerr := NewAppError("", "message", nil, "", http.StatusTeapot).Wrap(errors.New("wrapped")) + js := aerr.ToJSON() + berr := AppErrorFromJSON(strings.NewReader(js)) + require.Equal(t, "message", berr.Id) + require.Equal(t, "wrapped", berr.DetailedError) + require.Equal(t, http.StatusTeapot, berr.StatusCode) + + require.EqualError(t, berr, aerr.Error()) + }) + + t.Run("Detailed + Wrapped", func(t *testing.T) { + aerr := NewAppError("", "message", nil, "detail", http.StatusTeapot).Wrap(errors.New("wrapped")) + js := aerr.ToJSON() + berr := AppErrorFromJSON(strings.NewReader(js)) + require.Equal(t, "message", berr.Id) + require.Equal(t, "detail, wrapped", berr.DetailedError) + require.Equal(t, http.StatusTeapot, berr.StatusCode) + + require.EqualError(t, berr, aerr.Error()) + }) +} + func TestCopyStringMap(t *testing.T) { itemKey := "item1" originalMap := make(map[string]string)