first commit
This commit is contained in:
113
backend/tests/test_security.py
Normal file
113
backend/tests/test_security.py
Normal file
@@ -0,0 +1,113 @@
|
||||
"""Unit tests for security module"""
|
||||
|
||||
import pytest
|
||||
from datetime import datetime, timedelta
|
||||
from jose import jwt
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from app.core.security import (
|
||||
create_access_token,
|
||||
create_refresh_token,
|
||||
verify_password,
|
||||
get_password_hash,
|
||||
)
|
||||
from app.core.config import settings
|
||||
|
||||
|
||||
class TestPasswordHashing:
|
||||
"""Tests for password hashing functions"""
|
||||
|
||||
def test_hash_password(self):
|
||||
"""Test password hashing"""
|
||||
password = "test_password_123"
|
||||
hashed = get_password_hash(password)
|
||||
assert hashed != password
|
||||
assert len(hashed) > 0
|
||||
|
||||
def test_verify_correct_password(self):
|
||||
"""Test verification of correct password"""
|
||||
password = "test_password_123"
|
||||
hashed = get_password_hash(password)
|
||||
assert verify_password(password, hashed) is True
|
||||
|
||||
def test_verify_incorrect_password(self):
|
||||
"""Test verification of incorrect password"""
|
||||
password = "test_password_123"
|
||||
hashed = get_password_hash(password)
|
||||
assert verify_password("wrong_password", hashed) is False
|
||||
|
||||
def test_hash_is_unique(self):
|
||||
"""Test that hashes are unique for same password"""
|
||||
password = "test_password_123"
|
||||
hash1 = get_password_hash(password)
|
||||
hash2 = get_password_hash(password)
|
||||
assert hash1 != hash2 # bcrypt adds salt
|
||||
|
||||
|
||||
class TestTokenCreation:
|
||||
"""Tests for token creation functions"""
|
||||
|
||||
def test_create_access_token(self):
|
||||
"""Test access token creation"""
|
||||
data = {"sub": "123", "username": "testuser"}
|
||||
token = create_access_token(data)
|
||||
assert token is not None
|
||||
assert len(token) > 0
|
||||
|
||||
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
|
||||
assert payload["sub"] == "123"
|
||||
assert payload["username"] == "testuser"
|
||||
assert payload["type"] == "access"
|
||||
|
||||
def test_create_refresh_token(self):
|
||||
"""Test refresh token creation"""
|
||||
data = {"sub": "123"}
|
||||
token = create_refresh_token(data)
|
||||
assert token is not None
|
||||
|
||||
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
|
||||
assert payload["sub"] == "123"
|
||||
assert payload["type"] == "refresh"
|
||||
|
||||
def test_access_token_expiration(self):
|
||||
"""Test access token has correct expiration"""
|
||||
data = {"sub": "123"}
|
||||
token = create_access_token(data)
|
||||
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
|
||||
exp_timestamp = payload["exp"]
|
||||
# Token should expire in approximately 15 minutes (accounting for timezone)
|
||||
expected_minutes = settings.ACCESS_TOKEN_EXPIRE_MINUTES
|
||||
# The timestamp is in seconds since epoch
|
||||
import time
|
||||
|
||||
now_timestamp = time.time()
|
||||
minutes_diff = (exp_timestamp - now_timestamp) / 60
|
||||
assert expected_minutes - 1 < minutes_diff < expected_minutes + 1
|
||||
|
||||
def test_refresh_token_expiration(self):
|
||||
"""Test refresh token has correct expiration"""
|
||||
data = {"sub": "123"}
|
||||
token = create_refresh_token(data)
|
||||
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
|
||||
exp = datetime.fromtimestamp(payload["exp"])
|
||||
now = datetime.utcnow()
|
||||
# Token should expire in approximately 7 days (with some tolerance)
|
||||
delta = exp - now
|
||||
assert delta.days >= 6 # At least 6 days
|
||||
assert delta.days <= 8 # Less than 8 days
|
||||
|
||||
|
||||
class TestJWTSecurity:
|
||||
"""Tests for JWT security features"""
|
||||
|
||||
def test_invalid_token_raises_error(self):
|
||||
"""Test that invalid token raises JWTError"""
|
||||
with pytest.raises(jwt.JWTError):
|
||||
jwt.decode("invalid_token", settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
|
||||
|
||||
def test_token_with_wrong_secret_raises_error(self):
|
||||
"""Test that token with wrong secret raises error"""
|
||||
data = {"sub": "123"}
|
||||
token = create_access_token(data)
|
||||
with pytest.raises(jwt.JWTError):
|
||||
jwt.decode(token, "wrong_secret", algorithms=[settings.ALGORITHM])
|
||||
Reference in New Issue
Block a user