mirror of
https://github.com/sstent/FitTrack_GarminSync.git
synced 2026-01-26 00:51:44 +00:00
feat: Initial commit of FitTrack_GarminSync project
This commit is contained in:
114
examples/GarminSync/tests/activity_table_validation.sh
Executable file
114
examples/GarminSync/tests/activity_table_validation.sh
Executable file
@@ -0,0 +1,114 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Activity Table Validation Script
|
||||
# This script tests the activity table implementation
|
||||
|
||||
# Configuration
|
||||
API_URL="http://localhost:8888/api/api/activities" # Changed port to 8888 to match container
|
||||
TIMEOUT=10
|
||||
|
||||
# Function to display test results
|
||||
display_result() {
|
||||
local test_name=$1
|
||||
local result=$2
|
||||
local message=$3
|
||||
|
||||
if [ "$result" = "PASS" ]; then
|
||||
echo "✅ $test_name: $message"
|
||||
else
|
||||
echo "❌ $test_name: $message"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to wait for API to be ready
|
||||
wait_for_api() {
|
||||
echo "Waiting for API to start..."
|
||||
attempts=0
|
||||
max_attempts=60 # Increased timeout to 60 seconds
|
||||
|
||||
while true; do
|
||||
# Check for startup messages
|
||||
if curl -s -m 1 "http://localhost:8888" | grep -q "Uvicorn running on" || \
|
||||
curl -s -m 1 "http://localhost:8888" | grep -q "Application startup complete" || \
|
||||
curl -s -m 1 "http://localhost:8888" | grep -q "Server is ready"; then
|
||||
echo "API started successfully"
|
||||
break
|
||||
fi
|
||||
|
||||
attempts=$((attempts+1))
|
||||
if [ $attempts -ge $max_attempts ]; then
|
||||
echo "API failed to start within $max_attempts seconds"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
# Wait for API to be ready
|
||||
wait_for_api
|
||||
|
||||
# Test 1: Basic API response
|
||||
echo "Running basic API response test..."
|
||||
response=$(curl -s -m $TIMEOUT "$API_URL" | jq '.')
|
||||
if [ $? -eq 0 ]; then
|
||||
if [[ "$response" == *"activities"* ]] && [[ "$response" == *"total_pages"* ]] && [[ "$response" == *"status"* ]]; then
|
||||
display_result "Basic API Response" PASS "API returns expected structure"
|
||||
else
|
||||
display_result "Basic API Response" FAIL "API response doesn't contain expected fields"
|
||||
fi
|
||||
else
|
||||
display_result "Basic API Response" FAIL "API request failed"
|
||||
fi
|
||||
|
||||
# Test 2: Pagination test
|
||||
echo "Running pagination test..."
|
||||
page1=$(curl -s -m $TIMEOUT "$API_URL?page=1" | jq '.')
|
||||
page2=$(curl -s -m $TIMEOUT "$API_URL?page=2" | jq '.')
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
page1_count=$(echo "$page1" | jq '.activities | length')
|
||||
page2_count=$(echo "$page2" | jq '.activities | length')
|
||||
|
||||
if [ "$page1_count" -gt 0 ] && [ "$page2_count" -gt 0 ]; then
|
||||
display_result "Pagination Test" PASS "Both pages contain activities"
|
||||
else
|
||||
display_result "Pagination Test" FAIL "One or more pages are empty"
|
||||
fi
|
||||
else
|
||||
display_result "Pagination Test" FAIL "API request failed"
|
||||
fi
|
||||
|
||||
# Test 3: Data consistency test
|
||||
echo "Running data consistency test..."
|
||||
activity_id=$(echo "$page1" | jq -r '.activities[0].id')
|
||||
activity_name=$(echo "$page1" | jq -r '.activities[0].name')
|
||||
|
||||
details_response=$(curl -s -m $TIMEOUT "$API_URL/$activity_id" | jq '.')
|
||||
if [ $? -eq 0 ]; then
|
||||
details_id=$(echo "$details_response" | jq -r '.id')
|
||||
details_name=$(echo "$details_response" | jq -r '.name')
|
||||
|
||||
if [ "$activity_id" = "$details_id" ] && [ "$activity_name" = "$details_name" ]; then
|
||||
display_result "Data Consistency Test" PASS "Activity details match API response"
|
||||
else
|
||||
display_result "Data Consistency Test" FAIL "Activity details don't match API response"
|
||||
fi
|
||||
else
|
||||
display_result "Data Consistency Test" FAIL "API request failed"
|
||||
fi
|
||||
|
||||
# Test 4: Error handling test
|
||||
echo "Running error handling test..."
|
||||
error_response=$(curl -s -m $TIMEOUT "$API_URL/999999999" | jq '.')
|
||||
if [ $? -eq 0 ]; then
|
||||
if [[ "$error_response" == *"detail"* ]] && [[ "$error_response" == *"not found"* ]]; then
|
||||
display_result "Error Handling Test" PASS "API returns expected error for non-existent activity"
|
||||
else
|
||||
display_result "Error Handling Test" FAIL "API doesn't return expected error for non-existent activity"
|
||||
fi
|
||||
else
|
||||
display_result "Error Handling Test" FAIL "API request failed"
|
||||
fi
|
||||
|
||||
echo "All tests completed."
|
||||
110
examples/GarminSync/tests/test_sync.py
Normal file
110
examples/GarminSync/tests/test_sync.py
Normal file
@@ -0,0 +1,110 @@
|
||||
import pytest
|
||||
import sys
|
||||
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, Activity, get_activity_metrics
|
||||
|
||||
def test_sync_database_with_valid_activities():
|
||||
"""Test sync_database with valid API response"""
|
||||
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"}
|
||||
]
|
||||
|
||||
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 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()
|
||||
mock_client.get_activities.return_value = None
|
||||
|
||||
mock_session = MagicMock()
|
||||
|
||||
with patch('garminsync.database.get_session', return_value=mock_session):
|
||||
sync_database(mock_client)
|
||||
mock_session.add.assert_not_called()
|
||||
|
||||
def test_sync_database_with_missing_fields():
|
||||
"""Test sync_database with activities missing required fields"""
|
||||
mock_client = Mock()
|
||||
mock_client.get_activities.return_value = [
|
||||
{"activityId": 12345},
|
||||
{"startTimeLocal": "2023-01-02T11:00:00"},
|
||||
{"activityId": 67890, "startTimeLocal": "2023-01-03T12:00:00"}
|
||||
]
|
||||
|
||||
# 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)
|
||||
# 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()
|
||||
mock_client.get_activities.return_value = [
|
||||
{"activityId": 12345, "startTimeLocal": "2023-01-01T10:00:00"}
|
||||
]
|
||||
|
||||
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)
|
||||
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()
|
||||
mock_client.get_activities.return_value = [
|
||||
"invalid data",
|
||||
None,
|
||||
{"activityId": 12345, "startTimeLocal": "2023-01-01T10:00:00"}
|
||||
]
|
||||
|
||||
# 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)
|
||||
# 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
|
||||
Reference in New Issue
Block a user