94 lines
3.6 KiB
Python
94 lines
3.6 KiB
Python
"""Tests for security validators (username, password complexity)."""
|
|
|
|
import sys
|
|
import os
|
|
|
|
backend_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
if backend_dir not in sys.path:
|
|
sys.path.insert(0, backend_dir)
|
|
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
from app.schemas.user import UserCreate
|
|
|
|
|
|
# ── Username validation ──────────────────────────────────────────────
|
|
|
|
|
|
class TestUsernameValidation:
|
|
|
|
def test_valid_username(self):
|
|
u = UserCreate(username="john_doe", password="SecurePass123!@#")
|
|
assert u.username == "john_doe"
|
|
|
|
def test_valid_username_with_hyphens(self):
|
|
u = UserCreate(username="john-doe", password="SecurePass123!@#")
|
|
assert u.username == "john-doe"
|
|
|
|
def test_valid_username_numeric(self):
|
|
u = UserCreate(username="user123", password="SecurePass123!@#")
|
|
assert u.username == "user123"
|
|
|
|
def test_too_short_username(self):
|
|
with pytest.raises(ValidationError, match="3-50 characters"):
|
|
UserCreate(username="ab", password="SecurePass123!@#")
|
|
|
|
def test_username_with_spaces(self):
|
|
with pytest.raises(ValidationError, match="3-50 characters"):
|
|
UserCreate(username="john doe", password="SecurePass123!@#")
|
|
|
|
def test_username_with_special_chars(self):
|
|
with pytest.raises(ValidationError, match="3-50 characters"):
|
|
UserCreate(username="john@doe", password="SecurePass123!@#")
|
|
|
|
def test_reserved_username_system(self):
|
|
with pytest.raises(ValidationError):
|
|
UserCreate(username="system", password="SecurePass123!@#")
|
|
|
|
def test_invalid_username_path_chars(self):
|
|
with pytest.raises(ValidationError):
|
|
UserCreate(username="../admin", password="SecurePass123!@#")
|
|
|
|
def test_reserved_username_admin(self):
|
|
with pytest.raises(ValidationError, match="reserved"):
|
|
UserCreate(username="admin", password="SecurePass123!@#")
|
|
|
|
def test_reserved_username_root(self):
|
|
with pytest.raises(ValidationError, match="reserved"):
|
|
UserCreate(username="root", password="SecurePass123!@#")
|
|
|
|
def test_reserved_username_case_insensitive(self):
|
|
with pytest.raises(ValidationError, match="reserved"):
|
|
UserCreate(username="ADMIN", password="SecurePass123!@#")
|
|
|
|
|
|
# ── Password validation ─────────────────────────────────────────────
|
|
|
|
|
|
class TestPasswordValidation:
|
|
|
|
def test_valid_strong_password(self):
|
|
u = UserCreate(username="testuser", password="SecurePass123!@#")
|
|
assert u.password == "SecurePass123!@#"
|
|
|
|
def test_too_short_password(self):
|
|
with pytest.raises(ValidationError, match="12 characters"):
|
|
UserCreate(username="testuser", password="Short1!")
|
|
|
|
def test_no_uppercase(self):
|
|
with pytest.raises(ValidationError, match="uppercase"):
|
|
UserCreate(username="testuser", password="securepass123!@#")
|
|
|
|
def test_no_lowercase(self):
|
|
with pytest.raises(ValidationError, match="lowercase"):
|
|
UserCreate(username="testuser", password="SECUREPASS123!@#")
|
|
|
|
def test_no_digit(self):
|
|
with pytest.raises(ValidationError, match="digit"):
|
|
UserCreate(username="testuser", password="SecurePassword!@#")
|
|
|
|
def test_no_special_char(self):
|
|
with pytest.raises(ValidationError, match="special"):
|
|
UserCreate(username="testuser", password="SecurePass12345")
|