mirror of
https://github.com/sstent/FitTrack_GarminSync.git
synced 2026-01-25 08:35:23 +00:00
Implement CLI app for API interaction with MFA
- Create full CLI application with authentication, sync triggering, and status checking - Implement MFA support for secure authentication - Add token management with secure local storage - Create API client for backend communication - Implement data models for User Session, Sync Job, and Authentication Token - Add command-line interface with auth and sync commands - Include unit and integration tests - Follow project constitution standards for Python 3.13, type hints, and code quality - Support multiple output formats (table, JSON, CSV)
This commit is contained in:
124
cli/tests/integration/test_auth_flow.py
Normal file
124
cli/tests/integration/test_auth_flow.py
Normal file
@@ -0,0 +1,124 @@
|
||||
import pytest
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
# Add the src directory to the path for imports
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..'))
|
||||
|
||||
from src.auth.auth_manager import AuthManager
|
||||
from src.api.client import ApiClient
|
||||
from src.auth.token_manager import TokenManager
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch('src.api.client.httpx.AsyncClient')
|
||||
async def test_auth_flow_integration(mock_http_client):
|
||||
"""Integration test for complete authentication flow"""
|
||||
# Mock the HTTP client response
|
||||
mock_response = AsyncMock()
|
||||
mock_response.json.return_value = {
|
||||
"success": True,
|
||||
"session_id": "session123",
|
||||
"access_token": "token123",
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 3600,
|
||||
"user": {"id": "user123", "email": "test@example.com"}
|
||||
}
|
||||
mock_response.raise_for_status = MagicMock()
|
||||
|
||||
# Setup the mock client
|
||||
mock_http_client.return_value = mock_response
|
||||
mock_http_client.return_value.post.return_value = mock_response
|
||||
|
||||
# Create real instances (not mocks) for integration test
|
||||
api_client = ApiClient(base_url="https://test-api.garmin.com")
|
||||
token_manager = TokenManager()
|
||||
|
||||
# Mock the token manager methods to avoid file I/O
|
||||
token_manager.save_token = MagicMock()
|
||||
token_manager.load_token = MagicMock()
|
||||
token_manager.clear_token = MagicMock()
|
||||
token_manager.token_exists = MagicMock(return_value=False)
|
||||
|
||||
auth_manager = AuthManager(api_client, token_manager)
|
||||
|
||||
# Perform authentication
|
||||
session = await auth_manager.authenticate("test@example.com", "password123", "123456")
|
||||
|
||||
# Verify the session was created
|
||||
assert session is not None
|
||||
assert session.user_id == "user123"
|
||||
assert session.session_id == "session123"
|
||||
|
||||
# Verify token was saved
|
||||
token_manager.save_token.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch('src.api.client.httpx.AsyncClient')
|
||||
async def test_auth_logout_integration(mock_http_client):
|
||||
"""Integration test for authentication and logout flow"""
|
||||
# Mock successful auth response
|
||||
auth_response = AsyncMock()
|
||||
auth_response.json.return_value = {
|
||||
"success": True,
|
||||
"session_id": "session123",
|
||||
"access_token": "token123",
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 3600,
|
||||
"user": {"id": "user123", "email": "test@example.com"}
|
||||
}
|
||||
auth_response.raise_for_status = MagicMock()
|
||||
|
||||
# Mock successful logout response (if there was a logout API call)
|
||||
logout_response = AsyncMock()
|
||||
logout_response.json.return_value = {"success": True}
|
||||
logout_response.raise_for_status = MagicMock()
|
||||
|
||||
# Setup client mock
|
||||
mock_http_client.return_value.post.return_value = auth_response
|
||||
|
||||
# Create real instances with mocked file operations
|
||||
api_client = ApiClient(base_url="https://test-api.garmin.com")
|
||||
token_manager = TokenManager()
|
||||
|
||||
# Mock token manager methods
|
||||
token_manager.save_token = MagicMock()
|
||||
token_manager.load_token = MagicMock()
|
||||
token_manager.clear_token = MagicMock(return_value=True)
|
||||
token_manager.token_exists = MagicMock(return_value=True)
|
||||
|
||||
auth_manager = AuthManager(api_client, token_manager)
|
||||
|
||||
# Authenticate first
|
||||
session = await auth_manager.authenticate("test@example.com", "password123")
|
||||
assert session is not None
|
||||
|
||||
# Verify token was saved during auth
|
||||
token_manager.save_token.assert_called_once()
|
||||
|
||||
# Now logout
|
||||
logout_success = await auth_manager.logout()
|
||||
assert logout_success is True
|
||||
|
||||
# Verify token was cleared
|
||||
token_manager.clear_token.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_auth_status_check():
|
||||
"""Integration test for authentication status check"""
|
||||
# Create real instances with mocked file operations
|
||||
api_client = ApiClient(base_url="https://test-api.garmin.com")
|
||||
token_manager = TokenManager()
|
||||
|
||||
# Mock token manager methods
|
||||
token_manager.token_exists = MagicMock(return_value=True)
|
||||
|
||||
auth_manager = AuthManager(api_client, token_manager)
|
||||
|
||||
# Check if authenticated (should return True based on mock)
|
||||
is_auth = await auth_manager.is_authenticated()
|
||||
assert is_auth is True
|
||||
Reference in New Issue
Block a user