done runkeeper
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
# All the functionality needed to connect to Runkeeper
|
# All the functionality needed to connect to Runkeeper
|
||||||
from rowers.imports import *
|
from rowers.imports import *
|
||||||
|
import re
|
||||||
|
|
||||||
from rowsandall_app.settings import (
|
from rowsandall_app.settings import (
|
||||||
C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET,
|
C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET,
|
||||||
@@ -225,8 +226,10 @@ def createrunkeeperworkoutdata(w):
|
|||||||
# upload
|
# upload
|
||||||
def getidfromresponse(response):
|
def getidfromresponse(response):
|
||||||
uri = response.headers["Location"]
|
uri = response.headers["Location"]
|
||||||
id = uri[len(uri)-9:]
|
|
||||||
|
tester = re.compile('^\/fitnessActivities\/(\d+)$')
|
||||||
|
id = int(tester.match(uri).group(1))
|
||||||
|
|
||||||
return int(id)
|
return int(id)
|
||||||
|
|
||||||
def geturifromid(access_token,id):
|
def geturifromid(access_token,id):
|
||||||
|
|||||||
@@ -169,11 +169,11 @@ def get_workout(user,sporttracksid):
|
|||||||
s = requests.get(url,headers=headers)
|
s = requests.get(url,headers=headers)
|
||||||
|
|
||||||
data = s.json()
|
data = s.json()
|
||||||
|
|
||||||
strokedata = pd.DataFrame.from_dict({
|
strokedata = pd.DataFrame.from_dict({
|
||||||
key: pd.Series(value) for key, value in data.items()
|
key: pd.Series(value) for key, value in data.items()
|
||||||
})
|
})
|
||||||
|
|
||||||
return data,strokedata
|
return data,strokedata
|
||||||
|
|
||||||
# Create Workout Data for upload to SportTracks
|
# Create Workout Data for upload to SportTracks
|
||||||
|
|||||||
@@ -111,7 +111,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="grid_1 alpha">
|
<div class="grid_1 alpha">
|
||||||
<a href="https://runkeeper.com/activity/{{ workout.uploadedtorunkeeper }}">
|
<a href="https://runkeeper.com/user/{{ rkuserid }}/activity/{{ workout.uploadedtorunkeeper }}">
|
||||||
<img src="/static/img/rkchecked.png" alt="Runkeeper icon" width="60" height="60"></a>
|
<img src="/static/img/rkchecked.png" alt="Runkeeper icon" width="60" height="60"></a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
1
rowers/testdata/rkstrokes.txt
vendored
Normal file
1
rowers/testdata/rkstrokes.txt
vendored
Normal file
File diff suppressed because one or more lines are too long
1
rowers/testdata/rkworkoutslist.txt
vendored
Normal file
1
rowers/testdata/rkworkoutslist.txt
vendored
Normal file
File diff suppressed because one or more lines are too long
1
rowers/testdata/sporttracksstrokedata.txt
vendored
Normal file
1
rowers/testdata/sporttracksstrokedata.txt
vendored
Normal file
File diff suppressed because one or more lines are too long
153
rowers/tests.py
153
rowers/tests.py
@@ -82,6 +82,9 @@ def mocked_requests(*args, **kwargs):
|
|||||||
|
|
||||||
stravaworkoutlist = json.load(open('rowers/testdata/stravaworkoutlist.txt'))
|
stravaworkoutlist = json.load(open('rowers/testdata/stravaworkoutlist.txt'))
|
||||||
sporttracksworkoutlist = json.load(open('rowers/testdata/sporttracksworkouts.txt'))
|
sporttracksworkoutlist = json.load(open('rowers/testdata/sporttracksworkouts.txt'))
|
||||||
|
|
||||||
|
rkworkoutlistjson = json.load(open('rowers/testdata/rkworkoutslist.txt','r'))
|
||||||
|
|
||||||
stravasummaryjson = json.load(open('rowers/testdata/stravaworkoutsummary.txt','r'))
|
stravasummaryjson = json.load(open('rowers/testdata/stravaworkoutsummary.txt','r'))
|
||||||
|
|
||||||
stravatimejson = json.load(open('rowers/testdata/stravatimetestdata.txt','r'))
|
stravatimejson = json.load(open('rowers/testdata/stravatimetestdata.txt','r'))
|
||||||
@@ -100,6 +103,10 @@ def mocked_requests(*args, **kwargs):
|
|||||||
'cadence':stravaspmjson,
|
'cadence':stravaspmjson,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ststrokesjson = json.load(open('rowers/testdata/sporttracksstrokedata.txt','r'))
|
||||||
|
|
||||||
|
rkstrokesjson = json.load(open('rowers/testdata/rkstrokes.txt','r'))
|
||||||
|
|
||||||
class MockResponse:
|
class MockResponse:
|
||||||
def __init__(self, json_data, status_code):
|
def __init__(self, json_data, status_code):
|
||||||
self.json_data = json_data
|
self.json_data = json_data
|
||||||
@@ -108,6 +115,12 @@ def mocked_requests(*args, **kwargs):
|
|||||||
def json(self):
|
def json(self):
|
||||||
return self.json_data
|
return self.json_data
|
||||||
|
|
||||||
|
|
||||||
|
class MockHeaderResponse:
|
||||||
|
def __init__(self, header_data, status_code):
|
||||||
|
self.headers = header_data
|
||||||
|
self.status_code = status_code
|
||||||
|
|
||||||
class MockSession:
|
class MockSession:
|
||||||
def send(self,prepped):
|
def send(self,prepped):
|
||||||
# prepped.url
|
# prepped.url
|
||||||
@@ -129,6 +142,7 @@ def mocked_requests(*args, **kwargs):
|
|||||||
c2tester = re.compile('.*?log\.concept2\.com')
|
c2tester = re.compile('.*?log\.concept2\.com')
|
||||||
stravatester = re.compile('.*?strava\.com')
|
stravatester = re.compile('.*?strava\.com')
|
||||||
sttester = re.compile('.*?sporttracks\.mobi')
|
sttester = re.compile('.*?sporttracks\.mobi')
|
||||||
|
rktester = re.compile('.*?runkeeper\.com')
|
||||||
|
|
||||||
c2importregex = '.*?concept2.com\/api\/users\/me\/results\/\d+'
|
c2importregex = '.*?concept2.com\/api\/users\/me\/results\/\d+'
|
||||||
c2importtester = re.compile(c2importregex)
|
c2importtester = re.compile(c2importregex)
|
||||||
@@ -156,6 +170,54 @@ def mocked_requests(*args, **kwargs):
|
|||||||
|
|
||||||
stworkoutlistregex = '.*?sporttracks\.mobi\/api\/v2\/fitnessActivities$'
|
stworkoutlistregex = '.*?sporttracks\.mobi\/api\/v2\/fitnessActivities$'
|
||||||
stworkoutlisttester = re.compile(stworkoutlistregex)
|
stworkoutlisttester = re.compile(stworkoutlistregex)
|
||||||
|
|
||||||
|
ststrokesregex = '.*?sporttracks\.mobi\/api\/v2\/fitnessActivities/\d+$'
|
||||||
|
ststrokestester = re.compile(ststrokesregex)
|
||||||
|
|
||||||
|
rkuploadregex = '.*?api\.runkeeper\.com\/fitnessActivities$'
|
||||||
|
rkuploadtester = re.compile(rkuploadregex)
|
||||||
|
rkuserregex = '.*?api\.runkeeper\.com\/user$'
|
||||||
|
rkusertester = re.compile(rkuserregex)
|
||||||
|
rkstrokesregex = '.*?api\.runkeeper\.com\/fitnessActivities/\d+$'
|
||||||
|
rkstrokestester = re.compile(rkstrokesregex)
|
||||||
|
|
||||||
|
if rktester.match(args[0]):
|
||||||
|
if 'token' in args[0]:
|
||||||
|
json_data = {
|
||||||
|
'access_token': 'TA3n1vrNjuQJWw0TdCDHnjSmrjIPULhTlejMIWqq',
|
||||||
|
'expires_in': 604800,
|
||||||
|
'refresh_token': 'jHJhFzCfOOKB8oyiayubhLAlxaMkG3ruC1E8YxaR'
|
||||||
|
}
|
||||||
|
return MockResponse(json_data,200)
|
||||||
|
if rkuploadtester.match(args[0]):
|
||||||
|
if 'data' in kwargs:
|
||||||
|
# post
|
||||||
|
header_data = {
|
||||||
|
'Location': '/fitnessActivities/12'
|
||||||
|
}
|
||||||
|
return MockHeaderResponse(header_data,200)
|
||||||
|
else:
|
||||||
|
json_data = rkworkoutlistjson
|
||||||
|
return MockResponse(json_data,200)
|
||||||
|
if rkusertester.match(args[0]):
|
||||||
|
json_data = {
|
||||||
|
"userID": 1234567890,
|
||||||
|
"profile": "/profile",
|
||||||
|
"settings": "/settings",
|
||||||
|
"fitness_activities": "/fitnessActivities",
|
||||||
|
"strength_training_activities": "/strengthTrainingActivities",
|
||||||
|
"background_activities": "/backgroundActivities",
|
||||||
|
"sleep": "/sleep",
|
||||||
|
"nutrition": "/nutrition",
|
||||||
|
"weight": "/weight",
|
||||||
|
"general_measurements": "/generalMeasurements",
|
||||||
|
"diabetes": "/diabetes",
|
||||||
|
"records": "/records",
|
||||||
|
"team": "/team"
|
||||||
|
}
|
||||||
|
return MockResponse(json_data, 200)
|
||||||
|
if rkstrokestester.match(args[0]):
|
||||||
|
return MockResponse(rkstrokesjson,200)
|
||||||
|
|
||||||
if sttester.match(args[0]):
|
if sttester.match(args[0]):
|
||||||
if 'oauth2/token' in args[0]:
|
if 'oauth2/token' in args[0]:
|
||||||
@@ -165,6 +227,8 @@ def mocked_requests(*args, **kwargs):
|
|||||||
'refresh_token': 'jHJhFzCfOOKB8oyiayubhLAlxaMkG3ruC1E8YxaR'
|
'refresh_token': 'jHJhFzCfOOKB8oyiayubhLAlxaMkG3ruC1E8YxaR'
|
||||||
}
|
}
|
||||||
return MockResponse(json_data,200)
|
return MockResponse(json_data,200)
|
||||||
|
if ststrokestester.match(args[0]):
|
||||||
|
return MockResponse(ststrokesjson,200)
|
||||||
if stuploadtester.match(args[0]):
|
if stuploadtester.match(args[0]):
|
||||||
json_data = {
|
json_data = {
|
||||||
"uris": [
|
"uris": [
|
||||||
@@ -508,6 +572,95 @@ class STObjects(DjangoTestCase):
|
|||||||
|
|
||||||
res = add_workout_from_data(self.u,1,data,data)
|
res = add_workout_from_data(self.u,1,data,data)
|
||||||
|
|
||||||
|
class RunKeeperObjects(DjangoTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.c = Client()
|
||||||
|
self.u = User.objects.create_user('john',
|
||||||
|
'sander@ds.ds',
|
||||||
|
'koeinsloot')
|
||||||
|
|
||||||
|
self.u.first_name = 'John'
|
||||||
|
self.u.last_name = 'Sander'
|
||||||
|
self.u.save()
|
||||||
|
self.r = Rower.objects.create(user=self.u,gdproptin=True,
|
||||||
|
gdproptindate=timezone.now()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
self.r.runkeepertoken = '12'
|
||||||
|
|
||||||
|
self.r.save()
|
||||||
|
|
||||||
|
self.c.login(username='john',password='koeinsloot')
|
||||||
|
|
||||||
|
self.nu = datetime.datetime.now()
|
||||||
|
|
||||||
|
filename = 'rowers/testdata/testdata.csv'
|
||||||
|
|
||||||
|
rr = rrower(hrmax=self.r.max,hrut2=self.r.ut2,
|
||||||
|
hrut1=self.r.ut1,hrat=self.r.at,
|
||||||
|
hrtr=self.r.tr,hran=self.r.an,ftp=self.r.ftp)
|
||||||
|
row = rdata(filename,rower=rr)
|
||||||
|
totaldist = row.df['cum_dist'].max()
|
||||||
|
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
|
||||||
|
totaltime = totaltime+row.df.ix[0,' ElapsedTime (sec)']
|
||||||
|
|
||||||
|
|
||||||
|
hours = int(totaltime/3600.)
|
||||||
|
minutes = int((totaltime - 3600.*hours)/60.)
|
||||||
|
seconds = int(totaltime - 3600.*hours - 60.*minutes)
|
||||||
|
tenths = int(10*(totaltime - 3600.*hours - 60.*minutes - seconds))
|
||||||
|
|
||||||
|
duration = "%s:%s:%s.%s" % (hours,minutes,seconds,tenths)
|
||||||
|
|
||||||
|
|
||||||
|
workoutdate = row.rowdatetime.strftime('%Y-%m-%d')
|
||||||
|
workoutstarttime = row.rowdatetime.strftime('%H:%M:%S')
|
||||||
|
|
||||||
|
self.w = Workout.objects.create(
|
||||||
|
name='testworkout',workouttype='On-water',
|
||||||
|
user=self.r,date=self.nu.strftime('%Y-%m-%d'),
|
||||||
|
starttime=workoutstarttime,
|
||||||
|
startdatetime=row.rowdatetime,
|
||||||
|
duration=duration,distance=totaldist,
|
||||||
|
csvfilename=filename
|
||||||
|
)
|
||||||
|
|
||||||
|
@patch('rowers.runkeeperstuff.requests.post', side_effect=mocked_requests)
|
||||||
|
def test_runkeeper_callback(self, mock_post):
|
||||||
|
response = self.c.get('/runkeeper_callback?code=dsdoij232s',follow=True)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
@patch('rowers.runkeeperstuff.requests.post', side_effect=mocked_requests)
|
||||||
|
@patch('rowers.runkeeperstuff.requests.get', side_effect=mocked_requests)
|
||||||
|
def test_runkeeper_upload(self, mock_get, mock_post):
|
||||||
|
response = self.c.get('/rowers/workout/1/runkeeperuploadw/')
|
||||||
|
|
||||||
|
self.assertRedirects(response,
|
||||||
|
expected_url = '/rowers/workout/1/export',
|
||||||
|
status_code=302,target_status_code=200)
|
||||||
|
|
||||||
|
self.assertEqual(response.url, '/rowers/workout/1/export')
|
||||||
|
self.assertEqual(response.status_code, 302)
|
||||||
|
|
||||||
|
@patch('rowers.runkeeperstuff.requests.get', side_effect=mocked_requests)
|
||||||
|
def test_runkeeper_list(self, mock_get):
|
||||||
|
response = self.c.get('/rowers/workout/runkeeperimport',follow=True)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
|
@patch('rowers.imports.requests.get', side_effect=mocked_requests)
|
||||||
|
def test_runkeeper_import(self, mock_get):
|
||||||
|
|
||||||
|
response = self.c.get('/rowers/workout/runkeeperimport/12/',follow=True)
|
||||||
|
|
||||||
|
self.assertRedirects(response,
|
||||||
|
expected_url='/rowers/workout/2/edit',
|
||||||
|
status_code=302,target_status_code=200)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
|
||||||
class TestErrorPages(TestCase):
|
class TestErrorPages(TestCase):
|
||||||
def test_error_handlers(self):
|
def test_error_handlers(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user