package httputil // Tests for HTTP error mapping and response payloads. import ( "encoding/json" "errors" "net/http" "net/http/httptest" "testing" "github.com/gofiber/fiber/v3" "github.com/stretchr/testify/require" errorspkg "knowfoolery/backend/shared/domain/errors" ) // TestMapError verifies domain error codes map to HTTP status codes and response codes. func TestMapError(t *testing.T) { cases := []struct { name string err error statusCode int code string }{ {"nil", nil, http.StatusInternalServerError, "INTERNAL"}, {"not_found", errorspkg.Wrap(errorspkg.CodeNotFound, "missing", nil), http.StatusNotFound, "NOT_FOUND"}, {"invalid", errorspkg.Wrap(errorspkg.CodeInvalidInput, "bad", nil), http.StatusBadRequest, "INVALID_INPUT"}, {"unauthorized", errorspkg.Wrap(errorspkg.CodeUnauthorized, "no", nil), http.StatusUnauthorized, "UNAUTHORIZED"}, {"forbidden", errorspkg.Wrap(errorspkg.CodeForbidden, "no", nil), http.StatusForbidden, "FORBIDDEN"}, {"conflict", errorspkg.Wrap(errorspkg.CodeConflict, "conflict", nil), http.StatusConflict, "CONFLICT"}, {"rate_limit", errorspkg.Wrap(errorspkg.CodeRateLimitExceeded, "slow", nil), http.StatusTooManyRequests, "RATE_LIMIT_EXCEEDED"}, {"gone", errorspkg.Wrap(errorspkg.CodeSessionExpired, "gone", nil), http.StatusGone, "SESSION_EXPIRED"}, {"unprocessable", errorspkg.Wrap(errorspkg.CodeMaxAttemptsReached, "max", nil), http.StatusUnprocessableEntity, "MAX_ATTEMPTS_REACHED"}, {"generic", errors.New("boom"), http.StatusInternalServerError, "INTERNAL"}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { status, resp := MapError(tc.err) require.Equal(t, tc.statusCode, status) require.Equal(t, tc.code, resp.Code) }) } } // TestSendError verifies SendError writes the correct status and payload. func TestSendError(t *testing.T) { app := fiber.New() app.Get("/", func(c fiber.Ctx) error { return SendError(c, errorspkg.ErrNotFound) }) req := httptest.NewRequest(http.MethodGet, "/", nil) resp, err := app.Test(req) require.NoError(t, err) defer resp.Body.Close() require.Equal(t, http.StatusNotFound, resp.StatusCode) var body ErrorResponse require.NoError(t, json.NewDecoder(resp.Body).Decode(&body)) require.Equal(t, "NOT_FOUND", body.Code) }