diff --git a/errors.go b/errors.go index 9a56503..f4ea70e 100644 --- a/errors.go +++ b/errors.go @@ -94,40 +94,40 @@ func (x *Error) copy(dst *Error) { } // Printable returns printable object -func (x *Error) Printable() *printable { - e := &printable{ +func (x *Error) Printable() *Printable { + e := &Printable{ Message: x.msg, ID: x.id, StackTrace: x.Stacks(), - Cause: x.cause, Values: make(map[string]any), } for k, v := range x.values { e.Values[k] = v } + + if cause := Unwrap(x.cause); cause != nil { + e.Cause = cause.Printable() + } else if x.cause != nil { + e.Cause = x.cause.Error() + } return e } -type printable struct { +type Printable struct { Message string `json:"message"` ID string `json:"id"` StackTrace []*Stack `json:"stacktrace"` - Cause error `json:"cause"` + Cause any `json:"cause"` Values map[string]any `json:"values"` } // Error returns error message for error interface func (x *Error) Error() string { - s := x.msg - cause := x.cause - - if cause == nil { - return s + if x.cause == nil { + return x.msg } - s = fmt.Sprintf("%s: %v", s, cause.Error()) - - return s + return fmt.Sprintf("%s: %v", x.msg, x.cause.Error()) } // Format returns: diff --git a/errors_test.go b/errors_test.go index e36e544..27964cb 100644 --- a/errors_test.go +++ b/errors_test.go @@ -107,7 +107,7 @@ func TestErrorCode(t *testing.T) { } } -func TestPrintable(t *testing.T) { +func TestPrintableWithGoErr(t *testing.T) { cause := errors.New("test") err := goerr.Wrap(cause, "oops").ID("E001").With("blue", "five") @@ -118,8 +118,31 @@ func TestPrintable(t *testing.T) { if p.ID != "E001" { t.Errorf("Expected ID to be 'E001', got '%s'", p.ID) } - if p.Cause != cause { - t.Errorf("Expected cause to be '%v', got '%v'", cause, p.Cause) + if s, ok := p.Cause.(string); !ok { + t.Errorf("Expected cause is string, got '%t'", p.Cause) + } else if s != "test" { + t.Errorf("Expected message is 'test', got '%s'", s) + } + if p.Values["blue"] != "five" { + t.Errorf("Expected value for 'blue' to be 'five', got '%v'", p.Values["blue"]) + } +} + +func TestPrintableWithError(t *testing.T) { + cause := goerr.New("test") + err := goerr.Wrap(cause, "oops").ID("E001").With("blue", "five") + + p := err.Printable() + if p.Message != "oops" { + t.Errorf("Expected message to be 'oops', got '%s'", p.Message) + } + if p.ID != "E001" { + t.Errorf("Expected ID to be 'E001', got '%s'", p.ID) + } + if cp, ok := p.Cause.(*goerr.Printable); !ok { + t.Errorf("Expected cause is goerr.Printable, got '%t'", p.Cause) + } else if cp.Message != "test" { + t.Errorf("Expected message is 'test', got '%s'", cp.Message) } if p.Values["blue"] != "five" { t.Errorf("Expected value for 'blue' to be 'five', got '%v'", p.Values["blue"])