package handler import ( "net/http" "testing" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "gorm.io/gorm" "github.com/wangjia/jiu/backend/internal/middleware" "github.com/wangjia/jiu/backend/internal/model" "github.com/wangjia/jiu/backend/testutil" ) // setupOptionRouter 注册 product-options 名称路由(含 JWT)。 func setupOptionRouter(db *gorm.DB) *gin.Engine { h := NewProductOptionHandler(db) r := gin.New() r.Use(gin.Recovery()) api := r.Group("/api/v1") api.Use(middleware.JWT(db)) names := api.Group("/product-options/names") names.GET("", h.ListNames) return r } func TestProductOptionHandler_ListNamesKeyword(t *testing.T) { db := testutil.SetupTestDB() shop := testutil.CreateTestShop(db, "OPT001") user := testutil.CreateTestUser(db, shop.ID, "admin", "pass", "admin") token := getAuthToken(user.ID, shop.ID, "admin") r := setupOptionRouter(db) db.Create(&model.ProductNameOption{ TenantBase: model.TenantBase{ShopID: shop.ID}, Code: "P001", Name: "茅台", }) db.Create(&model.ProductNameOption{ TenantBase: model.TenantBase{ShopID: shop.ID}, Code: "P002", Name: "五粮液", }) // 1. 无 keyword → 返回全部 w := makeRequest(r, "GET", "/api/v1/product-options/names", token, nil) assert.Equal(t, http.StatusOK, w.Code) data := parseResponse(w)["data"].([]interface{}) assert.Len(t, data, 2) // 2. keyword 命中名称 w = makeRequest(r, "GET", "/api/v1/product-options/names?keyword=五粮", token, nil) assert.Equal(t, http.StatusOK, w.Code) data = parseResponse(w)["data"].([]interface{}) assert.Len(t, data, 1) assert.Equal(t, "五粮液", data[0].(map[string]interface{})["name"]) // 3. keyword 命中编码 w = makeRequest(r, "GET", "/api/v1/product-options/names?keyword=P001", token, nil) assert.Equal(t, http.StatusOK, w.Code) data = parseResponse(w)["data"].([]interface{}) assert.Len(t, data, 1) assert.Equal(t, "茅台", data[0].(map[string]interface{})["name"]) // 4. keyword 无命中 → 空 w = makeRequest(r, "GET", "/api/v1/product-options/names?keyword=不存在", token, nil) assert.Equal(t, http.StatusOK, w.Code) data = parseResponse(w)["data"].([]interface{}) assert.Len(t, data, 0) } func TestProductOptionHandler_ListNamesIsolation(t *testing.T) { db := testutil.SetupTestDB() shopA := testutil.CreateTestShop(db, "OPT_A") userA := testutil.CreateTestUser(db, shopA.ID, "adminA", "pass", "admin") tokenA := getAuthToken(userA.ID, shopA.ID, "admin") shopB := testutil.CreateTestShop(db, "OPT_B") r := setupOptionRouter(db) db.Create(&model.ProductNameOption{ TenantBase: model.TenantBase{ShopID: shopB.ID}, Name: "他店商品", }) // A 店即使 keyword 命中 B 店数据也查不到(shop_id 隔离) w := makeRequest(r, "GET", "/api/v1/product-options/names?keyword=他店", tokenA, nil) assert.Equal(t, http.StatusOK, w.Code) data := parseResponse(w)["data"].([]interface{}) assert.Len(t, data, 0) }