Skip to content

Commit 82bb87a

Browse files
Merge pull request #3 from piyush-jaiswal/feature/add-inital-tests
Add initial tests using pytest
2 parents d8019ef + 4162772 commit 82bb87a

File tree

6 files changed

+443
-0
lines changed

6 files changed

+443
-0
lines changed

requirements-test.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-r requirements.txt
2+
pytest==8.3.5

tests/__init__.py

Whitespace-only changes.

tests/conftest.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import os
2+
3+
import pytest
4+
5+
# TODO: Fix hack. Changes the env var before initializing the db for testing
6+
os.environ["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:"
7+
8+
from app import app, db
9+
10+
11+
@pytest.fixture
12+
def client():
13+
app.config["TESTING"] = True
14+
with app.test_client() as client:
15+
with app.app_context():
16+
db.create_all()
17+
yield client
18+
with app.app_context():
19+
db.drop_all()
20+
21+
22+
@pytest.fixture
23+
def register_user(client):
24+
def _register(email, password):
25+
return client.post(
26+
"/auth/register", json={"email": email, "password": password}
27+
)
28+
29+
return _register
30+
31+
32+
@pytest.fixture
33+
def login_user(client):
34+
def _login(email, password):
35+
return client.post("/auth/login", json={"email": email, "password": password})
36+
37+
return _login

tests/test_auth.py

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import pytest
2+
3+
from app.models import User
4+
from tests import utils
5+
6+
7+
class TestAuth:
8+
TEST_EMAIL = "[email protected]"
9+
TEST_PASSWORD = "testpassword"
10+
11+
@pytest.fixture(autouse=True)
12+
def setup(self, client):
13+
self.client = client
14+
with client.application.app_context():
15+
assert User.query.count() == 0
16+
17+
def _verify_user_in_db(self, email, should_exist=True):
18+
with self.client.application.app_context():
19+
user = User.get(email=email)
20+
if should_exist:
21+
assert user is not None
22+
assert user.email == email
23+
return user
24+
else:
25+
assert user is None
26+
27+
def _count_users(self):
28+
with self.client.application.app_context():
29+
return User.query.count()
30+
31+
def _test_invalid_request_data(self, endpoint, expected_status=400):
32+
response = self.client.post(endpoint, json={})
33+
assert response.status_code == expected_status
34+
35+
response = self.client.post(endpoint, json={"email": self.TEST_EMAIL})
36+
assert response.status_code == expected_status
37+
38+
response = self.client.post(endpoint, json={"password": self.TEST_PASSWORD})
39+
assert response.status_code == expected_status
40+
41+
response = self.client.post(endpoint, data="not json data")
42+
assert response.status_code == 415
43+
44+
def test_register_success(self, register_user):
45+
response = register_user(self.TEST_EMAIL, self.TEST_PASSWORD)
46+
47+
assert response.status_code == 201
48+
assert b"Registered!" in response.data
49+
assert self._count_users() == 1
50+
user = self._verify_user_in_db(self.TEST_EMAIL)
51+
assert user.password_hash != self.TEST_PASSWORD
52+
53+
def test_register_duplicate_email(self, register_user):
54+
register_user(self.TEST_EMAIL, self.TEST_PASSWORD)
55+
response = register_user(self.TEST_EMAIL, self.TEST_PASSWORD)
56+
57+
assert response.status_code == 409
58+
assert b"Email already exists" in response.data
59+
assert self._count_users() == 1
60+
self._verify_user_in_db(self.TEST_EMAIL)
61+
62+
def test_register_invalid_email_format(self, register_user):
63+
invalid_email = "not-an-email"
64+
response = register_user(invalid_email, self.TEST_PASSWORD)
65+
66+
assert response.status_code == 400
67+
data = response.get_json()
68+
assert data["code"] == "invalid_email_format"
69+
assert "error" in data
70+
self._verify_user_in_db(invalid_email, should_exist=False)
71+
72+
def test_register_invalid_data(self):
73+
self._test_invalid_request_data("/auth/register")
74+
assert self._count_users() == 0
75+
76+
def test_login_success(self, register_user, login_user):
77+
register_user(self.TEST_EMAIL, self.TEST_PASSWORD)
78+
response = login_user(self.TEST_EMAIL, self.TEST_PASSWORD)
79+
80+
assert response.status_code == 200
81+
data = response.get_json()
82+
assert "access_token" in data
83+
assert "refresh_token" in data
84+
assert len(data["access_token"]) > 0
85+
assert len(data["refresh_token"]) > 0
86+
87+
def test_login_invalid_password(self, register_user, login_user):
88+
register_user(self.TEST_EMAIL, self.TEST_PASSWORD)
89+
response = login_user(self.TEST_EMAIL, "wrongpassword")
90+
91+
assert response.status_code == 401
92+
assert b"Invalid username or password" in response.data
93+
94+
def test_login_invalid_data(self):
95+
self._test_invalid_request_data("/auth/login")
96+
97+
def test_refresh_token(self, register_user, login_user):
98+
register_user(self.TEST_EMAIL, self.TEST_PASSWORD)
99+
login_resp = login_user(self.TEST_EMAIL, self.TEST_PASSWORD)
100+
tokens = login_resp.get_json()
101+
refresh_token = tokens["refresh_token"]
102+
original_access_token = tokens["access_token"]
103+
104+
headers = utils.get_auth_header(refresh_token)
105+
refresh_resp = self.client.post("/auth/refresh", headers=headers)
106+
assert refresh_resp.status_code == 200
107+
data = refresh_resp.get_json()
108+
assert "access_token" in data
109+
assert data["access_token"] != original_access_token
110+
assert "refresh_token" not in data
111+
112+
def test_refresh_token_invalid(self, register_user, login_user):
113+
# Access token test
114+
register_user(self.TEST_EMAIL, self.TEST_PASSWORD)
115+
login_resp = login_user(self.TEST_EMAIL, self.TEST_PASSWORD)
116+
tokens = login_resp.get_json()
117+
access_token = tokens["access_token"]
118+
headers = utils.get_auth_header(access_token)
119+
response = self.client.post("/auth/refresh", headers=headers)
120+
121+
utils.verify_token_error_response(response, "invalid_token")
122+
123+
# Malformed token test
124+
malformed_headers = utils.get_invalid_token_headers()
125+
response = self.client.post("/auth/refresh", headers=malformed_headers)
126+
utils.verify_token_error_response(response, "invalid_token")
127+
128+
def test_refresh_token_missing_auth(self):
129+
response = self.client.post("/auth/refresh")
130+
utils.verify_token_error_response(response, "authorization_required")
131+
132+
def test_refresh_token_expired(self):
133+
expired_headers = utils.get_expired_token_headers(
134+
self.client.application.app_context()
135+
)
136+
response = self.client.post("/auth/refresh", headers=expired_headers)
137+
utils.verify_token_error_response(response, "token_expired")

0 commit comments

Comments
 (0)