package controller import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/QuantumNous/new-api/common" "github.com/QuantumNous/new-api/model" "github.com/glebarez/sqlite" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/gorm" ) func setupRedemptionControllerDB(t *testing.T) *gorm.DB { t.Helper() db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) require.NoError(t, err) sqlDB, _ := db.DB() sqlDB.SetMaxOpenConns(1) origDB := model.DB origLogDB := model.LOG_DB model.DB = db model.LOG_DB = db common.UsingSQLite = true common.RedisEnabled = false require.NoError(t, db.AutoMigrate(&model.User{}, &model.Redemption{}, &model.Log{})) t.Cleanup(func() { model.DB = origDB model.LOG_DB = origLogDB _ = sqlDB.Close() }) return db } func setupRedemptionRouter() *gin.Engine { gin.SetMode(gin.TestMode) r := gin.New() r.Use(func(c *gin.Context) { c.Set("id", 1) c.Next() }) g := r.Group("/api/redemption") g.POST("/", AddRedemption) g.PUT("/", UpdateRedemption) return r } func TestAddRedemptionStoresRemark(t *testing.T) { db := setupRedemptionControllerDB(t) router := setupRedemptionRouter() body, err := json.Marshal(map[string]interface{}{ "name": "campaign-a", "remark": "admin only note", "quota": 500000, "count": 1, "expired_time": 0, }) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/api/redemption/", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var rows []model.Redemption require.NoError(t, db.Find(&rows).Error) require.Len(t, rows, 1) assert.Equal(t, "campaign-a", rows[0].Name) assert.Equal(t, "admin only note", rows[0].Remark) } func TestUpdateRedemptionStoresRemark(t *testing.T) { db := setupRedemptionControllerDB(t) router := setupRedemptionRouter() row := model.Redemption{ Id: 1, UserId: 1, Key: "update-remark-key", Name: "campaign-b", Remark: "before update", Status: common.RedemptionCodeStatusEnabled, Quota: 500000, CreatedTime: common.GetTimestamp(), } require.NoError(t, db.Create(&row).Error) body, err := json.Marshal(map[string]interface{}{ "id": 1, "name": "campaign-b", "remark": "after update", "quota": 500000, "expired_time": 0, }) require.NoError(t, err) req := httptest.NewRequest(http.MethodPut, "/api/redemption/", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var stored model.Redemption require.NoError(t, db.First(&stored, 1).Error) assert.Equal(t, "after update", stored.Remark) } func TestUpdateRedemptionStatusOnlyKeepsRemark(t *testing.T) { db := setupRedemptionControllerDB(t) router := setupRedemptionRouter() row := model.Redemption{ Id: 1, UserId: 1, Key: "status-only-remark-key", Name: "campaign-c", Remark: "keep this remark", Status: common.RedemptionCodeStatusEnabled, Quota: 500000, CreatedTime: common.GetTimestamp(), } require.NoError(t, db.Create(&row).Error) body, err := json.Marshal(map[string]interface{}{ "id": 1, "status": common.RedemptionCodeStatusDisabled, "remark": "should not overwrite", }) require.NoError(t, err) req := httptest.NewRequest(http.MethodPut, "/api/redemption/?status_only=true", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var stored model.Redemption require.NoError(t, db.First(&stored, 1).Error) assert.Equal(t, common.RedemptionCodeStatusDisabled, stored.Status) assert.Equal(t, "keep this remark", stored.Remark) }