Spaces:
Running
Running
Commit ·
b4f32e7
1
Parent(s): df9be89
add pytest tests for users and applications
Browse files- tests/__init__.py +0 -0
- tests/conftest.py +92 -0
- tests/test_applications.py +96 -0
- tests/test_users.py +72 -0
tests/__init__.py
ADDED
|
File without changes
|
tests/conftest.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi.testclient import TestClient
|
| 2 |
+
from sqlalchemy import create_engine
|
| 3 |
+
from sqlalchemy.orm import sessionmaker
|
| 4 |
+
from app.cores.config import settings
|
| 5 |
+
import pytest
|
| 6 |
+
from app.cores.database import get_db, Base
|
| 7 |
+
from app.cores.security import create_access_token
|
| 8 |
+
from app.models.application import Application
|
| 9 |
+
from app.main import app
|
| 10 |
+
|
| 11 |
+
SQLALCHEMY_DATABASE_URL = f"postgresql://{settings.DATABASE_USERNAME}:{settings.DATABASE_PASSWORD}@{settings.DATABASE_HOSTNAME}:{settings.DATABASE_PORT}/{settings.DATABASE_NAME}_test"
|
| 12 |
+
engine = create_engine(SQLALCHEMY_DATABASE_URL)
|
| 13 |
+
TestingSessionMaker = sessionmaker(autoflush=False, autocommit=False, bind=engine)
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
@pytest.fixture()
|
| 17 |
+
def session():
|
| 18 |
+
Base.metadata.drop_all(bind=engine)
|
| 19 |
+
Base.metadata.create_all(bind=engine)
|
| 20 |
+
db = TestingSessionMaker()
|
| 21 |
+
try:
|
| 22 |
+
yield db
|
| 23 |
+
finally:
|
| 24 |
+
db.close()
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
@pytest.fixture()
|
| 28 |
+
def client(session):
|
| 29 |
+
def override_get_db():
|
| 30 |
+
try:
|
| 31 |
+
yield session
|
| 32 |
+
finally:
|
| 33 |
+
session.close()
|
| 34 |
+
app.dependency_overrides[get_db] = override_get_db
|
| 35 |
+
yield TestClient(app)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
@pytest.fixture
|
| 39 |
+
def create_test_user(client):
|
| 40 |
+
user_data = {
|
| 41 |
+
"email": "abdullah@gmail.com",
|
| 42 |
+
"password": "abdullah1234"
|
| 43 |
+
}
|
| 44 |
+
response = client.post("/users", json=user_data)
|
| 45 |
+
assert response.status_code == 201
|
| 46 |
+
new_user = response.json()
|
| 47 |
+
new_user["password"] = "abdullah1234"
|
| 48 |
+
return new_user
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
@pytest.fixture
|
| 52 |
+
def create_test_user2(client):
|
| 53 |
+
user_data = {
|
| 54 |
+
"email": "ali@gmail.com",
|
| 55 |
+
"password": "ali1234"
|
| 56 |
+
}
|
| 57 |
+
response = client.post("/users", json=user_data)
|
| 58 |
+
assert response.status_code == 201
|
| 59 |
+
new_user = response.json()
|
| 60 |
+
new_user["password"] = "ali1234"
|
| 61 |
+
return new_user
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
@pytest.fixture()
|
| 65 |
+
def token(create_test_user):
|
| 66 |
+
return create_access_token({"user_id": create_test_user["id"]})
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
@pytest.fixture()
|
| 70 |
+
def authorized_client(client, token):
|
| 71 |
+
client.headers = {
|
| 72 |
+
**client.headers,
|
| 73 |
+
"Authorization": f"Bearer {token}"
|
| 74 |
+
}
|
| 75 |
+
return client
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def create_application(application_data):
|
| 79 |
+
return Application(**application_data)
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
@pytest.fixture
|
| 83 |
+
def test_applications(create_test_user, session):
|
| 84 |
+
applications_data = [
|
| 85 |
+
{"company": "Google", "role": "Backend Engineer", "status": "applied", "applied_date": "2026-06-01", "user_id": create_test_user["id"]},
|
| 86 |
+
{"company": "Meta", "role": "SWE", "status": "interview", "applied_date": "2026-06-10", "user_id": create_test_user["id"]},
|
| 87 |
+
{"company": "Amazon", "role": "SDE", "status": "rejected", "applied_date": "2026-06-15", "user_id": create_test_user["id"]},
|
| 88 |
+
]
|
| 89 |
+
applications = list(map(create_application, applications_data))
|
| 90 |
+
session.add_all(applications)
|
| 91 |
+
session.commit()
|
| 92 |
+
return session.query(Application).all()
|
tests/test_applications.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
from app.models.application import ApplicationStatus
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def test_create_application(authorized_client):
|
| 6 |
+
response = authorized_client.post("/applications", json={
|
| 7 |
+
"company": "Google",
|
| 8 |
+
"role": "Backend Engineer",
|
| 9 |
+
"status": "applied",
|
| 10 |
+
"applied_date": "2026-06-01",
|
| 11 |
+
"jd_text": "We need a Python developer",
|
| 12 |
+
"notes": "Referred by a friend"
|
| 13 |
+
})
|
| 14 |
+
assert response.status_code == 201
|
| 15 |
+
data = response.json()
|
| 16 |
+
assert data["company"] == "Google"
|
| 17 |
+
assert data["role"] == "Backend Engineer"
|
| 18 |
+
assert data["status"] == "applied"
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def test_create_application_unauthorized(client):
|
| 22 |
+
response = client.post("/applications", json={
|
| 23 |
+
"company": "Google",
|
| 24 |
+
"role": "Backend Engineer",
|
| 25 |
+
"status": "applied",
|
| 26 |
+
"applied_date": "2026-06-01"
|
| 27 |
+
})
|
| 28 |
+
assert response.status_code == 401
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def test_get_all_applications(authorized_client, test_applications):
|
| 32 |
+
response = authorized_client.get("/applications")
|
| 33 |
+
assert response.status_code == 200
|
| 34 |
+
assert len(response.json()) == len(test_applications)
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def test_get_all_applications_unauthorized(client):
|
| 38 |
+
response = client.get("/applications")
|
| 39 |
+
assert response.status_code == 401
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def test_get_one_application(authorized_client, test_applications):
|
| 43 |
+
response = authorized_client.get(f"/applications/{test_applications[0].id}")
|
| 44 |
+
assert response.status_code == 200
|
| 45 |
+
data = response.json()
|
| 46 |
+
assert data["id"] == test_applications[0].id
|
| 47 |
+
assert data["company"] == test_applications[0].company
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
def test_get_one_application_not_found(authorized_client):
|
| 51 |
+
response = authorized_client.get("/applications/-99999")
|
| 52 |
+
assert response.status_code == 404
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def test_get_one_application_unauthorized(client, test_applications):
|
| 56 |
+
response = client.get(f"/applications/{test_applications[0].id}")
|
| 57 |
+
assert response.status_code == 401
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def test_update_application(authorized_client, test_applications):
|
| 61 |
+
response = authorized_client.put(f"/applications/{test_applications[0].id}", json={
|
| 62 |
+
"status": "interview",
|
| 63 |
+
"notes": "Got a call back"
|
| 64 |
+
})
|
| 65 |
+
assert response.status_code == 200
|
| 66 |
+
assert response.json()["status"] == "interview"
|
| 67 |
+
assert response.json()["notes"] == "Got a call back"
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def test_update_application_not_found(authorized_client):
|
| 71 |
+
response = authorized_client.put("/applications/-99999", json={
|
| 72 |
+
"status": "interview"
|
| 73 |
+
})
|
| 74 |
+
assert response.status_code == 404
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def test_update_application_unauthorized(client, test_applications):
|
| 78 |
+
response = client.put(f"/applications/{test_applications[0].id}", json={
|
| 79 |
+
"status": "interview"
|
| 80 |
+
})
|
| 81 |
+
assert response.status_code == 401
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def test_delete_application(authorized_client, test_applications):
|
| 85 |
+
response = authorized_client.delete(f"/applications/{test_applications[0].id}")
|
| 86 |
+
assert response.status_code == 204
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
def test_delete_application_not_found(authorized_client):
|
| 90 |
+
response = authorized_client.delete("/applications/-99999")
|
| 91 |
+
assert response.status_code == 404
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def test_delete_application_unauthorized(client, test_applications):
|
| 95 |
+
response = client.delete(f"/applications/{test_applications[0].id}")
|
| 96 |
+
assert response.status_code == 401
|
tests/test_users.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
from app.schemas.user import UserOut
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def test_create_user(client):
|
| 6 |
+
response = client.post("/users", json={
|
| 7 |
+
"email": "newuser@gmail.com",
|
| 8 |
+
"password": "password123"
|
| 9 |
+
})
|
| 10 |
+
assert response.status_code == 201
|
| 11 |
+
new_user = UserOut(**response.json())
|
| 12 |
+
assert new_user.email == "newuser@gmail.com"
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def test_create_user_duplicate_email(client):
|
| 16 |
+
client.post("/users", json={"email": "dup@gmail.com", "password": "pass123"})
|
| 17 |
+
response = client.post("/users", json={"email": "dup@gmail.com", "password": "pass123"})
|
| 18 |
+
assert response.status_code == 400
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def test_login_success(client, create_test_user):
|
| 22 |
+
response = client.post("/login", data={
|
| 23 |
+
"username": create_test_user["email"],
|
| 24 |
+
"password": create_test_user["password"]
|
| 25 |
+
})
|
| 26 |
+
assert response.status_code == 200
|
| 27 |
+
assert response.json()["token_type"] == "bearer"
|
| 28 |
+
assert "access_token" in response.json()
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def test_login_wrong_password(client, create_test_user):
|
| 32 |
+
response = client.post("/login", data={
|
| 33 |
+
"username": create_test_user["email"],
|
| 34 |
+
"password": "wrongpassword"
|
| 35 |
+
})
|
| 36 |
+
assert response.status_code == 401
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def test_login_wrong_email(client):
|
| 40 |
+
response = client.post("/login", data={
|
| 41 |
+
"username": "nonexistent@gmail.com",
|
| 42 |
+
"password": "somepassword"
|
| 43 |
+
})
|
| 44 |
+
assert response.status_code == 401
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def test_get_all_users(client, create_test_user):
|
| 48 |
+
response = client.get("/users")
|
| 49 |
+
assert response.status_code == 200
|
| 50 |
+
assert len(response.json()) > 0
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def test_update_password(authorized_client, create_test_user):
|
| 54 |
+
response = authorized_client.put("/users", json={
|
| 55 |
+
"old_password": create_test_user["password"],
|
| 56 |
+
"new_password": "newpassword123"
|
| 57 |
+
})
|
| 58 |
+
assert response.status_code == 200
|
| 59 |
+
assert response.json()["message"] == "Password updated successfully"
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def test_update_password_wrong_old(authorized_client):
|
| 63 |
+
response = authorized_client.put("/users", json={
|
| 64 |
+
"old_password": "wrongoldpassword",
|
| 65 |
+
"new_password": "newpassword123"
|
| 66 |
+
})
|
| 67 |
+
assert response.status_code == 400
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def test_delete_user(authorized_client, create_test_user):
|
| 71 |
+
response = authorized_client.delete(f"/users/{create_test_user['id']}")
|
| 72 |
+
assert response.status_code == 204
|