import pytest from datetime import datetime, timezone, timedelta from app.services.auth import ( get_password_hash, verify_password, create_access_token, decode_token, ) class TestPasswordHashing: """Tests for password hashing functions.""" def test_hash_password(self): """Test that password hashing works.""" password = "securepassword123" hashed = get_password_hash(password) assert hashed != password assert len(hashed) > 0 def test_verify_correct_password(self): """Test verifying correct password.""" password = "securepassword123" hashed = get_password_hash(password) assert verify_password(password, hashed) is True def test_verify_wrong_password(self): """Test verifying wrong password.""" password = "securepassword123" hashed = get_password_hash(password) assert verify_password("wrongpassword", hashed) is False def test_hash_is_unique(self): """Test that same password produces different hashes (salt).""" password = "securepassword123" hash1 = get_password_hash(password) hash2 = get_password_hash(password) assert hash1 != hash2 # Different salts def test_long_password_truncated(self): """Test that long passwords work (bcrypt 72 byte limit).""" long_password = "a" * 100 hashed = get_password_hash(long_password) assert verify_password(long_password, hashed) is True class TestJWT: """Tests for JWT token functions.""" def test_create_token(self): """Test creating a JWT token.""" token = create_access_token(data={"sub": "123"}) assert token is not None assert len(token) > 0 def test_decode_valid_token(self): """Test decoding a valid token.""" user_id = "123" token = create_access_token(data={"sub": user_id}) payload = decode_token(token) assert payload is not None assert payload["sub"] == user_id def test_decode_invalid_token(self): """Test decoding an invalid token.""" payload = decode_token("invalid.token.here") assert payload is None def test_decode_expired_token(self): """Test that expired tokens are rejected.""" # Create a token that expires immediately token = create_access_token( data={"sub": "123"}, expires_delta=timedelta(seconds=-1), # Already expired ) payload = decode_token(token) assert payload is None def test_token_contains_expiry(self): """Test that token contains expiration claim.""" token = create_access_token(data={"sub": "123"}) payload = decode_token(token) assert payload is not None assert "exp" in payload