Smail/backend/services/adminreset/client_test.go
smail b183aef0c7
Some checks are pending
Security Checks / security (push) Waiting to run
完善管理员重置结果提示并缩短邮件验证等待
2026-09-19 22:53:58 +08:00

112 lines
2.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package adminreset
import (
"context"
"errors"
"net"
"strings"
"testing"
"time"
)
type delayedEmailFlow struct {
testResetFlow
start func() error
}
func (f *delayedEmailFlow) Methods() []Method {
return []Method{{ID: "email:1", Label: "发送验证码到 root@example.com"}}
}
func (f *delayedEmailFlow) Start(method string) error {
if method != "email:1" {
return ErrInvalidRequest
}
if err := f.start(); err != nil {
return err
}
f.selected = true
return nil
}
func TestEmailPromptDoesNotWaitForDelivery(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
inputShown := make(chan struct{})
reset := false
flow := &delayedEmailFlow{
testResetFlow: testResetFlow{reset: func(string) error { reset = true; return nil }},
start: func() error {
select {
case <-inputShown:
return nil
case <-ctx.Done():
return ctx.Err()
}
},
}
server, client := net.Pipe()
defer client.Close()
done := make(chan struct{})
go func() {
defer close(done)
defer server.Close()
handleResetConnection(server, server.SetDeadline, func() (ResetSession, error) { return flow, nil }, NewSessionGuard(time.Minute))
}()
steps := 0
err := SendVerifiedResetWithInput(ctx, client, func(_ context.Context, prompt string) (string, error) {
steps++
if steps == 1 {
return "1", nil
}
if !strings.Contains(prompt, "正在发送") || !strings.Contains(prompt, "请输入邮件验证码") {
t.Errorf("缺少邮件发送状态或输入提示:%q", prompt)
}
close(inputShown)
return "fixture-code", nil
}, func() (string, error) { return "NewPass123", nil })
<-done
if err != nil || !reset {
t.Fatalf("邮件输入与发送未正确衔接:reset=%v err=%v", reset, err)
}
}
func TestEmailDeliveryFailureCancelsInputAndNeverAsksPassword(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
inputShown := make(chan struct{})
flow := &delayedEmailFlow{start: func() error {
select {
case <-inputShown:
return errors.New("mail unavailable")
case <-ctx.Done():
return ctx.Err()
}
}}
server, client := net.Pipe()
defer client.Close()
done := make(chan struct{})
go func() {
defer close(done)
defer server.Close()
handleResetConnection(server, server.SetDeadline, func() (ResetSession, error) { return flow, nil }, NewSessionGuard(time.Minute))
}()
steps := 0
err := SendVerifiedResetWithInput(ctx, client, func(inputContext context.Context, _ string) (string, error) {
steps++
if steps == 1 {
return "1", nil
}
close(inputShown)
<-inputContext.Done()
return "", inputContext.Err()
}, func() (string, error) {
t.Error("邮件发送失败后不应进入密码输入")
return "NewPass123", nil
})
<-done
if !errors.Is(err, ErrEmailDeliveryFailed) || ctx.Err() != nil {
t.Fatalf("邮件发送失败未及时取消输入:%v", err)
}
}