reaching 100% test coverage for the middleware unit tests

This commit is contained in:
2025-11-19 22:26:45 +01:00
parent a18ad48721
commit 23cf568c82
2 changed files with 104 additions and 0 deletions

View File

@@ -16,6 +16,7 @@ import pytest
from unittest.mock import Mock, MagicMock, patch from unittest.mock import Mock, MagicMock, patch
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from jose import jwt from jose import jwt
from fastapi import HTTPException
from middleware.auth import AuthManager from middleware.auth import AuthManager
from app.exceptions import ( from app.exceptions import (
@@ -350,6 +351,26 @@ class TestJWTTokenVerification:
with pytest.raises(InvalidTokenException): with pytest.raises(InvalidTokenException):
auth_manager.verify_token(token) auth_manager.verify_token(token)
def test_verify_token_additional_expiration_check(self):
"""Test the additional expiration check after jwt.decode."""
auth_manager = AuthManager()
# Create a token with expiration in the past
past_time = datetime.now(timezone.utc) - timedelta(minutes=1)
payload = {
"sub": "1",
"username": "testuser",
"exp": past_time.timestamp()
}
token = jwt.encode(payload, auth_manager.secret_key, algorithm=auth_manager.algorithm)
# Mock jwt.decode to bypass its expiration check and test line 205
with patch('middleware.auth.jwt.decode') as mock_decode:
mock_decode.return_value = payload
with pytest.raises(TokenExpiredException):
auth_manager.verify_token(token)
@pytest.mark.unit @pytest.mark.unit
@pytest.mark.auth @pytest.mark.auth
@@ -661,3 +682,62 @@ class TestEdgeCases:
# Result depends on how the filter is implemented # Result depends on how the filter is implemented
# This test documents the expected behavior # This test documents the expected behavior
assert result is None or result is mock_user assert result is None or result is mock_user
def test_verify_token_unexpected_exception(self):
"""Test generic exception handler in verify_token."""
auth_manager = AuthManager()
# Create a valid token with a mock user
mock_user = Mock(spec=User)
mock_user.id = 1
mock_user.username = "test"
mock_user.email = "test@example.com"
mock_user.role = "user"
token_data = auth_manager.create_access_token(mock_user)
token = token_data["access_token"]
# Mock jose.jwt.decode to raise an unexpected exception
with patch('middleware.auth.jwt.decode', side_effect=RuntimeError("Unexpected error")):
with pytest.raises(InvalidTokenException) as exc_info:
auth_manager.verify_token(token)
# The message should be "Authentication failed" from the generic except handler
assert "Authentication failed" in str(exc_info.value.message)
def test_require_role_decorator_wrapper_functionality(self):
"""Test the require_role decorator wrapper execution."""
auth_manager = AuthManager()
# Create a test function decorated with require_role
@auth_manager.require_role("admin")
def test_function(current_user, additional_arg=None):
return {"user": current_user.username, "arg": additional_arg}
# Test successful case - user has required role
admin_user = Mock(spec=User)
admin_user.role = "admin"
admin_user.username = "admin_user"
result = test_function(admin_user, additional_arg="test_value")
assert result["user"] == "admin_user"
assert result["arg"] == "test_value"
def test_require_role_decorator_blocks_wrong_role(self):
"""Test that require_role decorator blocks users with wrong role."""
auth_manager = AuthManager()
@auth_manager.require_role("admin")
def admin_only_function(current_user):
return {"status": "success"}
# Test with user that has wrong role
regular_user = Mock(spec=User)
regular_user.role = "user"
with pytest.raises(HTTPException) as exc_info:
admin_only_function(regular_user)
assert exc_info.value.status_code == 403
assert "Required role 'admin' not found" in exc_info.value.detail

View File

@@ -435,6 +435,10 @@ class TestVendorContextManager:
"/image.jpg", "/image.jpg",
"/style.css", "/style.css",
"/app.webmanifest", "/app.webmanifest",
"/static/", # Path starting with /static/ but no extension
"/media/uploads", # Path starting with /media/ but no extension
"/subfolder/favicon.ico", # favicon.ico in subfolder
"/favicon.ico.bak", # Contains favicon.ico but doesn't end with static extension (hits line 226)
]) ])
def test_is_static_file_request(self, path): def test_is_static_file_request(self, path):
"""Test static file detection for various paths and extensions.""" """Test static file detection for various paths and extensions."""
@@ -719,3 +723,23 @@ class TestEdgeCases:
# Should detect 'shop' as subdomain since it's the first part # Should detect 'shop' as subdomain since it's the first part
assert context["detection_method"] == "subdomain" assert context["detection_method"] == "subdomain"
assert context["subdomain"] == "shop" assert context["subdomain"] == "shop"
def test_get_vendor_logs_warning_when_not_found_subdomain(self):
"""Test that warning is logged when vendor is not found by subdomain."""
mock_db = Mock()
# Mock the complete query chain properly - need to mock filter twice and then first
mock_query = mock_db.query.return_value
mock_filter1 = mock_query.filter.return_value
mock_filter2 = mock_filter1.filter.return_value
mock_filter2.first.return_value = None
context = {"subdomain": "nonexistent", "detection_method": "subdomain"}
with patch('middleware.vendor_context.logger') as mock_logger:
vendor = VendorContextManager.get_vendor_from_context(mock_db, context)
assert vendor is None
# Verify warning was logged
mock_logger.warning.assert_called()
warning_message = str(mock_logger.warning.call_args)
assert "No active vendor found for subdomain" in warning_message and "nonexistent" in warning_message