init V
This commit is contained in:
248
garmin-connect-export/gcexport_test.py
Normal file
248
garmin-connect-export/gcexport_test.py
Normal file
@@ -0,0 +1,248 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Tests for gcexport.py; Call them with this command line:
|
||||
|
||||
py.test gcexport_test.py
|
||||
"""
|
||||
|
||||
from gcexport import *
|
||||
from io import StringIO
|
||||
|
||||
|
||||
def test_pace_or_speed_raw_cycling():
|
||||
# 10 m/s is 36 km/h
|
||||
assert pace_or_speed_raw(2, 4, 10.0) == 36.0
|
||||
|
||||
|
||||
def test_pace_or_speed_raw_running():
|
||||
# 3.33 m/s is 12 km/h is 5 min/km
|
||||
assert pace_or_speed_raw(1, 4, 10.0 / 3) == 5.0
|
||||
|
||||
|
||||
def test_pace_or_speed_formatted_cycling():
|
||||
# 10 m/s is 36 km/h
|
||||
assert pace_or_speed_formatted(2, 4, 10.0) == '36.0'
|
||||
|
||||
|
||||
def test_pace_or_speed_formatted_running():
|
||||
# 3.33 m/s is 12 km/h is 5 min/km
|
||||
assert pace_or_speed_formatted(1, 4, 10.0 / 3) == '05:00'
|
||||
|
||||
|
||||
def test_trunc6_more():
|
||||
assert trunc6(0.123456789) == '0.123456'
|
||||
|
||||
|
||||
def test_trunc6_less():
|
||||
assert trunc6(0.123) == '0.123000'
|
||||
|
||||
|
||||
def test_offset_date_time():
|
||||
assert offset_date_time("2018-03-08 12:23:22", "2018-03-08 11:23:22") == datetime(
|
||||
2018, 3, 8, 12, 23, 22, 0, FixedOffset(60, "LCL")
|
||||
)
|
||||
assert offset_date_time("2018-03-08 12:23:22", "2018-03-08 12:23:22") == datetime(
|
||||
2018, 3, 8, 12, 23, 22, 0, FixedOffset(0, "LCL")
|
||||
)
|
||||
|
||||
|
||||
def test_datetime_from_iso():
|
||||
assert datetime_from_iso("2018-03-08 12:23:22") == datetime(2018, 3, 8, 12, 23, 22, 0)
|
||||
assert datetime_from_iso("2018-03-08 12:23:22.0") == datetime(2018, 3, 8, 12, 23, 22, 0)
|
||||
assert datetime_from_iso("2018-03-08T12:23:22") == datetime(2018, 3, 8, 12, 23, 22, 0)
|
||||
assert datetime_from_iso("2018-03-08T12:23:22.0") == datetime(2018, 3, 8, 12, 23, 22, 0)
|
||||
|
||||
|
||||
def test_epoch_seconds_from_summary():
|
||||
# activity with a beginTimestamp
|
||||
with open('json/activity_2541953812_overview.json') as json_timestamp:
|
||||
summary = json.load(json_timestamp)
|
||||
assert summary['beginTimestamp'] == 1520508202000
|
||||
assert epoch_seconds_from_summary(summary) == 1520508202
|
||||
|
||||
# activity with a startTimeLocal without fractions
|
||||
with open('json/activity_multisport_overview.json') as json_timestamp:
|
||||
summary = json.load(json_timestamp)
|
||||
assert summary['beginTimestamp'] == None
|
||||
assert summary['startTimeLocal'] == '2021-04-11 11:50:49'
|
||||
assert epoch_seconds_from_summary(summary) == 1618134649
|
||||
|
||||
# activity with a startTimeLocal with fractions
|
||||
summary['startTimeLocal'] = '2021-04-11 11:50:50.3'
|
||||
assert epoch_seconds_from_summary(summary) == 1618134650
|
||||
|
||||
|
||||
def test_hhmmss_from_seconds():
|
||||
# check/document that no rounding happens in hhmmss_from_seconds and the caller must round itself:
|
||||
# 2969.6 s are 49 minutes and 29.6 seconds
|
||||
assert hhmmss_from_seconds(2969.6) == "00:49:29"
|
||||
assert hhmmss_from_seconds(round(2969.6)) == "00:49:30"
|
||||
|
||||
|
||||
def test_sanitize_filename():
|
||||
assert 'all_ascii' == sanitize_filename(u'all_ascii')
|
||||
assert 'deja_funf' == sanitize_filename(u'déjà fünf')
|
||||
assert 'deja_' == sanitize_filename(u'déjà fünf', 5)
|
||||
assert '' == sanitize_filename(u'')
|
||||
assert '' == sanitize_filename(None)
|
||||
|
||||
with open('json/activity_emoji.json') as json_data:
|
||||
details = json.load(json_data)
|
||||
assert 'Biel__Pavillon' == sanitize_filename(details['activityName'])
|
||||
|
||||
|
||||
def test_load_properties_keys():
|
||||
with open('csv_header_default.properties', 'r') as prop:
|
||||
csv_header_props = prop.read()
|
||||
csv_columns = []
|
||||
csv_headers = load_properties(csv_header_props, keys=csv_columns)
|
||||
|
||||
assert csv_columns[0] == 'startTimeIso'
|
||||
assert csv_headers['startTimeIso'] == "Start Time"
|
||||
|
||||
|
||||
def test_csv_write_record():
|
||||
with open('json/activitylist-service.json') as json_data_1:
|
||||
activities = json.load(json_data_1)
|
||||
with open('json/activity_emoji.json') as json_data_2:
|
||||
details = json.load(json_data_2)
|
||||
with open('json/activity_types.properties', 'r') as prop_1:
|
||||
activity_type_props = prop_1.read()
|
||||
activity_type_name = load_properties(activity_type_props)
|
||||
with open('json/event_types.properties', 'r') as prop_2:
|
||||
event_type_props = prop_2.read()
|
||||
event_type_name = load_properties(event_type_props)
|
||||
|
||||
extract = {}
|
||||
extract['start_time_with_offset'] = offset_date_time("2018-03-08 12:23:22", "2018-03-08 11:23:22")
|
||||
extract['end_time_with_offset'] = offset_date_time("2018-03-08 12:23:22", "2018-03-08 12:23:22")
|
||||
extract['elapsed_duration'] = 42.43
|
||||
extract['elapsed_seconds'] = 42
|
||||
extract['samples'] = None
|
||||
extract['device'] = "some device"
|
||||
extract['gear'] = "some gear"
|
||||
extract['hrZones'] = HR_ZONES_EMPTY
|
||||
extract['hrZones'][1] = json.loads('{ "secsInZone": 1689.269, "zoneLowBoundary": 138 }')
|
||||
|
||||
csv_file = StringIO()
|
||||
csv_filter = CsvFilter(csv_file, 'csv_header_all.properties')
|
||||
csv_write_record(csv_filter, extract, activities[0], details, activity_type_name, event_type_name)
|
||||
expected = '"Biel 🏛 Pavillon"'
|
||||
assert csv_file.getvalue()[69 : 69 + len(expected)] == expected
|
||||
|
||||
|
||||
def write_to_file_mock(filename, content, mode, file_time=None):
|
||||
pass
|
||||
|
||||
|
||||
def http_req_mock_device(url, post=None, headers=None):
|
||||
with open('json/device_856399.json') as json_device:
|
||||
return json_device.read()
|
||||
|
||||
|
||||
def test_extract_device():
|
||||
args = parse_arguments([])
|
||||
|
||||
with open('json/activity_2541953812.json') as json_detail:
|
||||
details = json.load(json_detail)
|
||||
assert u'fēnix 5 10.0.0.0' == extract_device({}, details, None, args, http_req_mock_device, write_to_file_mock)
|
||||
|
||||
with open('json/activity_154105348_gpx_device_null.json') as json_detail:
|
||||
details = json.load(json_detail)
|
||||
assert None == extract_device({}, details, None, args, http_req_mock_device, write_to_file_mock)
|
||||
|
||||
with open('json/activity_995784118_gpx_device_0.json') as json_detail:
|
||||
details = json.load(json_detail)
|
||||
assert None == extract_device({}, details, None, args, http_req_mock_device, write_to_file_mock)
|
||||
|
||||
|
||||
def http_req_mock_zones(url, post=None, headers=None):
|
||||
with open('json/activity_2541953812_zones.json') as json_zones:
|
||||
return json_zones.read()
|
||||
|
||||
|
||||
def test_load_zones():
|
||||
args = parse_arguments([])
|
||||
|
||||
zones = load_zones('2541953812', None, args, http_req_mock_zones, write_to_file_mock)
|
||||
assert 5 == len(zones)
|
||||
assert 100 == zones[0]['zoneLowBoundary']
|
||||
assert 138 == zones[1]['zoneLowBoundary']
|
||||
assert 148 == zones[2]['zoneLowBoundary']
|
||||
assert 168 == zones[3]['zoneLowBoundary']
|
||||
assert 182 == zones[4]['zoneLowBoundary']
|
||||
assert 2462.848 == zones[0]['secsInZone']
|
||||
|
||||
|
||||
def test_extract_display_name():
|
||||
with open('html/profile_simple.html') as html:
|
||||
profile_page = html.read()
|
||||
assert 'John.Doe' == extract_display_name(profile_page)
|
||||
|
||||
# some users reported (issue #65) to have an email address as display name
|
||||
with open('html/profile_email.html') as html:
|
||||
profile_page = html.read()
|
||||
assert 'john.doe@email.org' == extract_display_name(profile_page)
|
||||
|
||||
# some users reported to have a UUID as display name:
|
||||
# https://github.com/moderation/garmin-connect-export/issues/31
|
||||
with open('html/profile_uuid.html') as html:
|
||||
profile_page = html.read()
|
||||
assert '36e29d65-715c-456b-9115-84f0b9a0c0ba' == extract_display_name(profile_page)
|
||||
|
||||
|
||||
def test_resolve_path():
|
||||
assert resolve_path('root', 'sub/{YYYY}', '2018-03-08 12:23:22') == 'root/sub/2018'
|
||||
assert resolve_path('root', 'sub/{MM}', '2018-03-08 12:23:22') == 'root/sub/03'
|
||||
assert resolve_path('root', 'sub/{YYYY}/{MM}', '2018-03-08 12:23:22') == 'root/sub/2018/03'
|
||||
assert resolve_path('root', 'sub/{yyyy}', '2018-03-08 12:23:22') == 'root/sub/{yyyy}'
|
||||
assert resolve_path('root', 'sub/{YYYYMM}', '2018-03-08 12:23:22') == 'root/sub/{YYYYMM}'
|
||||
assert resolve_path('root', 'sub/all', '2018-03-08 12:23:22') == 'root/sub/all'
|
||||
|
||||
|
||||
mock_details_multi_counter = 0
|
||||
|
||||
|
||||
def http_req_mock_details_multi(url, post=None, headers=None):
|
||||
|
||||
global mock_details_multi_counter
|
||||
mock_details_multi_counter += 1
|
||||
|
||||
if mock_details_multi_counter == 1:
|
||||
with open('json/activity_multisport_detail.json') as json_stream:
|
||||
return json_stream.read()
|
||||
elif mock_details_multi_counter >= 2 & mock_details_multi_counter <= 6:
|
||||
with open('json/activity_multisport_child.json') as json_stream:
|
||||
json_string = json_stream.read()
|
||||
activity_id = url.split('/')[-1]
|
||||
return json_string.replace('6588349076', activity_id)
|
||||
else:
|
||||
raise Exception('mock_details_multi_counter has invalid value ' + str(mock_details_multi_counter))
|
||||
|
||||
|
||||
def test_fetch_multisports():
|
||||
args = parse_arguments([])
|
||||
|
||||
with open('json/activities-list.json') as json_detail:
|
||||
activity_summaries = json.load(json_detail)
|
||||
|
||||
# assert state before fetch_multisports
|
||||
assert activity_summaries[0]['activityId'] == 6609987243
|
||||
assert activity_summaries[1]['activityId'] == 6588349056
|
||||
assert activity_summaries[2]['activityId'] == 6585943400
|
||||
|
||||
global mock_details_multi_counter
|
||||
mock_details_multi_counter = 0
|
||||
fetch_multisports(activity_summaries, http_req_mock_details_multi, args)
|
||||
|
||||
# the entries 0/1/2 from before are now 0/1/7
|
||||
assert activity_summaries[0]['activityId'] == 6609987243
|
||||
assert activity_summaries[1]['activityId'] == 6588349056
|
||||
assert activity_summaries[7]['activityId'] == 6585943400
|
||||
|
||||
# at indexes 2..6 are now the five child activities
|
||||
assert activity_summaries[2]['activityId'] == 6588349067
|
||||
assert activity_summaries[3]['activityId'] == 6588349072
|
||||
assert activity_summaries[4]['activityId'] == 6588349076
|
||||
assert activity_summaries[5]['activityId'] == 6588349079
|
||||
assert activity_summaries[6]['activityId'] == 6588349081
|
||||
Reference in New Issue
Block a user