package agencyopening import ( "context" "encoding/json" "net/http" "net/http/httptest" "testing" "hyapp-admin-server/internal/appctx" "hyapp-admin-server/internal/integration/activityclient" "hyapp-admin-server/internal/middleware" activityv1 "hyapp.local/api/proto/activity/v1" "github.com/gin-gonic/gin" ) func TestApproveApplicationForwardsReviewRequest(t *testing.T) { activity := &fakeAgencyOpeningActivityClient{} router := newAgencyOpeningHandlerTestRouter(New(activity, nil)) request := httptest.NewRequest(http.MethodPost, "/admin/activity/agency-opening/applications/application-1/approve", nil) recorder := httptest.NewRecorder() router.ServeHTTP(recorder, request) if recorder.Code != http.StatusOK { t.Fatalf("status mismatch: got=%d body=%s", recorder.Code, recorder.Body.String()) } if activity.lastReview == nil || activity.lastReview.GetApplicationId() != "application-1" || activity.lastReview.GetAction() != "approve" || activity.lastReview.GetOperatorAdminId() != 7 || activity.lastReview.GetMeta().GetAppCode() != "lalu" || activity.lastReview.GetMeta().GetCaller() != "admin-server" { t.Fatalf("review request mismatch: %+v", activity.lastReview) } var envelope struct { Code int `json:"code"` Data struct { ApplicationID string `json:"application_id"` Status string `json:"status"` ApprovedAtMS int64 `json:"approved_at_ms"` ScoreStartMS int64 `json:"score_start_ms"` ScoreEndMS int64 `json:"score_end_ms"` ReviewedByAdminID int64 `json:"reviewed_by_admin_id"` } `json:"data"` } if err := json.Unmarshal(recorder.Body.Bytes(), &envelope); err != nil { t.Fatalf("decode response: %v", err) } if envelope.Code != 0 || envelope.Data.ApplicationID != "application-1" || envelope.Data.Status != "approved" || envelope.Data.ApprovedAtMS != 2000 || envelope.Data.ScoreStartMS != 2000 || envelope.Data.ScoreEndMS != 2000+24*60*60*1000 || envelope.Data.ReviewedByAdminID != 7 { t.Fatalf("approve response mismatch: %+v", envelope) } } func newAgencyOpeningHandlerTestRouter(handler *Handler) *gin.Engine { gin.SetMode(gin.TestMode) router := gin.New() router.Use(func(c *gin.Context) { // 这里模拟后台鉴权中间件已经把 app_code、request_id 和操作者写入上下文,测试只关注接口参数透传。 c.Request = c.Request.WithContext(appctx.WithContext(c.Request.Context(), "lalu")) c.Set(middleware.ContextRequestID, "agency-opening-handler-test") c.Set(middleware.ContextUserID, uint(7)) c.Set(middleware.ContextUsername, "tester") c.Next() }) router.POST("/admin/activity/agency-opening/applications/:application_id/approve", handler.ApproveApplication) return router } type fakeAgencyOpeningActivityClient struct { activityclient.Client lastReview *activityv1.ReviewAgencyOpeningApplicationRequest } func (f *fakeAgencyOpeningActivityClient) ReviewAgencyOpeningApplication(_ context.Context, req *activityv1.ReviewAgencyOpeningApplicationRequest) (*activityv1.ReviewAgencyOpeningApplicationResponse, error) { f.lastReview = req return &activityv1.ReviewAgencyOpeningApplicationResponse{ Application: &activityv1.AgencyOpeningApplication{ ApplicationId: req.GetApplicationId(), CycleId: "cycle-1", AgencyId: 8001, AgencyOwnerUserId: 42001, AgencyName: "Window Agency", HostCount: 12, Status: "approved", AppliedAtMs: 1000, ApprovedAtMs: 2000, ScoreStartMs: 2000, ScoreEndMs: 2000 + int64((24 * 60 * 60 * 1000)), ReviewedByAdminId: req.GetOperatorAdminId(), }, }, nil }