API - add typing

This commit is contained in:
Sam
2021-01-02 19:28:03 +01:00
parent 4705393a08
commit 634d06b05a
53 changed files with 1884 additions and 1075 deletions

View File

@ -1,21 +1,25 @@
import json
from uuid import uuid4
from fittrackee.activities.models import Activity, Sport
from fittrackee.users.models import User
from flask import Flask
from .utils import get_random_short_id
class TestGetActivities:
def test_it_gets_all_activities_for_authenticated_user(
self,
app,
user_1,
user_2,
sport_1_cycling,
sport_2_running,
activity_cycling_user_1,
activity_cycling_user_2,
activity_running_user_1,
):
app: Flask,
user_1: User,
user_2: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
activity_cycling_user_1: Activity,
activity_cycling_user_2: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -57,14 +61,14 @@ class TestGetActivities:
def test_it_gets_no_activities_for_authenticated_user_with_no_activities(
self,
app,
user_1,
user_2,
sport_1_cycling,
sport_2_running,
activity_cycling_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
user_2: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
activity_cycling_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -85,7 +89,9 @@ class TestGetActivities:
assert 'success' in data['status']
assert len(data['data']['activities']) == 0
def test_it_returns_401_if_user_is_not_authenticated(self, app):
def test_it_returns_401_if_user_is_not_authenticated(
self, app: Flask
) -> None:
client = app.test_client()
response = client.get('/api/activities')
@ -98,8 +104,12 @@ class TestGetActivities:
class TestGetActivitiesWithPagination:
def test_it_gets_activities_with_default_pagination(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -133,8 +143,12 @@ class TestGetActivitiesWithPagination:
assert '0:17:04' == data['data']['activities'][4]['duration']
def test_it_gets_first_page(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -168,8 +182,12 @@ class TestGetActivitiesWithPagination:
assert '0:17:04' == data['data']['activities'][4]['duration']
def test_it_gets_second_page(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -203,8 +221,12 @@ class TestGetActivitiesWithPagination:
assert '0:17:04' == data['data']['activities'][1]['duration']
def test_it_gets_empty_third_page(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -226,8 +248,12 @@ class TestGetActivitiesWithPagination:
assert len(data['data']['activities']) == 0
def test_it_returns_error_on_invalid_page_value(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -252,8 +278,12 @@ class TestGetActivitiesWithPagination:
)
def test_it_gets_5_activities_per_page(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -283,8 +313,12 @@ class TestGetActivitiesWithPagination:
)
def test_it_gets_3_activities_per_page(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -316,8 +350,12 @@ class TestGetActivitiesWithPagination:
class TestGetActivitiesWithFilters:
def test_it_gets_activities_with_date_filter(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -351,8 +389,12 @@ class TestGetActivitiesWithFilters:
assert '0:16:40' == data['data']['activities'][1]['duration']
def test_it_gets_no_activities_with_date_filter(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -374,8 +416,12 @@ class TestGetActivitiesWithFilters:
assert len(data['data']['activities']) == 0
def test_if_gets_activities_with_date_filter_from(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -406,8 +452,12 @@ class TestGetActivitiesWithFilters:
)
def test_it_gets_activities_with_date_filter_to(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -437,8 +487,12 @@ class TestGetActivitiesWithFilters:
)
def test_it_gets_activities_with_ascending_order(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -468,8 +522,12 @@ class TestGetActivitiesWithFilters:
)
def test_it_gets_activities_with_distance_filter(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -499,8 +557,12 @@ class TestGetActivitiesWithFilters:
)
def test_it_gets_activities_with_duration_filter(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -526,8 +588,12 @@ class TestGetActivitiesWithFilters:
)
def test_it_gets_activities_with_average_speed_filter(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -554,13 +620,13 @@ class TestGetActivitiesWithFilters:
def test_it_gets_activities_with_max_speed_filter(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
activity_cycling_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
activity_cycling_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
activity_cycling_user_1.max_speed = 25
activity_running_user_1.max_speed = 11
client = app.test_client()
@ -589,13 +655,13 @@ class TestGetActivitiesWithFilters:
def test_it_gets_activities_with_sport_filter(
self,
app,
user_1,
sport_1_cycling,
seven_activities_user_1,
sport_2_running,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
sport_2_running: Sport,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -623,8 +689,12 @@ class TestGetActivitiesWithFilters:
class TestGetActivitiesWithFiltersAndPagination:
def test_it_gets_page_2_with_date_filter(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -654,8 +724,12 @@ class TestGetActivitiesWithFiltersAndPagination:
)
def test_it_get_page_2_with_date_filter_and_ascending_order(
self, app, user_1, sport_1_cycling, seven_activities_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
seven_activities_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -687,8 +761,12 @@ class TestGetActivitiesWithFiltersAndPagination:
class TestGetActivity:
def test_it_gets_an_activity(
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -719,8 +797,13 @@ class TestGetActivity:
assert '1:00:00' == data['data']['activities'][0]['duration']
def test_it_returns_403_if_activity_belongs_to_a_different_user(
self, app, user_1, user_2, sport_1_cycling, activity_cycling_user_2
):
self,
app: Flask,
user_1: User,
user_2: User,
sport_1_cycling: Sport,
activity_cycling_user_2: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -741,7 +824,9 @@ class TestGetActivity:
assert 'error' in data['status']
assert 'You do not have permissions.' in data['message']
def test_it_returns_404_if_activity_does_not_exist(self, app, user_1):
def test_it_returns_404_if_activity_does_not_exist(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -763,8 +848,8 @@ class TestGetActivity:
assert len(data['data']['activities']) == 0
def test_it_returns_404_on_getting_gpx_if_activity_does_not_exist(
self, app, user_1
):
self, app: Flask, user_1: User
) -> None:
random_short_id = get_random_short_id()
client = app.test_client()
resp_login = client.post(
@ -788,8 +873,8 @@ class TestGetActivity:
assert data['data']['gpx'] == ''
def test_it_returns_404_on_getting_chart_data_if_activity_does_not_exist(
self, app, user_1
):
self, app: Flask, user_1: User
) -> None:
random_short_id = get_random_short_id()
client = app.test_client()
resp_login = client.post(
@ -813,8 +898,12 @@ class TestGetActivity:
assert data['data']['chart_data'] == ''
def test_it_returns_404_on_getting_gpx_if_activity_have_no_gpx(
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
activity_short_id = activity_cycling_user_1.short_id
client = app.test_client()
resp_login = client.post(
@ -840,8 +929,12 @@ class TestGetActivity:
)
def test_it_returns_404_if_activity_have_no_chart_data(
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
activity_short_id = activity_cycling_user_1.short_id
client = app.test_client()
resp_login = client.post(
@ -867,8 +960,12 @@ class TestGetActivity:
)
def test_it_returns_500_on_getting_gpx_if_an_activity_has_invalid_gpx_pathname( # noqa
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
activity_cycling_user_1.gpx = "some path"
client = app.test_client()
resp_login = client.post(
@ -895,8 +992,12 @@ class TestGetActivity:
assert 'data' not in data
def test_it_returns_500_on_getting_chart_data_if_an_activity_has_invalid_gpx_pathname( # noqa
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
activity_cycling_user_1.gpx = 'some path'
client = app.test_client()
resp_login = client.post(
@ -922,7 +1023,9 @@ class TestGetActivity:
)
assert 'data' not in data
def test_it_returns_404_if_activity_has_no_map(self, app, user_1):
def test_it_returns_404_if_activity_has_no_map(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',

View File

@ -2,12 +2,15 @@ import json
import os
from datetime import datetime
from io import BytesIO
from typing import Dict
from fittrackee.activities.models import Activity
from fittrackee.activities.models import Activity, Sport
from fittrackee.activities.utils_id import decode_short_id
from fittrackee.users.models import User
from flask import Flask
def assert_activity_data_with_gpx(data):
def assert_activity_data_with_gpx(data: Dict) -> None:
assert 'creation_date' in data['data']['activities'][0]
assert (
'Tue, 13 Mar 2018 12:44:45 GMT'
@ -70,7 +73,7 @@ def assert_activity_data_with_gpx(data):
assert records[3]['value'] == 4.61
def assert_activity_data_with_gpx_segments(data):
def assert_activity_data_with_gpx_segments(data: Dict) -> None:
assert 'creation_date' in data['data']['activities'][0]
assert (
'Tue, 13 Mar 2018 12:44:45 GMT'
@ -144,7 +147,7 @@ def assert_activity_data_with_gpx_segments(data):
assert records[2]['value'] == 4.59
def assert_activity_data_wo_gpx(data):
def assert_activity_data_wo_gpx(data: Dict) -> None:
assert 'creation_date' in data['data']['activities'][0]
assert (
data['data']['activities'][0]['activity_date']
@ -200,8 +203,8 @@ def assert_activity_data_wo_gpx(data):
class TestPostActivityWithGpx:
def test_it_adds_an_activity_with_gpx_file(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -230,8 +233,12 @@ class TestPostActivityWithGpx:
assert_activity_data_with_gpx(data)
def test_it_adds_an_activity_with_gpx_without_name(
self, app, user_1, sport_1_cycling, gpx_file_wo_name
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
gpx_file_wo_name: str,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -263,8 +270,12 @@ class TestPostActivityWithGpx:
assert_activity_data_with_gpx(data)
def test_it_adds_an_activity_with_gpx_without_name_timezone(
self, app, user_1, sport_1_cycling, gpx_file_wo_name
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
gpx_file_wo_name: str,
) -> None:
user_1.timezone = 'Europe/Paris'
client = app.test_client()
resp_login = client.post(
@ -297,8 +308,8 @@ class TestPostActivityWithGpx:
assert_activity_data_with_gpx(data)
def test_it_adds_get_an_activity_with_gpx_notes(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -327,8 +338,12 @@ class TestPostActivityWithGpx:
assert 'test activity' == data['data']['activities'][0]['notes']
def test_it_returns_500_if_gpx_file_has_not_tracks(
self, app, user_1, sport_1_cycling, gpx_file_wo_track
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
gpx_file_wo_track: str,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -352,12 +367,16 @@ class TestPostActivityWithGpx:
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 'Error during gpx processing.' in data['message']
assert 'data' not in data
def test_it_returns_500_if_gpx_has_invalid_xml(
self, app, user_1, sport_1_cycling, gpx_file_invalid_xml
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
gpx_file_invalid_xml: str,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -388,8 +407,8 @@ class TestPostActivityWithGpx:
assert 'data' not in data
def test_it_returns_400_if_activity_gpx_has_invalid_extension(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -416,8 +435,8 @@ class TestPostActivityWithGpx:
assert data['message'] == 'File extension not allowed.'
def test_it_returns_400_if_sport_id_is_not_provided(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -443,8 +462,8 @@ class TestPostActivityWithGpx:
assert data['message'] == 'Invalid payload.'
def test_it_returns_500_if_sport_id_does_not_exists(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -471,8 +490,8 @@ class TestPostActivityWithGpx:
assert data['message'] == 'Sport id: 2 does not exist'
def test_returns_400_if_no_gpx_file_is_provided(
self, app, user_1, sport_1_cycling
):
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -498,8 +517,8 @@ class TestPostActivityWithGpx:
class TestPostActivityWithoutGpx:
def test_it_adds_an_activity_without_gpx(
self, app, user_1, sport_1_cycling
):
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -531,8 +550,8 @@ class TestPostActivityWithoutGpx:
assert_activity_data_wo_gpx(data)
def test_it_returns_400_if_activity_date_is_missing(
self, app, user_1, sport_1_cycling
):
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -556,8 +575,8 @@ class TestPostActivityWithoutGpx:
assert 'Invalid payload.' in data['message']
def test_it_returns_500_if_activity_format_is_invalid(
self, app, user_1, sport_1_cycling
):
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -588,8 +607,12 @@ class TestPostActivityWithoutGpx:
assert 'Error during activity save.' in data['message']
def test_it_adds_activity_with_zero_value(
self, app, user_1, sport_1_cycling, sport_2_running
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -645,8 +668,8 @@ class TestPostActivityWithoutGpx:
class TestPostActivityWithZipArchive:
def test_it_adds_activities_with_zip_archive(
self, app, user_1, sport_1_cycling
):
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
file_path = os.path.join(app.root_path, 'tests/files/gpx_test.zip')
# 'gpx_test.zip' contains 3 gpx files (same data) and 1 non-gpx file
with open(file_path, 'rb') as zip_file:
@ -679,8 +702,8 @@ class TestPostActivityWithZipArchive:
assert_activity_data_with_gpx(data)
def test_it_returns_400_if_folder_is_present_in_zpi_archive(
self, app, user_1, sport_1_cycling
):
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
file_path = os.path.join(
app.root_path, 'tests/files/gpx_test_folder.zip'
)
@ -715,8 +738,8 @@ class TestPostActivityWithZipArchive:
assert len(data['data']['activities']) == 0
def test_it_returns_500_if_one_fle_in_zip_archive_is_invalid(
self, app, user_1, sport_1_cycling
):
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
file_path = os.path.join(
app.root_path, 'tests/files/gpx_test_incorrect.zip'
)
@ -747,13 +770,15 @@ class TestPostActivityWithZipArchive:
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 'Error during gpx processing.' in data['message']
assert 'data' not in data
class TestPostAndGetActivityWithGpx:
@staticmethod
def activity_assertion(app, gpx_file, with_segments):
def activity_assertion(
app: Flask, gpx_file: str, with_segments: bool
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -849,18 +874,22 @@ class TestPostAndGetActivityWithGpx:
)
def test_it_gets_an_activity_created_with_gpx(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
return self.activity_assertion(app, gpx_file, False)
def test_it_gets_an_activity_created_with_gpx_with_segments(
self, app, user_1, sport_1_cycling, gpx_file_with_segments
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
gpx_file_with_segments: str,
) -> None:
return self.activity_assertion(app, gpx_file_with_segments, True)
def test_it_gets_chart_data_for_an_activity_created_with_gpx(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -897,8 +926,8 @@ class TestPostAndGetActivityWithGpx:
assert data['data']['chart_data'] != ''
def test_it_gets_segment_chart_data_for_an_activity_created_with_gpx(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -935,8 +964,13 @@ class TestPostAndGetActivityWithGpx:
assert data['data']['chart_data'] != ''
def test_it_returns_403_on_getting_chart_data_if_activity_belongs_to_another_user( # noqa
self, app, user_1, user_2, sport_1_cycling, gpx_file
):
self,
app: Flask,
user_1: User,
user_2: User,
sport_1_cycling: Sport,
gpx_file: str,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -977,8 +1011,8 @@ class TestPostAndGetActivityWithGpx:
assert data['message'] == 'You do not have permissions.'
def test_it_returns_500_on_invalid_segment_id(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1015,8 +1049,8 @@ class TestPostAndGetActivityWithGpx:
assert 'data' not in data
def test_it_returns_404_if_segment_id_does_not_exist(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1055,8 +1089,8 @@ class TestPostAndGetActivityWithGpx:
class TestPostAndGetActivityWithoutGpx:
def test_it_add_and_gets_an_activity_wo_gpx(
self, app, user_1, sport_1_cycling
):
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1097,8 +1131,8 @@ class TestPostAndGetActivityWithoutGpx:
assert_activity_data_wo_gpx(data)
def test_it_adds_and_gets_an_activity_wo_gpx_notes(
self, app, user_1, sport_1_cycling
):
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1142,8 +1176,8 @@ class TestPostAndGetActivityWithoutGpx:
class TestPostAndGetActivityUsingTimezones:
def test_it_add_and_gets_an_activity_wo_gpx_with_timezone(
self, app, user_1, sport_1_cycling
):
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
user_1.timezone = 'Europe/Paris'
client = app.test_client()
resp_login = client.post(
@ -1192,8 +1226,8 @@ class TestPostAndGetActivityUsingTimezones:
)
def test_it_adds_and_gets_activities_date_filter_with_timezone_new_york(
self, app, user_1_full, sport_1_cycling
):
self, app: Flask, user_1_full: User, sport_1_cycling: Sport
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1239,8 +1273,12 @@ class TestPostAndGetActivityUsingTimezones:
)
def test_it_adds_and_gets_activities_date_filter_with_timezone_paris(
self, app, user_1_paris, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1_paris: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',

View File

@ -1,12 +1,15 @@
import json
from typing import Dict
from fittrackee.activities.models import Activity
from fittrackee.activities.models import Activity, Sport
from fittrackee.activities.utils_id import decode_short_id
from fittrackee.users.models import User
from flask import Flask
from .utils import get_random_short_id, post_an_activity
def assert_activity_data_with_gpx(data, sport_id):
def assert_activity_data_with_gpx(data: Dict, sport_id: int) -> None:
assert 'creation_date' in data['data']['activities'][0]
assert (
'Tue, 13 Mar 2018 12:44:45 GMT'
@ -51,8 +54,13 @@ def assert_activity_data_with_gpx(data, sport_id):
class TestEditActivityWithGpx:
def test_it_updates_title_for_an_activity_with_gpx(
self, app, user_1, sport_1_cycling, sport_2_running, gpx_file
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
gpx_file: str,
) -> None:
token, activity_short_id = post_an_activity(app, gpx_file)
client = app.test_client()
@ -72,8 +80,13 @@ class TestEditActivityWithGpx:
assert_activity_data_with_gpx(data, sport_2_running.id)
def test_it_adds_notes_for_an_activity_with_gpx(
self, app, user_1, sport_1_cycling, sport_2_running, gpx_file
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
gpx_file: str,
) -> None:
token, activity_short_id = post_an_activity(app, gpx_file)
client = app.test_client()
@ -92,8 +105,14 @@ class TestEditActivityWithGpx:
assert data['data']['activities'][0]['notes'] == 'test notes'
def test_it_raises_403_when_editing_an_activity_from_different_user(
self, app, user_1, user_2, sport_1_cycling, sport_2_running, gpx_file
):
self,
app: Flask,
user_1: User,
user_2: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
gpx_file: str,
) -> None:
_, activity_short_id = post_an_activity(app, gpx_file)
client = app.test_client()
resp_login = client.post(
@ -118,8 +137,13 @@ class TestEditActivityWithGpx:
assert 'You do not have permissions.' in data['message']
def test_it_updates_sport(
self, app, user_1, sport_1_cycling, sport_2_running, gpx_file
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
gpx_file: str,
) -> None:
token, activity_short_id = post_an_activity(app, gpx_file)
client = app.test_client()
@ -139,8 +163,8 @@ class TestEditActivityWithGpx:
assert_activity_data_with_gpx(data, sport_2_running.id)
def test_it_returns_400_if_payload_is_empty(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
token, activity_short_id = post_an_activity(app, gpx_file)
client = app.test_client()
@ -157,8 +181,8 @@ class TestEditActivityWithGpx:
assert 'Invalid payload.' in data['message']
def test_it_raises_500_if_sport_does_not_exists(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
token, activity_short_id = post_an_activity(app, gpx_file)
client = app.test_client()
@ -181,12 +205,12 @@ class TestEditActivityWithGpx:
class TestEditActivityWithoutGpx:
def test_it_updates_an_activity_wo_gpx(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
activity_cycling_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
activity_cycling_user_1: Activity,
) -> None:
activity_short_id = activity_cycling_user_1.short_id
client = app.test_client()
resp_login = client.post(
@ -266,8 +290,12 @@ class TestEditActivityWithoutGpx:
assert records[3]['value'] == 8.0
def test_it_adds_notes_to_an_activity_wo_gpx(
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
activity_short_id = activity_cycling_user_1.short_id
client = app.test_client()
resp_login = client.post(
@ -338,8 +366,13 @@ class TestEditActivityWithoutGpx:
assert records[3]['value'] == 10.0
def test_returns_403_when_editing_an_activity_wo_gpx_from_different_user(
self, app, user_1, user_2, sport_1_cycling, activity_cycling_user_2
):
self,
app: Flask,
user_1: User,
user_2: User,
sport_1_cycling: Sport,
activity_cycling_user_2: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -372,12 +405,12 @@ class TestEditActivityWithoutGpx:
def test_it_updates_an_activity_wo_gpx_with_timezone(
self,
app,
user_1_paris,
sport_1_cycling,
sport_2_running,
activity_cycling_user_1,
):
app: Flask,
user_1_paris: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
activity_cycling_user_1: Activity,
) -> None:
activity_short_id = activity_cycling_user_1.short_id
client = app.test_client()
resp_login = client.post(
@ -453,12 +486,12 @@ class TestEditActivityWithoutGpx:
def test_it_updates_only_sport_and_distance_an_activity_wo_gpx(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
activity_cycling_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
activity_cycling_user_1: Activity,
) -> None:
activity_short_id = activity_cycling_user_1.short_id
client = app.test_client()
resp_login = client.post(
@ -525,8 +558,12 @@ class TestEditActivityWithoutGpx:
assert records[3]['value'] == 20.0
def test_it_returns_400_if_payload_is_empty(
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -550,8 +587,12 @@ class TestEditActivityWithoutGpx:
assert 'Invalid payload.' in data['message']
def test_it_returns_500_if_date_format_is_invalid(
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -585,8 +626,8 @@ class TestEditActivityWithoutGpx:
)
def test_it_returns_404_if_edited_activity_does_not_exists(
self, app, user_1, sport_1_cycling
):
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -618,8 +659,13 @@ class TestEditActivityWithoutGpx:
class TestRefreshActivityWithGpx:
def test_refresh_an_activity_with_gpx(
self, app, user_1, sport_1_cycling, sport_2_running, gpx_file
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
gpx_file: str,
) -> None:
token, activity_short_id = post_an_activity(app, gpx_file)
activity_uuid = decode_short_id(activity_short_id)
client = app.test_client()

View File

@ -1,21 +1,23 @@
import json
import os
from fittrackee.activities.models import Activity
from fittrackee.activities.models import Activity, Sport
from fittrackee.activities.utils import get_absolute_file_path
from fittrackee.users.models import User
from flask import Flask
from .utils import get_random_short_id, post_an_activity
def get_gpx_filepath(activity_id):
def get_gpx_filepath(activity_id: int) -> str:
activity = Activity.query.filter_by(id=activity_id).first()
return activity.gpx
class TestDeleteActivityWithGpx:
def test_it_deletes_an_activity_with_gpx(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
token, activity_short_id = post_an_activity(app, gpx_file)
client = app.test_client()
@ -27,8 +29,13 @@ class TestDeleteActivityWithGpx:
assert response.status_code == 204
def test_it_returns_403_when_deleting_an_activity_from_different_user(
self, app, user_1, user_2, sport_1_cycling, gpx_file
):
self,
app: Flask,
user_1: User,
user_2: User,
sport_1_cycling: Sport,
gpx_file: str,
) -> None:
_, activity_short_id = post_an_activity(app, gpx_file)
client = app.test_client()
resp_login = client.post(
@ -51,7 +58,9 @@ class TestDeleteActivityWithGpx:
assert 'error' in data['status']
assert 'You do not have permissions.' in data['message']
def test_it_returns_404_if_activity_does_not_exist(self, app, user_1):
def test_it_returns_404_if_activity_does_not_exist(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -70,8 +79,8 @@ class TestDeleteActivityWithGpx:
assert 'not found' in data['status']
def test_it_returns_500_when_deleting_an_activity_with_gpx_invalid_file(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
token, activity_short_id = post_an_activity(app, gpx_file)
client = app.test_client()
gpx_filepath = get_gpx_filepath(1)
@ -95,8 +104,12 @@ class TestDeleteActivityWithGpx:
class TestDeleteActivityWithoutGpx:
def test_it_deletes_an_activity_wo_gpx(
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -113,8 +126,13 @@ class TestDeleteActivityWithoutGpx:
assert response.status_code == 204
def test_it_returns_403_when_deleting_an_activity_from_different_user(
self, app, user_1, user_2, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
user_2: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',

View File

@ -1,12 +1,19 @@
from uuid import UUID
from fittrackee.activities.models import Activity, Sport
from fittrackee.activities.utils_id import decode_short_id
from fittrackee.users.models import User
from flask import Flask
class TestActivityModel:
def test_activity_model(
self, app, sport_1_cycling, user_1, activity_cycling_user_1
):
self,
app: Flask,
sport_1_cycling: Sport,
user_1: User,
activity_cycling_user_1: Activity,
) -> None:
activity_cycling_user_1.title = 'Test'
assert 1 == activity_cycling_user_1.id
@ -55,12 +62,12 @@ class TestActivityModel:
def test_activity_segment_model(
self,
app,
sport_1_cycling,
user_1,
activity_cycling_user_1,
activity_cycling_user_1_segment,
):
app: Flask,
sport_1_cycling: Sport,
user_1: User,
activity_cycling_user_1: Activity,
activity_cycling_user_1_segment: Activity,
) -> None:
assert (
f'<Segment \'{activity_cycling_user_1_segment.segment_id}\' '
f'for activity \'{activity_cycling_user_1.short_id}\'>'

View File

@ -1,17 +1,21 @@
import json
from fittrackee.activities.models import Activity, Sport
from fittrackee.users.models import User
from flask import Flask
class TestGetRecords:
def test_it_gets_records_for_authenticated_user(
self,
app,
user_1,
user_2,
sport_1_cycling,
sport_2_running,
activity_cycling_user_1,
activity_cycling_user_2,
):
app: Flask,
user_1: User,
user_2: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
activity_cycling_user_1: Activity,
activity_cycling_user_2: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -85,13 +89,13 @@ class TestGetRecords:
def test_it_gets_no_records_if_user_has_no_activity(
self,
app,
user_1,
user_2,
sport_1_cycling,
sport_2_running,
activity_cycling_user_2,
):
app: Flask,
user_1: User,
user_2: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
activity_cycling_user_2: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -112,8 +116,12 @@ class TestGetRecords:
assert len(data['data']['records']) == 0
def test_it_gets_no_records_if_activity_has_zero_value(
self, app, user_1, sport_1_cycling, sport_2_running
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -151,8 +159,8 @@ class TestGetRecords:
assert len(data['data']['records']) == 0
def test_it_gets_updated_records_after_activities_post_and_patch(
self, app, user_1, sport_1_cycling
):
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -696,8 +704,12 @@ class TestGetRecords:
assert len(data['data']['records']) == 0
def test_it_gets_updated_records_after_sport_change(
self, app, user_1, sport_1_cycling, sport_2_running
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',

View File

@ -1,12 +1,18 @@
import datetime
from fittrackee.activities.models import Record
from fittrackee.activities.models import Activity, Record, Sport
from fittrackee.users.models import User
from flask import Flask
class TestRecordModel:
def test_record_model(
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
record_ld = Record.query.filter_by(
user_id=activity_cycling_user_1.user_id,
sport_id=activity_cycling_user_1.sport_id,
@ -29,8 +35,12 @@ class TestRecordModel:
assert 'value' in record_serialize
def test_record_model_with_none_value(
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
record_ld = Record.query.filter_by(
user_id=activity_cycling_user_1.user_id,
sport_id=activity_cycling_user_1.sport_id,
@ -49,8 +59,12 @@ class TestRecordModel:
assert record_serialize['value'] is None
def test_average_speed_records(
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
record_as = Record.query.filter_by(
user_id=activity_cycling_user_1.user_id,
sport_id=activity_cycling_user_1.sport_id,
@ -66,8 +80,12 @@ class TestRecordModel:
assert isinstance(record_serialize.get('value'), float)
def test_add_farest_distance_records(
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
record_fd = Record.query.filter_by(
user_id=activity_cycling_user_1.user_id,
sport_id=activity_cycling_user_1.sport_id,
@ -83,8 +101,12 @@ class TestRecordModel:
assert isinstance(record_serialize.get('value'), float)
def test_add_longest_duration_records(
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
record_ld = Record.query.filter_by(
user_id=activity_cycling_user_1.user_id,
sport_id=activity_cycling_user_1.sport_id,
@ -100,8 +122,12 @@ class TestRecordModel:
assert isinstance(record_serialize.get('value'), str)
def test_add_longest_duration_records_with_zero(
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
record_ld = Record.query.filter_by(
user_id=activity_cycling_user_1.user_id,
sport_id=activity_cycling_user_1.sport_id,
@ -118,8 +144,12 @@ class TestRecordModel:
assert isinstance(record_serialize.get('value'), str)
def test_max_speed_records_no_value(
self, app, user_1, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
record_ms = Record.query.filter_by(
user_id=activity_cycling_user_1.user_id,
sport_id=activity_cycling_user_1.sport_id,

View File

@ -1,5 +1,9 @@
import json
from fittrackee.activities.models import Activity, Sport
from fittrackee.users.models import User
from flask import Flask
expected_sport_1_cycling_result = {
'id': 1,
'label': 'Cycling',
@ -32,8 +36,12 @@ expected_sport_1_cycling_inactive_admin_result['has_activities'] = False
class TestGetSports:
def test_it_gets_all_sports(
self, app, user_1, sport_1_cycling, sport_2_running
):
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -57,8 +65,12 @@ class TestGetSports:
assert data['data']['sports'][1] == expected_sport_2_running_result
def test_it_gets_all_sports_with_inactive_one(
self, app, user_1, sport_1_cycling_inactive, sport_2_running
):
self,
app: Flask,
user_1: User,
sport_1_cycling_inactive: Sport,
sport_2_running: Sport,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -85,8 +97,12 @@ class TestGetSports:
assert data['data']['sports'][1] == expected_sport_2_running_result
def test_it_gets_all_sports_with_admin_rights(
self, app, user_1_admin, sport_1_cycling_inactive, sport_2_running
):
self,
app: Flask,
user_1_admin: User,
sport_1_cycling_inactive: Sport,
sport_2_running: Sport,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -118,7 +134,9 @@ class TestGetSports:
class TestGetSport:
def test_it_gets_a_sport(self, app, user_1, sport_1_cycling):
def test_it_gets_a_sport(
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -140,7 +158,9 @@ class TestGetSport:
assert len(data['data']['sports']) == 1
assert data['data']['sports'][0] == expected_sport_1_cycling_result
def test_it_returns_404_if_sport_does_not_exist(self, app, user_1):
def test_it_returns_404_if_sport_does_not_exist(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -162,8 +182,8 @@ class TestGetSport:
assert len(data['data']['sports']) == 0
def test_it_gets_a_inactive_sport(
self, app, user_1, sport_1_cycling_inactive
):
self, app: Flask, user_1: User, sport_1_cycling_inactive: Sport
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -189,8 +209,8 @@ class TestGetSport:
)
def test_it_get_an_inactive_sport_with_admin_rights(
self, app, user_1_admin, sport_1_cycling_inactive
):
self, app: Flask, user_1_admin: User, sport_1_cycling_inactive: Sport
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -219,7 +239,9 @@ class TestGetSport:
class TestUpdateSport:
def test_it_disables_a_sport(self, app, user_1_admin, sport_1_cycling):
def test_it_disables_a_sport(
self, app: Flask, user_1_admin: User, sport_1_cycling: Sport
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -246,7 +268,9 @@ class TestUpdateSport:
assert data['data']['sports'][0]['is_active'] is False
assert data['data']['sports'][0]['has_activities'] is False
def test_it_enables_a_sport(self, app, user_1_admin, sport_1_cycling):
def test_it_enables_a_sport(
self, app: Flask, user_1_admin: User, sport_1_cycling: Sport
) -> None:
sport_1_cycling.is_active = False
client = app.test_client()
resp_login = client.post(
@ -275,8 +299,12 @@ class TestUpdateSport:
assert data['data']['sports'][0]['has_activities'] is False
def test_it_disables_a_sport_with_activities(
self, app, user_1_admin, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1_admin: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -304,8 +332,12 @@ class TestUpdateSport:
assert data['data']['sports'][0]['has_activities'] is True
def test_it_enables_a_sport_with_activities(
self, app, user_1_admin, sport_1_cycling, activity_cycling_user_1
):
self,
app: Flask,
user_1_admin: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
) -> None:
sport_1_cycling.is_active = False
client = app.test_client()
resp_login = client.post(
@ -334,8 +366,8 @@ class TestUpdateSport:
assert data['data']['sports'][0]['has_activities'] is True
def test_returns_error_if_user_has_no_admin_rights(
self, app, user_1, sport_1_cycling
):
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -358,7 +390,9 @@ class TestUpdateSport:
assert 'error' in data['status']
assert 'You do not have permissions.' in data['message']
def test_returns_error_if_payload_is_invalid(self, app, user_1_admin):
def test_returns_error_if_payload_is_invalid(
self, app: Flask, user_1_admin: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -383,7 +417,9 @@ class TestUpdateSport:
assert 'error' in data['status']
assert 'Invalid payload.' in data['message']
def test_it_returns_error_if_sport_does_not_exist(self, app, user_1_admin):
def test_it_returns_error_if_sport_does_not_exist(
self, app: Flask, user_1_admin: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',

View File

@ -1,6 +1,15 @@
from typing import Dict, Optional
from fittrackee.activities.models import Activity, Sport
from fittrackee.users.models import User
from flask import Flask
class TestSportModel:
@staticmethod
def assert_sport_model(sport, is_admin=False):
def assert_sport_model(
sport: Sport, is_admin: Optional[bool] = False
) -> Dict:
assert 1 == sport.id
assert 'Cycling' == sport.label
assert '<Sport \'Cycling\'>' == str(sport)
@ -11,18 +20,26 @@ class TestSportModel:
assert serialized_sport['is_active'] is True
return serialized_sport
def test_sport_model(self, app, sport_1_cycling):
def test_sport_model(self, app: Flask, sport_1_cycling: Sport) -> None:
serialized_sport = self.assert_sport_model(sport_1_cycling)
assert 'has_activities' not in serialized_sport
def test_sport_model_with_activity(
self, app, sport_1_cycling, user_1, activity_cycling_user_1
):
self,
app: Flask,
sport_1_cycling: Sport,
user_1: User,
activity_cycling_user_1: Activity,
) -> None:
serialized_sport = self.assert_sport_model(sport_1_cycling)
assert 'has_activities' not in serialized_sport
def test_sport_model_with_activity_as_admin(
self, app, sport_1_cycling, user_1, activity_cycling_user_1
):
self,
app: Flask,
sport_1_cycling: Sport,
user_1: User,
activity_cycling_user_1: Activity,
) -> None:
serialized_sport = self.assert_sport_model(sport_1_cycling, True)
assert serialized_sport['has_activities'] is True

View File

@ -1,8 +1,14 @@
import json
from fittrackee.activities.models import Activity, Sport
from fittrackee.users.models import User
from flask import Flask
class TestGetStatsByTime:
def test_it_gets_no_stats_when_user_has_no_activities(self, app, user_1):
def test_it_gets_no_stats_when_user_has_no_activities(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -23,7 +29,9 @@ class TestGetStatsByTime:
assert 'success' in data['status']
assert data['data']['statistics'] == {}
def test_it_returns_error_when_user_does_not_exists(self, app, user_1):
def test_it_returns_error_when_user_does_not_exists(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -46,13 +54,13 @@ class TestGetStatsByTime:
def test_it_returns_error_if_date_format_is_invalid(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -78,13 +86,13 @@ class TestGetStatsByTime:
def test_it_returns_error_if_period_is_invalid(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -107,13 +115,13 @@ class TestGetStatsByTime:
def test_it_gets_stats_by_time_all_activities(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -156,13 +164,13 @@ class TestGetStatsByTime:
def test_it_gets_stats_for_april_2018(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -198,13 +206,13 @@ class TestGetStatsByTime:
def test_it_gets_stats_for_april_2018_with_paris_timezone(
self,
app,
user_1_paris,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1_paris: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -241,13 +249,13 @@ class TestGetStatsByTime:
def test_it_gets_stats_by_year(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -290,13 +298,13 @@ class TestGetStatsByTime:
def test_it_gets_stats_by_year_for_april_2018(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -332,13 +340,13 @@ class TestGetStatsByTime:
def test_it_gets_stats_by_year_for_april_2018_with_paris_timezone(
self,
app,
user_1_paris,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1_paris: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -374,13 +382,13 @@ class TestGetStatsByTime:
def test_it_gets_stats_by_month(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -451,13 +459,13 @@ class TestGetStatsByTime:
def test_it_gets_stats_by_month_with_new_york_timezone(
self,
app,
user_1_full,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1_full: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -528,13 +536,13 @@ class TestGetStatsByTime:
def test_it_gets_stats_by_month_for_april_2018(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -570,13 +578,13 @@ class TestGetStatsByTime:
def test_it_gets_stats_by_week(
self,
app,
user_1_full,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1_full: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -647,13 +655,13 @@ class TestGetStatsByTime:
def test_it_gets_stats_by_week_for_week_13(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -689,13 +697,13 @@ class TestGetStatsByTime:
def test_if_get_stats_by_week_starting_with_monday(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -766,13 +774,13 @@ class TestGetStatsByTime:
def test_it_gets_stats_by_week_starting_with_monday_for_week_13(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -810,13 +818,13 @@ class TestGetStatsByTime:
class TestGetStatsBySport:
def test_it_gets_stats_by_sport(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -850,13 +858,13 @@ class TestGetStatsBySport:
def test_it_get_stats_for_sport_1(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -885,13 +893,13 @@ class TestGetStatsBySport:
def test_it_returns_errors_if_user_does_not_exist(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -914,13 +922,13 @@ class TestGetStatsBySport:
def test_it_returns_error_if_sport_does_not_exist(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -943,13 +951,13 @@ class TestGetStatsBySport:
def test_it_returns_error_if_sport_id_is_invalid(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
seven_activities_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
seven_activities_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -976,8 +984,8 @@ class TestGetStatsBySport:
class TestGetAllStats:
def test_it_returns_all_stats_when_users_have_no_activities(
self, app, user_1_admin, user_2
):
self, app: Flask, user_1_admin: User, user_2: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1005,16 +1013,16 @@ class TestGetAllStats:
def test_it_gets_app_all_stats_with_activities(
self,
app,
user_1_admin,
user_2,
user_3,
sport_1_cycling,
sport_2_running,
activity_cycling_user_1,
activity_cycling_user_2,
activity_running_user_1,
):
app: Flask,
user_1_admin: User,
user_2: User,
user_3: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
activity_cycling_user_1: Activity,
activity_cycling_user_2: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1042,16 +1050,16 @@ class TestGetAllStats:
def test_it_returns_error_if_user_has_no_admin_rights(
self,
app,
user_1,
user_2,
user_3,
sport_1_cycling,
sport_2_running,
activity_cycling_user_1,
activity_cycling_user_2,
activity_running_user_1,
):
app: Flask,
user_1: User,
user_2: User,
user_3: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
activity_cycling_user_1: Activity,
activity_cycling_user_2: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',

View File

@ -1,15 +1,17 @@
import json
from io import BytesIO
from typing import Tuple
from uuid import uuid4
from fittrackee.activities.utils_id import encode_uuid
from flask import Flask
def get_random_short_id():
def get_random_short_id() -> str:
return encode_uuid(uuid4())
def post_an_activity(app, gpx_file):
def post_an_activity(app: Flask, gpx_file: str) -> Tuple[str, str]:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',

View File

@ -1,8 +1,13 @@
import json
from fittrackee.users.models import User
from flask import Flask
class TestGetConfig:
def test_it_gets_application_config(self, app, user_1):
def test_it_gets_application_config(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -33,8 +38,8 @@ class TestGetConfig:
)
def test_it_returns_error_if_application_has_no_config(
self, app_no_config, user_1_admin
):
self, app_no_config: Flask, user_1_admin: User
) -> None:
client = app_no_config.test_client()
resp_login = client.post(
'/api/auth/login',
@ -59,8 +64,8 @@ class TestGetConfig:
assert 'Error on getting configuration.' in data['message']
def test_it_returns_error_if_application_has_several_config(
self, app, app_config, user_1_admin
):
self, app: Flask, app_config: Flask, user_1_admin: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -86,7 +91,9 @@ class TestGetConfig:
class TestUpdateConfig:
def test_it_updates_config_when_user_is_admin(self, app, user_1_admin):
def test_it_updates_config_when_user_is_admin(
self, app: Flask, user_1_admin: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -114,7 +121,9 @@ class TestUpdateConfig:
assert data['data']['max_zip_file_size'] == 10485760
assert data['data']['max_users'] == 10
def test_it_updates_all_config(self, app, user_1_admin):
def test_it_updates_all_config(
self, app: Flask, user_1_admin: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -150,7 +159,9 @@ class TestUpdateConfig:
assert data['data']['max_zip_file_size'] == 25000
assert data['data']['max_users'] == 50
def test_it_returns_403_when_user_is_not_an_admin(self, app, user_1):
def test_it_returns_403_when_user_is_not_an_admin(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -174,7 +185,9 @@ class TestUpdateConfig:
assert 'error' in data['status']
assert 'You do not have permissions.' in data['message']
def test_it_returns_400_if_invalid_is_payload(self, app, user_1_admin):
def test_it_returns_400_if_invalid_is_payload(
self, app: Flask, user_1_admin: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -200,8 +213,8 @@ class TestUpdateConfig:
assert 'Invalid payload.' in data['message']
def test_it_returns_error_on_update_if_application_has_no_config(
self, app_no_config, user_1_admin
):
self, app_no_config: Flask, user_1_admin: User
) -> None:
client = app_no_config.test_client()
resp_login = client.post(
'/api/auth/login',

View File

@ -1,8 +1,9 @@
from fittrackee.application.models import AppConfig
from flask import Flask
class TestConfigModel:
def test_application_config(self, app):
def test_application_config(self, app: Flask) -> None:
app_config = AppConfig.query.first()
assert 1 == app_config.id

View File

@ -1,8 +1,10 @@
import os
from flask import Flask
class TestConfig:
def test_development_config(self, app):
def test_development_config(self, app: Flask) -> None:
app.config.from_object('fittrackee.config.DevelopmentConfig')
assert app.config['DEBUG']
assert not app.config['TESTING']
@ -10,7 +12,7 @@ class TestConfig:
'DATABASE_URL'
)
def test_testing_config(self, app):
def test_testing_config(self, app: Flask) -> None:
app.config.from_object('fittrackee.config.TestingConfig')
assert app.config['DEBUG']
assert app.config['TESTING']

View File

@ -1,8 +1,10 @@
import json
from flask import Flask
class TestHealthCheck:
def test_it_returns_pong_on_health_check(self, app):
def test_it_returns_pong_on_health_check(self, app: Flask) -> None:
""" => Ensure the /health_check route behaves correctly."""
client = app.test_client()
response = client.get('/api/ping')

View File

@ -1,5 +1,6 @@
import datetime
import os
from typing import Generator, Optional
import pytest
from fittrackee import create_app, db
@ -11,10 +12,10 @@ from fittrackee.users.models import User
os.environ['FLASK_ENV'] = 'testing'
os.environ['APP_SETTINGS'] = 'fittrackee.config.TestingConfig'
# to avoid resetting dev database during tests
os.environ['DATABASE_URL'] = os.getenv('DATABASE_TEST_URL')
os.environ['DATABASE_URL'] = os.environ['DATABASE_TEST_URL']
def get_app_config(with_config=False):
def get_app_config(with_config: Optional[bool] = False) -> Optional[AppConfig]:
if with_config:
config = AppConfig()
config.gpx_limit_import = 10
@ -28,7 +29,7 @@ def get_app_config(with_config=False):
return None
def get_app(with_config=False):
def get_app(with_config: Optional[bool] = False) -> Generator:
app = create_app()
with app.app_context():
db.create_all()
@ -46,7 +47,7 @@ def get_app(with_config=False):
@pytest.fixture
def app(monkeypatch):
def app(monkeypatch: pytest.MonkeyPatch) -> Generator:
monkeypatch.setenv('EMAIL_URL', 'smtp://none:none@0.0.0.0:1025')
if os.getenv('TILE_SERVER_URL'):
monkeypatch.delenv('TILE_SERVER_URL')
@ -56,24 +57,24 @@ def app(monkeypatch):
@pytest.fixture
def app_no_config():
def app_no_config() -> Generator:
yield from get_app(with_config=False)
@pytest.fixture
def app_ssl(monkeypatch):
def app_ssl(monkeypatch: pytest.MonkeyPatch) -> Generator:
monkeypatch.setenv('EMAIL_URL', 'smtp://none:none@0.0.0.0:1025?ssl=True')
yield from get_app(with_config=True)
@pytest.fixture
def app_tls(monkeypatch):
def app_tls(monkeypatch: pytest.MonkeyPatch) -> Generator:
monkeypatch.setenv('EMAIL_URL', 'smtp://none:none@0.0.0.0:1025?tls=True')
yield from get_app(with_config=True)
@pytest.fixture()
def app_config():
def app_config() -> AppConfig:
config = AppConfig()
config.gpx_limit_import = 10
config.max_single_file_size = 1048576
@ -85,7 +86,7 @@ def app_config():
@pytest.fixture()
def user_1():
def user_1() -> User:
user = User(username='test', email='test@test.com', password='12345678')
db.session.add(user)
db.session.commit()
@ -93,7 +94,7 @@ def user_1():
@pytest.fixture()
def user_1_admin():
def user_1_admin() -> User:
admin = User(
username='admin', email='admin@example.com', password='12345678'
)
@ -104,7 +105,7 @@ def user_1_admin():
@pytest.fixture()
def user_1_full():
def user_1_full() -> User:
user = User(username='test', email='test@test.com', password='12345678')
user.first_name = 'John'
user.last_name = 'Doe'
@ -119,7 +120,7 @@ def user_1_full():
@pytest.fixture()
def user_1_paris():
def user_1_paris() -> User:
user = User(username='test', email='test@test.com', password='12345678')
user.timezone = 'Europe/Paris'
db.session.add(user)
@ -128,7 +129,7 @@ def user_1_paris():
@pytest.fixture()
def user_2():
def user_2() -> User:
user = User(username='toto', email='toto@toto.com', password='87654321')
db.session.add(user)
db.session.commit()
@ -136,7 +137,7 @@ def user_2():
@pytest.fixture()
def user_2_admin():
def user_2_admin() -> User:
user = User(username='toto', email='toto@toto.com', password='87654321')
user.admin = True
db.session.add(user)
@ -145,7 +146,7 @@ def user_2_admin():
@pytest.fixture()
def user_3():
def user_3() -> User:
user = User(username='sam', email='sam@test.com', password='12345678')
user.weekm = True
db.session.add(user)
@ -154,7 +155,7 @@ def user_3():
@pytest.fixture()
def sport_1_cycling():
def sport_1_cycling() -> Sport:
sport = Sport(label='Cycling')
db.session.add(sport)
db.session.commit()
@ -162,7 +163,7 @@ def sport_1_cycling():
@pytest.fixture()
def sport_1_cycling_inactive():
def sport_1_cycling_inactive() -> Sport:
sport = Sport(label='Cycling')
sport.is_active = False
db.session.add(sport)
@ -171,7 +172,7 @@ def sport_1_cycling_inactive():
@pytest.fixture()
def sport_2_running():
def sport_2_running() -> Sport:
sport = Sport(label='Running')
db.session.add(sport)
db.session.commit()
@ -179,7 +180,7 @@ def sport_2_running():
@pytest.fixture()
def activity_cycling_user_1():
def activity_cycling_user_1() -> Activity:
activity = Activity(
user_id=1,
sport_id=1,
@ -196,7 +197,9 @@ def activity_cycling_user_1():
@pytest.fixture()
def activity_cycling_user_1_segment(activity_cycling_user_1):
def activity_cycling_user_1_segment(
activity_cycling_user_1: Activity,
) -> ActivitySegment:
activity_segment = ActivitySegment(
activity_id=activity_cycling_user_1.id,
activity_uuid=activity_cycling_user_1.uuid,
@ -211,7 +214,7 @@ def activity_cycling_user_1_segment(activity_cycling_user_1):
@pytest.fixture()
def activity_running_user_1():
def activity_running_user_1() -> Activity:
activity = Activity(
user_id=1,
sport_id=2,
@ -226,7 +229,7 @@ def activity_running_user_1():
@pytest.fixture()
def seven_activities_user_1():
def seven_activities_user_1() -> Activity:
activity = Activity(
user_id=1,
sport_id=1,
@ -308,7 +311,7 @@ def seven_activities_user_1():
@pytest.fixture()
def activity_cycling_user_2():
def activity_cycling_user_2() -> Activity:
activity = Activity(
user_id=2,
sport_id=1,
@ -323,7 +326,7 @@ def activity_cycling_user_2():
@pytest.fixture()
def gpx_file():
def gpx_file() -> str:
return (
'<?xml version=\'1.0\' encoding=\'UTF-8\'?>'
'<gpx xmlns:gpxdata="http://www.cluetrust.com/XML/GPXDATA/1/0" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" xmlns:gpxext="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns="http://www.topografix.com/GPX/1/1">' # noqa
@ -438,7 +441,7 @@ def gpx_file():
@pytest.fixture()
def gpx_file_wo_name():
def gpx_file_wo_name() -> str:
return (
'<?xml version=\'1.0\' encoding=\'UTF-8\'?>'
'<gpx xmlns:gpxdata="http://www.cluetrust.com/XML/GPXDATA/1/0" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" xmlns:gpxext="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns="http://www.topografix.com/GPX/1/1">' # noqa
@ -552,7 +555,7 @@ def gpx_file_wo_name():
@pytest.fixture()
def gpx_file_wo_track():
def gpx_file_wo_track() -> str:
return (
'<?xml version=\'1.0\' encoding=\'UTF-8\'?>'
'<gpx xmlns:gpxdata="http://www.cluetrust.com/XML/GPXDATA/1/0" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" xmlns:gpxext="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns="http://www.topografix.com/GPX/1/1">' # noqa
@ -562,7 +565,7 @@ def gpx_file_wo_track():
@pytest.fixture()
def gpx_file_invalid_xml():
def gpx_file_invalid_xml() -> str:
return (
'<?xml version=\'1.0\' encoding=\'UTF-8\'?>'
'<gpx xmlns:gpxdata="http://www.cluetrust.com/XML/GPXDATA/1/0" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" xmlns:gpxext="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns="http://www.topografix.com/GPX/1/1">' # noqa
@ -571,7 +574,7 @@ def gpx_file_invalid_xml():
@pytest.fixture()
def gpx_file_with_segments():
def gpx_file_with_segments() -> str:
return (
'<?xml version=\'1.0\' encoding=\'UTF-8\'?>'
'<gpx xmlns:gpxdata="http://www.cluetrust.com/XML/GPXDATA/1/0" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" xmlns:gpxext="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns="http://www.topografix.com/GPX/1/1">' # noqa

View File

@ -1,13 +1,15 @@
from unittest.mock import patch
from typing import Any
from unittest.mock import Mock, patch
from fittrackee import email_service
from fittrackee.email.email import EmailMessage
from flask import Flask
from ..template_results.password_reset_request import expected_en_text_body
class TestEmailMessage:
def test_it_generate_email_data(self):
def test_it_generate_email_data(self) -> None:
message = EmailMessage(
sender='fittrackee@example.com',
recipient='test@test.com',
@ -40,14 +42,14 @@ class TestEmailSending:
}
@staticmethod
def get_args(call_args):
def get_args(call_args: Any) -> Any:
if len(call_args) == 2:
args, _ = call_args
else:
_, args, _ = call_args
return args
def assert_smtp(self, smtp):
def assert_smtp(self, smtp: Mock) -> None:
assert smtp.sendmail.call_count == 1
call_args = self.get_args(smtp.sendmail.call_args)
assert call_args[0] == 'fittrackee@example.com'
@ -56,7 +58,9 @@ class TestEmailSending:
@patch('smtplib.SMTP_SSL')
@patch('smtplib.SMTP')
def test_it_sends_message(self, mock_smtp, mock_smtp_ssl, app):
def test_it_sends_message(
self, mock_smtp: Mock, mock_smtp_ssl: Mock, app: Flask
) -> None:
email_service.send(
template='password_reset_request',
@ -72,8 +76,8 @@ class TestEmailSending:
@patch('smtplib.SMTP_SSL')
@patch('smtplib.SMTP')
def test_it_sends_message_with_ssl(
self, mock_smtp, mock_smtp_ssl, app_ssl
):
self, mock_smtp: Mock, mock_smtp_ssl: Mock, app_ssl: Flask
) -> None:
email_service.send(
template='password_reset_request',
lang='en',
@ -88,8 +92,8 @@ class TestEmailSending:
@patch('smtplib.SMTP_SSL')
@patch('smtplib.SMTP')
def test_it_sends_message_with_tls(
self, mock_smtp, mock_smtp_ssl, app_tls
):
self, mock_smtp: Mock, mock_smtp_ssl: Mock, app_tls: Flask
) -> None:
email_service.send(
template='password_reset_request',
lang='en',

View File

@ -1,5 +1,6 @@
import pytest
from fittrackee.email.email import EmailTemplate
from flask import Flask
from ..template_results.password_reset_request import (
expected_en_html_body,
@ -17,8 +18,10 @@ class TestEmailTemplateForPasswordRequest:
('fr', 'FitTrackee - Réinitialiser votre mot de passe'),
],
)
def test_it_gets_subject(self, app, lang, expected_subject):
email_template = EmailTemplate(app.config.get('TEMPLATES_FOLDER'))
def test_it_gets_subject(
self, app: Flask, lang: str, expected_subject: str
) -> None:
email_template = EmailTemplate(app.config['TEMPLATES_FOLDER'])
subject = email_template.get_content(
'password_reset_request', lang, 'subject.txt', {}
@ -30,8 +33,10 @@ class TestEmailTemplateForPasswordRequest:
'lang, expected_text_body',
[('en', expected_en_text_body), ('fr', expected_fr_text_body)],
)
def test_it_gets_text_body(self, app, lang, expected_text_body):
email_template = EmailTemplate(app.config.get('TEMPLATES_FOLDER'))
def test_it_gets_text_body(
self, app: Flask, lang: str, expected_text_body: str
) -> None:
email_template = EmailTemplate(app.config['TEMPLATES_FOLDER'])
email_data = {
'expiration_delay': '3 seconds' if lang == 'en' else '3 secondes',
'username': 'test',
@ -46,8 +51,8 @@ class TestEmailTemplateForPasswordRequest:
assert text_body == expected_text_body
def test_it_gets_en_html_body(self, app):
email_template = EmailTemplate(app.config.get('TEMPLATES_FOLDER'))
def test_it_gets_en_html_body(self, app: Flask) -> None:
email_template = EmailTemplate(app.config['TEMPLATES_FOLDER'])
email_data = {
'expiration_delay': '3 seconds',
'username': 'test',
@ -62,8 +67,8 @@ class TestEmailTemplateForPasswordRequest:
assert expected_en_html_body in text_body
def test_it_gets_fr_html_body(self, app):
email_template = EmailTemplate(app.config.get('TEMPLATES_FOLDER'))
def test_it_gets_fr_html_body(self, app: Flask) -> None:
email_template = EmailTemplate(app.config['TEMPLATES_FOLDER'])
email_data = {
'expiration_delay': '3 secondes',
'username': 'test',

View File

@ -3,12 +3,12 @@ from fittrackee.email.utils_email import InvalidEmailUrlScheme, parse_email_url
class TestEmailUrlParser:
def test_it_raises_error_if_url_scheme_is_invalid(self):
def test_it_raises_error_if_url_scheme_is_invalid(self) -> None:
url = 'stmp://username:password@localhost:587'
with pytest.raises(InvalidEmailUrlScheme):
parse_email_url(url)
def test_it_parses_email_url(self):
def test_it_parses_email_url(self) -> None:
url = 'smtp://test@example.com:12345678@localhost:25'
parsed_email = parse_email_url(url)
assert parsed_email['username'] == 'test@example.com'
@ -18,7 +18,7 @@ class TestEmailUrlParser:
assert parsed_email['use_tls'] is False
assert parsed_email['use_ssl'] is False
def test_it_parses_email_url_with_tls(self):
def test_it_parses_email_url_with_tls(self) -> None:
url = 'smtp://test@example.com:12345678@localhost:587?tls=True'
parsed_email = parse_email_url(url)
assert parsed_email['username'] == 'test@example.com'
@ -28,7 +28,7 @@ class TestEmailUrlParser:
assert parsed_email['use_tls'] is True
assert parsed_email['use_ssl'] is False
def test_it_parses_email_url_with_ssl(self):
def test_it_parses_email_url_with_ssl(self) -> None:
url = 'smtp://test@example.com:12345678@localhost:465?ssl=True'
parsed_email = parse_email_url(url)
assert parsed_email['username'] == 'test@example.com'

View File

@ -1,14 +1,17 @@
import json
from datetime import datetime, timedelta
from io import BytesIO
from unittest.mock import patch
from unittest.mock import Mock, patch
from fittrackee.activities.models import Activity, Sport
from fittrackee.users.models import User
from fittrackee.users.utils_token import get_user_token
from flask import Flask
from freezegun import freeze_time
class TestUserRegistration:
def test_user_can_register(self, app):
def test_user_can_register(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
@ -31,7 +34,9 @@ class TestUserRegistration:
assert response.content_type == 'application/json'
assert response.status_code == 201
def test_it_returns_error_if_user_already_exists(self, app, user_1):
def test_it_returns_error_if_user_already_exists(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
response = client.post(
'/api/auth/register',
@ -51,7 +56,9 @@ class TestUserRegistration:
assert response.content_type == 'application/json'
assert response.status_code == 400
def test_it_returns_error_if_username_is_too_short(self, app):
def test_it_returns_error_if_username_is_too_short(
self, app: Flask
) -> None:
client = app.test_client()
response = client.post(
@ -73,7 +80,9 @@ class TestUserRegistration:
assert response.content_type == 'application/json'
assert response.status_code == 400
def test_it_returns_error_if_username_is_too_long(self, app):
def test_it_returns_error_if_username_is_too_long(
self, app: Flask
) -> None:
client = app.test_client()
response = client.post(
'/api/auth/register',
@ -93,7 +102,7 @@ class TestUserRegistration:
assert response.content_type == 'application/json'
assert response.status_code == 400
def test_it_returns_error_if_email_is_invalid(self, app):
def test_it_returns_error_if_email_is_invalid(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
@ -115,7 +124,9 @@ class TestUserRegistration:
assert response.content_type == 'application/json'
assert response.status_code == 400
def test_it_returns_error_if_password_is_too_short(self, app):
def test_it_returns_error_if_password_is_too_short(
self, app: Flask
) -> None:
client = app.test_client()
response = client.post(
@ -137,7 +148,7 @@ class TestUserRegistration:
assert response.content_type == 'application/json'
assert response.status_code == 400
def test_it_returns_error_if_passwords_mismatch(self, app):
def test_it_returns_error_if_passwords_mismatch(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
@ -162,7 +173,7 @@ class TestUserRegistration:
assert response.content_type == 'application/json'
assert response.status_code == 400
def test_it_returns_error_if_payload_is_invalid(self, app):
def test_it_returns_error_if_payload_is_invalid(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
'/api/auth/register',
@ -174,7 +185,7 @@ class TestUserRegistration:
assert 'Invalid payload.', data['message']
assert 'error', data['status']
def test_it_returns_error_if_username_is_missing(self, app):
def test_it_returns_error_if_username_is_missing(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
@ -194,7 +205,7 @@ class TestUserRegistration:
assert 'Invalid payload.' in data['message']
assert 'error' in data['status']
def test_it_returns_error_if_email_is_missing(self, app):
def test_it_returns_error_if_email_is_missing(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
@ -214,7 +225,7 @@ class TestUserRegistration:
assert 'Invalid payload.' in data['message']
assert 'error' in data['status']
def test_it_returns_error_if_password_is_missing(self, app):
def test_it_returns_error_if_password_is_missing(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
@ -234,7 +245,9 @@ class TestUserRegistration:
assert 'Invalid payload.', data['message']
assert 'error', data['status']
def test_it_returns_error_if_password_confirmation_is_missing(self, app):
def test_it_returns_error_if_password_confirmation_is_missing(
self, app: Flask
) -> None:
client = app.test_client()
response = client.post(
'/api/auth/register',
@ -250,7 +263,7 @@ class TestUserRegistration:
assert 'Invalid payload.' in data['message']
assert 'error' in data['status']
def test_it_returns_error_if_username_is_invalid(self, app):
def test_it_returns_error_if_username_is_invalid(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
@ -276,7 +289,7 @@ class TestUserRegistration:
class TestUserLogin:
def test_user_can_register(self, app, user_1):
def test_user_can_register(self, app: Flask, user_1: User) -> None:
client = app.test_client()
response = client.post(
@ -292,7 +305,9 @@ class TestUserLogin:
assert data['message'] == 'Successfully logged in.'
assert data['auth_token']
def test_it_returns_error_if_user_does_not_exists(self, app):
def test_it_returns_error_if_user_does_not_exists(
self, app: Flask
) -> None:
client = app.test_client()
response = client.post(
@ -307,7 +322,7 @@ class TestUserLogin:
assert data['status'] == 'error'
assert data['message'] == 'Invalid credentials.'
def test_it_returns_error_on_invalid_payload(self, app):
def test_it_returns_error_on_invalid_payload(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
@ -322,7 +337,9 @@ class TestUserLogin:
assert data['status'] == 'error'
assert data['message'] == 'Invalid payload.'
def test_it_returns_error_if_password_is_invalid(self, app, user_1):
def test_it_returns_error_if_password_is_invalid(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
response = client.post(
@ -339,7 +356,7 @@ class TestUserLogin:
class TestUserLogout:
def test_user_can_logout(self, app, user_1):
def test_user_can_logout(self, app: Flask, user_1: User) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -360,7 +377,9 @@ class TestUserLogout:
assert data['message'] == 'Successfully logged out.'
assert response.status_code == 200
def test_it_returns_error_with_expired_token(self, app, user_1):
def test_it_returns_error_with_expired_token(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
now = datetime.utcnow()
resp_login = client.post(
@ -381,7 +400,7 @@ class TestUserLogout:
assert data['message'] == 'Signature expired. Please log in again.'
assert response.status_code == 401
def test_it_returns_error_with_invalid_token(self, app):
def test_it_returns_error_with_invalid_token(self, app: Flask) -> None:
client = app.test_client()
response = client.get(
'/api/auth/logout', headers=dict(Authorization='Bearer invalid')
@ -391,7 +410,7 @@ class TestUserLogout:
assert data['message'] == 'Invalid token. Please log in again.'
assert response.status_code == 401
def test_it_returns_error_with_invalid_headers(self, app):
def test_it_returns_error_with_invalid_headers(self, app: Flask) -> None:
client = app.test_client()
response = client.get('/api/auth/logout', headers=dict())
data = json.loads(response.data.decode())
@ -401,7 +420,9 @@ class TestUserLogout:
class TestUserProfile:
def test_it_returns_user_minimal_profile(self, app, user_1):
def test_it_returns_user_minimal_profile(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -432,7 +453,9 @@ class TestUserProfile:
assert data['data']['total_duration'] == '0:00:00'
assert response.status_code == 200
def test_it_returns_user_full_profile(self, app, user_1_full):
def test_it_returns_user_full_profile(
self, app: Flask, user_1_full: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -470,13 +493,13 @@ class TestUserProfile:
def test_it_returns_user_profile_with_activities(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
activity_cycling_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
activity_cycling_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -505,7 +528,7 @@ class TestUserProfile:
assert data['data']['total_duration'] == '2:40:00'
assert response.status_code == 200
def test_it_returns_error_if_headers_are_invalid(self, app):
def test_it_returns_error_if_headers_are_invalid(self, app: Flask) -> None:
client = app.test_client()
response = client.get(
'/api/auth/profile', headers=dict(Authorization='Bearer invalid')
@ -517,7 +540,7 @@ class TestUserProfile:
class TestUserProfileUpdate:
def test_it_updates_user_profile(self, app, user_1):
def test_it_updates_user_profile(self, app: Flask, user_1: User) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -568,7 +591,9 @@ class TestUserProfileUpdate:
assert data['data']['total_distance'] == 0
assert data['data']['total_duration'] == '0:00:00'
def test_it_updates_user_profile_without_password(self, app, user_1):
def test_it_updates_user_profile_without_password(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -617,7 +642,9 @@ class TestUserProfileUpdate:
assert data['data']['total_distance'] == 0
assert data['data']['total_duration'] == '0:00:00'
def test_it_returns_error_if_fields_are_missing(self, app, user_1):
def test_it_returns_error_if_fields_are_missing(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -638,7 +665,9 @@ class TestUserProfileUpdate:
assert data['message'] == 'Invalid payload.'
assert response.status_code == 400
def test_it_returns_error_if_payload_is_empty(self, app, user_1):
def test_it_returns_error_if_payload_is_empty(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -659,7 +688,9 @@ class TestUserProfileUpdate:
assert 'Invalid payload.' in data['message']
assert 'error' in data['status']
def test_it_returns_error_if_passwords_mismatch(self, app, user_1):
def test_it_returns_error_if_passwords_mismatch(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -697,8 +728,8 @@ class TestUserProfileUpdate:
assert response.status_code == 400
def test_it_returns_error_if_password_confirmation_is_missing(
self, app, user_1
):
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -736,7 +767,7 @@ class TestUserProfileUpdate:
class TestUserPicture:
def test_it_updates_user_picture(self, app, user_1):
def test_it_updates_user_picture(self, app: Flask, user_1: User) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -774,7 +805,9 @@ class TestUserPicture:
assert 'avatar.png' not in user_1.picture
assert 'avatar2.png' in user_1.picture
def test_it_returns_error_if_file_is_missing(self, app, user_1):
def test_it_returns_error_if_file_is_missing(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -794,7 +827,9 @@ class TestUserPicture:
assert data['message'] == 'No file part.'
assert response.status_code == 400
def test_it_returns_error_if_file_is_invalid(self, app, user_1):
def test_it_returns_error_if_file_is_invalid(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -818,8 +853,8 @@ class TestUserPicture:
class TestRegistrationConfiguration:
def test_it_returns_error_if_it_exceeds_max_users(
self, app, user_1_admin, user_2, user_3
):
self, app: Flask, user_1_admin: User, user_2: User, user_3: User
) -> None:
client = app.test_client()
resp_login = client.post(
@ -859,8 +894,12 @@ class TestRegistrationConfiguration:
assert data['message'] == 'Error. Registration is disabled.'
def test_it_disables_registration_on_user_registration(
self, app_no_config, app_config, user_1_admin, user_2
):
self,
app_no_config: Flask,
app_config: Flask,
user_1_admin: User,
user_2: User,
) -> None:
app_config.max_users = 3
client = app_no_config.test_client()
client.post(
@ -894,11 +933,11 @@ class TestRegistrationConfiguration:
def test_it_does_not_disable_registration_on_user_registration(
self,
app_no_config,
app_config,
user_1_admin,
user_2,
):
app_no_config: Flask,
app_config: Flask,
user_1_admin: User,
user_2: User,
) -> None:
app_config.max_users = 4
client = app_no_config.test_client()
client.post(
@ -932,8 +971,8 @@ class TestPasswordResetRequest:
@patch('smtplib.SMTP_SSL')
@patch('smtplib.SMTP')
def test_it_requests_password_reset_when_user_exists(
self, mock_smtp, mock_smtp_ssl, app, user_1
):
self, mock_smtp: Mock, mock_smtp_ssl: Mock, app: Flask, user_1: User
) -> None:
client = app.test_client()
response = client.post(
'/api/auth/password/reset-request',
@ -946,7 +985,9 @@ class TestPasswordResetRequest:
assert data['status'] == 'success'
assert data['message'] == 'Password reset request processed.'
def test_it_does_not_return_error_when_user_does_not_exist(self, app):
def test_it_does_not_return_error_when_user_does_not_exist(
self, app: Flask
) -> None:
client = app.test_client()
response = client.post(
@ -960,7 +1001,7 @@ class TestPasswordResetRequest:
assert data['status'] == 'success'
assert data['message'] == 'Password reset request processed.'
def test_it_returns_error_on_invalid_payload(self, app):
def test_it_returns_error_on_invalid_payload(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
@ -974,7 +1015,7 @@ class TestPasswordResetRequest:
assert data['message'] == 'Invalid payload.'
assert data['status'] == 'error'
def test_it_returns_error_on_empty_payload(self, app):
def test_it_returns_error_on_empty_payload(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
@ -990,7 +1031,7 @@ class TestPasswordResetRequest:
class TestPasswordUpdate:
def test_it_returns_error_if_payload_is_empty(self, app):
def test_it_returns_error_if_payload_is_empty(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
@ -1009,7 +1050,7 @@ class TestPasswordUpdate:
assert data['status'] == 'error'
assert data['message'] == 'Invalid payload.'
def test_it_returns_error_if_token_is_missing(self, app):
def test_it_returns_error_if_token_is_missing(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
@ -1028,7 +1069,7 @@ class TestPasswordUpdate:
assert data['status'] == 'error'
assert data['message'] == 'Invalid payload.'
def test_it_returns_error_if_password_is_missing(self, app):
def test_it_returns_error_if_password_is_missing(self, app: Flask) -> None:
client = app.test_client()
response = client.post(
@ -1047,7 +1088,9 @@ class TestPasswordUpdate:
assert data['status'] == 'error'
assert data['message'] == 'Invalid payload.'
def test_it_returns_error_if_password_confirmation_is_missing(self, app):
def test_it_returns_error_if_password_confirmation_is_missing(
self, app: Flask
) -> None:
client = app.test_client()
response = client.post(
@ -1066,7 +1109,7 @@ class TestPasswordUpdate:
assert data['status'] == 'error'
assert data['message'] == 'Invalid payload.'
def test_it_returns_error_if_token_is_invalid(self, app):
def test_it_returns_error_if_token_is_invalid(self, app: Flask) -> None:
token = get_user_token(1)
client = app.test_client()
@ -1087,7 +1130,9 @@ class TestPasswordUpdate:
assert data['status'] == 'error'
assert data['message'] == 'Invalid token. Please request a new token.'
def test_it_returns_error_if_token_is_expired(self, app, user_1):
def test_it_returns_error_if_token_is_expired(
self, app: Flask, user_1: User
) -> None:
now = datetime.utcnow()
token = get_user_token(user_1.id, password_reset=True)
client = app.test_client()
@ -1112,7 +1157,9 @@ class TestPasswordUpdate:
data['message'] == 'Invalid token. Please request a new token.'
)
def test_it_returns_error_if_password_is_invalid(self, app, user_1):
def test_it_returns_error_if_password_is_invalid(
self, app: Flask, user_1: User
) -> None:
token = get_user_token(user_1.id, password_reset=True)
client = app.test_client()
@ -1133,7 +1180,7 @@ class TestPasswordUpdate:
assert data['status'] == 'error'
assert data['message'] == 'Password: 8 characters required.\n'
def test_it_update_password(self, app, user_1):
def test_it_update_password(self, app: Flask, user_1: User) -> None:
token = get_user_token(user_1.id, password_reset=True)
client = app.test_client()

View File

@ -3,9 +3,15 @@ from datetime import datetime, timedelta
from io import BytesIO
from unittest.mock import patch
from fittrackee.activities.models import Activity, Sport
from fittrackee.users.models import User
from flask import Flask
class TestGetUser:
def test_it_gets_single_user_without_activities(self, app, user_1, user_2):
def test_it_gets_single_user_without_activities(
self, app: Flask, user_1: User, user_2: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -47,13 +53,13 @@ class TestGetUser:
def test_it_gets_single_user_with_activities(
self,
app,
user_1,
sport_1_cycling,
sport_2_running,
activity_cycling_user_1,
activity_running_user_1,
):
app: Flask,
user_1: User,
sport_1_cycling: Sport,
sport_2_running: Sport,
activity_cycling_user_1: Activity,
activity_running_user_1: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -93,7 +99,9 @@ class TestGetUser:
assert user['total_distance'] == 22
assert user['total_duration'] == '2:40:00'
def test_it_returns_error_if_user_does_not_exist(self, app, user_1):
def test_it_returns_error_if_user_does_not_exist(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -116,7 +124,9 @@ class TestGetUser:
class TestGetUsers:
def test_it_get_users_list(self, app, user_1, user_2, user_3):
def test_it_get_users_list(
self, app: Flask, user_1: User, user_2: User, user_3: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -179,16 +189,16 @@ class TestGetUsers:
def test_it_gets_users_list_with_activities(
self,
app,
user_1,
user_2,
user_3,
sport_1_cycling,
activity_cycling_user_1,
sport_2_running,
activity_running_user_1,
activity_cycling_user_2,
):
app: Flask,
user_1: User,
user_2: User,
user_3: User,
sport_1_cycling: Sport,
activity_cycling_user_1: Activity,
sport_2_running: Sport,
activity_running_user_1: Activity,
activity_cycling_user_2: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -249,11 +259,11 @@ class TestGetUsers:
@patch('fittrackee.users.users.USER_PER_PAGE', 2)
def test_it_gets_first_page_on_users_list(
self,
app,
user_1,
user_2,
user_3,
):
app: Flask,
user_1: User,
user_2: User,
user_3: User,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -284,11 +294,11 @@ class TestGetUsers:
@patch('fittrackee.users.users.USER_PER_PAGE', 2)
def test_it_gets_next_page_on_users_list(
self,
app,
user_1,
user_2,
user_3,
):
app: Flask,
user_1: User,
user_2: User,
user_3: User,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -318,11 +328,11 @@ class TestGetUsers:
def test_it_gets_empty_next_page_on_users_list(
self,
app,
user_1,
user_2,
user_3,
):
app: Flask,
user_1: User,
user_2: User,
user_3: User,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -352,11 +362,11 @@ class TestGetUsers:
def test_it_gets_user_list_with_2_per_page(
self,
app,
user_1,
user_2,
user_3,
):
app: Flask,
user_1: User,
user_2: User,
user_3: User,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -386,11 +396,11 @@ class TestGetUsers:
def test_it_gets_next_page_on_user_list_with_2_per_page(
self,
app,
user_1,
user_2,
user_3,
):
app: Flask,
user_1: User,
user_2: User,
user_3: User,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -419,8 +429,8 @@ class TestGetUsers:
}
def test_it_gets_users_list_ordered_by_username(
self, app, user_1, user_2, user_3
):
self, app: Flask, user_1: User, user_2: User, user_3: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -451,8 +461,8 @@ class TestGetUsers:
}
def test_it_gets_users_list_ordered_by_username_ascending(
self, app, user_1, user_2, user_3
):
self, app: Flask, user_1: User, user_2: User, user_3: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -484,8 +494,8 @@ class TestGetUsers:
}
def test_it_gets_users_list_ordered_by_username_descending(
self, app, user_1, user_2, user_3
):
self, app: Flask, user_1: User, user_2: User, user_3: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -517,8 +527,8 @@ class TestGetUsers:
}
def test_it_gets_users_list_ordered_by_creation_date(
self, app, user_2, user_3, user_1_admin
):
self, app: Flask, user_2: User, user_3: User, user_1_admin: User
) -> None:
user_2.created_at = datetime.utcnow() - timedelta(days=1)
user_3.created_at = datetime.utcnow() - timedelta(hours=1)
user_1_admin.created_at = datetime.utcnow()
@ -555,8 +565,8 @@ class TestGetUsers:
}
def test_it_gets_users_list_ordered_by_creation_date_ascending(
self, app, user_2, user_3, user_1_admin
):
self, app: Flask, user_2: User, user_3: User, user_1_admin: User
) -> None:
user_2.created_at = datetime.utcnow() - timedelta(days=1)
user_3.created_at = datetime.utcnow() - timedelta(hours=1)
user_1_admin.created_at = datetime.utcnow()
@ -593,8 +603,8 @@ class TestGetUsers:
}
def test_it_gets_users_list_ordered_by_creation_date_descending(
self, app, user_2, user_3, user_1_admin
):
self, app: Flask, user_2: User, user_3: User, user_1_admin: User
) -> None:
user_2.created_at = datetime.utcnow() - timedelta(days=1)
user_3.created_at = datetime.utcnow() - timedelta(hours=1)
user_1_admin.created_at = datetime.utcnow()
@ -631,8 +641,8 @@ class TestGetUsers:
}
def test_it_gets_users_list_ordered_by_admin_rights(
self, app, user_2, user_1_admin, user_3
):
self, app: Flask, user_2: User, user_1_admin: User, user_3: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -666,8 +676,8 @@ class TestGetUsers:
}
def test_it_gets_users_list_ordered_by_admin_rights_ascending(
self, app, user_2, user_1_admin, user_3
):
self, app: Flask, user_2: User, user_1_admin: User, user_3: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -701,8 +711,8 @@ class TestGetUsers:
}
def test_it_gets_users_list_ordered_by_admin_rights_descending(
self, app, user_2, user_3, user_1_admin
):
self, app: Flask, user_2: User, user_3: User, user_1_admin: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -737,13 +747,13 @@ class TestGetUsers:
def test_it_gets_users_list_ordered_by_activities_count(
self,
app,
user_1,
user_2,
user_3,
sport_1_cycling,
activity_cycling_user_2,
):
app: Flask,
user_1: User,
user_2: User,
user_3: User,
sport_1_cycling: Sport,
activity_cycling_user_2: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -779,13 +789,13 @@ class TestGetUsers:
def test_it_gets_users_list_ordered_by_activities_count_ascending(
self,
app,
user_1,
user_2,
user_3,
sport_1_cycling,
activity_cycling_user_2,
):
app: Flask,
user_1: User,
user_2: User,
user_3: User,
sport_1_cycling: Sport,
activity_cycling_user_2: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -821,13 +831,13 @@ class TestGetUsers:
def test_it_gets_users_list_ordered_by_activities_count_descending(
self,
app,
user_1,
user_2,
user_3,
sport_1_cycling,
activity_cycling_user_2,
):
app: Flask,
user_1: User,
user_2: User,
user_3: User,
sport_1_cycling: Sport,
activity_cycling_user_2: Activity,
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -862,8 +872,8 @@ class TestGetUsers:
}
def test_it_gets_users_list_filtering_on_username(
self, app, user_1, user_2, user_3
):
self, app: Flask, user_1: User, user_2: User, user_3: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -893,8 +903,8 @@ class TestGetUsers:
}
def test_it_returns_empty_users_list_filtering_on_username(
self, app, user_1, user_2, user_3
):
self, app: Flask, user_1: User, user_2: User, user_3: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -923,8 +933,8 @@ class TestGetUsers:
}
def test_it_users_list_with_complex_query(
self, app, user_1, user_2, user_3
):
self, app: Flask, user_1: User, user_2: User, user_3: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -955,7 +965,9 @@ class TestGetUsers:
class TestGetUserPicture:
def test_it_return_error_if_user_has_no_picture(self, app, user_1):
def test_it_return_error_if_user_has_no_picture(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
response = client.get(f'/api/users/{user_1.username}/picture')
@ -965,7 +977,9 @@ class TestGetUserPicture:
assert 'not found' in data['status']
assert 'No picture.' in data['message']
def test_it_returns_error_if_user_does_not_exist(self, app, user_1):
def test_it_returns_error_if_user_does_not_exist(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
response = client.get('/api/users/not_existing/picture')
@ -977,7 +991,9 @@ class TestGetUserPicture:
class TestUpdateUser:
def test_it_adds_admin_rights_to_a_user(self, app, user_1_admin, user_2):
def test_it_adds_admin_rights_to_a_user(
self, app: Flask, user_1_admin: User, user_2: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1006,8 +1022,8 @@ class TestUpdateUser:
assert user['admin'] is True
def test_it_removes_admin_rights_to_a_user(
self, app, user_1_admin, user_2
):
self, app: Flask, user_1_admin: User, user_2: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1037,8 +1053,8 @@ class TestUpdateUser:
assert user['admin'] is False
def test_it_returns_error_if_payload_for_admin_rights_is_empty(
self, app, user_1_admin, user_2
):
self, app: Flask, user_1_admin: User, user_2: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1064,8 +1080,8 @@ class TestUpdateUser:
assert 'Invalid payload.' in data['message']
def test_it_returns_error_if_payload_for_admin_rights_is_invalid(
self, app, user_1_admin, user_2
):
self, app: Flask, user_1_admin: User, user_2: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1094,8 +1110,8 @@ class TestUpdateUser:
)
def test_it_returns_error_if_user_can_not_change_admin_rights(
self, app, user_1, user_2
):
self, app: Flask, user_1: User, user_2: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1120,7 +1136,9 @@ class TestUpdateUser:
class TestDeleteUser:
def test_user_can_delete_its_own_account(self, app, user_1):
def test_user_can_delete_its_own_account(
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1139,8 +1157,8 @@ class TestDeleteUser:
assert response.status_code == 204
def test_user_with_activity_can_delete_its_own_account(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1171,8 +1189,8 @@ class TestDeleteUser:
assert response.status_code == 204
def test_user_with_picture_can_delete_its_own_account(
self, app, user_1, sport_1_cycling, gpx_file
):
self, app: Flask, user_1: User, sport_1_cycling: Sport, gpx_file: str
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1200,8 +1218,8 @@ class TestDeleteUser:
assert response.status_code == 204
def test_user_can_not_delete_another_user_account(
self, app, user_1, user_2
):
self, app: Flask, user_1: User, user_2: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1223,8 +1241,8 @@ class TestDeleteUser:
assert 'You do not have permissions.' in data['message']
def test_it_returns_error_when_deleting_non_existing_user(
self, app, user_1
):
self, app: Flask, user_1: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1246,8 +1264,8 @@ class TestDeleteUser:
assert 'User does not exist.' in data['message']
def test_admin_can_delete_another_user_account(
self, app, user_1_admin, user_2
):
self, app: Flask, user_1_admin: User, user_2: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1268,8 +1286,8 @@ class TestDeleteUser:
assert response.status_code == 204
def test_admin_can_delete_its_own_account(
self, app, user_1_admin, user_2_admin
):
self, app: Flask, user_1_admin: User, user_2_admin: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1290,8 +1308,8 @@ class TestDeleteUser:
assert response.status_code == 204
def test_admin_can_not_delete_its_own_account_if_no_other_admin(
self, app, user_1_admin, user_2
):
self, app: Flask, user_1_admin: User, user_2: User
) -> None:
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
@ -1317,8 +1335,13 @@ class TestDeleteUser:
)
def test_it_enables_registration_on_user_delete(
self, app_no_config, app_config, user_1_admin, user_2, user_3
):
self,
app_no_config: Flask,
app_config: Flask,
user_1_admin: User,
user_2: User,
user_3: User,
) -> None:
app_config.max_users = 3
client = app_no_config.test_client()
resp_login = client.post(
@ -1351,8 +1374,13 @@ class TestDeleteUser:
assert response.status_code == 201
def test_it_does_not_enable_registration_on_user_delete(
self, app_no_config, app_config, user_1_admin, user_2, user_3
):
self,
app_no_config: Flask,
app_config: Flask,
user_1_admin: User,
user_2: User,
user_3: User,
) -> None:
app_config.max_users = 2
client = app_no_config.test_client()
resp_login = client.post(

View File

@ -1,8 +1,9 @@
from fittrackee.users.models import User
from flask import Flask
class TestUserModel:
def test_user_model(self, app, user_1):
def test_user_model(self, app: Flask, user_1: User) -> None:
assert '<User \'test\'>' == str(user_1)
serialized_user = user_1.serialize()
@ -23,15 +24,15 @@ class TestUserModel:
assert serialized_user['total_distance'] == 0
assert serialized_user['total_duration'] == '0:00:00'
def test_encode_auth_token(self, app, user_1):
def test_encode_auth_token(self, app: Flask, user_1: User) -> None:
auth_token = user_1.encode_auth_token(user_1.id)
assert isinstance(auth_token, str)
def test_encode_password_token(self, app, user_1):
def test_encode_password_token(self, app: Flask, user_1: User) -> None:
password_token = user_1.encode_password_reset_token(user_1.id)
assert isinstance(password_token, str)
def test_decode_auth_token(self, app, user_1):
def test_decode_auth_token(self, app: Flask, user_1: User) -> None:
auth_token = user_1.encode_auth_token(user_1.id)
assert isinstance(auth_token, str)
assert User.decode_auth_token(auth_token) == user_1.id