Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test auth #39

Merged
merged 4 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 98 additions & 2 deletions backend-app/tests/unit/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from io import BytesIO
from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock

import pandas as pd
import pytest
Expand All @@ -13,7 +13,7 @@
from app.models import user as api_m
from app.models.database import User as db_user
from app.models.file_db import create_file_table_class, update_schema
from app.models.user import UserCreate, UserInDB
from app.models.user import User, UserCreate, UserInDB
from app.sql_db.crud import create_user, get_db, update_is_active, update_is_admin
from app.sql_db.database import Base
from app.sql_db.file_crud import create_update_table, insert_data
Expand Down Expand Up @@ -197,6 +197,92 @@ def mock_user():
return user


@pytest.fixture
def mock_user_is_active_not_admin():
"""Fixture for mocking a user."""
user = User(
id=1,
email="[email protected]",
password="test1",
hashed_password="test1fake_hash",
is_active=True,
)
return user


@pytest.fixture
def mock_user_not_active_not_admin():
"""Fixture for mocking a user."""
user = User(
id=1,
email="[email protected]",
password="test1",
hashed_password="test1fake_hash",
is_active=False,
)
return user


@pytest.fixture
def mock_user_is_active_is_admin():
"""Fixture for mocking a user."""
user = User(
id=1,
email="[email protected]",
password="test1",
hashed_password="test1fake_hash",
is_active=True,
is_admin=True,
)
return user


@pytest.fixture
def mock_user_not_active_is_admin():
"""Fixture for mocking a user."""
user = User(
id=1,
email="[email protected]",
password="test1",
hashed_password="test1fake_hash",
is_active=False,
is_admin=True,
)
return user


@pytest.fixture
def mock_get_current_user_is_active_not_admin(mock_user_is_active_not_admin):
"""Fixture for mocking get_current_user to return the mock user."""
mock_function = MagicMock()
mock_function.return_value = mock_user_is_active_not_admin
return mock_function


@pytest.fixture
def mock_get_current_user_not_active_not_admin(mock_user_not_active_not_admin):
"""Fixture for mocking get_current_user to return the mock user."""
mock_function = MagicMock()
mock_function.return_value = mock_user_not_active_not_admin
return mock_function


@pytest.fixture
def mock_get_current_user_is_active_is_admin(mock_user_is_active_is_admin):
"""Fixture for mocking get_current_user to return the mock user."""
mock_function = MagicMock()
mock_function.return_value = mock_user_is_active_is_admin
return mock_function


@pytest.fixture
def mock_get_current_user_not_active_is_admin(mock_user_not_active_is_admin):
"""Fixture for mocking get_current_user to return the mock user."""
mock_function = MagicMock()
mock_function.return_value = mock_user_not_active_is_admin
return mock_function


@pytest.fixture
def mock_get_user_by_email_success(mock_user):
"""Fixture for mocking get_user_by_email to return the mock user."""
Expand Down Expand Up @@ -233,3 +319,13 @@ def valid_token(valid_token_payload):
def mock_jwt_decode(valid_token_payload):
"""Mock jwt.decode to return a valid payload."""
return MagicMock(return_value=valid_token_payload)


@pytest.fixture
def mock_authenticate_user(mock_get_user_by_email_success):
return MagicMock(return_value=mock_get_user_by_email_success)


@pytest.fixture
def mock_create_access_token_valid_token(valid_token):
return MagicMock(return_value=valid_token)
120 changes: 119 additions & 1 deletion backend-app/tests/unit/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
from fastapi.exceptions import HTTPException
from jose import JWTError, jwt

from app.api.auth import authenticate_user, create_access_token, get_current_user
from app.api.auth import (
authenticate_user,
create_access_token,
get_current_active_user,
get_current_user,
)


