package handler import ( "encoding/json" "errors" "fmt" "io" "net/http" "net/http/httptest" "testing" "github.com/Tencent/WeKnora/internal/application/service" apperrors "github.com/Tencent/WeKnora/internal/errors" "github.com/Tencent/WeKnora/internal/middleware" "github.com/gin-gonic/gin" ) func TestEmbedManagementErrorMapping(t *testing.T) { gin.SetMode(gin.TestMode) tests := []struct { name string err error status int message string }{ {"forbidden", apperrors.NewForbiddenError("owner or admin required"), http.StatusForbidden, "owner or admin required"}, {"wrapped forbidden", fmt.Errorf("list: %w", apperrors.NewForbiddenError("owner or admin required")), http.StatusForbidden, "owner or admin required"}, {"agent missing", service.ErrAgentNotFound, http.StatusNotFound, "agent not found"}, {"wrapped agent missing", fmt.Errorf("list: %w", service.ErrAgentNotFound), http.StatusNotFound, "agent not found"}, {"channel missing", service.ErrEmbedChannelNotFound, http.StatusNotFound, "embed channel not found"}, {"typed missing", apperrors.NewNotFoundError("agent not found"), http.StatusNotFound, "agent not found"}, {"validation", apperrors.NewBadRequestError("agent_id is required"), http.StatusBadRequest, "agent_id is required"}, {"unexpected failure", errors.New("database credentials must stay private"), http.StatusInternalServerError, "operation failed"}, {"internal app failure", apperrors.NewInternalServerError("private failure details"), http.StatusInternalServerError, "operation failed"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { router := gin.New() router.Use(middleware.ErrorHandler()) var observedStatus int var recorded error router.Use(func(c *gin.Context) { c.Next() observedStatus = c.Writer.Status() if c.Errors.Last() != nil { recorded = c.Errors.Last().Err } }) router.GET("/agents/agent-1/embed-channels", func(c *gin.Context) { writeEmbedMgmtError(c, tt.err) }) writer := httptest.NewRecorder() router.ServeHTTP(writer, httptest.NewRequest(http.MethodGet, "/agents/agent-1/embed-channels", nil)) if writer.Code != tt.status || observedStatus != tt.status { t.Fatalf("response status %d, audit status %d, want %d", writer.Code, observedStatus, tt.status) } var appErr *apperrors.AppError if !errors.As(recorded, &appErr) || appErr.Message != tt.message { t.Fatalf("unexpected audit error: %v", recorded) } var body struct { Error struct { Message string `json:"message"` } `json:"error"` } decoder := json.NewDecoder(writer.Body) if err := decoder.Decode(&body); err != nil || body.Error.Message != tt.message { t.Fatalf("invalid response: %v, %#v", err, body) } var extra any if err := decoder.Decode(&extra); err != io.EOF { t.Fatalf("error middleware wrote more than one response: %v", err) } }) } }