mirror of
https://github.com/sstent/go-garth.git
synced 2026-01-27 01:21:47 +00:00
working auth and activity list
This commit is contained in:
335
garth/tests/data/test_body_battery_data.py
Normal file
335
garth/tests/data/test_body_battery_data.py
Normal file
@@ -0,0 +1,335 @@
|
||||
from datetime import date
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from garth import BodyBatteryData, DailyBodyBatteryStress
|
||||
from garth.http import Client
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_body_battery_data_get(authed_client: Client):
|
||||
body_battery_data = BodyBatteryData.get("2023-07-20", client=authed_client)
|
||||
assert isinstance(body_battery_data, list)
|
||||
|
||||
if body_battery_data:
|
||||
# Check first event if available
|
||||
event = body_battery_data[0]
|
||||
assert event is not None
|
||||
|
||||
# Test body battery readings property
|
||||
readings = event.body_battery_readings
|
||||
assert isinstance(readings, list)
|
||||
|
||||
if readings:
|
||||
# Test reading structure
|
||||
reading = readings[0]
|
||||
assert hasattr(reading, "timestamp")
|
||||
assert hasattr(reading, "status")
|
||||
assert hasattr(reading, "level")
|
||||
assert hasattr(reading, "version")
|
||||
|
||||
# Test level properties
|
||||
assert event.current_level is not None and isinstance(
|
||||
event.current_level, int
|
||||
)
|
||||
assert event.max_level is not None and isinstance(
|
||||
event.max_level, int
|
||||
)
|
||||
assert event.min_level is not None and isinstance(
|
||||
event.min_level, int
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_body_battery_data_list(authed_client: Client):
|
||||
days = 3
|
||||
end = date(2023, 7, 20)
|
||||
body_battery_data = BodyBatteryData.list(end, days, client=authed_client)
|
||||
assert isinstance(body_battery_data, list)
|
||||
|
||||
# Test that we get data (may be empty if no events)
|
||||
assert len(body_battery_data) >= 0
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_daily_body_battery_stress_get(authed_client: Client):
|
||||
daily_data = DailyBodyBatteryStress.get("2023-07-20", client=authed_client)
|
||||
|
||||
if daily_data:
|
||||
# Test basic structure
|
||||
assert daily_data.user_profile_pk
|
||||
assert daily_data.calendar_date == date(2023, 7, 20)
|
||||
assert daily_data.start_timestamp_gmt
|
||||
assert daily_data.end_timestamp_gmt
|
||||
|
||||
# Test stress data
|
||||
assert isinstance(daily_data.max_stress_level, int)
|
||||
assert isinstance(daily_data.avg_stress_level, int)
|
||||
assert isinstance(daily_data.stress_values_array, list)
|
||||
assert isinstance(daily_data.body_battery_values_array, list)
|
||||
|
||||
# Test stress readings property
|
||||
stress_readings = daily_data.stress_readings
|
||||
assert isinstance(stress_readings, list)
|
||||
|
||||
if stress_readings:
|
||||
stress_reading = stress_readings[0]
|
||||
assert hasattr(stress_reading, "timestamp")
|
||||
assert hasattr(stress_reading, "stress_level")
|
||||
|
||||
# Test body battery readings property
|
||||
bb_readings = daily_data.body_battery_readings
|
||||
assert isinstance(bb_readings, list)
|
||||
|
||||
if bb_readings:
|
||||
bb_reading = bb_readings[0]
|
||||
assert hasattr(bb_reading, "timestamp")
|
||||
assert hasattr(bb_reading, "status")
|
||||
assert hasattr(bb_reading, "level")
|
||||
assert hasattr(bb_reading, "version")
|
||||
|
||||
# Test computed properties
|
||||
assert daily_data.current_body_battery is not None and isinstance(
|
||||
daily_data.current_body_battery, int
|
||||
)
|
||||
assert daily_data.max_body_battery is not None and isinstance(
|
||||
daily_data.max_body_battery, int
|
||||
)
|
||||
assert daily_data.min_body_battery is not None and isinstance(
|
||||
daily_data.min_body_battery, int
|
||||
)
|
||||
|
||||
# Test body battery change
|
||||
if len(bb_readings) >= 2:
|
||||
change = daily_data.body_battery_change
|
||||
assert change is not None
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_daily_body_battery_stress_get_no_data(authed_client: Client):
|
||||
# Test with a date that likely has no data
|
||||
daily_data = DailyBodyBatteryStress.get("2020-01-01", client=authed_client)
|
||||
# Should return None if no data available
|
||||
assert daily_data is None or isinstance(daily_data, DailyBodyBatteryStress)
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_daily_body_battery_stress_list(authed_client: Client):
|
||||
days = 3
|
||||
end = date(2023, 7, 20)
|
||||
# Use max_workers=1 to avoid VCR issues with concurrent requests
|
||||
daily_data_list = DailyBodyBatteryStress.list(
|
||||
end, days, client=authed_client, max_workers=1
|
||||
)
|
||||
assert isinstance(daily_data_list, list)
|
||||
assert (
|
||||
len(daily_data_list) <= days
|
||||
) # May be less if some days have no data
|
||||
|
||||
# Test that each item is correct type
|
||||
for daily_data in daily_data_list:
|
||||
assert isinstance(daily_data, DailyBodyBatteryStress)
|
||||
assert isinstance(daily_data.calendar_date, date)
|
||||
assert daily_data.user_profile_pk
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_body_battery_properties_edge_cases(authed_client: Client):
|
||||
# Test empty data handling
|
||||
daily_data = DailyBodyBatteryStress.get("2023-07-20", client=authed_client)
|
||||
|
||||
if daily_data:
|
||||
# Test with potentially empty arrays
|
||||
if not daily_data.body_battery_values_array:
|
||||
assert daily_data.body_battery_readings == []
|
||||
assert daily_data.current_body_battery is None
|
||||
assert daily_data.max_body_battery is None
|
||||
assert daily_data.min_body_battery is None
|
||||
assert daily_data.body_battery_change is None
|
||||
|
||||
if not daily_data.stress_values_array:
|
||||
assert daily_data.stress_readings == []
|
||||
|
||||
|
||||
# Error handling tests for BodyBatteryData.get()
|
||||
def test_body_battery_data_get_api_error():
|
||||
"""Test handling of API errors."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.side_effect = Exception("API Error")
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
assert result == []
|
||||
|
||||
|
||||
def test_body_battery_data_get_invalid_response():
|
||||
"""Test handling of non-list responses."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.return_value = {"error": "Invalid response"}
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
assert result == []
|
||||
|
||||
|
||||
def test_body_battery_data_get_missing_event_data():
|
||||
"""Test handling of items with missing event data."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.return_value = [
|
||||
{"activityName": "Test", "averageStress": 25} # Missing "event" key
|
||||
]
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
assert len(result) == 1
|
||||
assert result[0].event is None
|
||||
|
||||
|
||||
def test_body_battery_data_get_missing_event_start_time():
|
||||
"""Test handling of event data missing eventStartTimeGmt."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.return_value = [
|
||||
{
|
||||
"event": {"eventType": "sleep"}, # Missing eventStartTimeGmt
|
||||
"activityName": "Test",
|
||||
"averageStress": 25,
|
||||
}
|
||||
]
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
assert result == [] # Should skip invalid items
|
||||
|
||||
|
||||
def test_body_battery_data_get_invalid_datetime_format():
|
||||
"""Test handling of invalid datetime format."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.return_value = [
|
||||
{
|
||||
"event": {
|
||||
"eventType": "sleep",
|
||||
"eventStartTimeGmt": "invalid-date",
|
||||
},
|
||||
"activityName": "Test",
|
||||
"averageStress": 25,
|
||||
}
|
||||
]
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
assert result == [] # Should skip invalid items
|
||||
|
||||
|
||||
def test_body_battery_data_get_invalid_field_types():
|
||||
"""Test handling of invalid field types."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.return_value = [
|
||||
{
|
||||
"event": {
|
||||
"eventType": "sleep",
|
||||
"eventStartTimeGmt": "2023-07-20T10:00:00.000Z",
|
||||
"timezoneOffset": "invalid", # Should be number
|
||||
"durationInMilliseconds": "invalid", # Should be number
|
||||
"bodyBatteryImpact": "invalid", # Should be number
|
||||
},
|
||||
"activityName": "Test",
|
||||
"averageStress": "invalid", # Should be number
|
||||
"stressValuesArray": "invalid", # Should be list
|
||||
"bodyBatteryValuesArray": "invalid", # Should be list
|
||||
}
|
||||
]
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
assert len(result) == 1
|
||||
# Should handle invalid types gracefully
|
||||
|
||||
|
||||
def test_body_battery_data_get_validation_error():
|
||||
"""Test handling of validation errors during object creation."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.return_value = [
|
||||
{
|
||||
"event": {
|
||||
"eventType": "sleep",
|
||||
"eventStartTimeGmt": "2023-07-20T10:00:00.000Z",
|
||||
# Missing required fields for BodyBatteryEvent
|
||||
},
|
||||
# Missing required fields for BodyBatteryData
|
||||
}
|
||||
]
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
# Should handle validation errors and continue processing
|
||||
assert isinstance(result, list)
|
||||
assert len(result) == 1 # Should create object with missing fields as None
|
||||
assert result[0].event is not None # Event should be created
|
||||
assert result[0].activity_name is None # Missing fields should be None
|
||||
|
||||
|
||||
def test_body_battery_data_get_mixed_valid_invalid():
|
||||
"""Test processing with mix of valid and invalid items."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.return_value = [
|
||||
{
|
||||
"event": {
|
||||
"eventType": "sleep",
|
||||
"eventStartTimeGmt": "2023-07-20T10:00:00.000Z",
|
||||
"timezoneOffset": -25200000,
|
||||
"durationInMilliseconds": 28800000,
|
||||
"bodyBatteryImpact": 35,
|
||||
"feedbackType": "good_sleep",
|
||||
"shortFeedback": "Good sleep",
|
||||
},
|
||||
"activityName": None,
|
||||
"activityType": None,
|
||||
"activityId": None,
|
||||
"averageStress": 15.5,
|
||||
"stressValuesArray": [[1689811800000, 12]],
|
||||
"bodyBatteryValuesArray": [[1689811800000, "charging", 45, 1.0]],
|
||||
},
|
||||
{
|
||||
# Invalid - missing eventStartTimeGmt
|
||||
"event": {"eventType": "sleep"},
|
||||
"activityName": "Test",
|
||||
},
|
||||
]
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
# Should process valid items and skip invalid ones
|
||||
assert len(result) == 1 # Only the valid item should be processed
|
||||
assert result[0].event is not None
|
||||
|
||||
|
||||
def test_body_battery_data_get_unexpected_error():
|
||||
"""Test handling of unexpected errors during object creation."""
|
||||
mock_client = MagicMock()
|
||||
|
||||
# Create a special object that raises an exception when accessed
|
||||
class ExceptionRaisingDict(dict):
|
||||
def get(self, key, default=None):
|
||||
if key == "activityName":
|
||||
raise RuntimeError("Unexpected error during object creation")
|
||||
return super().get(key, default)
|
||||
|
||||
# Create mock data with problematic item
|
||||
mock_response_item = ExceptionRaisingDict(
|
||||
{
|
||||
"event": {
|
||||
"eventType": "sleep",
|
||||
"eventStartTimeGmt": "2023-07-20T10:00:00.000Z",
|
||||
"timezoneOffset": -25200000,
|
||||
"durationInMilliseconds": 28800000,
|
||||
"bodyBatteryImpact": 35,
|
||||
"feedbackType": "good_sleep",
|
||||
"shortFeedback": "Good sleep",
|
||||
},
|
||||
"activityName": None,
|
||||
"activityType": None,
|
||||
"activityId": None,
|
||||
"averageStress": 15.5,
|
||||
"stressValuesArray": [[1689811800000, 12]],
|
||||
"bodyBatteryValuesArray": [[1689811800000, "charging", 45, 1.0]],
|
||||
}
|
||||
)
|
||||
|
||||
mock_client.connectapi.return_value = [mock_response_item]
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
# Should handle unexpected errors and return empty list
|
||||
assert result == []
|
||||
Reference in New Issue
Block a user