checkpoint 2

This commit is contained in:
2025-08-22 20:29:04 -07:00
parent 6273138a65
commit 6c1fe70fa2
13 changed files with 678 additions and 122 deletions

View File

@@ -1,102 +1,110 @@
import pytest
import sys
from unittest.mock import Mock, patch
from unittest.mock import Mock, patch, MagicMock
# Add the project root to the Python path
sys.path.insert(0, '/app')
from garminsync.database import sync_database
from garminsync.garmin import GarminClient
from garminsync.database import sync_database, Activity, get_activity_metrics
def test_sync_database_with_valid_activities():
"""Test sync_database with valid API response"""
mock_client = Mock(spec=GarminClient)
mock_client = Mock()
mock_client.get_activities.return_value = [
{"activityId": 12345, "startTimeLocal": "2023-01-01T10:00:00"},
{"activityId": 67890, "startTimeLocal": "2023-01-02T11:00:00"}
]
with patch('garminsync.database.get_session') as mock_session:
mock_session.return_value.query.return_value.filter_by.return_value.first.return_value = None
mock_session = MagicMock()
mock_session.query.return_value.filter_by.return_value.first.return_value = None
with patch('garminsync.database.get_session', return_value=mock_session), \
patch('garminsync.database.get_activity_metrics', return_value={
"activityType": {"typeKey": "running"},
"summaryDTO": {
"duration": 3600,
"distance": 10.0,
"maxHR": 180,
"calories": 400
}
}):
sync_database(mock_client)
# Verify get_activities was called
mock_client.get_activities.assert_called_once_with(0, 1000)
# Verify database operations
mock_session.return_value.add.assert_called()
mock_session.return_value.commit.assert_called()
# Verify activities processed
assert mock_session.add.call_count == 2
assert mock_session.commit.called
def test_sync_database_with_none_activities():
"""Test sync_database with None response from API"""
mock_client = Mock(spec=GarminClient)
mock_client = Mock()
mock_client.get_activities.return_value = None
with patch('garminsync.database.get_session') as mock_session:
mock_session = MagicMock()
with patch('garminsync.database.get_session', return_value=mock_session):
sync_database(mock_client)
# Verify get_activities was called
mock_client.get_activities.assert_called_once_with(0, 1000)
# Verify no database operations
mock_session.return_value.add.assert_not_called()
mock_session.return_value.commit.assert_not_called()
mock_session.add.assert_not_called()
def test_sync_database_with_missing_fields():
"""Test sync_database with activities missing required fields"""
mock_client = Mock(spec=GarminClient)
mock_client = Mock()
mock_client.get_activities.return_value = [
{"activityId": 12345}, # Missing startTimeLocal
{"startTimeLocal": "2023-01-02T11:00:00"}, # Missing activityId
{"activityId": 67890, "startTimeLocal": "2023-01-03T12:00:00"} # Valid
{"activityId": 12345},
{"startTimeLocal": "2023-01-02T11:00:00"},
{"activityId": 67890, "startTimeLocal": "2023-01-03T12:00:00"}
]
with patch('garminsync.database.get_session') as mock_session:
mock_session.return_value.query.return_value.filter_by.return_value.first.return_value = None
# Create a mock that returns None for existing activity
mock_session = MagicMock()
mock_session.query.return_value.filter_by.return_value.first.return_value = None
with patch('garminsync.database.get_session', return_value=mock_session), \
patch('garminsync.database.get_activity_metrics', return_value={
"summaryDTO": {"duration": 3600.0}
}):
sync_database(mock_client)
# Verify only one activity was added (the valid one)
assert mock_session.return_value.add.call_count == 1
mock_session.return_value.commit.assert_called()
# Only valid activity should be added
assert mock_session.add.call_count == 1
added_activity = mock_session.add.call_args[0][0]
assert added_activity.activity_id == 67890
def test_sync_database_with_existing_activities():
"""Test sync_database doesn't duplicate existing activities"""
mock_client = Mock(spec=GarminClient)
mock_client = Mock()
mock_client.get_activities.return_value = [
{"activityId": 12345, "startTimeLocal": "2023-01-01T10:00:00"}
]
with patch('garminsync.database.get_session') as mock_session:
# Mock existing activity
mock_session.return_value.query.return_value.filter_by.return_value.first.return_value = Mock()
mock_session = MagicMock()
mock_session.query.return_value.filter_by.return_value.first.return_value = Mock()
with patch('garminsync.database.get_session', return_value=mock_session), \
patch('garminsync.database.get_activity_metrics', return_value={
"summaryDTO": {"duration": 3600.0}
}):
sync_database(mock_client)
# Verify no new activities were added
mock_session.return_value.add.assert_not_called()
mock_session.return_value.commit.assert_called()
mock_session.add.assert_not_called()
def test_sync_database_with_invalid_activity_data():
"""Test sync_database with invalid activity data types"""
mock_client = Mock(spec=GarminClient)
mock_client = Mock()
mock_client.get_activities.return_value = [
"invalid activity data", # Not a dict
None, # None value
{"activityId": 12345, "startTimeLocal": "2023-01-01T10:00:00"} # Valid
"invalid data",
None,
{"activityId": 12345, "startTimeLocal": "2023-01-01T10:00:00"}
]
with patch('garminsync.database.get_session') as mock_session:
mock_session.return_value.query.return_value.filter_by.return_value.first.return_value = None
# Create a mock that returns None for existing activity
mock_session = MagicMock()
mock_session.query.return_value.filter_by.return_value.first.return_value = None
with patch('garminsync.database.get_session', return_value=mock_session), \
patch('garminsync.database.get_activity_metrics', return_value={
"summaryDTO": {"duration": 3600.0}
}):
sync_database(mock_client)
# Verify only one activity was added (the valid one)
assert mock_session.return_value.add.call_count == 1
mock_session.return_value.commit.assert_called()
# Only valid activity should be added
assert mock_session.add.call_count == 1
added_activity = mock_session.add.call_args[0][0]
assert added_activity.activity_id == 12345