API - add typing
This commit is contained in:
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user