package integration import ( "context" "encoding/json" "fmt" "testing" "time" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/pkg/constants" pkgGorm "github.com/break/junhong_cmp_fiber/pkg/gorm" "github.com/break/junhong_cmp_fiber/pkg/response" "github.com/break/junhong_cmp_fiber/tests/testutils/integ" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // ==================== Part 1: 套餐系列 API 测试 ==================== func TestPackageSeriesAPI_Create(t *testing.T) { env := integ.NewIntegrationTestEnv(t) timestamp := time.Now().Unix() seriesCode := fmt.Sprintf("TEST_SERIES_%d", timestamp) body := map[string]interface{}{ "series_code": seriesCode, "series_name": "测试套餐系列", "description": "API集成测试创建的套餐系列", } jsonBody, _ := json.Marshal(body) resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/package-series", jsonBody) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, 200, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) dataMap, ok := result.Data.(map[string]interface{}) require.True(t, ok) assert.Equal(t, seriesCode, dataMap["series_code"]) assert.Equal(t, "测试套餐系列", dataMap["series_name"]) assert.Equal(t, float64(constants.StatusEnabled), dataMap["status"]) t.Logf("创建的套餐系列 ID: %v", dataMap["id"]) } func TestPackageSeriesAPI_Get(t *testing.T) { env := integ.NewIntegrationTestEnv(t) timestamp := time.Now().Unix() seriesCode := fmt.Sprintf("TEST_SERIES_%d", timestamp) series := &model.PackageSeries{ SeriesCode: seriesCode, SeriesName: "测试套餐系列", Description: "测试描述", Status: constants.StatusEnabled, BaseModel: model.BaseModel{ Creator: 1, }, } require.NoError(t, env.TX.Create(series).Error) url := fmt.Sprintf("/api/admin/package-series/%d", series.ID) resp, err := env.AsSuperAdmin().Request("GET", url, nil) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, 200, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) dataMap := result.Data.(map[string]interface{}) assert.Equal(t, seriesCode, dataMap["series_code"]) assert.Equal(t, "测试套餐系列", dataMap["series_name"]) } func TestPackageSeriesAPI_List(t *testing.T) { env := integ.NewIntegrationTestEnv(t) timestamp := time.Now().Unix() seriesList := []*model.PackageSeries{ { SeriesCode: fmt.Sprintf("TEST_LIST_%d_001", timestamp), SeriesName: "列表测试系列1", Status: constants.StatusEnabled, BaseModel: model.BaseModel{Creator: 1}, }, { SeriesCode: fmt.Sprintf("TEST_LIST_%d_002", timestamp), SeriesName: "列表测试系列2", Status: constants.StatusEnabled, BaseModel: model.BaseModel{Creator: 1}, }, } for _, s := range seriesList { require.NoError(t, env.TX.Create(s).Error) } resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/package-series?page=1&page_size=20", nil) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, 200, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) } func TestPackageSeriesAPI_Update(t *testing.T) { env := integ.NewIntegrationTestEnv(t) timestamp := time.Now().Unix() seriesCode := fmt.Sprintf("TEST_SERIES_%d", timestamp) series := &model.PackageSeries{ SeriesCode: seriesCode, SeriesName: "原始系列名称", Description: "原始描述", Status: constants.StatusEnabled, BaseModel: model.BaseModel{ Creator: 1, }, } require.NoError(t, env.TX.Create(series).Error) body := map[string]interface{}{ "series_name": "更新后的系列名称", "description": "更新后的描述", } jsonBody, _ := json.Marshal(body) url := fmt.Sprintf("/api/admin/package-series/%d", series.ID) resp, err := env.AsSuperAdmin().Request("PUT", url, jsonBody) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, 200, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) dataMap := result.Data.(map[string]interface{}) assert.Equal(t, "更新后的系列名称", dataMap["series_name"]) assert.Equal(t, "更新后的描述", dataMap["description"]) } func TestPackageSeriesAPI_UpdateStatus(t *testing.T) { env := integ.NewIntegrationTestEnv(t) timestamp := time.Now().Unix() seriesCode := fmt.Sprintf("TEST_SERIES_%d", timestamp) series := &model.PackageSeries{ SeriesCode: seriesCode, SeriesName: "测试系列", Status: constants.StatusEnabled, BaseModel: model.BaseModel{ Creator: 1, }, } require.NoError(t, env.TX.Create(series).Error) body := map[string]interface{}{ "status": constants.StatusDisabled, } jsonBody, _ := json.Marshal(body) url := fmt.Sprintf("/api/admin/package-series/%d/status", series.ID) resp, err := env.AsSuperAdmin().Request("PATCH", url, jsonBody) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, 200, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) var updatedSeries model.PackageSeries env.RawDB().First(&updatedSeries, series.ID) assert.Equal(t, constants.StatusDisabled, updatedSeries.Status) } func TestPackageSeriesAPI_Delete(t *testing.T) { env := integ.NewIntegrationTestEnv(t) timestamp := time.Now().Unix() seriesCode := fmt.Sprintf("TEST_SERIES_%d", timestamp) series := &model.PackageSeries{ SeriesCode: seriesCode, SeriesName: "测试系列", Status: constants.StatusEnabled, BaseModel: model.BaseModel{ Creator: 1, }, } require.NoError(t, env.TX.Create(series).Error) url := fmt.Sprintf("/api/admin/package-series/%d", series.ID) resp, err := env.AsSuperAdmin().Request("DELETE", url, nil) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, 200, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) var deletedSeries model.PackageSeries err = env.RawDB().First(&deletedSeries, series.ID).Error assert.Error(t, err, "删除后应查不到套餐系列") } // ==================== Part 2: 套餐 API 测试 ==================== func TestPackageAPI_Create(t *testing.T) { env := integ.NewIntegrationTestEnv(t) timestamp := time.Now().Unix() packageCode := fmt.Sprintf("TEST_PKG_%d", timestamp) body := map[string]interface{}{ "package_code": packageCode, "package_name": "测试套餐", "package_type": "formal", "duration_months": 12, "price": 99900, "data_type": "real", "real_data_mb": 10240, } jsonBody, _ := json.Marshal(body) resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/packages", jsonBody) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, 200, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) dataMap, ok := result.Data.(map[string]interface{}) require.True(t, ok) assert.Equal(t, packageCode, dataMap["package_code"]) assert.Equal(t, "测试套餐", dataMap["package_name"]) assert.Equal(t, float64(constants.StatusEnabled), dataMap["status"]) assert.Equal(t, float64(2), dataMap["shelf_status"]) // 默认下架 t.Logf("创建的套餐 ID: %v", dataMap["id"]) } func TestPackageAPI_UpdateStatus_DisableForceOffShelf(t *testing.T) { env := integ.NewIntegrationTestEnv(t) timestamp := time.Now().Unix() packageCode := fmt.Sprintf("TEST_PKG_%d", timestamp) // 先创建套餐 createBody := map[string]interface{}{ "package_code": packageCode, "package_name": "测试套餐", "package_type": "formal", "duration_months": 12, "price": 99900, } jsonBody, _ := json.Marshal(createBody) createResp, err := env.AsSuperAdmin().Request("POST", "/api/admin/packages", jsonBody) require.NoError(t, err) defer createResp.Body.Close() var createResult response.Response err = json.NewDecoder(createResp.Body).Decode(&createResult) require.NoError(t, err) require.Equal(t, 0, createResult.Code) dataMap := createResult.Data.(map[string]interface{}) pkgID := uint(dataMap["id"].(float64)) // 先上架套餐 shelfBody := map[string]interface{}{ "shelf_status": 1, } shelfJsonBody, _ := json.Marshal(shelfBody) shelfResp, err := env.AsSuperAdmin().Request("PATCH", fmt.Sprintf("/api/admin/packages/%d/shelf", pkgID), shelfJsonBody) require.NoError(t, err) defer shelfResp.Body.Close() // 禁用套餐 disableBody := map[string]interface{}{ "status": constants.StatusDisabled, } disableJsonBody, _ := json.Marshal(disableBody) disableResp, err := env.AsSuperAdmin().Request("PATCH", fmt.Sprintf("/api/admin/packages/%d/status", pkgID), disableJsonBody) require.NoError(t, err) defer disableResp.Body.Close() var disableResult response.Response err = json.NewDecoder(disableResp.Body).Decode(&disableResult) require.NoError(t, err) t.Logf("禁用响应: 状态码=%d, 错误码=%d, 消息=%s", disableResp.StatusCode, disableResult.Code, disableResult.Message) require.Equal(t, 200, disableResp.StatusCode, "禁用套餐应该成功") require.Equal(t, 0, disableResult.Code, "禁用套餐应该返回成功") // 验证禁用后自动下架 var updatedPkg model.Package ctx := pkgGorm.SkipDataPermission(context.Background()) require.NoError(t, env.RawDB().WithContext(ctx).First(&updatedPkg, pkgID).Error) assert.Equal(t, constants.StatusDisabled, updatedPkg.Status, "套餐应该被禁用") assert.Equal(t, 2, updatedPkg.ShelfStatus, "禁用时应该强制下架") t.Logf("禁用套餐后,状态: %d, 上架状态: %d", updatedPkg.Status, updatedPkg.ShelfStatus) } func TestPackageAPI_UpdateShelfStatus_DisabledCannotOnShelf(t *testing.T) { env := integ.NewIntegrationTestEnv(t) timestamp := time.Now().Unix() packageCode := fmt.Sprintf("TEST_PKG_%d", timestamp) // 先创建套餐 createBody := map[string]interface{}{ "package_code": packageCode, "package_name": "测试套餐", "package_type": "formal", "duration_months": 12, "price": 99900, } jsonBody, _ := json.Marshal(createBody) createResp, err := env.AsSuperAdmin().Request("POST", "/api/admin/packages", jsonBody) require.NoError(t, err) defer createResp.Body.Close() var createResult response.Response err = json.NewDecoder(createResp.Body).Decode(&createResult) require.NoError(t, err) require.Equal(t, 0, createResult.Code) dataMap := createResult.Data.(map[string]interface{}) pkgID := uint(dataMap["id"].(float64)) // 禁用套餐 disableBody := map[string]interface{}{ "status": constants.StatusDisabled, } disableJsonBody, _ := json.Marshal(disableBody) disableResp, err := env.AsSuperAdmin().Request("PATCH", fmt.Sprintf("/api/admin/packages/%d/status", pkgID), disableJsonBody) require.NoError(t, err) defer disableResp.Body.Close() var disableResult response.Response err = json.NewDecoder(disableResp.Body).Decode(&disableResult) require.NoError(t, err) t.Logf("禁用响应: 状态码=%d, 错误码=%d, 消息=%s", disableResp.StatusCode, disableResult.Code, disableResult.Message) require.Equal(t, 200, disableResp.StatusCode, "禁用套餐应该成功") require.Equal(t, 0, disableResult.Code, "禁用套餐应该返回成功") // 尝试上架禁用的套餐 shelfBody := map[string]interface{}{ "shelf_status": 1, } shelfJsonBody, _ := json.Marshal(shelfBody) shelfResp, err := env.AsSuperAdmin().Request("PATCH", fmt.Sprintf("/api/admin/packages/%d/shelf", pkgID), shelfJsonBody) require.NoError(t, err) defer shelfResp.Body.Close() // 应该返回错误 var result response.Response err = json.NewDecoder(shelfResp.Body).Decode(&result) require.NoError(t, err) assert.NotEqual(t, 0, result.Code, "禁用的套餐不能上架,应返回错误码") // 验证套餐仍然是下架状态 var unchangedPkg model.Package ctx := pkgGorm.SkipDataPermission(context.Background()) require.NoError(t, env.RawDB().WithContext(ctx).First(&unchangedPkg, pkgID).Error) assert.Equal(t, 2, unchangedPkg.ShelfStatus, "禁用的套餐应该保持下架状态") t.Logf("尝试上架禁用套餐失败,错误码: %d, 消息: %s", result.Code, result.Message) } func TestPackageAPI_Get(t *testing.T) { env := integ.NewIntegrationTestEnv(t) timestamp := time.Now().Unix() packageCode := fmt.Sprintf("TEST_PKG_%d", timestamp) pkg := &model.Package{ PackageCode: packageCode, PackageName: "测试套餐", PackageType: "formal", DurationMonths: 12, Status: constants.StatusEnabled, ShelfStatus: 2, BaseModel: model.BaseModel{ Creator: 1, }, } require.NoError(t, env.TX.Create(pkg).Error) url := fmt.Sprintf("/api/admin/packages/%d", pkg.ID) resp, err := env.AsSuperAdmin().Request("GET", url, nil) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, 200, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) dataMap := result.Data.(map[string]interface{}) assert.Equal(t, packageCode, dataMap["package_code"]) assert.Equal(t, "测试套餐", dataMap["package_name"]) } func TestPackageAPI_List(t *testing.T) { env := integ.NewIntegrationTestEnv(t) timestamp := time.Now().Unix() pkgList := []*model.Package{ { PackageCode: fmt.Sprintf("TEST_LIST_%d_001", timestamp), PackageName: "列表测试套餐1", PackageType: "formal", DurationMonths: 12, Status: constants.StatusEnabled, ShelfStatus: 1, BaseModel: model.BaseModel{Creator: 1}, }, { PackageCode: fmt.Sprintf("TEST_LIST_%d_002", timestamp), PackageName: "列表测试套餐2", PackageType: "addon", DurationMonths: 1, Status: constants.StatusEnabled, ShelfStatus: 2, BaseModel: model.BaseModel{Creator: 1}, }, } for _, p := range pkgList { require.NoError(t, env.TX.Create(p).Error) } resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/packages?page=1&page_size=20", nil) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, 200, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) } func TestPackageAPI_Update(t *testing.T) { env := integ.NewIntegrationTestEnv(t) timestamp := time.Now().Unix() packageCode := fmt.Sprintf("TEST_PKG_%d", timestamp) pkg := &model.Package{ PackageCode: packageCode, PackageName: "原始套餐名称", PackageType: "formal", DurationMonths: 12, Status: constants.StatusEnabled, ShelfStatus: 2, BaseModel: model.BaseModel{ Creator: 1, }, } require.NoError(t, env.TX.Create(pkg).Error) body := map[string]interface{}{ "package_name": "更新后的套餐名称", "price": 119900, } jsonBody, _ := json.Marshal(body) url := fmt.Sprintf("/api/admin/packages/%d", pkg.ID) resp, err := env.AsSuperAdmin().Request("PUT", url, jsonBody) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, 200, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) dataMap := result.Data.(map[string]interface{}) assert.Equal(t, "更新后的套餐名称", dataMap["package_name"]) assert.Equal(t, float64(119900), dataMap["price"]) } func TestPackageAPI_Delete(t *testing.T) { env := integ.NewIntegrationTestEnv(t) timestamp := time.Now().Unix() packageCode := fmt.Sprintf("TEST_PKG_%d", timestamp) pkg := &model.Package{ PackageCode: packageCode, PackageName: "测试套餐", PackageType: "formal", DurationMonths: 12, Status: constants.StatusEnabled, ShelfStatus: 2, BaseModel: model.BaseModel{ Creator: 1, }, } require.NoError(t, env.TX.Create(pkg).Error) url := fmt.Sprintf("/api/admin/packages/%d", pkg.ID) resp, err := env.AsSuperAdmin().Request("DELETE", url, nil) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, 200, resp.StatusCode) var result response.Response err = json.NewDecoder(resp.Body).Decode(&result) require.NoError(t, err) assert.Equal(t, 0, result.Code) var deletedPkg model.Package err = env.RawDB().First(&deletedPkg, pkg.ID).Error assert.Error(t, err, "删除后应查不到套餐") }