File size: 5,440 Bytes
dbe78dd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
"""Unit tests for API dependencies."""
import pytest
import base64
import json
from unittest.mock import patch
from fastapi import HTTPException


class TestValidateBearerToken:
    """Test cases for bearer token validation dependency."""
    
    def setup_method(self):
        """Set up test fixtures."""
        # Create a valid JWT token for testing
        header = {"alg": "HS256", "typ": "JWT"}
        payload = {"sub": "1234567890", "name": "John Doe", "iat": 1516239022}
        
        header_b64 = base64.urlsafe_b64encode(
            json.dumps(header).encode()
        ).decode().rstrip('=')
        payload_b64 = base64.urlsafe_b64encode(
            json.dumps(payload).encode()
        ).decode().rstrip('=')
        
        self.valid_token = f"{header_b64}.{payload_b64}.test_signature"
        self.valid_auth_header = f"Bearer {self.valid_token}"
    
    @pytest.mark.asyncio
    async def test_validate_bearer_token_success(self):
        """Test successful bearer token validation."""
        # Import here to avoid module loading issues during collection
        from interfaces.api.dependencies import validate_bearer_token
        
        result = await validate_bearer_token(self.valid_auth_header)
        assert result == self.valid_token
    
    @pytest.mark.asyncio
    async def test_validate_bearer_token_missing_header(self):
        """Test validation fails when Authorization header is missing."""
        from interfaces.api.dependencies import validate_bearer_token
        
        with pytest.raises(HTTPException) as exc_info:
            await validate_bearer_token(None)
        
        assert exc_info.value.status_code == 401
        assert "Missing Authorization header" in exc_info.value.detail
        assert exc_info.value.headers["WWW-Authenticate"] == "Bearer"
    
    @pytest.mark.asyncio
    async def test_validate_bearer_token_invalid_format(self):
        """Test validation fails for invalid Authorization header format."""
        from interfaces.api.dependencies import validate_bearer_token
        
        with pytest.raises(HTTPException) as exc_info:
            await validate_bearer_token("Basic dXNlcjpwYXNz")  # Basic auth instead of Bearer
        
        assert exc_info.value.status_code == 401
        assert "Invalid Authorization header format" in exc_info.value.detail
        assert exc_info.value.headers["WWW-Authenticate"] == "Bearer"
    
    @pytest.mark.asyncio
    async def test_validate_bearer_token_missing_bearer_prefix(self):
        """Test validation fails when Bearer prefix is missing."""
        from interfaces.api.dependencies import validate_bearer_token
        
        with pytest.raises(HTTPException) as exc_info:
            await validate_bearer_token(self.valid_token)  # Token without "Bearer " prefix
        
        assert exc_info.value.status_code == 401
        assert "Invalid Authorization header format" in exc_info.value.detail
    
    @pytest.mark.asyncio
    async def test_validate_bearer_token_empty_token(self):
        """Test validation fails for empty token after Bearer prefix."""
        from interfaces.api.dependencies import validate_bearer_token
        
        with pytest.raises(HTTPException) as exc_info:
            await validate_bearer_token("Bearer ")  # Bearer with no token
        
        assert exc_info.value.status_code == 401
        assert "Empty bearer token" in exc_info.value.detail
    
    @pytest.mark.asyncio
    async def test_validate_bearer_token_invalid_jwt_structure(self):
        """Test validation fails for invalid JWT token structure."""
        from interfaces.api.dependencies import validate_bearer_token
        
        with pytest.raises(HTTPException) as exc_info:
            await validate_bearer_token("Bearer invalid.token")  # Invalid JWT structure
        
        assert exc_info.value.status_code == 401
        assert "Invalid JWT token structure" in exc_info.value.detail
    
    @pytest.mark.asyncio
    async def test_validate_bearer_token_malformed_jwt(self):
        """Test validation fails for malformed JWT."""
        from interfaces.api.dependencies import validate_bearer_token
        
        with pytest.raises(HTTPException) as exc_info:
            await validate_bearer_token("Bearer not_a_jwt_at_all")
        
        assert exc_info.value.status_code == 401
        assert "Invalid JWT token structure" in exc_info.value.detail
    
    @pytest.mark.asyncio
    async def test_validate_bearer_token_case_sensitive(self):
        """Test that Bearer prefix is case sensitive."""
        with pytest.raises(HTTPException) as exc_info:
            await validate_bearer_token(f"bearer {self.valid_token}")  # lowercase 'bearer'
        
        assert exc_info.value.status_code == 401
        assert "Invalid Authorization header format" in exc_info.value.detail
    
    @pytest.mark.asyncio
    async def test_validate_bearer_token_extra_spaces(self):
        """Test handling of extra spaces in Authorization header."""
        # Should work with proper spacing
        result = await validate_bearer_token(f"Bearer {self.valid_token}")
        assert result == self.valid_token
        
        # Should fail with extra spaces
        with pytest.raises(HTTPException) as exc_info:
            await validate_bearer_token(f"Bearer  {self.valid_token}")  # Extra space
        
        assert exc_info.value.status_code == 401