package promo import ( "context" "testing" "time" promomodel "github.com/perfect-panel/server/internal/model/promo" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/internal/types" "github.com/perfect-panel/server/pkg/xerr" pkgerrors "github.com/pkg/errors" "github.com/redis/go-redis/v9" ) func TestCreateRuleAcceptsMillisecondTimestamps(t *testing.T) { startTime := int64(1777618800000) endTime := int64(1782802800000) var inserted *promomodel.Rule svcCtx := &svc.ServiceContext{ Redis: redis.NewClient(&redis.Options{Addr: "127.0.0.1:0"}), PromoModel: fakePromoModel{ insertRule: func(_ context.Context, rule *promomodel.Rule) error { inserted = rule return nil }, }, } _, err := NewCreateRuleLogic(context.Background(), svcCtx).CreateRule(&types.CreatePromoRuleRequest{ Name: "618活动", Type: promomodel.RuleTypeInactiveUser, Params: map[string]interface{}{"inactive_months": float64(1)}, Priority: 0, StartTime: &startTime, EndTime: &endTime, }) if err != nil { t.Fatalf("CreateRule returned error: %v", err) } if inserted == nil { t.Fatal("rule was not inserted") } assertPromoRuleTime(t, inserted.StartTime, time.UnixMilli(startTime)) assertPromoRuleTime(t, inserted.EndTime, time.UnixMilli(endTime)) } func TestUpdateRuleAcceptsMillisecondTimestamps(t *testing.T) { startTime := int64(1777618800000) endTime := int64(1782802800000) existing := &promomodel.Rule{Id: 9, Enabled: true} var updated *promomodel.Rule svcCtx := &svc.ServiceContext{ Redis: redis.NewClient(&redis.Options{Addr: "127.0.0.1:0"}), PromoModel: fakePromoModel{ findRule: func(_ context.Context, id int64) (*promomodel.Rule, error) { if id != existing.Id { t.Fatalf("FindRule id = %d, want %d", id, existing.Id) } return existing, nil }, updateRule: func(_ context.Context, rule *promomodel.Rule) error { updated = rule return nil }, }, } _, err := NewUpdateRuleLogic(context.Background(), svcCtx).UpdateRule(&types.UpdatePromoRuleRequest{ Id: existing.Id, Name: "618活动", Type: promomodel.RuleTypeInactiveUser, Params: map[string]interface{}{"inactive_months": float64(1)}, Priority: 0, StartTime: &startTime, EndTime: &endTime, }) if err != nil { t.Fatalf("UpdateRule returned error: %v", err) } if updated == nil { t.Fatal("rule was not updated") } assertPromoRuleTime(t, updated.StartTime, time.UnixMilli(startTime)) assertPromoRuleTime(t, updated.EndTime, time.UnixMilli(endTime)) } func TestRuleRejectsOutOfRangeTimestamp(t *testing.T) { startTime := int64(253402300800000) endTime := int64(253402304400000) svcCtx := &svc.ServiceContext{PromoModel: fakePromoModel{ insertRule: func(context.Context, *promomodel.Rule) error { t.Fatal("InsertRule should not be called for invalid timestamp") return nil }, }} _, err := NewCreateRuleLogic(context.Background(), svcCtx).CreateRule(&types.CreatePromoRuleRequest{ Name: "bad time", Type: promomodel.RuleTypeInactiveUser, Params: map[string]interface{}{"inactive_months": float64(1)}, Priority: 0, StartTime: &startTime, EndTime: &endTime, }) assertInvalidParams(t, err) } func assertPromoRuleTime(t *testing.T, got *time.Time, want time.Time) { t.Helper() if got == nil { t.Fatalf("time is nil, want %v", want) } if !got.Equal(want) { t.Fatalf("time = %v, want %v", *got, want) } } func assertInvalidParams(t *testing.T, err error) { t.Helper() if err == nil { t.Fatal("expected error") } codeErr, ok := pkgerrors.Cause(err).(*xerr.CodeError) if !ok { t.Fatalf("expected CodeError, got %T", pkgerrors.Cause(err)) } if got := codeErr.GetErrCode(); got != xerr.InvalidParams { t.Fatalf("error code = %d, want %d", got, xerr.InvalidParams) } }