From fa4a094cf306b4362174676206d15745916b3e4e Mon Sep 17 00:00:00 2001 From: Sam Date: Wed, 6 Jun 2018 12:09:09 +0200 Subject: [PATCH] API: statistics by time or sport - #9 --- mpwo_api/mpwo_api/activities/stats.py | 111 ++- mpwo_api/mpwo_api/tests/conftest.py | 44 +- mpwo_api/mpwo_api/tests/test_stats_api.py | 895 +++++++++++++++++++--- 3 files changed, 922 insertions(+), 128 deletions(-) diff --git a/mpwo_api/mpwo_api/activities/stats.py b/mpwo_api/mpwo_api/activities/stats.py index f0a6055f..5c0f9920 100644 --- a/mpwo_api/mpwo_api/activities/stats.py +++ b/mpwo_api/mpwo_api/activities/stats.py @@ -5,20 +5,20 @@ from mpwo_api import appLog from ..users.models import User from ..users.utils import authenticate -from .models import Activity, convert_timedelta_to_integer +from .models import Activity, Sport, convert_timedelta_to_integer stats_blueprint = Blueprint('stats', __name__) -@stats_blueprint.route('/stats//by_week', methods=['GET']) +@stats_blueprint.route('/stats//by_time', methods=['GET']) @authenticate -def get_activities(auth_user_id, user_id): +def get_activities_by_time(auth_user_id, user_id): """Get activities statistics for a user""" try: user = User.query.filter_by(id=user_id).first() if not user: response_object = { - 'status': 'fail', + 'status': 'not found', 'message': 'User does not exist.' } return jsonify(response_object), 404 @@ -26,6 +26,7 @@ def get_activities(auth_user_id, user_id): params = request.args.copy() date_from = params.get('from') date_to = params.get('to') + time = params.get('time') activities_list = {} activities = Activity.query.filter( @@ -39,20 +40,104 @@ def get_activities(auth_user_id, user_id): ).all() for activity in activities: - week = f'W{datetime.strftime(activity.activity_date, "%U")}' # noqa - sport = activity.sports.label - if week not in activities_list: - activities_list[week] = {} - if sport not in activities_list[week]: - activities_list[week][sport] = { + if time == 'week': + time_period = datetime.strftime(activity.activity_date, "%Y-W%U") # noqa + elif time == 'weekm': # week start Monday + time_period = datetime.strftime(activity.activity_date, "%Y-W%W") # noqa + elif time == 'month': + time_period = datetime.strftime(activity.activity_date, "%Y-%m") # noqa + elif time == 'year' or not time: + time_period = datetime.strftime(activity.activity_date, "%Y") + else: + response_object = { + 'status': 'fail', + 'message': 'Invalid time period.' + } + return jsonify(response_object), 400 + sport_id = activity.sport_id + if time_period not in activities_list: + activities_list[time_period] = {} + if sport_id not in activities_list[time_period]: + activities_list[time_period][sport_id] = { 'nb_activities': 0, 'total_distance': 0., 'total_duration': 0, } - activities_list[week][sport]['nb_activities'] += 1 - activities_list[week][sport]['total_distance'] += \ + activities_list[time_period][sport_id]['nb_activities'] += 1 + activities_list[time_period][sport_id]['total_distance'] += \ float(activity.distance) - activities_list[week][sport]['total_duration'] += \ + activities_list[time_period][sport_id]['total_duration'] += \ + convert_timedelta_to_integer(activity.duration) + + response_object = { + 'status': 'success', + 'data': { + 'statistics': activities_list + } + } + code = 200 + except Exception as e: + appLog.error(e) + response_object = { + 'status': 'error', + 'message': 'Error. Please try again or contact the administrator.' + } + code = 500 + return jsonify(response_object), code + + +@stats_blueprint.route('/stats//by_sport', methods=['GET']) +@authenticate +def get_activities_by_sport(auth_user_id, user_id): + """Get activities statistics for a user""" + try: + user = User.query.filter_by(id=user_id).first() + if not user: + response_object = { + 'status': 'not found', + 'message': 'User does not exist.' + } + return jsonify(response_object), 404 + + params = request.args.copy() + date_from = params.get('from') + date_to = params.get('to') + + sport_id = params.get('sport_id') + if sport_id: + sport = Sport.query.filter_by(id=sport_id).first() + if not sport: + print('not sport') + response_object = { + 'status': 'not found', + 'message': 'Sport does not exist.' + } + return jsonify(response_object), 404 + + activities = Activity.query.filter( + Activity.user_id == user_id, + Activity.activity_date >= datetime.strptime(date_from, '%Y-%m-%d') + if date_from else True, + Activity.activity_date <= datetime.strptime(date_to, '%Y-%m-%d') + if date_to else True, + Activity.sport_id == sport_id if sport_id else True, + ).order_by( + Activity.activity_date.asc() + ).all() + + activities_list = {} + for activity in activities: + sport_id = activity.sport_id + if sport_id not in activities_list: + activities_list[sport_id] = { + 'nb_activities': 0, + 'total_distance': 0., + 'total_duration': 0, + } + activities_list[sport_id]['nb_activities'] += 1 + activities_list[sport_id]['total_distance'] += \ + float(activity.distance) + activities_list[sport_id]['total_duration'] += \ convert_timedelta_to_integer(activity.duration) response_object = { diff --git a/mpwo_api/mpwo_api/tests/conftest.py b/mpwo_api/mpwo_api/tests/conftest.py index c3a6516e..44c50e67 100644 --- a/mpwo_api/mpwo_api/tests/conftest.py +++ b/mpwo_api/mpwo_api/tests/conftest.py @@ -125,24 +125,6 @@ def activity_running_user_1(): @pytest.fixture() def seven_activities_user_1(): - activity = Activity( - user_id=1, - sport_id=1, - activity_date=datetime.datetime.strptime('01/01/2018', '%d/%m/%Y'), - distance=10, - duration=datetime.timedelta(seconds=1024) - ) - db.session.add(activity) - db.session.flush() - activity = Activity( - user_id=1, - sport_id=1, - activity_date=datetime.datetime.strptime('01/04/2018', '%d/%m/%Y'), - distance=8, - duration=datetime.timedelta(seconds=6000) - ) - db.session.add(activity) - db.session.flush() activity = Activity( user_id=1, sport_id=1, @@ -155,18 +137,18 @@ def seven_activities_user_1(): activity = Activity( user_id=1, sport_id=1, - activity_date=datetime.datetime.strptime('09/05/2018', '%d/%m/%Y'), + activity_date=datetime.datetime.strptime('01/06/2017', '%d/%m/%Y'), distance=10, - duration=datetime.timedelta(seconds=3000) + duration=datetime.timedelta(seconds=3456) ) db.session.add(activity) db.session.flush() activity = Activity( user_id=1, sport_id=1, - activity_date=datetime.datetime.strptime('01/06/2017', '%d/%m/%Y'), + activity_date=datetime.datetime.strptime('01/01/2018', '%d/%m/%Y'), distance=10, - duration=datetime.timedelta(seconds=3456) + duration=datetime.timedelta(seconds=1024) ) db.session.add(activity) db.session.flush() @@ -187,6 +169,24 @@ def seven_activities_user_1(): duration=datetime.timedelta(seconds=1000) ) db.session.add(activity) + db.session.flush() + activity = Activity( + user_id=1, + sport_id=1, + activity_date=datetime.datetime.strptime('01/04/2018', '%d/%m/%Y'), + distance=8, + duration=datetime.timedelta(seconds=6000) + ) + db.session.add(activity) + db.session.flush() + activity = Activity( + user_id=1, + sport_id=1, + activity_date=datetime.datetime.strptime('09/05/2018', '%d/%m/%Y'), + distance=10, + duration=datetime.timedelta(seconds=3000) + ) + db.session.add(activity) db.session.commit() return activity diff --git a/mpwo_api/mpwo_api/tests/test_stats_api.py b/mpwo_api/mpwo_api/tests/test_stats_api.py index c1eab336..c0e2f4bf 100644 --- a/mpwo_api/mpwo_api/tests/test_stats_api.py +++ b/mpwo_api/mpwo_api/tests/test_stats_api.py @@ -1,7 +1,7 @@ import json -def test_get_stats_no_activities(app, user_1): +def test_get_stats_by_time_no_activities(app, user_1): client = app.test_client() resp_login = client.post( '/api/auth/login', @@ -12,7 +12,7 @@ def test_get_stats_no_activities(app, user_1): content_type='application/json' ) response = client.get( - f'/api/stats/{user_1.id}/by_week', + f'/api/stats/{user_1.id}/by_time', headers=dict( Authorization='Bearer ' + json.loads( resp_login.data.decode() @@ -26,7 +26,7 @@ def test_get_stats_no_activities(app, user_1): assert data['data']['statistics'] == {} -def test_get_stats_no_user(app, user_1): +def test_get_stats_by_time_no_user(app, user_1): client = app.test_client() resp_login = client.post( '/api/auth/login', @@ -37,7 +37,7 @@ def test_get_stats_no_user(app, user_1): content_type='application/json' ) response = client.get( - f'/api/stats/1000/by_week', + f'/api/stats/1000/by_time', headers=dict( Authorization='Bearer ' + json.loads( resp_login.data.decode() @@ -47,13 +47,13 @@ def test_get_stats_no_user(app, user_1): data = json.loads(response.data.decode()) assert response.status_code == 404 - assert 'fail' in data['status'] + assert 'not found' in data['status'] assert 'User does not exist.' in data['message'] -def test_get_stats_all_activities( +def test_get_stats_by_time_all_activities_error( app, user_1, sport_1_cycling, sport_2_running, - activity_cycling_user_1, activity_running_user_1 + seven_activities_user_1, activity_running_user_1 ): client = app.test_client() resp_login = client.post( @@ -65,92 +65,801 @@ def test_get_stats_all_activities( content_type='application/json' ) response = client.get( - f'/api/stats/{user_1.id}/by_week', - headers=dict( - Authorization='Bearer ' + json.loads( - resp_login.data.decode() - )['auth_token'] - ) - ) - data = json.loads(response.data.decode()) - - assert response.status_code == 200 - assert 'success' in data['status'] - assert data['data']['statistics']['W00'] == \ - { - 'Cycling': - { - 'nb_activities': 1, - 'total_distance': 10.0, - 'total_duration': 1024 - } - } - - assert data['data']['statistics']['W13'] == \ - { - 'Running': - { - 'nb_activities': 1, - 'total_distance': 12.0, - 'total_duration': 6000 - } - } - - -def test_get_stats_all_activities_week_13( - app, user_1, sport_1_cycling, sport_2_running, - activity_cycling_user_1, activity_running_user_1 -): - 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.get( - f'/api/stats/{user_1.id}/by_week?from=2018-04-01&to=2018-04-30', - headers=dict( - Authorization='Bearer ' + json.loads( - resp_login.data.decode() - )['auth_token'] - ) - ) - data = json.loads(response.data.decode()) - - assert response.status_code == 200 - assert 'success' in data['status'] - assert data['data']['statistics'] == \ - { - 'W13': - { - 'Running': - { - 'nb_activities': 1, - 'total_distance': 12.0, - 'total_duration': 6000 - } - } - } - - -def test_get_stats_all_activities_error( - app, user_1, sport_1_cycling, sport_2_running, - activity_cycling_user_1, activity_running_user_1 -): - 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.get( - f'/api/stats/{user_1.id}/by_week?from="2018-04-01&to=2018-04-30', + f'/api/stats/{user_1.id}/by_time?from="2018-04-01&to=2018-04-30', + headers=dict( + 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. Please try again or contact the administrator.' \ + in data['message'] + + +def test_get_stats_by_time_all_activities_invalid_period( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_time?from=2018-04-01&to=2018-04-30&time=day', # noqa + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 400 + assert 'fail' in data['status'] + assert 'Invalid time period.' in data['message'] + + +def test_get_stats_by_time_all_activities( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_time', + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 200 + assert 'success' in data['status'] + assert data['data']['statistics'] == \ + { + '2017': + { + '1': + { + 'nb_activities': 2, + 'total_distance': 15.0, + 'total_duration': 4480 + } + }, + '2018': + { + '1': + { + 'nb_activities': 5, + 'total_distance': 39.0, + 'total_duration': 11624 + }, + '2': + { + 'nb_activities': 1, + 'total_distance': 12.0, + 'total_duration': 6000 + } + } + } + + +def test_get_stats_by_time_all_activities_april_2018( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_time?from=2018-04-01&to=2018-04-30', + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 200 + assert 'success' in data['status'] + assert data['data']['statistics'] == \ + { + '2018': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 8.0, + 'total_duration': 6000 + }, + '2': + { + 'nb_activities': 1, + 'total_distance': 12.0, + 'total_duration': 6000 + } + } + } + + +def test_get_stats_by_year_all_activities( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_time?time=year', + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 200 + assert 'success' in data['status'] + assert data['data']['statistics'] == \ + { + '2017': + { + '1': + { + 'nb_activities': 2, + 'total_distance': 15.0, + 'total_duration': 4480 + } + }, + '2018': + { + '1': + { + 'nb_activities': 5, + 'total_distance': 39.0, + 'total_duration': 11624 + }, + '2': + { + 'nb_activities': 1, + 'total_distance': 12.0, + 'total_duration': 6000 + } + } + } + + +def test_get_stats_by_year_all_activities_april_2018( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_time?from=2018-04-01&to=2018-04-30&time=year', # noqa + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 200 + assert 'success' in data['status'] + assert data['data']['statistics'] == \ + { + '2018': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 8.0, + 'total_duration': 6000 + }, + '2': + { + 'nb_activities': 1, + 'total_distance': 12.0, + 'total_duration': 6000 + } + } + } + + +def test_get_stats_by_month_all_activities( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_time?time=month', + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 200 + assert 'success' in data['status'] + assert data['data']['statistics'] == \ + { + '2017-03': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 5.0, + 'total_duration': 1024 + } + }, + '2017-06': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 10.0, + 'total_duration': 3456 + } + }, + '2018-01': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 10.0, + 'total_duration': 1024 + } + }, + '2018-02': + { + '1': + { + 'nb_activities': 2, + 'total_distance': 11.0, + 'total_duration': 1600 + } + }, + '2018-04': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 8.0, + 'total_duration': 6000 + }, + '2': + { + 'nb_activities': 1, + 'total_distance': 12.0, + 'total_duration': 6000 + } + }, + '2018-05': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 10.0, + 'total_duration': 3000 + } + } + } + + +def test_get_stats_by_month_all_activities_april_2018( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_time?from=2018-04-01&to=2018-04-30&time=month', # noqa + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 200 + assert 'success' in data['status'] + assert data['data']['statistics'] == \ + { + '2018-04': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 8.0, + 'total_duration': 6000 + }, + '2': + { + 'nb_activities': 1, + 'total_distance': 12.0, + 'total_duration': 6000 + } + } + } + + +def test_get_stats_by_week_all_activities( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_time?time=week', + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 200 + assert 'success' in data['status'] + assert data['data']['statistics'] == \ + { + '2017-W12': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 5.0, + 'total_duration': 1024 + } + }, + '2017-W22': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 10.0, + 'total_duration': 3456 + } + }, + '2018-W00': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 10.0, + 'total_duration': 1024 + } + }, + '2018-W13': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 8.0, + 'total_duration': 6000 + }, + '2': + { + 'nb_activities': 1, + 'total_distance': 12.0, + 'total_duration': 6000 + } + }, + '2018-W07': + { + '1': + { + 'nb_activities': 2, + 'total_distance': 11.0, + 'total_duration': 1600 + } + }, + '2018-W18': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 10.0, + 'total_duration': 3000 + } + } + } + + +def test_get_stats_by_week_all_activities_week_13( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_time?from=2018-04-01&to=2018-04-30&time=week', # noqa + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 200 + assert 'success' in data['status'] + assert data['data']['statistics'] == \ + { + '2018-W13': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 8.0, + 'total_duration': 6000 + }, + '2': + { + 'nb_activities': 1, + 'total_distance': 12.0, + 'total_duration': 6000 + } + } + } + + +def test_get_stats_by_weekm_all_activities( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_time?time=weekm', + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 200 + assert 'success' in data['status'] + assert data['data']['statistics'] == \ + { + '2017-W12': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 5.0, + 'total_duration': 1024 + } + }, + '2017-W22': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 10.0, + 'total_duration': 3456 + } + }, + '2018-W01': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 10.0, + 'total_duration': 1024 + } + }, + '2018-W08': + { + '1': + { + 'nb_activities': 2, + 'total_distance': 11.0, + 'total_duration': 1600 + } + }, + '2018-W13': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 8.0, + 'total_duration': 6000 + }, + '2': + { + 'nb_activities': 1, + 'total_distance': 12.0, + 'total_duration': 6000 + } + }, + '2018-W19': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 10.0, + 'total_duration': 3000 + } + } + } + + +def test_get_stats_by_weekm_all_activities_week_13( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_time?from=2018-04-01&to=2018-04-30&time=weekm', # noqa + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 200 + assert 'success' in data['status'] + assert data['data']['statistics'] == \ + { + '2018-W13': + { + '1': + { + 'nb_activities': 1, + 'total_distance': 8.0, + 'total_duration': 6000 + }, + '2': + { + 'nb_activities': 1, + 'total_distance': 12.0, + 'total_duration': 6000 + } + } + } + + +def test_get_stats_by_sport_all_activities( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_sport', + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 200 + assert 'success' in data['status'] + assert data['data']['statistics'] == \ + { + '1': + { + 'nb_activities': 7, + 'total_distance': 54.0, + 'total_duration': 16104 + }, + '2': + { + 'nb_activities': 1, + 'total_distance': 12.0, + 'total_duration': 6000 + } + } + + +def test_get_stats_by_sport_all_activities_sport_1( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_sport?sport_id=1', + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 200 + assert 'success' in data['status'] + assert data['data']['statistics'] == \ + { + '1': + { + 'nb_activities': 7, + 'total_distance': 54.0, + 'total_duration': 16104 + } + } + + +def test_get_stats_by_sport_all_activities_invalid_user( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/1000/by_sport?sport_id=1', + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 404 + assert 'not found' in data['status'] + assert 'User does not exist.' in data['message'] + + +def test_get_stats_by_sport_all_activities_invalid_sport( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_sport?sport_id=999', + headers=dict( + Authorization='Bearer ' + json.loads( + resp_login.data.decode() + )['auth_token'] + ) + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 404 + assert 'not found' in data['status'] + assert 'Sport does not exist.' in data['message'] + + +def test_get_stats_by_sport_all_activities_error( + app, user_1, sport_1_cycling, sport_2_running, + seven_activities_user_1, activity_running_user_1 +): + 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.get( + f'/api/stats/{user_1.id}/by_sport?sport_id="999', headers=dict( Authorization='Bearer ' + json.loads( resp_login.data.decode()