diff --git a/README.md b/README.md
index a969989b..970cfe3b 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
[![Flask Version](https://img.shields.io/badge/flask-1.0-brightgreen.svg)](http://flask.pocoo.org/)
[![React Version](https://img.shields.io/badge/react-16.3-brightgreen.svg)](https://reactjs.org/)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/45d64b31e37e4890a239b8298e66a011)](https://www.codacy.com/app/SamR1/mpwo?utm_source=github.com&utm_medium=referral&utm_content=SamR1/mpwo&utm_campaign=badger)
-[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/45d64b31e37e4890a239b8298e66a011)](https://www.codacy.com/app/SamR1/mpwo?utm_source=github.com&utm_medium=referral&utm_content=SamR1/mpwo&utm_campaign=Badge_Coverage)1
+[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/45d64b31e37e4890a239b8298e66a011)](https://www.codacy.com/app/SamR1/mpwo?utm_source=github.com&utm_medium=referral&utm_content=SamR1/mpwo&utm_campaign=Badge_Coverage)1
[![Build Status](https://travis-ci.org/SamR1/mpwo.svg?branch=master)](https://travis-ci.org/SamR1/mpwo)
Self hosted workout/activity tracker written with Flask and React (_work in progress_).
diff --git a/mpwo_api/mpwo_api/activities/activities.py b/mpwo_api/mpwo_api/activities/activities.py
index c22a707f..2e40021c 100644
--- a/mpwo_api/mpwo_api/activities/activities.py
+++ b/mpwo_api/mpwo_api/activities/activities.py
@@ -122,7 +122,7 @@ def get_activity_gpx(auth_user_id, activity_id):
@activities_blueprint.route('/activities', methods=['POST'])
@authenticate
def post_activity(auth_user_id):
- """Post an activity"""
+ """Post an activity (with gpx file)"""
response_object = verify_extension('activity', request)
if response_object['status'] != 'success':
return jsonify(response_object), 400
@@ -142,6 +142,13 @@ def post_activity(auth_user_id):
activity_file.save(file_path)
gpx_data = get_gpx_info(file_path)
+ if gpx_data is None:
+ response_object = {
+ 'status': 'error',
+ 'message': 'Error during gpx file parsing.'
+ }
+ return jsonify(response_object), 500
+
sport = Sport.query.filter_by(id=activity_data.get('sport_id')).first()
new_filepath = get_new_file_path(
auth_user_id=auth_user_id,
diff --git a/mpwo_api/mpwo_api/activities/utils.py b/mpwo_api/mpwo_api/activities/utils.py
index 984c5c4d..f9a06de1 100644
--- a/mpwo_api/mpwo_api/activities/utils.py
+++ b/mpwo_api/mpwo_api/activities/utils.py
@@ -116,7 +116,8 @@ def get_gpx_info(gpx_file):
gpx_data = {
'name': gpx.tracks[0].name,
- 'segments': []}
+ 'segments': []
+ }
max_speed = 0
start = 0
diff --git a/mpwo_api/mpwo_api/tests/test_activities_api_1_post.py b/mpwo_api/mpwo_api/tests/test_activities_api_1_post.py
index 4fb69a3c..2e8e6e1f 100644
--- a/mpwo_api/mpwo_api/tests/test_activities_api_1_post.py
+++ b/mpwo_api/mpwo_api/tests/test_activities_api_1_post.py
@@ -8,7 +8,6 @@ def assert_activity_data_with_gpx(data):
assert 1 == data['data']['activities'][0]['user_id']
assert 1 == data['data']['activities'][0]['sport_id']
assert '0:04:10' == data['data']['activities'][0]['duration']
- assert 'just an activity' == data['data']['activities'][0]['title']
assert data['data']['activities'][0]['ascent'] == 0.4
assert data['data']['activities'][0]['ave_speed'] == 4.6
assert data['data']['activities'][0]['descent'] == 23.4
@@ -66,11 +65,13 @@ def test_add_an_activity_gpx(app, user_1, sport_1_cycling, gpx_file):
data = json.loads(response.data.decode())
assert response.status_code == 201
+ assert 'created' in data['status']
assert len(data['data']['activities']) == 1
+ assert 'just an activity' == data['data']['activities'][0]['title']
assert_activity_data_with_gpx(data)
-def test_get_an_activity_with_gpx(app, user_1, sport_1_cycling, gpx_file):
+def test_add_an_activity_with_gpx(app, user_1, sport_1_cycling, gpx_file):
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@@ -106,10 +107,78 @@ def test_get_an_activity_with_gpx(app, user_1, sport_1_cycling, gpx_file):
assert response.status_code == 200
assert 'success' in data['status']
assert len(data['data']['activities']) == 1
+ assert 'just an activity' == data['data']['activities'][0]['title']
assert_activity_data_with_gpx(data)
-def test_add_an_activity_gpx_invalid_file(
+def test_add_an_activity_with_gpx_without_name(
+ app, user_1, sport_1_cycling, gpx_file_wo_name
+):
+ client = app.test_client()
+ resp_login = client.post(
+ '/api/auth/login',
+ data=json.dumps(dict(
+ email='test@test.com',
+ password='12345678'
+ )),
+ content_type='application/json'
+ )
+ response = client.post(
+ '/api/activities',
+ data=dict(
+ file=(BytesIO(str.encode(gpx_file_wo_name)), 'example.gpx'),
+ data='{"sport_id": 1}'
+ ),
+ headers=dict(
+ content_type='multipart/form-data',
+ Authorization='Bearer ' + json.loads(
+ resp_login.data.decode()
+ )['auth_token']
+ )
+ )
+ data = json.loads(response.data.decode())
+
+ assert response.status_code == 201
+ assert 'created' in data['status']
+ assert len(data['data']['activities']) == 1
+ assert 'Cycling - 2018-03-13 12:44:45' == data['data']['activities'][0]['title'] # noqa
+ assert_activity_data_with_gpx(data)
+
+
+def test_add_an_activity_with_gpx_invalid_file(
+ app, user_1, sport_1_cycling, gpx_file_wo_track
+):
+ client = app.test_client()
+ resp_login = client.post(
+ '/api/auth/login',
+ data=json.dumps(dict(
+ email='test@test.com',
+ password='12345678'
+ )),
+ content_type='application/json'
+ )
+ response = client.post(
+ '/api/activities',
+ data=dict(
+ file=(BytesIO(str.encode(gpx_file_wo_track)), 'example.gpx'),
+ data='{"sport_id": 1}'
+ ),
+ headers=dict(
+ content_type='multipart/form-data',
+ Authorization='Bearer ' + json.loads(
+ resp_login.data.decode()
+ )['auth_token']
+ )
+ )
+ data = json.loads(response.data.decode())
+
+ assert response.status_code == 500
+ assert 'error' in data['status']
+ assert 'Error during gpx file parsing.' in data['message']
+ assert 'data' not in data
+
+
+def test_add_an_activity_gpx_invalid_extension(
app, user_1, sport_1_cycling, gpx_file
):
client = app.test_client()