package main import ( "encoding/json" "net/http" "net/http/httptest" "path/filepath" "strconv" "strings" "testing" "github.com/gin-gonic/gin" "github.com/glebarez/sqlite" "gorm.io/gorm" businessbiz "kra/internal/biz/business" "kra/internal/biz/system" businessdata "kra/internal/data/business" systemdata "kra/internal/data/system" "kra/internal/server/handler" "kra/internal/server/router" businessservice "kra/internal/service/business" ) func TestOtherSettingsHTTPPersistenceAndAccess(t *testing.T) { db, err := gorm.Open(sqlite.Open(filepath.Join(t.TempDir(), "settings.db")), &gorm.Config{}) if err != nil { t.Fatal(err) } pool, _ := db.DB() t.Cleanup(func() { _ = pool.Close() }) for _, step := range systemdata.Migrations() { if err := step.Migrate(db); err != nil { t.Fatal(err) } } uc := businessbiz.NewOtherSettingsUsecase(businessdata.NewOtherSettingsRepo(businessHTTPData{db}), nil) engine := gin.New() engine.Use(func(c *gin.Context) { role, _ := strconv.ParseUint(c.GetHeader("X-Test-Role"), 10, 64) if role != 0 { c.Request = c.Request.WithContext(system.NewActorContext(c.Request.Context(), system.Actor{UserID: 1, AuthorityID: uint(role)})) } c.Next() }) router.RegisterOtherSettings(engine.Group(""), handler.NewOtherSettings(businessservice.NewOtherSettingsService(uc))) call := func(role int, method, body string) map[string]any { t.Helper() req := httptest.NewRequest(method, "/sw/settings/effectiveness", strings.NewReader(body)) req.Header.Set("Content-Type", "application/json") req.Header.Set("X-Test-Role", strconv.Itoa(role)) recorder := httptest.NewRecorder() engine.ServeHTTP(recorder, req) var result map[string]any if err := json.Unmarshal(recorder.Body.Bytes(), &result); err != nil { t.Fatal(err) } return result } for _, role := range []int{0, 901, 902, 903} { if call(role, http.MethodGet, "")["code"] == float64(0) { t.Fatal("非超管不得读取设置") } if call(role, http.MethodPut, `{"amount":10,"days":10}`)["code"] == float64(0) { t.Fatal("非超管不得写入设置") } } value := call(888, http.MethodGet, "")["data"].(map[string]any) if value["amount"] != float64(3000) || value["days"] != float64(30) { t.Fatal("首次访问默认值错误") } for _, body := range []string{`{}`, `{"amount":0}`, `{"amount":-1,"days":30}`, `{"amount":3.5,"days":30}`, `{"amount":0,"days":0}`, `{"amount":"3000","days":30}`} { if call(888, http.MethodPut, body)["code"] == float64(0) { t.Fatalf("非法输入被接受: %s", body) } } if call(888, http.MethodPut, `{"amount":0,"days":14}`)["code"] != float64(0) { t.Fatal("合法设置保存失败") } value = call(888, http.MethodGet, "")["data"].(map[string]any) if value["amount"] != float64(0) || value["days"] != float64(14) || value["updatedAt"] == "" { t.Fatal("读取未回显已保存值") } var raw string if err := db.Table("sys_params").Select("value").Where(map[string]any{"key": "sw.channel_effectiveness"}).Scan(&raw).Error; err != nil || raw != `{"amount":0,"days":14}` { t.Fatalf("应使用参数表的单条 JSON: %s %v", raw, err) } if call(888, http.MethodPut, `{"amount":3000,"days":30}`)["code"] != float64(0) { t.Fatal("默认值无法重新保存") } }