"""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")