def test_authenticate_user_success(mock_db, mock_get_user_by_email_success, mock_user, monkeypatch):
Expand Down Expand Up @@ -195,3 +200,116 @@ async def test_get_current_user_user_not_found(
assert exc_info.value.detail == "Could not validate credentials"
mock_jwt_decode.assert_called_once_with(valid_token, TEST_SECRET_KEY, algorithms=["HS256"])
mock_get_user_by_email_none.assert_called_once_with(mock_db, email=valid_token_payload["sub"])


@pytest.mark.asyncio
async def test_get_current_active_user_success(
mock_user_is_active_not_admin, mock_get_current_user_is_active_not_admin, monkeypatch
):
monkeypatch.setattr("app.api.auth.get_current_user", mock_get_current_user_is_active_not_admin)

user = await get_current_active_user(mock_user_is_active_not_admin)

assert user.id == mock_user_is_active_not_admin.id


@pytest.mark.asyncio
async def test_get_current_active_user_not_active(
mock_user_not_active_not_admin, mock_get_current_user_not_active_not_admin, monkeypatch
):
monkeypatch.setattr("app.api.auth.get_current_user", mock_get_current_user_not_active_not_admin)

with pytest.raises(HTTPException) as exc_info:
await get_current_active_user(mock_user_not_active_not_admin)

assert exc_info.value.status_code == 400
assert exc_info.value.detail == "Inactive user"


@pytest.mark.asyncio
async def test_get_current_active_admin_success(
mock_user_is_active_is_admin, mock_get_current_user_is_active_is_admin, monkeypatch
):
monkeypatch.setattr("app.api.auth.get_current_user", mock_get_current_user_is_active_is_admin)

user = await get_current_active_user(mock_user_is_active_is_admin)

assert user.id == mock_user_is_active_is_admin.id


@pytest.mark.asyncio
async def test_get_current_active_admin_not_active_is_admin(
mock_user_not_active_is_admin, mock_get_current_user_not_active_is_admin, monkeypatch
):
monkeypatch.setattr("app.api.auth.get_current_user", mock_get_current_user_not_active_is_admin)

with pytest.raises(HTTPException) as exc_info:
await get_current_active_user(mock_user_not_active_is_admin)

assert exc_info.value.status_code == 400
assert exc_info.value.detail == "Inactive user"


@pytest.mark.asyncio
async def test_get_current_admin_not_active_not_admin(
mock_user_not_active_not_admin, mock_get_current_user_not_active_not_admin, monkeypatch
):
monkeypatch.setattr("app.api.auth.get_current_user", mock_get_current_user_not_active_not_admin)

with pytest.raises(HTTPException) as exc_info:
await get_current_active_user(mock_user_not_active_not_admin)

assert exc_info.value.status_code == 400
assert exc_info.value.detail == "Inactive user"


def test_api_helth_check(client):
# GET request
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"Status": "Something Different"}


def test_health_check_post(client):
# POST request to a GET-only route
response = client.post("/")
assert response.status_code == 405 # Method Not Allowed


def test_health_check_wrong_url(client):
# Wrong URL
response = client.get("/wrong-url")
assert response.status_code == 404 # Not Found


def test_successful_login(
client,
mock_authenticate_user,
mock_create_access_token_valid_token,
valid_token,
db,
monkeypatch,
):

monkeypatch.setattr("app.api.auth.authenticate_user", mock_authenticate_user)
monkeypatch.setattr("app.api.auth.create_access_token", mock_create_access_token_valid_token)

# Prepare the data as if it is coming from OAuth2PasswordRequestForm
login_data = {"username": "[email protected]", "password": "test1fake_hash"}

# Send a POST request to the /token endpoint
response = client.post("/token", data=login_data)

# Assert that the status code is 200 OK
assert response.status_code == 200

# Assert that the response JSON contains the correct token
expected_response = {
"access_token": valid_token,
"token_type": "bearer",
"message": "Welcome!",
}
assert response.json() == expected_response

# # Ensure the authenticate_user was called with correct arguments
mock_authenticate_user.assert_called_once_with("[email protected]", "test1fake_hash", db=db)
Loading