Files
xiaoxia-saas/tests/unit/test_verification_code.py
CI Bot 68e55df83b
CI/CD Pipeline / Check if frontend-only change (push) Has been cancelled
CI/CD Pipeline / Validate - Code Quality (push) Has been cancelled
CI/CD Pipeline / Validate - Type Check (mypy) (push) Has been cancelled
CI/CD Pipeline / Validate - Migration (alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / PR Build API Image (push) Has been cancelled
CI/CD Pipeline / PR Build Web Image (push) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (push) Has been cancelled
CI/CD Pipeline / Build Staging API Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
style: auto-format with black + isort + prettier
2026-07-24 10:59:46 +00:00

71 lines
2.7 KiB
Python
Executable File

"""VerificationCode 领域实体单测."""
from datetime import datetime, timedelta, timezone
import pytest
from packages.domain.verification_code import VerificationCode
class TestVerificationCodeCreate:
def test_create_default_ttl(self):
code = VerificationCode.create(recipient="test@example.com", code_type="email_bind")
assert code.id
assert code.recipient == "test@example.com"
assert code.code_type == "email_bind"
assert len(code.code) == 6
assert code.code.isdigit()
assert code.used_at is None
assert code.attempts == 0
# 默认5分钟过期
assert code.expires_at > code.created_at
assert (code.expires_at - code.created_at).total_seconds() == pytest.approx(300, abs=1)
def test_create_custom_ttl(self):
code = VerificationCode.create(recipient="13800138000", code_type="phone_login", ttl_seconds=60)
assert (code.expires_at - code.created_at).total_seconds() == pytest.approx(60, abs=1)
def test_create_custom_code(self):
code = VerificationCode.create(recipient="test@example.com", code_type="reset_password", custom_code="123456")
assert code.code == "123456"
def test_create_recipient_stripped(self):
code = VerificationCode.create(recipient=" test@example.com ", code_type="email_bind")
assert code.recipient == "test@example.com"
class TestVerificationCodeStatus:
def test_is_valid_initial(self):
code = VerificationCode.create(recipient="test@example.com", code_type="email_bind")
assert code.is_valid is True
assert code.is_expired is False
assert code.is_used is False
def test_mark_used(self):
code = VerificationCode.create(recipient="test@example.com", code_type="email_bind")
code.mark_used()
assert code.is_used is True
assert code.used_at is not None
assert code.is_valid is False
def test_is_expired_future(self):
code = VerificationCode.create(recipient="test@example.com", code_type="email_bind", ttl_seconds=3600)
assert code.is_expired is False
def test_increment_attempts(self):
code = VerificationCode.create(recipient="test@example.com", code_type="email_bind")
assert code.attempts == 0
code.increment_attempts()
assert code.attempts == 1
code.increment_attempts()
assert code.attempts == 2
def test_is_valid_after_expired(self):
code = VerificationCode.create(recipient="test@example.com", code_type="email_bind", ttl_seconds=0)
# 0秒TTL,立即可能过期(有极小概率因时间差没过)
import time
time.sleep(0.01)
assert code.is_expired is True
assert code.is_valid is False