Skip to content

Commit fec2a31

Browse files
Improve JWT tests
1 parent 4c4f815 commit fec2a31

File tree

1 file changed

+37
-2
lines changed

1 file changed

+37
-2
lines changed

tests/test_auth.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1+
import math
2+
13
import pytest
24

35
from app.models import User
46
from tests import utils
7+
from flask_jwt_extended import decode_token
58

69

710
class TestAuth:
811
TEST_EMAIL = "[email protected]"
912
TEST_PASSWORD = "testpassword"
13+
ACCESS_TOKEN_DELTA = 10800 # 3 hours in seconds
14+
REFRESH_TOKEN_DELTA = 259200 # 3 days in seconds
1015

1116
@pytest.fixture(autouse=True)
1217
def setup(self, client):
@@ -41,6 +46,33 @@ def _test_invalid_request_data(self, endpoint, expected_status=400):
4146
response = self.client.post(endpoint, data="not json data")
4247
assert response.status_code == 415
4348

49+
def _decode_token(self, token):
50+
return decode_token(token, allow_expired=False)
51+
52+
def _assert_jwt_structure(self, token, expected_sub, expected_type, fresh=False):
53+
assert token.count(".") == 2, f"Token does not have three segments: {token}"
54+
payload = self._decode_token(token)
55+
assert payload["sub"] == expected_sub
56+
assert payload["type"] == expected_type
57+
assert "iat" in payload
58+
assert "exp" in payload
59+
assert "jti" in payload
60+
assert payload["fresh"] is fresh
61+
62+
# Expiry check
63+
expected_delta = None
64+
if expected_type == "access":
65+
expected_delta = self.ACCESS_TOKEN_DELTA
66+
if expected_type == "refresh":
67+
expected_delta = self.REFRESH_TOKEN_DELTA
68+
69+
if expected_delta is not None:
70+
actual_delta = payload["exp"] - payload["iat"]
71+
# Allow a small margin (e.g., 0-2 seconds) for processing time
72+
assert math.isclose(actual_delta, expected_delta, abs_tol=2), (
73+
f"Token expiry delta {actual_delta} != expected {expected_delta}"
74+
)
75+
4476
def test_register_success(self, register_user):
4577
response = register_user(self.TEST_EMAIL, self.TEST_PASSWORD)
4678

@@ -81,8 +113,9 @@ def test_login_success(self, register_user, login_user):
81113
data = response.get_json()
82114
assert "access_token" in data
83115
assert "refresh_token" in data
84-
assert len(data["access_token"]) > 0
85-
assert len(data["refresh_token"]) > 0
116+
117+
self._assert_jwt_structure(data["access_token"], expected_sub="1", expected_type="access", fresh=True)
118+
self._assert_jwt_structure(data["refresh_token"], expected_sub="1", expected_type="refresh")
86119

87120
def test_login_invalid_password(self, register_user, login_user):
88121
register_user(self.TEST_EMAIL, self.TEST_PASSWORD)
@@ -109,6 +142,8 @@ def test_refresh_token(self, register_user, login_user):
109142
assert data["access_token"] != original_access_token
110143
assert "refresh_token" not in data
111144

145+
self._assert_jwt_structure(data["access_token"], expected_sub="1", expected_type="access", fresh=False)
146+
112147
def test_refresh_token_invalid(self, register_user, login_user):
113148
# Access token test
114149
register_user(self.TEST_EMAIL, self.TEST_PASSWORD)

0 commit comments

Comments
 (0)