temp
This commit is contained in:
681
internal/domains/user/entities/sms_code_test.go
Normal file
681
internal/domains/user/entities/sms_code_test.go
Normal file
@@ -0,0 +1,681 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSMSCode_Validate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
smsCode *SMSCode
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "有效验证码",
|
||||
smsCode: &SMSCode{
|
||||
Phone: "13800138000",
|
||||
Code: "123456",
|
||||
Scene: SMSSceneRegister,
|
||||
ExpiresAt: time.Now().Add(time.Hour),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "手机号为空",
|
||||
smsCode: &SMSCode{
|
||||
Phone: "",
|
||||
Code: "123456",
|
||||
Scene: SMSSceneRegister,
|
||||
ExpiresAt: time.Now().Add(time.Hour),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "验证码为空",
|
||||
smsCode: &SMSCode{
|
||||
Phone: "13800138000",
|
||||
Code: "",
|
||||
Scene: SMSSceneRegister,
|
||||
ExpiresAt: time.Now().Add(time.Hour),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "场景为空",
|
||||
smsCode: &SMSCode{
|
||||
Phone: "13800138000",
|
||||
Code: "123456",
|
||||
Scene: "",
|
||||
ExpiresAt: time.Now().Add(time.Hour),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "过期时间为零",
|
||||
smsCode: &SMSCode{
|
||||
Phone: "13800138000",
|
||||
Code: "123456",
|
||||
Scene: SMSSceneRegister,
|
||||
ExpiresAt: time.Time{},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "手机号格式无效",
|
||||
smsCode: &SMSCode{
|
||||
Phone: "123",
|
||||
Code: "123456",
|
||||
Scene: SMSSceneRegister,
|
||||
ExpiresAt: time.Now().Add(time.Hour),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "验证码格式无效-包含字母",
|
||||
smsCode: &SMSCode{
|
||||
Phone: "13800138000",
|
||||
Code: "12345a",
|
||||
Scene: SMSSceneRegister,
|
||||
ExpiresAt: time.Now().Add(time.Hour),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "验证码长度过短",
|
||||
smsCode: &SMSCode{
|
||||
Phone: "13800138000",
|
||||
Code: "123",
|
||||
Scene: SMSSceneRegister,
|
||||
ExpiresAt: time.Now().Add(time.Hour),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.smsCode.Validate()
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSMSCode_VerifyCode(t *testing.T) {
|
||||
now := time.Now()
|
||||
expiresAt := now.Add(time.Hour)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
smsCode *SMSCode
|
||||
inputCode string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "验证码正确",
|
||||
smsCode: &SMSCode{
|
||||
Code: "123456",
|
||||
Used: false,
|
||||
ExpiresAt: expiresAt,
|
||||
},
|
||||
inputCode: "123456",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "验证码错误",
|
||||
smsCode: &SMSCode{
|
||||
Code: "123456",
|
||||
Used: false,
|
||||
ExpiresAt: expiresAt,
|
||||
},
|
||||
inputCode: "654321",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "验证码已使用",
|
||||
smsCode: &SMSCode{
|
||||
Code: "123456",
|
||||
Used: true,
|
||||
ExpiresAt: expiresAt,
|
||||
},
|
||||
inputCode: "123456",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "验证码已过期",
|
||||
smsCode: &SMSCode{
|
||||
Code: "123456",
|
||||
Used: false,
|
||||
ExpiresAt: now.Add(-time.Hour),
|
||||
},
|
||||
inputCode: "123456",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.smsCode.VerifyCode(tt.inputCode)
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
// 验证码正确时应该被标记为已使用
|
||||
assert.True(t, tt.smsCode.Used)
|
||||
assert.NotNil(t, tt.smsCode.UsedAt)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSMSCode_IsExpired(t *testing.T) {
|
||||
now := time.Now()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
smsCode *SMSCode
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "未过期",
|
||||
smsCode: &SMSCode{
|
||||
ExpiresAt: now.Add(time.Hour),
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "已过期",
|
||||
smsCode: &SMSCode{
|
||||
ExpiresAt: now.Add(-time.Hour),
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "刚好过期",
|
||||
smsCode: &SMSCode{
|
||||
ExpiresAt: now,
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := tt.smsCode.IsExpired()
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSMSCode_IsValid(t *testing.T) {
|
||||
now := time.Now()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
smsCode *SMSCode
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "有效验证码",
|
||||
smsCode: &SMSCode{
|
||||
Used: false,
|
||||
ExpiresAt: now.Add(time.Hour),
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "已使用",
|
||||
smsCode: &SMSCode{
|
||||
Used: true,
|
||||
ExpiresAt: now.Add(time.Hour),
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "已过期",
|
||||
smsCode: &SMSCode{
|
||||
Used: false,
|
||||
ExpiresAt: now.Add(-time.Hour),
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "已使用且已过期",
|
||||
smsCode: &SMSCode{
|
||||
Used: true,
|
||||
ExpiresAt: now.Add(-time.Hour),
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := tt.smsCode.IsValid()
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSMSCode_CanResend(t *testing.T) {
|
||||
now := time.Now()
|
||||
minInterval := 60 * time.Second
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
smsCode *SMSCode
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "已使用-可以重发",
|
||||
smsCode: &SMSCode{
|
||||
Used: true,
|
||||
CreatedAt: now.Add(-30 * time.Second),
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "已过期-可以重发",
|
||||
smsCode: &SMSCode{
|
||||
Used: false,
|
||||
ExpiresAt: now.Add(-time.Hour),
|
||||
CreatedAt: now.Add(-30 * time.Second),
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "未过期且未使用-间隔足够-可以重发",
|
||||
smsCode: &SMSCode{
|
||||
Used: false,
|
||||
ExpiresAt: now.Add(time.Hour),
|
||||
CreatedAt: now.Add(-2 * time.Minute),
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "未过期且未使用-间隔不足-不能重发",
|
||||
smsCode: &SMSCode{
|
||||
Used: false,
|
||||
ExpiresAt: now.Add(time.Hour),
|
||||
CreatedAt: now.Add(-30 * time.Second),
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := tt.smsCode.CanResend(minInterval)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSMSCode_GetRemainingTime(t *testing.T) {
|
||||
now := time.Now()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
smsCode *SMSCode
|
||||
expected time.Duration
|
||||
}{
|
||||
{
|
||||
name: "未过期",
|
||||
smsCode: &SMSCode{
|
||||
ExpiresAt: now.Add(time.Hour),
|
||||
},
|
||||
expected: time.Hour,
|
||||
},
|
||||
{
|
||||
name: "已过期",
|
||||
smsCode: &SMSCode{
|
||||
ExpiresAt: now.Add(-time.Hour),
|
||||
},
|
||||
expected: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := tt.smsCode.GetRemainingTime()
|
||||
// 由于时间计算可能有微小差异,我们检查是否在合理范围内
|
||||
if tt.expected > 0 {
|
||||
assert.True(t, result > 0)
|
||||
assert.True(t, result <= tt.expected)
|
||||
} else {
|
||||
assert.Equal(t, tt.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSMSCode_GetMaskedCode(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
code string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "6位验证码",
|
||||
code: "123456",
|
||||
expected: "1***6",
|
||||
},
|
||||
{
|
||||
name: "4位验证码",
|
||||
code: "1234",
|
||||
expected: "1***4",
|
||||
},
|
||||
{
|
||||
name: "短验证码",
|
||||
code: "12",
|
||||
expected: "***",
|
||||
},
|
||||
{
|
||||
name: "单字符",
|
||||
code: "1",
|
||||
expected: "***",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
smsCode := &SMSCode{Code: tt.code}
|
||||
result := smsCode.GetMaskedCode()
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSMSCode_GetMaskedPhone(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
phone string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "标准手机号",
|
||||
phone: "13800138000",
|
||||
expected: "138****8000",
|
||||
},
|
||||
{
|
||||
name: "短手机号",
|
||||
phone: "138001",
|
||||
expected: "138001",
|
||||
},
|
||||
{
|
||||
name: "空手机号",
|
||||
phone: "",
|
||||
expected: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
smsCode := &SMSCode{Phone: tt.phone}
|
||||
result := smsCode.GetMaskedPhone()
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSMSCode_IsSceneValid(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
scene SMSScene
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "注册场景",
|
||||
scene: SMSSceneRegister,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "登录场景",
|
||||
scene: SMSSceneLogin,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "无效场景",
|
||||
scene: "invalid",
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
smsCode := &SMSCode{Scene: tt.scene}
|
||||
result := smsCode.IsSceneValid()
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSMSCode_GetSceneName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
scene SMSScene
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "注册场景",
|
||||
scene: SMSSceneRegister,
|
||||
expected: "用户注册",
|
||||
},
|
||||
{
|
||||
name: "登录场景",
|
||||
scene: SMSSceneLogin,
|
||||
expected: "用户登录",
|
||||
},
|
||||
{
|
||||
name: "无效场景",
|
||||
scene: "invalid",
|
||||
expected: "invalid",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
smsCode := &SMSCode{Scene: tt.scene}
|
||||
result := smsCode.GetSceneName()
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSMSCode_IsSuspicious(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
smsCode *SMSCode
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "正常记录",
|
||||
smsCode: &SMSCode{
|
||||
IP: "192.168.1.1",
|
||||
UserAgent: "Mozilla/5.0",
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "IP为空-可疑",
|
||||
smsCode: &SMSCode{
|
||||
IP: "",
|
||||
UserAgent: "Mozilla/5.0",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "UserAgent为空-可疑",
|
||||
smsCode: &SMSCode{
|
||||
IP: "192.168.1.1",
|
||||
UserAgent: "",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "IP和UserAgent都为空-可疑",
|
||||
smsCode: &SMSCode{
|
||||
IP: "",
|
||||
UserAgent: "",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := tt.smsCode.IsSuspicious()
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSMSCode_GetSecurityInfo(t *testing.T) {
|
||||
now := time.Now()
|
||||
smsCode := &SMSCode{
|
||||
IP: "192.168.1.1",
|
||||
UserAgent: "Mozilla/5.0",
|
||||
Scene: SMSSceneRegister,
|
||||
CreatedAt: now,
|
||||
}
|
||||
|
||||
securityInfo := smsCode.GetSecurityInfo()
|
||||
|
||||
assert.Equal(t, "192.168.1.1", securityInfo["ip"])
|
||||
assert.Equal(t, "Mozilla/5.0", securityInfo["user_agent"])
|
||||
assert.Equal(t, false, securityInfo["suspicious"])
|
||||
assert.Equal(t, "用户注册", securityInfo["scene"])
|
||||
assert.Equal(t, now, securityInfo["created_at"])
|
||||
}
|
||||
|
||||
func TestIsValidScene(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
scene SMSScene
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "注册场景",
|
||||
scene: SMSSceneRegister,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "登录场景",
|
||||
scene: SMSSceneLogin,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "无效场景",
|
||||
scene: "invalid",
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := IsValidScene(tt.scene)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSceneName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
scene SMSScene
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "注册场景",
|
||||
scene: SMSSceneRegister,
|
||||
expected: "用户注册",
|
||||
},
|
||||
{
|
||||
name: "登录场景",
|
||||
scene: SMSSceneLogin,
|
||||
expected: "用户登录",
|
||||
},
|
||||
{
|
||||
name: "无效场景",
|
||||
scene: "invalid",
|
||||
expected: "invalid",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := GetSceneName(tt.scene)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewSMSCode(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
phone string
|
||||
code string
|
||||
scene SMSScene
|
||||
expireTime time.Duration
|
||||
clientIP string
|
||||
userAgent string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "有效参数",
|
||||
phone: "13800138000",
|
||||
code: "123456",
|
||||
scene: SMSSceneRegister,
|
||||
expireTime: time.Hour,
|
||||
clientIP: "192.168.1.1",
|
||||
userAgent: "Mozilla/5.0",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "无效手机号",
|
||||
phone: "123",
|
||||
code: "123456",
|
||||
scene: SMSSceneRegister,
|
||||
expireTime: time.Hour,
|
||||
clientIP: "192.168.1.1",
|
||||
userAgent: "Mozilla/5.0",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "无效验证码",
|
||||
phone: "13800138000",
|
||||
code: "123",
|
||||
scene: SMSSceneRegister,
|
||||
expireTime: time.Hour,
|
||||
clientIP: "192.168.1.1",
|
||||
userAgent: "Mozilla/5.0",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
smsCode, err := NewSMSCode(tt.phone, tt.code, tt.scene, tt.expireTime, tt.clientIP, tt.userAgent)
|
||||
if tt.expectError {
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, smsCode)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, smsCode)
|
||||
assert.Equal(t, tt.phone, smsCode.Phone)
|
||||
assert.Equal(t, tt.code, smsCode.Code)
|
||||
assert.Equal(t, tt.scene, smsCode.Scene)
|
||||
assert.Equal(t, tt.clientIP, smsCode.IP)
|
||||
assert.Equal(t, tt.userAgent, smsCode.UserAgent)
|
||||
assert.False(t, smsCode.Used)
|
||||
assert.True(t, smsCode.ExpiresAt.After(time.Now()))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user