spark-server/internal/module/sms/logic/send_more_test.go
2026-09-22 17:07:26 +08:00

111 lines
2.9 KiB
Go

package logic
import (
"context"
"errors"
"testing"
smsentity "spark-server/internal/module/sms/entity"
smsmodel "spark-server/internal/module/sms/model"
"spark-server/internal/pkg/errs"
"spark-server/internal/pkg/reqctx"
)
type stubEmail struct {
n int
}
func (s *stubEmail) SendOTP(context.Context, string, smsentity.Purpose, string, string) error {
s.n++
return nil
}
type stubPhone struct {
carrier smsentity.Carrier
n int
}
func (s *stubPhone) Carrier() smsentity.Carrier { return s.carrier }
func (s *stubPhone) SendOTP(context.Context, string, smsentity.Purpose, string) error {
s.n++
return nil
}
type stubAccounts struct {
email string
}
func (s stubAccounts) EmailByUserID(context.Context, int64) (string, error) {
return s.email, nil
}
func TestSendUnifiedEmail(t *testing.T) {
store := smsmodel.NewMemoryStore()
mail := &stubEmail{}
svc := NewService(store, mail, nil, nil)
out, err := svc.Send(t.Context(), SendCodeInput{
Purpose: smsentity.PurposeLogin,
Target: "ada@example.com",
})
if err != nil || out == nil || mail.n != 1 {
t.Fatalf("send %+v %v mail=%d", out, err, mail.n)
}
}
func TestSendPhoneDispatchesByCarrier(t *testing.T) {
store := smsmodel.NewMemoryStore()
mobile := &stubPhone{carrier: smsentity.CarrierMobile}
unicom := &stubPhone{carrier: smsentity.CarrierUnicom}
svc := NewService(store, nil, []PhoneCarrierSender{mobile, unicom}, nil)
_, err := svc.Send(t.Context(), SendCodeInput{
Purpose: smsentity.PurposeLogin,
Target: "13812345678",
})
if err != nil || mobile.n != 1 || unicom.n != 0 {
t.Fatalf("mobile %v mobile=%d unicom=%d", err, mobile.n, unicom.n)
}
_, err = svc.Send(t.Context(), SendCodeInput{
Purpose: smsentity.PurposeLogin,
Target: "13012345678",
})
if err != nil || unicom.n != 1 {
t.Fatalf("unicom %v unicom=%d", err, unicom.n)
}
}
func TestGuardAccountDeletePurpose(t *testing.T) {
store := smsmodel.NewMemoryStore()
svc := NewService(store, &stubEmail{}, nil, stubAccounts{email: "me@example.com"})
ctx := reqctx.With(t.Context(), &reqctx.RequestContext{UserID: 9})
_, err := svc.Send(ctx, SendCodeInput{
Purpose: smsentity.PurposeAccountDelete,
Target: "other@example.com",
})
if !errors.Is(err, errs.ErrForbidden) {
t.Fatalf("wrong email %v", err)
}
_, err = svc.Send(ctx, SendCodeInput{
Purpose: smsentity.PurposeAccountDelete,
Target: "me@example.com",
})
if err != nil {
t.Fatal(err)
}
}
func TestClearTargetRemovesCode(t *testing.T) {
store := smsmodel.NewMemoryStore()
svc := NewService(store, nil, nil, nil)
ctx := t.Context()
email := "ada@example.com"
key := storeKey(smsentity.ChannelEmail, smsentity.PurposeLogin, email)
if err := store.Put(ctx, key, "123456", 60); err != nil {
t.Fatal(err)
}
svc.ClearTarget(ctx, smsentity.ChannelEmail, email)
if err := svc.CheckAndConsume(ctx, smsentity.ChannelEmail, smsentity.PurposeLogin, email, "123456"); !errors.Is(err, errs.ErrVerifyCodeInvalid) {
t.Fatalf("still there %v", err)
}
}