feat: implement Fitbit OAuth, Garmin MFA, and optimize segment discovery

- Add Fitbit authentication flow (save credentials, OAuth callback handling)
- Implement Garmin MFA support with successful session/cookie handling
- Optimize segment discovery with new sampling and activity query services
- Refactor database session management in discovery API for better testability
- Enhance activity data parsing for charts and analysis
- Update tests to use testcontainers and proper dependency injection
- Clean up repository by ignoring and removing tracked transient files (.pyc, .db)
This commit is contained in:
2026-01-16 15:35:26 -08:00
parent 45dbc32295
commit d1cfd0fd8e
217 changed files with 1795 additions and 922 deletions

View File

@@ -0,0 +1,42 @@
import pytest
from unittest.mock import MagicMock
from sqlalchemy import func
from datetime import datetime, timezone
from src.models.activity import Activity
from src.models.segment import Segment
@pytest.fixture
def mock_db_session():
return MagicMock()
def test_optimization_logic(mock_db_session):
# Setup test data object
activity = MagicMock(spec=Activity)
activity.id = 256
activity.last_segment_scan_timestamp = None
# 1. Reset
# Logic in original script: manually reset timestamp.
# Here we test the optimization logic steps.
# Scene 1: last_scan is None. Logic should PROCEED.
last_scan = activity.last_segment_scan_timestamp
assert last_scan is None
# If the logic in Job Manager checks `if last_scan >= max_seg_date`, it returns False (Don't skip).
# Scene 2: last_scan exists and new Segments exist.
max_seg_date_mock = datetime(2023, 1, 2, 12, 0, 0, tzinfo=timezone.utc)
mock_db_session.query.return_value.scalar.return_value = max_seg_date_mock
# Set activity last scan to OLDER
activity.last_segment_scan_timestamp = datetime(2023, 1, 1, 12, 0, 0, tzinfo=timezone.utc)
# Check Logic
should_skip = (activity.last_segment_scan_timestamp >= max_seg_date_mock)
assert should_skip is False
# Scene 3: last_scan is NEWER
activity.last_segment_scan_timestamp = datetime(2023, 1, 3, 12, 0, 0, tzinfo=timezone.utc)
should_skip = (activity.last_segment_scan_timestamp >= max_seg_date_mock)
assert should_skip is True