package vehicle import ( "fmt" "math" "testing" "time" "github.com/glebarez/sqlite" "github.com/stretchr/testify/require" "gorm.io/gorm" "wails-app/internal/dao" "wails-app/internal/global" "wails-app/internal/model/vehicle/request" ) func setupFeeConfigTest(t *testing.T) *FeeConfigService { t.Helper() dsn := fmt.Sprintf("file:fee-config-%d?mode=memory&cache=shared", time.Now().UnixNano()) db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{}) require.NoError(t, err) sqlDB, err := db.DB() require.NoError(t, err) t.Cleanup(func() { _ = sqlDB.Close() if global.GVA_DB == db { global.GVA_DB = nil } }) global.GVA_DB = db require.NoError(t, db.AutoMigrate(&dao.VehicleType{}, &dao.FeeConfig{})) require.NoError(t, db.Create(&dao.VehicleType{Name: "临时车", IsSystem: true}).Error) return &FeeConfigService{} } func validReq() request.FeeConfigCreate { return request.FeeConfigCreate{ VehicleTypeID: 1, StartTime: 15, StartFee: 5, UnitTime: 30, UnitFee: 3, DailyMaxFee: 30, VIPDiscount: 1.0, } } func TestCreateFeeConfigAcceptsValidRules(t *testing.T) { svc := setupFeeConfigTest(t) require.NoError(t, svc.CreateFeeConfig(validReq())) var config dao.FeeConfig require.NoError(t, global.GVA_DB.First(&config, "vehicle_type_id = ?", uint(1)).Error) require.Equal(t, 30.0, config.DailyMaxFee) } func TestCreateFeeConfigRejectsInvalidRules(t *testing.T) { svc := setupFeeConfigTest(t) cases := []struct { name string mut func(*request.FeeConfigCreate) want string }{ {"负免费时长", func(r *request.FeeConfigCreate) { r.StartTime = -1 }, "免费时长"}, {"单位时间为零", func(r *request.FeeConfigCreate) { r.UnitTime = 0 }, "单位时间"}, {"负起步价", func(r *request.FeeConfigCreate) { r.StartFee = -1 }, "起步价"}, {"负单位费用", func(r *request.FeeConfigCreate) { r.UnitFee = -1 }, "单位费用"}, {"负日封顶", func(r *request.FeeConfigCreate) { r.DailyMaxFee = -1 }, "日封顶"}, {"封顶低于起步价", func(r *request.FeeConfigCreate) { r.DailyMaxFee = 3 }, "日封顶"}, {"折扣大于1", func(r *request.FeeConfigCreate) { r.VIPDiscount = 1.5 }, "VIP折扣"}, {"折扣为负", func(r *request.FeeConfigCreate) { r.VIPDiscount = -0.5 }, "VIP折扣"}, {"折扣为NaN", func(r *request.FeeConfigCreate) { r.VIPDiscount = math.NaN() }, "VIP折扣"}, {"起步价为NaN", func(r *request.FeeConfigCreate) { r.StartFee = math.NaN() }, "起步价"}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { req := validReq() tc.mut(&req) err := svc.CreateFeeConfig(req) require.Error(t, err) require.Contains(t, err.Error(), tc.want) }) } // 全部拒绝,未入库 var count int64 require.NoError(t, global.GVA_DB.Model(&dao.FeeConfig{}).Count(&count).Error) require.Zero(t, count) } func TestUpdateFeeConfigRejectsInvalidRules(t *testing.T) { svc := setupFeeConfigTest(t) require.NoError(t, svc.CreateFeeConfig(validReq())) var existing dao.FeeConfig require.NoError(t, global.GVA_DB.First(&existing).Error) update := request.FeeConfigUpdate{ ID: existing.ID, VehicleTypeID: 1, StartTime: 15, StartFee: 5, UnitTime: 0, UnitFee: 3, DailyMaxFee: 30, VIPDiscount: 1.0, } require.Error(t, svc.UpdateFeeConfig(update)) // 原配置未被修改 var after dao.FeeConfig require.NoError(t, global.GVA_DB.First(&after, existing.ID).Error) require.Equal(t, 30, after.UnitTime) } func TestListFeeConfigsHandlesZeroPage(t *testing.T) { svc := setupFeeConfigTest(t) require.NoError(t, svc.CreateFeeConfig(validReq())) // Page=0 兜底为第 1 页,不产生负 offset total, list, err := svc.ListFeeConfigs(request.FeeConfigQuery{Page: 0, PageSize: 0}) require.NoError(t, err) require.Equal(t, int64(1), total) require.Len(t, list, 1) }