FitMop/backend/tests/test_api.py

120 lines
4.5 KiB
Python

from unittest.mock import MagicMock, patch
import pytest
from fastapi.testclient import TestClient
from main import app
client = TestClient(app, raise_server_exceptions=False)
@pytest.fixture
def mock_sync():
with patch("main.GarminSync") as mock:
yield mock
@pytest.fixture
def mock_engine():
with patch("main.RecommendationEngine") as mock:
yield mock
def test_health():
response = client.get("/health")
assert response.status_code == 200
assert response.json() == {"status": "ok"}
def test_get_activities_success(mock_sync):
mock_instance = mock_sync.return_value
mock_instance.load_local_activities.return_value = [{"activityId": 1}]
response = client.get("/activities")
assert response.status_code == 200
assert response.json() == [{"activityId": 1}]
def test_get_activities_error(mock_sync):
mock_instance = mock_sync.return_value
mock_instance.load_local_activities.side_effect = Exception("Load failed")
response = client.get("/activities")
assert response.status_code == 500
assert "INTERNAL_SERVER_ERROR" in response.json()["error"]
def test_get_recommendation(mock_sync, mock_engine):
mock_sync_instance = mock_sync.return_value
mock_sync_instance.load_local_activities.return_value = []
mock_engine_instance = mock_engine.return_value
mock_engine_instance.get_recommendation.return_value = "Great job!"
response = client.get("/recommendation")
assert response.status_code == 200
assert response.json() == {"recommendation": "Great job!"}
def test_auth_status_unauthenticated(monkeypatch):
monkeypatch.setenv("GARMIN_EMAIL", "")
response = client.get("/auth/status")
assert response.json()["authenticated"] is False
def test_auth_status_failure(monkeypatch):
monkeypatch.setenv("GARMIN_EMAIL", "test@test.com")
with patch("main.GarminClient") as mock_client:
mock_client.return_value.login.return_value = "FAILURE"
response = client.get("/auth/status")
assert response.json()["authenticated"] is False
assert response.json()["message"] == "Login failed"
def test_auth_status_success(monkeypatch, mock_sync):
monkeypatch.setenv("GARMIN_EMAIL", "test@test.com")
monkeypatch.setenv("GARMIN_PASSWORD", "pass")
with patch("main.GarminClient") as mock_client:
mock_client.return_value.login.return_value = "SUCCESS"
response = client.get("/auth/status")
assert response.json()["authenticated"] is True
def test_auth_status_mfa_required(monkeypatch):
monkeypatch.setenv("GARMIN_EMAIL", "test@test.com")
with patch("main.GarminClient") as mock_client:
mock_client.return_value.login.return_value = "MFA_REQUIRED"
response = client.get("/auth/status")
assert response.json()["status"] == "MFA_REQUIRED"
def test_login_success(mock_sync):
with patch("main.GarminClient") as mock_client:
mock_client.return_value.login.return_value = "SUCCESS"
with patch("builtins.open", MagicMock()):
response = client.post("/auth/login", json={"email": "a", "password": "b"})
assert response.status_code == 200
assert response.json()["status"] == "SUCCESS"
def test_login_mfa_required():
with patch("main.GarminClient") as mock_client:
mock_client.return_value.login.return_value = "MFA_REQUIRED"
response = client.post("/auth/login", json={"email": "a", "password": "b"})
assert response.json()["status"] == "MFA_REQUIRED"
def test_login_missing_data(monkeypatch):
monkeypatch.setenv("GARMIN_EMAIL", "")
monkeypatch.setenv("GARMIN_PASSWORD", "")
response = client.post("/auth/login", json={})
assert response.status_code == 400
def test_login_invalid_creds():
with patch("main.GarminClient") as mock_client:
mock_client.return_value.login.return_value = "FAILURE"
response = client.post("/auth/login", json={"email": "a", "password": "b"})
assert response.status_code == 401
def test_trigger_sync_success(mock_sync):
with patch("main.GarminClient") as mock_client:
mock_client.return_value.login.return_value = "SUCCESS"
mock_sync.return_value.sync_activities.return_value = 5
response = client.post("/sync")
assert response.status_code == 200
assert response.json()["synced_count"] == 5
def test_trigger_sync_unauthorized():
with patch("main.GarminClient") as mock_client:
mock_client.return_value.login.return_value = "FAILURE"
response = client.post("/sync")
assert response.status_code == 401