146 lines
5.2 KiB
Python
146 lines
5.2 KiB
Python
import pytest
|
|
import os
|
|
from unittest.mock import MagicMock, patch
|
|
from datetime import date
|
|
from garmin.client import GarminClient
|
|
|
|
@pytest.fixture
|
|
def mock_garmin():
|
|
with patch("garmin.client.Garmin") as mock:
|
|
yield mock
|
|
|
|
@pytest.fixture
|
|
def mock_garth():
|
|
with patch("garmin.client.garth") as mock:
|
|
yield mock
|
|
|
|
@pytest.fixture
|
|
def mock_sso():
|
|
with patch("garmin.client.garth_login") as mock_login, \
|
|
patch("garmin.client.resume_login") as mock_resume_login:
|
|
yield mock_login, mock_resume_login
|
|
|
|
def test_client_init():
|
|
client = GarminClient(email="test@example.com", password="password")
|
|
assert client.email == "test@example.com"
|
|
assert client.password == "password"
|
|
|
|
def test_login_success(mock_sso, mock_garmin, mock_garth):
|
|
mock_login, _ = mock_sso
|
|
mock_login.return_value = (MagicMock(), MagicMock())
|
|
client = GarminClient(email="test@example.com", password="password")
|
|
|
|
with patch("os.path.exists", return_value=False):
|
|
assert client.login(force_login=True) == "SUCCESS"
|
|
mock_login.assert_called_once()
|
|
|
|
def test_login_mfa_required(mock_sso):
|
|
mock_login, _ = mock_sso
|
|
mock_login.return_value = ("needs_mfa", {"some": "state"})
|
|
|
|
client = GarminClient(email="test@example.com", password="password")
|
|
with patch("os.path.exists", return_value=False):
|
|
assert client.login(force_login=True) == "MFA_REQUIRED"
|
|
assert GarminClient._temp_client_state == {"some": "state"}
|
|
|
|
def test_login_mfa_complete(mock_sso, mock_garmin, mock_garth):
|
|
_, mock_resume_login = mock_sso
|
|
mock_client = MagicMock()
|
|
mock_client.oauth1_token = MagicMock()
|
|
state = {"some": "state", "client": mock_client}
|
|
GarminClient._temp_client_state = state
|
|
|
|
client = GarminClient(email="test@example.com", password="password")
|
|
assert client.login(mfa_code="123456") == "SUCCESS"
|
|
mock_resume_login.assert_called_with(state, "123456")
|
|
assert GarminClient._temp_client_state is None
|
|
assert mock_client.dump.called
|
|
|
|
def test_login_resume_success(mock_garmin):
|
|
client = GarminClient(email="test@example.com", password="password")
|
|
inst = MagicMock()
|
|
mock_garmin.return_value = inst
|
|
with patch("os.path.exists", return_value=True), \
|
|
patch("os.path.getsize", return_value=100):
|
|
assert client.login() == "SUCCESS"
|
|
inst.login.assert_called_with(tokenstore=client.token_store)
|
|
|
|
def test_login_resume_fail_no_force(mock_garmin, mock_sso):
|
|
mock_login, _ = mock_sso
|
|
inst = MagicMock()
|
|
inst.login.side_effect = Exception("Resume fail")
|
|
mock_garmin.return_value = inst
|
|
|
|
client = GarminClient(email="test", password="test")
|
|
with patch("os.path.exists", return_value=True), \
|
|
patch("os.path.getsize", return_value=100):
|
|
assert client.login() == "FAILURE"
|
|
assert mock_login.call_count == 0
|
|
|
|
def test_login_resume_fail_with_force(mock_garmin, mock_sso):
|
|
mock_login, _ = mock_sso
|
|
mock_login.return_value = (MagicMock(), MagicMock())
|
|
|
|
inst1 = MagicMock()
|
|
inst1.login.side_effect = Exception("Resume fail")
|
|
inst2 = MagicMock()
|
|
inst2.login.return_value = None
|
|
mock_garmin.side_effect = [inst1, inst2]
|
|
|
|
client = GarminClient(email="test", password="test")
|
|
with patch("os.path.exists", return_value=True), \
|
|
patch("os.path.getsize", return_value=100), \
|
|
patch("os.remove") as mock_remove:
|
|
assert client.login(force_login=True) == "SUCCESS"
|
|
assert mock_login.call_count == 1
|
|
|
|
def test_login_failure(mock_sso):
|
|
mock_login, _ = mock_sso
|
|
mock_login.side_effect = Exception("Fatal error")
|
|
client = GarminClient(email="test@example.com", password="password")
|
|
|
|
with patch("os.path.exists", return_value=False):
|
|
assert client.login(force_login=True) == "FAILURE"
|
|
|
|
def test_get_activities_not_logged_in():
|
|
client = GarminClient()
|
|
with pytest.raises(RuntimeError, match="Client not logged in"):
|
|
client.get_activities(date.today(), date.today())
|
|
|
|
def test_get_activities_success(mock_garmin):
|
|
mock_instance = mock_garmin.return_value
|
|
mock_instance.get_activities_by_date.return_value = [{"activityId": 123}]
|
|
|
|
client = GarminClient()
|
|
client.client = mock_instance
|
|
|
|
activities = client.get_activities(date(2023, 1, 1), date(2023, 1, 2))
|
|
assert activities == [{"activityId": 123}]
|
|
|
|
def test_get_activities_failure(mock_garmin):
|
|
mock_instance = mock_garmin.return_value
|
|
mock_instance.get_activities_by_date.side_effect = Exception("err")
|
|
|
|
client = GarminClient()
|
|
client.client = mock_instance
|
|
|
|
assert client.get_activities(date.today(), date.today()) == []
|
|
|
|
def test_get_stats_success(mock_garmin):
|
|
mock_instance = mock_garmin.return_value
|
|
mock_instance.get_stats.return_value = {"steps": 1000}
|
|
|
|
client = GarminClient()
|
|
client.client = mock_instance
|
|
stats = client.get_stats(date(2023, 1, 1))
|
|
assert stats == {"steps": 1000}
|
|
|
|
def test_get_user_summary_success(mock_garmin):
|
|
mock_instance = mock_garmin.return_value
|
|
mock_instance.get_user_summary.return_value = {"calories": 2000}
|
|
|
|
client = GarminClient()
|
|
client.client = mock_instance
|
|
summary = client.get_user_summary(date(2023, 1, 1))
|
|
assert summary == {"calories": 2000}
|