package user import ( "context" "encoding/json" "fmt" "testing" "time" "github.com/alicebob/miniredis/v2" "github.com/perfect-panel/server/internal/config" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/pkg/constant" "github.com/redis/go-redis/v9" "github.com/stretchr/testify/assert" ) func TestVerifyEmailCode(t *testing.T) { // 1. Setup Miniredis mr, err := miniredis.Run() assert.NoError(t, err) defer mr.Close() rdb := redis.NewClient(&redis.Options{ Addr: mr.Addr(), }) // 2. Setup ServiceContext serverCtx := &svc.ServiceContext{ Redis: rdb, Config: config.Config{ VerifyCode: config.VerifyCode{ ExpireTime: 300, // 5 minutes validity }, }, } ctx := context.Background() email := "test@example.com" code := "123456" // Helper to set code in redis setCode := func(scene string, c string, lastAt int64) { payload := CacheKeyPayload{ Code: c, LastAt: lastAt, } val, _ := json.Marshal(payload) key := fmt.Sprintf("%s:%s:%s", config.AuthCodeCacheKey, scene, email) rdb.Set(ctx, key, string(val), time.Hour) } t.Run("Success_DeleteAccountScene", func(t *testing.T) { mr.FlushAll() setCode(constant.DeleteAccount.String(), code, time.Now().Unix()) err := verifyEmailCode(ctx, serverCtx, email, code) assert.NoError(t, err) // Verify key is deleted key := fmt.Sprintf("%s:%s:%s", config.AuthCodeCacheKey, constant.DeleteAccount.String(), email) exists := rdb.Exists(ctx, key).Val() assert.Equal(t, int64(0), exists) }) t.Run("Success_SecurityScene", func(t *testing.T) { mr.FlushAll() setCode(constant.Security.String(), code, time.Now().Unix()) err := verifyEmailCode(ctx, serverCtx, email, code) assert.NoError(t, err) }) t.Run("Fail_WrongCode", func(t *testing.T) { mr.FlushAll() setCode(constant.DeleteAccount.String(), code, time.Now().Unix()) err := verifyEmailCode(ctx, serverCtx, email, "wrong") assert.Error(t, err) assert.Contains(t, err.Error(), "verification code error") }) t.Run("Fail_Expired", func(t *testing.T) { mr.FlushAll() // Set time to 301 seconds ago (expired) expiredTime := time.Now().Add(-301 * time.Second).Unix() setCode(constant.DeleteAccount.String(), code, expiredTime) err := verifyEmailCode(ctx, serverCtx, email, code) assert.Error(t, err) }) t.Run("Fail_NoCode", func(t *testing.T) { mr.FlushAll() err := verifyEmailCode(ctx, serverCtx, email, code) assert.Error(t, err) }) }