214 lines
7.8 KiB
Python
214 lines
7.8 KiB
Python
# tests/test_auth_service.py
|
|
import pytest
|
|
from fastapi import HTTPException
|
|
|
|
from app.services.auth_service import AuthService
|
|
from models.api_models import UserLogin, UserRegister
|
|
from models.database_models import User
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.auth
|
|
class TestAuthService:
|
|
"""Test suite for AuthService following the application's testing patterns"""
|
|
|
|
def setup_method(self):
|
|
"""Setup method following the same pattern as admin service tests"""
|
|
self.service = AuthService()
|
|
|
|
def test_register_user_success(self, db):
|
|
"""Test successful user registration"""
|
|
user_data = UserRegister(
|
|
email="newuser@example.com", username="newuser123", password="securepass123"
|
|
)
|
|
|
|
user = self.service.register_user(db, user_data)
|
|
|
|
assert user is not None
|
|
assert user.email == "newuser@example.com"
|
|
assert user.username == "newuser123"
|
|
assert user.role == "user"
|
|
assert user.is_active is True
|
|
assert user.hashed_password != "securepass123" # Should be hashed
|
|
|
|
def test_register_user_email_already_exists(self, db, test_user):
|
|
"""Test registration fails when email already exists"""
|
|
user_data = UserRegister(
|
|
email=test_user.email, # Use existing email
|
|
username="differentuser",
|
|
password="securepass123",
|
|
)
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
self.service.register_user(db, user_data)
|
|
|
|
assert exc_info.value.status_code == 400
|
|
assert "Email already registered" in str(exc_info.value.detail)
|
|
|
|
def test_register_user_username_already_exists(self, db, test_user):
|
|
"""Test registration fails when username already exists"""
|
|
user_data = UserRegister(
|
|
email="different@example.com",
|
|
username=test_user.username, # Use existing username
|
|
password="securepass123",
|
|
)
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
self.service.register_user(db, user_data)
|
|
|
|
assert exc_info.value.status_code == 400
|
|
assert "Username already taken" in str(exc_info.value.detail)
|
|
|
|
def test_login_user_success(self, db, test_user):
|
|
"""Test successful user login"""
|
|
user_credentials = UserLogin(
|
|
username=test_user.username, password="testpass123"
|
|
)
|
|
|
|
result = self.service.login_user(db, user_credentials)
|
|
|
|
assert "token_data" in result
|
|
assert "user" in result
|
|
assert result["user"].id == test_user.id
|
|
assert result["user"].username == test_user.username
|
|
assert "access_token" in result["token_data"]
|
|
assert "token_type" in result["token_data"]
|
|
assert "expires_in" in result["token_data"]
|
|
|
|
def test_login_user_wrong_username(self, db):
|
|
"""Test login fails with wrong username"""
|
|
user_credentials = UserLogin(username="nonexistentuser", password="testpass123")
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
self.service.login_user(db, user_credentials)
|
|
|
|
assert exc_info.value.status_code == 401
|
|
assert "Incorrect username or password" in str(exc_info.value.detail)
|
|
|
|
def test_login_user_wrong_password(self, db, test_user):
|
|
"""Test login fails with wrong password"""
|
|
user_credentials = UserLogin(
|
|
username=test_user.username, password="wrongpassword"
|
|
)
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
self.service.login_user(db, user_credentials)
|
|
|
|
assert exc_info.value.status_code == 401
|
|
assert "Incorrect username or password" in str(exc_info.value.detail)
|
|
|
|
def test_login_user_inactive_user(self, db, test_user):
|
|
"""Test login fails for inactive user"""
|
|
# Deactivate user
|
|
test_user.is_active = False
|
|
db.commit()
|
|
|
|
user_credentials = UserLogin(
|
|
username=test_user.username, password="testpass123"
|
|
)
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
self.service.login_user(db, user_credentials)
|
|
|
|
assert exc_info.value.status_code == 401
|
|
assert "Incorrect username or password" in str(exc_info.value.detail)
|
|
|
|
def test_get_user_by_email(self, db, test_user):
|
|
"""Test getting user by email"""
|
|
user = self.service.get_user_by_email(db, test_user.email)
|
|
|
|
assert user is not None
|
|
assert user.id == test_user.id
|
|
assert user.email == test_user.email
|
|
|
|
def test_get_user_by_email_not_found(self, db):
|
|
"""Test getting user by email when user doesn't exist"""
|
|
user = self.service.get_user_by_email(db, "nonexistent@example.com")
|
|
|
|
assert user is None
|
|
|
|
def test_get_user_by_username(self, db, test_user):
|
|
"""Test getting user by username"""
|
|
user = self.service.get_user_by_username(db, test_user.username)
|
|
|
|
assert user is not None
|
|
assert user.id == test_user.id
|
|
assert user.username == test_user.username
|
|
|
|
def test_get_user_by_username_not_found(self, db):
|
|
"""Test getting user by username when user doesn't exist"""
|
|
user = self.service.get_user_by_username(db, "nonexistentuser")
|
|
|
|
assert user is None
|
|
|
|
def test_email_exists_true(self, db, test_user):
|
|
"""Test email_exists returns True when email exists"""
|
|
exists = self.service.email_exists(db, test_user.email)
|
|
|
|
assert exists is True
|
|
|
|
def test_email_exists_false(self, db):
|
|
"""Test email_exists returns False when email doesn't exist"""
|
|
exists = self.service.email_exists(db, "nonexistent@example.com")
|
|
|
|
assert exists is False
|
|
|
|
def test_username_exists_true(self, db, test_user):
|
|
"""Test username_exists returns True when username exists"""
|
|
exists = self.service.username_exists(db, test_user.username)
|
|
|
|
assert exists is True
|
|
|
|
def test_username_exists_false(self, db):
|
|
"""Test username_exists returns False when username doesn't exist"""
|
|
exists = self.service.username_exists(db, "nonexistentuser")
|
|
|
|
assert exists is False
|
|
|
|
def test_authenticate_user_success(self, db, test_user):
|
|
"""Test successful user authentication"""
|
|
user = self.service.authenticate_user(db, test_user.username, "testpass123")
|
|
|
|
assert user is not None
|
|
assert user.id == test_user.id
|
|
assert user.username == test_user.username
|
|
|
|
def test_authenticate_user_wrong_password(self, db, test_user):
|
|
"""Test authentication fails with wrong password"""
|
|
user = self.service.authenticate_user(db, test_user.username, "wrongpassword")
|
|
|
|
assert user is None
|
|
|
|
def test_authenticate_user_nonexistent(self, db):
|
|
"""Test authentication fails with nonexistent user"""
|
|
user = self.service.authenticate_user(db, "nonexistentuser", "password")
|
|
|
|
assert user is None
|
|
|
|
def test_create_access_token(self, test_user):
|
|
"""Test creating access token for user"""
|
|
token_data = self.service.create_access_token(test_user)
|
|
|
|
assert "access_token" in token_data
|
|
assert "token_type" in token_data
|
|
assert "expires_in" in token_data
|
|
assert token_data["token_type"] == "bearer"
|
|
assert isinstance(token_data["expires_in"], int)
|
|
assert token_data["expires_in"] > 0
|
|
|
|
def test_hash_password(self):
|
|
"""Test password hashing"""
|
|
password = "testpassword123"
|
|
hashed = self.service.hash_password(password)
|
|
|
|
assert hashed != password
|
|
assert len(hashed) > len(password)
|
|
assert hashed.startswith("$") # bcrypt hash format
|
|
|
|
def test_hash_password_different_results(self):
|
|
"""Test that hashing same password produces different hashes (salt)"""
|
|
password = "testpassword123"
|
|
hash1 = self.service.hash_password(password)
|
|
hash2 = self.service.hash_password(password)
|
|
|
|
assert hash1 != hash2 # Should be different due to salt
|