diff --git a/backend/shared/domain/errors/errors_test.go b/backend/shared/domain/errors/errors_test.go index 42d3afd..d2a6d7d 100644 --- a/backend/shared/domain/errors/errors_test.go +++ b/backend/shared/domain/errors/errors_test.go @@ -25,12 +25,20 @@ func TestDomainError_Is(t *testing.T) { require.True(t, errors.Is(err, target)) } +// TestDomainError_Is_DifferentCode ensures errors.Is returns false for different codes. +func TestDomainError_Is_DifferentCode(t *testing.T) { + err := Wrap(CodeForbidden, "nope", nil) + target := New(CodeUnauthorized, "other") + require.False(t, errors.Is(err, target)) +} + // TestDomainError_NewAndWrapFields verifies fields are set for New and Wrap. func TestDomainError_NewAndWrapFields(t *testing.T) { created := New(CodeConflict, "conflict") require.Equal(t, CodeConflict, created.Code) require.Equal(t, "conflict", created.Message) require.Nil(t, created.Err) + require.Nil(t, errors.Unwrap(created)) root := errors.New("root") wrapped := Wrap(CodeInternal, "internal", root) diff --git a/backend/shared/infra/utils/httputil/errors_test.go b/backend/shared/infra/utils/httputil/errors_test.go index 90c6d6b..5285ccf 100644 --- a/backend/shared/infra/utils/httputil/errors_test.go +++ b/backend/shared/infra/utils/httputil/errors_test.go @@ -46,6 +46,58 @@ func TestMapError(t *testing.T) { } } +// TestMapError_AllCodes ensures all known error codes map to expected HTTP status codes. +func TestMapError_AllCodes(t *testing.T) { + cases := []struct { + code errorspkg.ErrorCode + statusCode int + }{ + {errorspkg.CodeNotFound, http.StatusNotFound}, + {errorspkg.CodeQuestionNotFound, http.StatusNotFound}, + {errorspkg.CodeUserNotFound, http.StatusNotFound}, + + {errorspkg.CodeInvalidInput, http.StatusBadRequest}, + {errorspkg.CodeValidationFailed, http.StatusBadRequest}, + {errorspkg.CodeInvalidPlayerName, http.StatusBadRequest}, + {errorspkg.CodeInvalidAnswer, http.StatusBadRequest}, + + {errorspkg.CodeUnauthorized, http.StatusUnauthorized}, + {errorspkg.CodeInvalidToken, http.StatusUnauthorized}, + {errorspkg.CodeTokenExpired, http.StatusUnauthorized}, + + {errorspkg.CodeForbidden, http.StatusForbidden}, + {errorspkg.CodeMFARequired, http.StatusForbidden}, + {errorspkg.CodeEmailNotVerified, http.StatusForbidden}, + + {errorspkg.CodeConflict, http.StatusConflict}, + {errorspkg.CodeUserAlreadyExists, http.StatusConflict}, + {errorspkg.CodeGameInProgress, http.StatusConflict}, + + {errorspkg.CodeRateLimitExceeded, http.StatusTooManyRequests}, + + {errorspkg.CodeSessionExpired, http.StatusGone}, + {errorspkg.CodeSessionNotActive, http.StatusGone}, + + {errorspkg.CodeMaxAttemptsReached, http.StatusUnprocessableEntity}, + {errorspkg.CodeNoQuestionsAvailable, http.StatusUnprocessableEntity}, + + {errorspkg.CodeInternal, http.StatusInternalServerError}, + } + + for _, tc := range cases { + status, resp := MapError(errorspkg.New(tc.code, "message")) + require.Equal(t, tc.statusCode, status) + require.Equal(t, tc.code.String(), resp.Code) + } +} + +// TestMapError_UnknownCode ensures unknown codes fall back to 500. +func TestMapError_UnknownCode(t *testing.T) { + status, resp := MapError(errorspkg.New(errorspkg.ErrorCode("UNKNOWN"), "oops")) + require.Equal(t, http.StatusInternalServerError, status) + require.Equal(t, "UNKNOWN", resp.Code) +} + // TestSendError verifies SendError writes the correct status and payload. func TestSendError(t *testing.T) { app := fiber.New()