diff --git a/src/apps/job/tests/test_jobs_services.py b/src/apps/job/tests/test_jobs_services.py index 7eba1d08b3a..d8fc7382661 100644 --- a/src/apps/job/tests/test_jobs_services.py +++ b/src/apps/job/tests/test_jobs_services.py @@ -5,7 +5,7 @@ from apps.job.crud import JobCRUD from apps.job.db.schemas import JobSchema from apps.job.service import JobService -from apps.users.db.schemas import UserSchema +from apps.users.domain import User @pytest.mark.parametrize("status,", (JobStatus.in_progress, JobStatus.pending, JobStatus.retry)) @@ -54,31 +54,29 @@ async def test_change_status_without_details( assert job_updated.status == JobStatus.success -async def test_get_or_create_owned__create_job_default_status_is_pending( - session: AsyncSession, tom: UserSchema -) -> None: - job_name = "tomjob" - srv = JobService(session, tom.id) +async def test_get_or_create_owned__create_job_default_status_is_pending(session: AsyncSession, user: User) -> None: + job_name = "userjob" + srv = JobService(session, user.id) job = await srv.get_or_create_owned(job_name) assert job.status == JobStatus.pending - assert job.creator_id == tom.id + assert job.creator_id == user.id assert job.name == job_name -async def test_get_or_create_owned__create_job_with_status_in_progress(session: AsyncSession, tom: UserSchema) -> None: - job_name = "tomjob" - srv = JobService(session, tom.id) +async def test_get_or_create_owned__create_job_with_status_in_progress(session: AsyncSession, user: User) -> None: + job_name = "userjob" + srv = JobService(session, user.id) job = await srv.get_or_create_owned(job_name, status=JobStatus.in_progress) assert job.status == JobStatus.in_progress async def test_get_or_create_owned__create_job_with_details( session: AsyncSession, - tom: UserSchema, + user: User, job_details: dict[str, str], ) -> None: - job_name = "tomjob" - srv = JobService(session, tom.id) + job_name = "userjob" + srv = JobService(session, user.id) job = await srv.get_or_create_owned(job_name, details=job_details) assert job.details == job_details diff --git a/src/apps/logs/tests.py b/src/apps/logs/tests.py index 9a785c55133..3a8b21a0c8d 100644 --- a/src/apps/logs/tests.py +++ b/src/apps/logs/tests.py @@ -1,4 +1,3 @@ -import uuid from pytest import fixture, mark @@ -7,7 +6,7 @@ EMPTY_DESCRIPTIONS = [ dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test1", notification_descriptions=None, notification_in_queue=[{"name": "in_queue1"}], @@ -15,7 +14,7 @@ ), dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test2", notification_descriptions=[], notification_in_queue=[{"name": "in_queue2"}], @@ -23,7 +22,7 @@ ), dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test3", notification_descriptions=None, notification_in_queue=[{"name": "in_queue2"}], @@ -34,7 +33,7 @@ EMPTY_QUEUE = [ dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test1", notification_descriptions=[{"name": "description"}], notification_in_queue=None, @@ -42,7 +41,7 @@ ), dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test2", notification_descriptions=[{"name": "description"}], notification_in_queue=[], @@ -50,7 +49,7 @@ ), dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test3", notification_descriptions=[{"name": "description"}], notification_in_queue=None, @@ -61,7 +60,7 @@ EMPTY_SCHEDULE = [ dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test1", notification_descriptions=[{"name": "description"}], notification_in_queue=[{"name": "in_queue1"}], @@ -69,7 +68,7 @@ ), dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test2", notification_descriptions=[{"name": "description"}], notification_in_queue=[{"name": "in_queue2"}], @@ -77,7 +76,7 @@ ), dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test3", notification_descriptions=[{"name": "description"}], notification_in_queue=[{"name": "in_queue2"}], @@ -91,7 +90,7 @@ def dummy_logs_payload() -> list[dict]: return [ dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type=f"test{i}", notification_descriptions=[{"sample": f"descriptions{i}"}], notification_in_queue=[{"sample": f"queue{i}"}], @@ -103,14 +102,11 @@ def dummy_logs_payload() -> list[dict]: class TestNotificationLogs(BaseTest): logs_url = "/logs/notification" - fixtures = [ - "users/fixtures/user_devices.json", - ] - async def test_create_log(self, client): + async def test_create_log(self, client, device_tom): create_data = dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test", notification_descriptions=[{"sample": "json"}], notification_in_queue=[{"sample": "json"}], @@ -121,10 +117,10 @@ async def test_create_log(self, client): assert response.status_code == 201, response.json() assert response.json()["result"]["id"] - async def test_retrieve_log(self, client): + async def test_retrieve_log(self, client, device_tom): query = dict( email="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id=device_tom, ) response = await client.get(self.logs_url, query=query) @@ -132,9 +128,10 @@ async def test_retrieve_log(self, client): assert response.status_code == 200, response.json() assert isinstance(response.json()["result"], list) + new_device_id = "new_device_id" create_data = dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id=new_device_id, action_type="test", notification_descriptions=[{"sample": "json"}], notification_in_queue=[{"sample": "json"}], @@ -147,7 +144,7 @@ async def test_retrieve_log(self, client): query = dict( email="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id=new_device_id, limit=10, ) @@ -178,7 +175,7 @@ async def test_create_log_use_previous_value_if_attribute_null( create_data = dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test", notification_descriptions=description, notification_in_queue=queue, @@ -198,7 +195,7 @@ async def test_create_log_use_none_value_if_attribute_null_at_first_log(self, cl self.logs_url, data=dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test", notification_descriptions=None, notification_in_queue=[{"name": "notification_in_queue"}], @@ -216,7 +213,7 @@ async def test_create_log_use_previous_non_null_if_attribute_null(self, client): payloads = [ dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test", notification_descriptions=[{"name": "descriptions1"}], notification_in_queue=[{"name": "in_queue1"}], @@ -224,7 +221,7 @@ async def test_create_log_use_previous_non_null_if_attribute_null(self, client): ), dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test", notification_descriptions=None, notification_in_queue=[{"name": "in_queue2"}], @@ -237,7 +234,7 @@ async def test_create_log_use_previous_non_null_if_attribute_null(self, client): create_data = dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test", notification_descriptions=None, notification_in_queue=[{"name": "in_queue3"}], @@ -256,7 +253,7 @@ async def test_create_log_allow_empty_array(self, client): payloads = [ dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test", notification_descriptions=[{"name": "descriptions1"}], notification_in_queue=[{"name": "in_queue1"}], @@ -264,7 +261,7 @@ async def test_create_log_allow_empty_array(self, client): ), dict( user_id="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", action_type="test", notification_descriptions=[], notification_in_queue=[{"name": "in_queue2"}], @@ -278,7 +275,7 @@ async def test_create_log_allow_empty_array(self, client): query = dict( email="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", limit=5, ) @@ -309,7 +306,7 @@ async def test_create_log_allow_empty_array_if_prev_is_none(self, client, param, query = dict( email="tom@mindlogger.com", - device_id=str(uuid.uuid4()), + device_id="deviceid", limit=5, ) diff --git a/src/apps/users/services/user.py b/src/apps/users/services/user.py index ce03cf5d8c0..c7a73de8266 100644 --- a/src/apps/users/services/user.py +++ b/src/apps/users/services/user.py @@ -15,13 +15,13 @@ def __init__(self, session) -> None: self.session = session # TODO: Remove later, keep for now for backward compatibility for tests - async def create_superuser(self, uuid_: uuid.UUID = uuid.uuid4()) -> None: + async def create_superuser(self, test_id: uuid.UUID = uuid.uuid4()) -> None: crud = UsersCRUD(self.session) super_admin = await crud.get_super_admin() # Let's keep this frozen feature if super_admin is None: super_admin = UserSchema( - id=uuid_, + id=test_id, email=hash_sha224(settings.super_admin.email), first_name=settings.super_admin.first_name, last_name=settings.super_admin.last_name, @@ -38,12 +38,12 @@ async def create_superuser(self, uuid_: uuid.UUID = uuid.uuid4()) -> None: await UserWorkspaceCRUD(self.session).save(schema=workspace) # TODO: Remove later, keep for now for backward compatibility for tests - async def create_anonymous_respondent(self, uuid_: uuid.UUID = uuid.uuid4()) -> None: + async def create_anonymous_respondent(self, test_id: uuid.UUID = uuid.uuid4()) -> None: crud = UsersCRUD(self.session) anonymous_respondent = await crud.get_anonymous_respondent() if not anonymous_respondent: anonymous_respondent = UserSchema( - id=uuid_, + id=test_id, email=hash_sha224(settings.anonymous_respondent.email), first_name=settings.anonymous_respondent.first_name, last_name=settings.anonymous_respondent.last_name, @@ -55,16 +55,26 @@ async def create_anonymous_respondent(self, uuid_: uuid.UUID = uuid.uuid4()) -> ) await crud.save(anonymous_respondent) - async def create_user(self, data: UserCreate) -> User: - user_schema = await UsersCRUD(self.session).save( - UserSchema( + # TODO: remove test_id, when all JSON fixtures are deleted + async def create_user(self, data: UserCreate, test_id: uuid.UUID | None = None) -> User: + if test_id is not None: + schema = UserSchema( + id=test_id, email=data.hashed_email, first_name=data.first_name, last_name=data.last_name, hashed_password=data.hashed_password, email_encrypted=data.email, ) - ) + else: + schema = UserSchema( + email=data.hashed_email, + first_name=data.first_name, + last_name=data.last_name, + hashed_password=data.hashed_password, + email_encrypted=data.email, + ) + user_schema = await UsersCRUD(self.session).save(schema) user: User = User.from_orm(user_schema) return user diff --git a/src/apps/users/tests/fixtures/user_devices.py b/src/apps/users/tests/fixtures/user_devices.py new file mode 100644 index 00000000000..e5e4d7149fa --- /dev/null +++ b/src/apps/users/tests/fixtures/user_devices.py @@ -0,0 +1,22 @@ +from typing import cast + +import pytest +from sqlalchemy.ext.asyncio import AsyncSession + +from apps.users.cruds.user_device import UserDevicesCRUD +from apps.users.db.schemas import UserDeviceSchema +from apps.users.domain import User +from apps.users.services.user_device import UserDeviceService + + +@pytest.fixture(scope="session", autouse=True) +async def device_tom(tom: User, global_session: AsyncSession): + service = UserDeviceService(global_session, tom.id) + await service.add_device("deviceid") + await global_session.commit() + crud = UserDevicesCRUD(global_session) + device = await crud._get("device_id", "deviceid") + device = cast(UserDeviceSchema, device) + yield device.device_id + await service.remove_device("deviceid") + await global_session.commit() diff --git a/src/apps/users/tests/fixtures/users.py b/src/apps/users/tests/fixtures/users.py index 5b07b6f72b3..413f79a4724 100644 --- a/src/apps/users/tests/fixtures/users.py +++ b/src/apps/users/tests/fixtures/users.py @@ -3,42 +3,45 @@ import pytest from pydantic import EmailStr +from pytest import Config from sqlalchemy.ext.asyncio import AsyncSession from apps.users.cruds.user import UsersCRUD -from apps.users.db.schemas import UserSchema -from apps.users.domain import UserCreate +from apps.users.domain import User, UserCreate from apps.users.services.user import UserService from apps.workspaces.crud.workspaces import UserWorkspaceCRUD +async def _get_or_create_user( + crud: UsersCRUD, create_data: UserCreate, global_session: AsyncSession, id_: uuid.UUID | None +) -> User: + user_db = await crud.get_user_or_none_by_email(create_data.email) + if not user_db: + user = await UserService(global_session).create_user(create_data, test_id=id_) + await global_session.commit() + else: + user = User.from_orm(user_db) + return user + + @pytest.fixture(scope="session", autouse=True) -def tom_create() -> UserCreate: +def user_create() -> UserCreate: return UserCreate( - email=EmailStr("tom@mindlogger.com"), + email=EmailStr("user@example.com"), password="Test1234!", - first_name="Tom", - last_name="Isaak", + first_name="user", + last_name="test", ) @pytest.fixture(scope="session", autouse=True) -async def tom(tom_create: UserCreate, global_session: AsyncSession) -> AsyncGenerator: - crud = UsersCRUD(global_session) - user = await crud.save( - UserSchema( - id=uuid.UUID("7484f34a-3acc-4ee6-8a94-fd7299502fa1"), - email=tom_create.hashed_email, - email_encrypted=tom_create.email, - first_name=tom_create.first_name, - last_name=tom_create.last_name, - hashed_password=tom_create.hashed_password, - ) +def tom_create() -> UserCreate: + return UserCreate( + email=EmailStr("tom@mindlogger.com"), + password="Test1234!", + first_name="Tom", + last_name="Isaak", ) - await global_session.commit() - yield user - await crud._delete(id=user.id) - await global_session.commit() @pytest.fixture(scope="session", autouse=True) @@ -51,25 +54,6 @@ def lucy_create() -> UserCreate: ) -@pytest.fixture(scope="session", autouse=True) -async def lucy(lucy_create: UserCreate, global_session): - crud = UsersCRUD(global_session) - user = await crud.save( - UserSchema( - id=uuid.UUID("7484f34a-3acc-4ee6-8a94-fd7299502fa2"), - email=lucy_create.hashed_email, - email_encrypted=lucy_create.email, - first_name=lucy_create.first_name, - last_name=lucy_create.last_name, - hashed_password=lucy_create.hashed_password, - ) - ) - await global_session.commit() - yield user - await crud._delete(id=user.id) - await global_session.commit() - - @pytest.fixture(scope="session", autouse=True) def bob_create() -> UserCreate: return UserCreate( @@ -80,25 +64,6 @@ def bob_create() -> UserCreate: ) -@pytest.fixture(scope="session", autouse=True) -async def bob(bob_create: UserCreate, global_session): - crud = UsersCRUD(global_session) - user = await crud.save( - UserSchema( - id=uuid.UUID("7484f34a-3acc-4ee6-8a94-fd7299502fa3"), - email=bob_create.hashed_email, - email_encrypted=bob_create.email, - first_name=bob_create.first_name, - last_name=bob_create.last_name, - hashed_password=bob_create.hashed_password, - ) - ) - await global_session.commit() - yield user - await crud._delete(id=user.id) - await global_session.commit() - - @pytest.fixture(scope="session", autouse=True) def mike_create() -> UserCreate: return UserCreate( @@ -110,85 +75,100 @@ def mike_create() -> UserCreate: @pytest.fixture(scope="session", autouse=True) -async def mike(mike_create: UserCreate, global_session): +async def user(user_create: UserCreate, global_session: AsyncSession, pytestconfig: Config): + """Use this fixture if you need for some test clean user without nothing.""" crud = UsersCRUD(global_session) - user = await crud.save( - UserSchema( - id=uuid.UUID("7484f34a-3acc-4ee6-8a94-fd7299502fa4"), - email=mike_create.hashed_email, - email_encrypted=mike_create.email, - first_name=mike_create.first_name, - last_name=mike_create.last_name, - hashed_password=mike_create.hashed_password, - ) + user = await _get_or_create_user(crud, user_create, global_session, None) + yield user + if not pytestconfig.getoption("--keepdb"): + await crud._delete(id=user.id) + await global_session.commit() + + +@pytest.fixture(scope="session", autouse=True) +async def tom(tom_create: UserCreate, global_session: AsyncSession, pytestconfig: Config) -> AsyncGenerator: + crud = UsersCRUD(global_session) + user = await _get_or_create_user( + crud, tom_create, global_session, uuid.UUID("7484f34a-3acc-4ee6-8a94-fd7299502fa1") ) - await global_session.commit() yield user - await crud._delete(id=user.id) - await global_session.commit() + if not pytestconfig.getoption("--keepdb"): + await crud._delete(id=user.id) + await global_session.commit() @pytest.fixture(scope="session", autouse=True) -def user_create() -> UserCreate: - return UserCreate( - email=EmailStr("user@example.com"), - password="Test1234!", - first_name="user", - last_name="test", +async def lucy(lucy_create: UserCreate, global_session: AsyncSession, pytestconfig: Config): + crud = UsersCRUD(global_session) + user = await _get_or_create_user( + crud, lucy_create, global_session, uuid.UUID("7484f34a-3acc-4ee6-8a94-fd7299502fa2") ) + yield user + if not pytestconfig.getoption("--keepdb"): + await crud._delete(id=user.id) + await global_session.commit() @pytest.fixture(scope="session", autouse=True) -async def user(user_create: UserCreate, global_session: AsyncSession): - """Use this fixture if you need for some test clean user without nothing.""" +async def bob(bob_create: UserCreate, global_session: AsyncSession, pytestconfig: Config): crud = UsersCRUD(global_session) - user = await crud.save( - UserSchema( - email=user_create.hashed_email, - email_encrypted=user_create.email, - first_name=user_create.first_name, - last_name=user_create.last_name, - hashed_password=user_create.hashed_password, - ) + user = await _get_or_create_user( + crud, bob_create, global_session, uuid.UUID("7484f34a-3acc-4ee6-8a94-fd7299502fa3") ) - await global_session.commit() yield user - await crud._delete(id=user.id) - await global_session.commit() + if not pytestconfig.getoption("--keepdb"): + await crud._delete(id=user.id) + await global_session.commit() @pytest.fixture(scope="session", autouse=True) -async def anonym(global_session): +async def mike(mike_create: UserCreate, global_session: AsyncSession, pytestconfig: Config): crud = UsersCRUD(global_session) - await UserService(global_session).create_anonymous_respondent( - uuid_=uuid.UUID("7484f34a-3acc-4ee6-8a94-fd7299502fa7") + user = await _get_or_create_user( + crud, mike_create, global_session, uuid.UUID("7484f34a-3acc-4ee6-8a94-fd7299502fa4") ) - await global_session.commit() - yield - await crud._delete(is_anonymous_respondent=True) - await global_session.commit() + yield user + if not pytestconfig.getoption("--keepdb"): + await crud._delete(id=user.id) + await global_session.commit() @pytest.fixture(scope="session", autouse=True) -async def superadmin(global_session): - uuid_ = uuid.UUID("57b63dfa-5cee-4a53-a69e-0a35407e601d") +async def anonym(global_session: AsyncSession, pytestconfig: Config): crud = UsersCRUD(global_session) - await UserService(global_session).create_superuser(uuid_=uuid_) - await global_session.commit() - yield - await UserWorkspaceCRUD(global_session)._delete(user_id=uuid_) - await crud._delete(is_super_admin=True) + schema = await crud.get_super_admin() + if not schema: + await UserService(global_session).create_anonymous_respondent( + test_id=uuid.UUID("7484f34a-3acc-4ee6-8a94-fd7299502fa7") + ) + schema = await crud.get_super_admin() + user = User.from_orm(schema) await global_session.commit() + yield user + if not pytestconfig.getoption("--keepdb"): + await crud._delete(is_anonymous_respondent=True) + await global_session.commit() + + +@pytest.fixture(scope="session", autouse=True) +async def superadmin(global_session: AsyncSession, pytestconfig: Config): + id_ = uuid.UUID("57b63dfa-5cee-4a53-a69e-0a35407e601d") + crud = UsersCRUD(global_session) + schema = await crud.get_super_admin() + if not schema: + await UserService(global_session).create_superuser(test_id=id_) + await global_session.commit() + schema = await crud.get_super_admin() + user = User.from_orm(schema) + yield user + if not pytestconfig.getoption("--keepdb"): + await UserWorkspaceCRUD(global_session)._delete(user_id=id_) + await crud._delete(is_super_admin=True) + await global_session.commit() @pytest.fixture(scope="session", autouse=True) async def all_session_users( - tom: UserSchema, - lucy: UserSchema, - bob: UserSchema, - mike: UserSchema, - user: UserSchema, - anonym: UserSchema, - superadmin: UserSchema, -) -> list[UserSchema]: - return [tom, lucy, bob, mike, user, anonym, superadmin] + user: User, tom: User, lucy: User, bob: User, mike: User, anonym: User, superadmin: User +) -> list[User]: + return [user, tom, lucy, bob, mike, anonym, superadmin] diff --git a/src/apps/users/tests/test_password.py b/src/apps/users/tests/test_password.py index 2091a16c5b8..fdecf1404dd 100644 --- a/src/apps/users/tests/test_password.py +++ b/src/apps/users/tests/test_password.py @@ -3,6 +3,7 @@ import uuid from unittest.mock import AsyncMock +import pytest from httpx import Response as HttpResponse from pytest_mock import MockFixture from starlette import status @@ -10,9 +11,8 @@ from apps.authentication.domain.login import UserLoginRequest from apps.authentication.router import router as auth_router from apps.mailing.services import TestMail -from apps.shared.test import BaseTest from apps.shared.test.client import TestClient -from apps.users.domain import PasswordRecoveryRequest, User, UserCreateRequest +from apps.users.domain import PasswordRecoveryRequest, UserCreate from apps.users.errors import PasswordHasSpacesError, ReencryptionInProgressError from apps.users.router import router as user_router from apps.users.tests.factories import CacheEntryFactory, PasswordRecoveryInfoFactory, PasswordUpdateRequestFactory @@ -21,47 +21,37 @@ from infrastructure.utility import RedisCache -class TestPassword(BaseTest): - get_token_url = auth_router.url_path_for("get_token") - user_create_url = user_router.url_path_for("user_create") - password_update_url = user_router.url_path_for("password_update") - password_recovery_url = user_router.url_path_for("password_recovery") - password_recovery_approve_url = user_router.url_path_for("password_recovery_approve") - password_recovery_healthcheck_url = user_router.url_path_for("password_recovery_healthcheck") - - create_request_user = UserCreateRequest( - email="tom2@mindlogger.com", - first_name="Tom", - last_name="Isaak", - password="Test1234!", - ) - - cache_entry = CacheEntryFactory.build( +@pytest.fixture(scope="class") +def cache_entry(user: UserCreate): + return CacheEntryFactory.build( instance=PasswordRecoveryInfoFactory.build( - email=create_request_user.dict()["email"], + email=user.email, ), created_at=datetime.datetime.utcnow(), ) - async def test_password_update(self, mock_reencrypt_kiq, client): - # Creating new user - await client.post(self.user_create_url, data=self.create_request_user.dict()) - login_request_user: UserLoginRequest = UserLoginRequest(**self.create_request_user.dict()) +@pytest.mark.usefixtures("mock_reencrypt_kiq", "cache_entry") +class TestPassword: + get_token_url = auth_router.url_path_for("get_token") + user_create_url = user_router.url_path_for("user_create") + password_update_url = user_router.url_path_for("password_update") + password_recovery_url = user_router.url_path_for("password_recovery") + password_recovery_approve_url = user_router.url_path_for("password_recovery_approve") + password_recovery_healthcheck_url = user_router.url_path_for("password_recovery_healthcheck") + async def test_password_update(self, mock_reencrypt_kiq: AsyncMock, client: TestClient, user_create: UserCreate): # User get token - await client.login( - url=self.get_token_url, - **login_request_user.dict(), - ) + await client.login(url=self.get_token_url, email=user_create.email, password=user_create.password) # Password update - password_update_request = PasswordUpdateRequestFactory.build(prev_password=self.create_request_user.password) + password_update_request = PasswordUpdateRequestFactory.build(prev_password=user_create.password) response: HttpResponse = await client.put(self.password_update_url, data=password_update_request.dict()) + assert response.status_code == status.HTTP_200_OK # User get token with new password login_request_user = UserLoginRequest( - email=self.create_request_user.dict()["email"], + email=user_create.email, password=password_update_request.dict()["password"], ) @@ -70,23 +60,12 @@ async def test_password_update(self, mock_reencrypt_kiq, client): **login_request_user.dict(), ) - assert response.status_code == status.HTTP_200_OK - assert response.status_code == status.HTTP_200_OK assert internal_response.status_code == status.HTTP_200_OK mock_reencrypt_kiq.assert_awaited_once() - async def test_password_recovery( - self, - mock_reencrypt_kiq: AsyncMock, - client: TestClient, - ): - # Creating new user - await client.post(self.user_create_url, data=self.create_request_user.dict()) - + async def test_password_recovery(self, client: TestClient, user_create: UserCreate): # Password recovery - password_recovery_request: PasswordRecoveryRequest = PasswordRecoveryRequest( - email=self.create_request_user.dict()["email"] - ) + password_recovery_request: PasswordRecoveryRequest = PasswordRecoveryRequest(email=user_create.dict()["email"]) response = await client.post( url=self.password_recovery_url, @@ -96,7 +75,7 @@ async def test_password_recovery( cache = RedisCache() assert response.status_code == status.HTTP_201_CREATED - keys = await cache.keys(key="PasswordRecoveryCache:tom2@mindlogger.com*") + keys = await cache.keys(key=f"PasswordRecoveryCache:{user_create.email}*") assert len(keys) == 1 assert password_recovery_request.email in keys[0] assert len(TestMail.mails) == 1 @@ -110,28 +89,17 @@ async def test_password_recovery( assert response.status_code == status.HTTP_201_CREATED - new_keys = await cache.keys(key="PasswordRecoveryCache:tom2@mindlogger.com*") + new_keys = await cache.keys(key=f"PasswordRecoveryCache:{user_create.email}*") assert len(keys) == 1 assert keys[0] != new_keys[0] assert len(TestMail.mails) == 2 assert TestMail.mails[0].recipients[0] == password_recovery_request.email - async def test_password_recovery_approve( - self, - mock_reencrypt_kiq: AsyncMock, - client: TestClient, - ): + async def test_password_recovery_approve(self, client: TestClient, user_create: UserCreate): cache = RedisCache() - # Creating new user - internal_response = await client.post(self.user_create_url, data=self.create_request_user.dict()) - - expected_result = internal_response.json() - # Password recovery - password_recovery_request: PasswordRecoveryRequest = PasswordRecoveryRequest( - email=self.create_request_user.dict()["email"] - ) + password_recovery_request: PasswordRecoveryRequest = PasswordRecoveryRequest(email=user_create.dict()["email"]) response = await client.post( url=self.password_recovery_url, @@ -139,10 +107,10 @@ async def test_password_recovery_approve( ) assert response.status_code == status.HTTP_201_CREATED - key = (await cache.keys(key="PasswordRecoveryCache:tom2@mindlogger.com*"))[0].split(":")[-1] + key = (await cache.keys(key=f"PasswordRecoveryCache:{user_create.email}*"))[0].split(":")[-1] data = { - "email": self.create_request_user.dict()["email"], + "email": user_create.dict()["email"], "key": key, "password": "new_password", } @@ -151,29 +119,16 @@ async def test_password_recovery_approve( url=self.password_recovery_approve_url, data=data, ) - - keys = await cache.keys(key="PasswordRecoveryCache:tom2@mindlogger.com*") - assert response.status_code == status.HTTP_200_OK - assert response.json() == expected_result - assert len(keys) == 0 + keys = await cache.keys(key="PasswordRecoveryCache:{user_create.email}*") assert len(keys) == 0 - async def test_password_recovery_approve_expired( - self, - mock_reencrypt_kiq: AsyncMock, - client: TestClient, - ): + async def test_password_recovery_approve_expired(self, client: TestClient, user_create: UserCreate): cache = RedisCache() settings.authentication.password_recover.expiration = 1 - # Creating new user - await client.post(self.user_create_url, data=self.create_request_user.dict()) - # Password recovery - password_recovery_request: PasswordRecoveryRequest = PasswordRecoveryRequest( - email=self.create_request_user.dict()["email"] - ) + password_recovery_request: PasswordRecoveryRequest = PasswordRecoveryRequest(email=user_create.dict()["email"]) response = await client.post( url=self.password_recovery_url, @@ -181,11 +136,11 @@ async def test_password_recovery_approve_expired( ) assert response.status_code == status.HTTP_201_CREATED - key = (await cache.keys(key="PasswordRecoveryCache:tom2@mindlogger.com*"))[0].split(":")[-1] + key = (await cache.keys(key=f"PasswordRecoveryCache:{user_create.email}*"))[0].split(":")[-1] await asyncio.sleep(2) data = { - "email": self.create_request_user.dict()["email"], + "email": user_create.dict()["email"], "key": key, "password": "new_password", } @@ -195,7 +150,7 @@ async def test_password_recovery_approve_expired( data=data, ) - keys = await cache.keys(key="PasswordRecoveryCache:tom2@mindlogger.com*") + keys = await cache.keys(key=f"PasswordRecoveryCache:{user_create.email}*") assert response.status_code == status.HTTP_404_NOT_FOUND assert len(keys) == 0 @@ -203,8 +158,7 @@ async def test_password_recovery_approve_expired( async def test_update_password__password_contains_whitespaces( self, client: TestClient, - user_create: UserCreateRequest, - user: User, + user_create: UserCreate, ): await client.login( self.get_token_url, @@ -225,8 +179,7 @@ async def test_update_password__password_contains_whitespaces( async def test_update_password__reencryption_already_in_progress( self, client: TestClient, - user_create: UserCreateRequest, - user: User, + user_create: UserCreate, mocker: MockFixture, ): await client.login( diff --git a/src/apps/users/tests/test_reencrypt_user_answers.py b/src/apps/users/tests/test_reencrypt_user_answers.py index 083051d1e15..eb4202c5447 100644 --- a/src/apps/users/tests/test_reencrypt_user_answers.py +++ b/src/apps/users/tests/test_reencrypt_user_answers.py @@ -23,7 +23,6 @@ from apps.job.service import JobService from apps.shared.encryption import generate_dh_aes_key, generate_dh_public_key, generate_dh_user_private_key from apps.themes.service import ThemeService -from apps.users.db.schemas import UserSchema from apps.users.domain import User, UserCreate from apps.users.tasks import reencrypt_answers from apps.workspaces.constants import StorageType @@ -37,10 +36,10 @@ def client_meta() -> ClientMeta: @pytest.fixture -def job_model(tom) -> Job: +def job_model(user) -> Job: return Job( name="reencrypt_answers", - creator_id=tom.id, + creator_id=user.id, status=JobStatus.in_progress, id=uuid.uuid4(), created_at=datetime.datetime.utcnow(), @@ -49,7 +48,7 @@ def job_model(tom) -> Job: @pytest.fixture -async def applet(session: AsyncSession, tom: UserSchema, applet_minimal_data: AppletCreate) -> AppletFull: +async def applet(session: AsyncSession, tom: User, applet_minimal_data: AppletCreate) -> AppletFull: srv = AppletService(session, tom.id) await ThemeService(session, tom.id).get_or_create_default() applet = await srv.create(applet_minimal_data) @@ -58,12 +57,12 @@ async def applet(session: AsyncSession, tom: UserSchema, applet_minimal_data: Ap @pytest.fixture def answer_item_create( - tom: UserSchema, - tom_create: UserCreate, + user: User, + user_create: UserCreate, applet: AppletFull, single_select_item_create: ActivityItemCreate, ) -> ItemAnswerCreate: - private_key = generate_dh_user_private_key(tom.id, tom_create.email, tom_create.password) + private_key = generate_dh_user_private_key(user.id, user_create.email, user_create.password) public_key = generate_dh_public_key(private_key, test_constants.TEST_PRIME, test_constants.TEST_BASE) aes_key = generate_dh_aes_key(private_key, test_constants.TEST_PUBLIC_KEY, test_constants.TEST_PRIME) encryptor = AnswerEncryptor(bytes(aes_key)) @@ -90,7 +89,7 @@ def answer_item_create( @pytest.fixture async def answer( session: AsyncSession, - tom: UserSchema, + user: User, applet: AppletFull, answer_item_create: ItemAnswerCreate, client_meta: ClientMeta, @@ -104,7 +103,7 @@ async def answer( created_at=datetime.datetime.utcnow(), client=client_meta, ) - srv = AnswerService(session, tom.id) + srv = AnswerService(session, user.id) answer = await srv.create_answer(answer_create) return answer @@ -112,7 +111,7 @@ async def answer( @pytest.fixture async def answer_second( session: AsyncSession, - tom: UserSchema, + user: User, applet: AppletFull, answer_item_create: ItemAnswerCreate, client_meta: ClientMeta, @@ -126,7 +125,7 @@ async def answer_second( created_at=datetime.datetime.utcnow(), client=client_meta, ) - srv = AnswerService(session, tom.id) + srv = AnswerService(session, user.id) answer = await srv.create_answer(answer_create) return answer @@ -135,7 +134,7 @@ async def answer_second( async def answer_arbitrary( session: AsyncSession, arbitrary_session: AsyncSession, - tom: UserSchema, + user: User, applet: AppletFull, answer_item_create: ItemAnswerCreate, client_meta: ClientMeta, @@ -149,14 +148,14 @@ async def answer_arbitrary( created_at=datetime.datetime.utcnow(), client=client_meta, ) - srv = AnswerService(session, tom.id, arbitrary_session=arbitrary_session) + srv = AnswerService(session, user.id, arbitrary_session=arbitrary_session) answer = await srv.create_answer(answer_create) return answer async def test_reencrypt_answers_no_applets_job_started_with_status_in_progress( - tom: UserSchema, - tom_create: UserCreate, + user: User, + user_create: UserCreate, mock_get_session: AsyncSession, mocker: MockerFixture, job_model: Job, @@ -166,15 +165,15 @@ async def test_reencrypt_answers_no_applets_job_started_with_status_in_progress( # job does not exist in db, so mock update mocker.patch("apps.job.crud.JobCRUD.update") spy = mocker.spy(JobService, "change_status") - task = await reencrypt_answers.kiq(tom.id, tom.email_encrypted, tom_create.password, "new-pass", retries=0) + task = await reencrypt_answers.kiq(user.id, user.email_encrypted, user_create.password, "new-pass", retries=0) await task.wait_result() # ANY - self spy.assert_awaited_once_with(ANY, job_model.id, JobStatus.success) async def test_reencrypt_answers_no_applets_job_started_with_another_status( - tom: UserSchema, - tom_create: UserCreate, + user: User, + user_create: UserCreate, mock_get_session: AsyncSession, mocker: MockerFixture, job_model: Job, @@ -183,15 +182,15 @@ async def test_reencrypt_answers_no_applets_job_started_with_another_status( mocker.patch("apps.job.service.JobService.get_or_create_owned", return_value=job_model) mocker.patch("apps.job.crud.JobCRUD.update") spy = mocker.spy(JobService, "change_status") - task = await reencrypt_answers.kiq(tom.id, tom.email_encrypted, tom_create.password, "new-pass", retries=0) + task = await reencrypt_answers.kiq(user.id, user.email_encrypted, user_create.password, "new-pass", retries=0) await task.wait_result() spy.assert_any_await(ANY, job_model.id, JobStatus.in_progress) spy.assert_awaited_with(ANY, job_model.id, JobStatus.success) async def test_reencrypt_answers_no_answers( - tom: UserSchema, - tom_create: UserCreate, + user: User, + user_create: UserCreate, mock_get_session: AsyncSession, mocker: MockerFixture, job_model: Job, @@ -201,15 +200,15 @@ async def test_reencrypt_answers_no_answers( mocker.patch("apps.job.service.JobService.get_or_create_owned", return_value=job_model) mocker.patch("apps.job.crud.JobCRUD.update") spy = mocker.spy(JobService, "change_status") - task = await reencrypt_answers.kiq(tom.id, tom.email_encrypted, tom_create.password, "new-pass", retries=0) + task = await reencrypt_answers.kiq(user.id, user.email_encrypted, user_create.password, "new-pass", retries=0) await task.wait_result() spy.assert_awaited_once_with(ANY, job_model.id, JobStatus.success) async def test_reencrypt_answers_not_valid_public_key_answer_not_reencrypted( session: AsyncSession, - tom: UserSchema, - tom_create: UserCreate, + user: User, + user_create: UserCreate, mock_get_session: AsyncSession, mocker: MockerFixture, job_model: Job, @@ -223,12 +222,12 @@ async def test_reencrypt_answers_not_valid_public_key_answer_not_reencrypted( act_id_version = f"{applet.activities[0].id}_{applet.version}" answer_before = (await AnswerItemsCRUD(session).get_by_answer_and_activity(answer_id, [act_id_version]))[0].answer applet_update_data = AppletUpdate(**applet_minimal_data.dict(exclude_unset=True)) - await AppletService(session, tom.id).update(applet.id, applet_update_data) + await AppletService(session, user.id).update(applet.id, applet_update_data) job_model.status = JobStatus.in_progress mocker.patch("apps.job.service.JobService.get_or_create_owned", return_value=job_model) mocker.patch("apps.job.crud.JobCRUD.update") spy = mocker.spy(JobService, "change_status") - task = await reencrypt_answers.kiq(tom.id, tom.email_encrypted, tom_create.password, "new-pass", retries=0) + task = await reencrypt_answers.kiq(user.id, user.email_encrypted, user_create.password, "new-pass", retries=0) await task.wait_result() spy.assert_awaited_once_with(ANY, job_model.id, JobStatus.success) answer_after = (await AnswerItemsCRUD(session).get_by_answer_and_activity(answer_id, [act_id_version]))[0].answer @@ -237,8 +236,8 @@ async def test_reencrypt_answers_not_valid_public_key_answer_not_reencrypted( async def test_reencrypt_answers_success( session: AsyncSession, - tom: UserSchema, - tom_create: UserCreate, + user: User, + user_create: UserCreate, mock_get_session: AsyncSession, mocker: MockerFixture, job_model: Job, @@ -256,7 +255,7 @@ async def test_reencrypt_answers_success( mocker.patch("apps.job.service.JobService.get_or_create_owned", return_value=job_model) mocker.patch("apps.job.crud.JobCRUD.update") spy = mocker.spy(JobService, "change_status") - task = await reencrypt_answers.kiq(tom.id, tom.email_encrypted, tom_create.password, "new-pass", retries=0) + task = await reencrypt_answers.kiq(user.id, user.email_encrypted, user_create.password, "new-pass", retries=0) await task.wait_result() spy.assert_awaited_once_with(ANY, job_model.id, JobStatus.success) answers_after = list( @@ -270,8 +269,8 @@ async def test_reencrypt_answers_success( async def test_reencrypt_answers_exception_during_reencrypt_no_retries( session: AsyncSession, - tom: UserSchema, - tom_create: UserCreate, + user: User, + user_create: UserCreate, mock_get_session: AsyncSession, mocker: MockerFixture, job_model: Job, @@ -279,7 +278,7 @@ async def test_reencrypt_answers_exception_during_reencrypt_no_retries( answer: AnswerSchema, ): answer_id = answer.id - user_id = tom.id + user_id = user.id act_id_version = f"{applet.activities[0].id}_{applet.version}" answer_before = (await AnswerItemsCRUD(session).get_by_answer_and_activity(answer_id, [act_id_version]))[0].answer job_model.status = JobStatus.in_progress @@ -287,7 +286,7 @@ async def test_reencrypt_answers_exception_during_reencrypt_no_retries( mocker.patch("apps.job.crud.JobCRUD.update") mocker.patch("apps.answers.service.AnswerService.reencrypt_user_answers", side_effect=Exception("ERROR")) spy = mocker.spy(JobService, "change_status") - task = await reencrypt_answers.kiq(tom.id, tom.email_encrypted, tom_create.password, "new-pass", retries=0) + task = await reencrypt_answers.kiq(user.id, user.email_encrypted, user_create.password, "new-pass", retries=0) await task.wait_result() err_msg = f"Reencryption {user_id}: cannot process applet " f"{applet.id}, skip" spy.assert_awaited_once_with(ANY, job_model.id, JobStatus.error, dict(errors=[err_msg, "ERROR"])) @@ -297,8 +296,8 @@ async def test_reencrypt_answers_exception_during_reencrypt_no_retries( async def test_reencrypt_answers_exception_during_reencrypt_with_retries( session: AsyncSession, - tom: UserSchema, - tom_create: UserCreate, + user: User, + user_create: UserCreate, mock_get_session: AsyncSession, mocker: MockerFixture, job_model: Job, @@ -313,7 +312,7 @@ async def test_reencrypt_answers_exception_during_reencrypt_with_retries( mocker.patch("apps.job.crud.JobCRUD.update") mocker.patch("apps.answers.service.AnswerService.reencrypt_user_answers", side_effect=Exception("ERROR")) spy = mocker.spy(JobService, "change_status") - task = await reencrypt_answers.kiq(tom.id, tom.email_encrypted, tom_create.password, "new-pass", retries=1) + task = await reencrypt_answers.kiq(user.id, user.email_encrypted, user_create.password, "new-pass", retries=1) await task.wait_result() spy.assert_any_await(ANY, job_model.id, JobStatus.retry) answer_after = (await AnswerItemsCRUD(session).get_by_answer_and_activity(answer_id, [act_id_version]))[0].answer @@ -323,8 +322,8 @@ async def test_reencrypt_answers_exception_during_reencrypt_with_retries( async def test_reencrypt_answers_arbitrary( session: AsyncSession, arbitrary_session: AsyncSession, - tom: UserSchema, - tom_create: UserCreate, + user: User, + user_create: UserCreate, mock_get_session: AsyncSession, mocker: MockerFixture, job_model: Job, @@ -342,8 +341,8 @@ async def test_reencrypt_answers_arbitrary( storage_type=StorageType.AWS, storage_region="us-east-1", ) - await WorkspaceService(session, tom.id).create_workspace_from_user(User.from_orm(tom)) - await WorkspaceService(session, tom.id).set_arbitrary_server(w) + await WorkspaceService(session, user.id).create_workspace_from_user(User.from_orm(user)) + await WorkspaceService(session, user.id).set_arbitrary_server(w) answer_id = answer_arbitrary.id act_id_version = f"{applet.activities[0].id}_{applet.version}" answer_before = (await AnswerItemsCRUD(arbitrary_session).get_by_answer_and_activity(answer_id, [act_id_version]))[ @@ -353,7 +352,7 @@ async def test_reencrypt_answers_arbitrary( mocker.patch("apps.job.service.JobService.get_or_create_owned", return_value=job_model) mocker.patch("apps.job.crud.JobCRUD.update") spy = mocker.spy(JobService, "change_status") - task = await reencrypt_answers.kiq(tom.id, tom.email_encrypted, tom_create.password, "new-pass", retries=0) + task = await reencrypt_answers.kiq(user.id, user.email_encrypted, user_create.password, "new-pass", retries=0) await task.wait_result() spy.assert_awaited_once_with(ANY, job_model.id, JobStatus.success) answer_after = (await AnswerItemsCRUD(arbitrary_session).get_by_answer_and_activity(answer_id, [act_id_version]))[ diff --git a/src/apps/users/tests/test_user.py b/src/apps/users/tests/test_user.py index e890c7b2ce9..18a1c5c5dbf 100644 --- a/src/apps/users/tests/test_user.py +++ b/src/apps/users/tests/test_user.py @@ -1,108 +1,74 @@ import pytest -from pydantic import EmailError +from pydantic import EmailError, EmailStr +from sqlalchemy.ext.asyncio import AsyncSession from starlette import status -from apps.authentication.domain.login import UserLoginRequest from apps.authentication.router import router as auth_router from apps.shared.domain import to_camelcase -from apps.shared.test import BaseTest +from apps.shared.test.client import TestClient from apps.users import UsersCRUD -from apps.users.domain import UserCreateRequest +from apps.users.domain import UserCreate, UserCreateRequest from apps.users.errors import PasswordHasSpacesError, UserIsDeletedError from apps.users.router import router as user_router from apps.users.tests.factories import UserUpdateRequestFactory -class TestUser(BaseTest): +@pytest.fixture +def request_data() -> UserCreateRequest: + return UserCreateRequest( + email=EmailStr("tom2@mindlogger.com"), + first_name="Tom", + last_name="Isaak", + password="Test1234!", + ) + + +@pytest.mark.usefixtures("user") +class TestUser: get_token_url = auth_router.url_path_for("get_token") user_create_url = user_router.url_path_for("user_create") user_retrieve_url = user_router.url_path_for("user_retrieve") user_update_url = user_router.url_path_for("user_update") user_delete_url = user_router.url_path_for("user_delete") - create_request_user = UserCreateRequest( - email="tom2@mindlogger.com", - first_name="Tom", - last_name="Isaak", - password="Test1234!", - ) user_update_request = UserUpdateRequestFactory.build() - async def test_user_create(self, client): - # Creating new user - response = await client.post(self.user_create_url, data=self.create_request_user.dict()) + async def test_user_create(self, client: TestClient, request_data: UserCreateRequest): + response = await client.post(self.user_create_url, data=request_data.dict()) assert response.status_code == status.HTTP_201_CREATED result = response.json()["result"] - for k, v in self.create_request_user: + for k, v in request_data: if k != "password": assert v == result[to_camelcase(k)] - async def test_user_create_exist(self, client): - # Creating new user - await client.post(self.user_create_url, data=self.create_request_user.dict()) - # Creating a user that already exists - response = await client.post(self.user_create_url, data=self.create_request_user.dict()) + async def test_user_create_exist( + self, client: TestClient, request_data: UserCreateRequest, user_create: UserCreate + ): + request_data.email = user_create.email + response = await client.post(self.user_create_url, data=request_data.dict()) assert response.status_code == status.HTTP_400_BAD_REQUEST - async def test_user_retrieve(self, client): - # Creating new user - await client.post(self.user_create_url, data=self.create_request_user.dict()) - - login_request_user: UserLoginRequest = UserLoginRequest(**self.create_request_user.dict()) - - # User get token - await client.login( - url=self.get_token_url, - **login_request_user.dict(), - ) - - # User retrieve + async def test_user_retrieve(self, client: TestClient, user_create: UserCreate): + await client.login(url=self.get_token_url, email=user_create.email, password="Test1234!") response = await client.get(self.user_retrieve_url) assert response.status_code == status.HTTP_200_OK - async def test_user_update(self, client): - # Creating new user - await client.post(self.user_create_url, data=self.create_request_user.dict()) - - login_request_user: UserLoginRequest = UserLoginRequest(**self.create_request_user.dict()) - - # User get token - await client.login( - url=self.get_token_url, - **login_request_user.dict(), - ) - - # User update + async def test_user_update(self, client: TestClient, user_create: UserCreate): + await client.login(url=self.get_token_url, email=user_create.email, password="Test1234!") response = await client.put(self.user_update_url, data=self.user_update_request.dict()) - assert response.status_code == status.HTTP_200_OK - async def test_user_delete(self, session, client): - """UsersCRUD.get_by_email should raise an error - if user is deleted. - """ - # Creating new user - await client.post(self.user_create_url, data=self.create_request_user.dict()) - - # Authorize user - login_request_user: UserLoginRequest = UserLoginRequest(**self.create_request_user.dict()) - await client.login( - url=self.get_token_url, - **login_request_user.dict(), - ) - - # Delete user + async def test_user_delete(self, session: AsyncSession, client: TestClient, user_create: UserCreate): + await client.login(url=self.get_token_url, email=user_create.email, password="Test1234!") response = await client.delete( self.user_delete_url, ) - - with pytest.raises(UserIsDeletedError): - await UsersCRUD(session).get_by_email(login_request_user.email) - assert response.status_code == status.HTTP_204_NO_CONTENT + with pytest.raises(UserIsDeletedError): + await UsersCRUD(session).get_by_email(user_create.email) - async def test_create_user_password_contains_whitespaces(self, client): - data = self.create_request_user.dict() + async def test_create_user_password_contains_whitespaces(self, client: TestClient, request_data: UserCreateRequest): + data = request_data.dict() data["password"] = "Test1234 !" response = await client.post(self.user_create_url, data=data) assert response.status_code == status.HTTP_400_BAD_REQUEST @@ -110,8 +76,8 @@ async def test_create_user_password_contains_whitespaces(self, client): assert len(result) == 1 assert result[0]["message"] == PasswordHasSpacesError.message - async def test_create_user_not_valid_email(self, client): - data = self.create_request_user.dict() + async def test_create_user_not_valid_email(self, client: TestClient, request_data: UserCreateRequest): + data = request_data.dict() data["email"] = "tom2@mindlogger@com" response = await client.post(self.user_create_url, data=data) assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY diff --git a/src/apps/users/tests/unit/test_user_crud.py b/src/apps/users/tests/unit/test_user_crud.py index 08da6727d07..fe6de060ad5 100644 --- a/src/apps/users/tests/unit/test_user_crud.py +++ b/src/apps/users/tests/unit/test_user_crud.py @@ -11,10 +11,10 @@ from apps.users.errors import UserAlreadyExistError, UserIsDeletedError, UserNotFound -async def test_get_user_by_id(tom: UserSchema, session: AsyncSession): +async def test_get_user_by_id(user: User, session: AsyncSession): crud = UsersCRUD(session) - user = await crud.get_by_id(tom.id) - assert user.id == tom.id + act = await crud.get_by_id(user.id) + assert act.id == user.id async def test_get_user_by_id__user_does_not_exists(session: AsyncSession, uuid_zero: uuid.UUID): @@ -23,23 +23,21 @@ async def test_get_user_by_id__user_does_not_exists(session: AsyncSession, uuid_ await crud.get_by_id(uuid_zero) -async def test_get_user_by_id__user_deleted(session: AsyncSession, tom: UserSchema): +async def test_get_user_by_id__user_deleted(session: AsyncSession, user: User): crud = UsersCRUD(session) - user_id = tom.id - await crud.update_by_id(user_id, UserSchema(is_deleted=True)) - await session.commit() + await crud.update_by_id(user.id, UserSchema(is_deleted=True)) with pytest.raises(UserIsDeletedError): - await crud.get_by_id(user_id) + await crud.get_by_id(user.id) async def test_get_user_by_email( - tom: UserSchema, + user: User, session: AsyncSession, - tom_create: UserCreate, + user_create: UserCreate, ): crud = UsersCRUD(session) - user = await crud.get_by_email(tom_create.email) - assert user.id == tom.id + act = await crud.get_by_email(user_create.email) + assert act.id == user.id async def test_get_user_by_email__user_does_not_exists(session: AsyncSession): @@ -50,153 +48,147 @@ async def test_get_user_by_email__user_does_not_exists(session: AsyncSession): async def test_get_user_by_email__user_deleted( session: AsyncSession, - tom: UserSchema, - tom_create: UserCreate, + user: User, + user_create: UserCreate, ): crud = UsersCRUD(session) - await crud.update_by_id(tom.id, UserSchema(is_deleted=True)) - await session.commit() + await crud.update_by_id(user.id, UserSchema(is_deleted=True)) with pytest.raises(UserIsDeletedError): - await crud.get_by_email(tom_create.email) + await crud.get_by_email(user_create.email) -async def test_create_user_minimal_data(tom_create: UserCreate, session: AsyncSession): +async def test_create_user_minimal_data(user_create: UserCreate, session: AsyncSession): crud = UsersCRUD(session) user = await crud.save( UserSchema( - hashed_password=tom_create.password, - last_name=tom_create.last_name, - first_name=tom_create.first_name, + hashed_password=user_create.password, + last_name=user_create.last_name, + first_name=user_create.first_name, ) ) assert user.email_encrypted is None # Interesting case assert user.email is None - assert user.first_name == tom_create.first_name - assert user.last_name == tom_create.last_name + assert user.first_name == user_create.first_name + assert user.last_name == user_create.last_name assert not user.is_super_admin assert not user.is_anonymous_respondent assert not user.is_legacy_deleted_respondent -async def test_create_user__user_already_exists(tom_create: UserCreate, session: AsyncSession, tom: UserSchema): +async def test_create_user__user_already_exists(user_create: UserCreate, session: AsyncSession): crud = UsersCRUD(session) with pytest.raises(UserAlreadyExistError): await crud.save( UserSchema( - hashed_password=tom_create.password, - last_name=tom_create.last_name, - first_name=tom_create.first_name, - email=hash_sha224(tom_create.email), + hashed_password=user_create.password, + last_name=user_create.last_name, + first_name=user_create.first_name, + email=hash_sha224(user_create.email), ) ) -async def test_update_user(tom: UserSchema, session: AsyncSession): +async def test_update_user(user: User, session: AsyncSession): crud = UsersCRUD(session) data = UserUpdateRequest(first_name="new", last_name="new") - user = await crud.update(User.from_orm(tom), data) - await session.commit() - assert user.first_name == data.first_name - assert user.last_name == data.last_name + updated = await crud.update(user, data) + assert updated.first_name == data.first_name + assert updated.last_name == data.last_name -async def test_update_user_by_id(tom: UserSchema, session: AsyncSession): +async def test_update_user_by_id(user: User, session: AsyncSession): crud = UsersCRUD(session) new_first_name = "new" - user = await crud.update_by_id(tom.id, UserSchema(first_name=new_first_name)) - assert user.first_name == new_first_name + updated = await crud.update_by_id(user.id, UserSchema(first_name=new_first_name)) + assert updated.first_name == new_first_name -async def test_update_encrypted_email(tom: UserSchema, session: AsyncSession): +async def test_update_encrypted_email(user: User, session: AsyncSession): crud = UsersCRUD(session) new_email = "newemail@example.com" - user = await crud.update_encrypted_email(User.from_orm(tom), new_email) - assert user.email_encrypted == new_email + updated = await crud.update_encrypted_email(user, new_email) + assert updated.email_encrypted == new_email -async def test_delete_user__soft_delete(tom: UserSchema, session: AsyncSession): +async def test_delete_user__soft_delete(user: User, session: AsyncSession): crud = UsersCRUD(session) - deleted = await crud.delete(tom.id) + deleted = await crud.delete(user.id) assert deleted.is_deleted -async def test_change_password(tom: UserSchema, session: AsyncSession): +async def test_change_password(user: User, session: AsyncSession): crud = UsersCRUD(session) new_password = "newpassword" - user_id = tom.id - assert tom.hashed_password != new_password + user_id = user.id + assert user.hashed_password != new_password await crud.change_password( - User.from_orm(tom), + user, UserChangePassword(hashed_password=new_password), ) - await session.commit() - user = await crud._get("id", user_id) - user = cast(UserSchema, user) - assert user.hashed_password == new_password + updated = await crud._get("id", user_id) + updated = cast(UserSchema, updated) + assert updated.hashed_password == new_password async def test_update_last_seet_at( faketime, - tom: UserSchema, + user: User, session: AsyncSession, ): crud = UsersCRUD(session) - user_id = tom.id - assert tom.last_seen_at != faketime.current_utc - await crud.update_last_seen_by_id(tom.id) + user_db = await crud._get("id", user.id) + user_db = cast(UserSchema, user_db) + assert user_db.last_seen_at != faketime.current_utc + await crud.update_last_seen_by_id(user.id) await session.commit() - user = await crud._get("id", user_id) - user = cast(UserSchema, user) - assert user.last_seen_at == faketime.current_utc + updated = await crud._get("id", user.id) + updated = cast(UserSchema, updated) + assert updated.last_seen_at == faketime.current_utc -async def test_user_exists_by_id(tom: UserSchema, session: AsyncSession): +async def test_user_exists_by_id(user: User, session: AsyncSession): crud = UsersCRUD(session) - result = await crud.exist_by_id(tom.id) + result = await crud.exist_by_id(user.id) assert result async def test_user_exists_by_id__user_does_not_exist( session: AsyncSession, uuid_zero: uuid.UUID, - tom: UserSchema, ): crud = UsersCRUD(session) result = await crud.exist_by_id(uuid_zero) assert not result -async def test_user_exists_by_id__user_deleted(session: AsyncSession, tom: UserSchema): +async def test_user_exists_by_id__user_deleted(session: AsyncSession, user: User): crud = UsersCRUD(session) - await crud.update_by_id(tom.id, UserSchema(is_deleted=True)) - result = await crud.exist_by_id(tom.id) + await crud.update_by_id(user.id, UserSchema(is_deleted=True)) + result = await crud.exist_by_id(user.id) assert not result -async def test_get_super_admin(session: AsyncSession, tom: UserSchema): +async def test_get_super_admin(session: AsyncSession): crud = UsersCRUD(session) user = await crud.get_super_admin() user = cast(UserSchema, user) assert user.is_super_admin -async def test_get_users_by_ids__no_user_with_id(session: AsyncSession, tom: UserSchema, uuid_zero: uuid.UUID): +async def test_get_users_by_ids__no_user_with_id(session: AsyncSession, user: User, uuid_zero: uuid.UUID): crud = UsersCRUD(session) result = await crud.get_by_ids([uuid_zero]) assert not result -async def test_get_users_by_ids(session: AsyncSession, tom: UserSchema, uuid_zero: uuid.UUID): +async def test_get_users_by_ids(session: AsyncSession, user: User, uuid_zero: uuid.UUID): crud = UsersCRUD(session) - result = await crud.get_by_ids([uuid_zero, tom.id]) + result = await crud.get_by_ids([uuid_zero, user.id]) assert len(result) == 1 -async def test_get_user_by_email_or_none__user_does_not_exist( - session: AsyncSession, - tom: UserSchema, -): +async def test_get_user_by_email_or_none__user_does_not_exist(session: AsyncSession): crud = UsersCRUD(session) user = await crud.get_user_or_none_by_email("doesnotexist@example.com") assert user is None @@ -204,10 +196,10 @@ async def test_get_user_by_email_or_none__user_does_not_exist( async def test_get_user_by_email_or_none( session: AsyncSession, - tom: UserSchema, - tom_create: UserCreate, + user: User, + user_create: UserCreate, ): crud = UsersCRUD(session) - user = await crud.get_user_or_none_by_email(tom_create.email) - user = cast(UserSchema, user) - assert user.id == tom.id + user_db = await crud.get_user_or_none_by_email(user_create.email) + user_db = cast(UserSchema, user_db) + assert user_db.id == user.id diff --git a/src/apps/users/tests/unit/test_user_service.py b/src/apps/users/tests/unit/test_user_service.py index 5d9de0709cb..76b7359d7f0 100644 --- a/src/apps/users/tests/unit/test_user_service.py +++ b/src/apps/users/tests/unit/test_user_service.py @@ -5,16 +5,15 @@ from sqlalchemy.ext.asyncio import AsyncSession from apps.users.cruds.user import UsersCRUD -from apps.users.db.schemas import UserSchema from apps.users.domain import User, UserCreate from apps.users.errors import UserNotFound from apps.users.services.user import UserService -async def test_get_user_by_id(session: AsyncSession, tom: UserSchema): +async def test_get_user_by_id(session: AsyncSession, user: User): srv = UserService(session) - result = await srv.get(tom.id) - assert result == User.from_orm(tom) + result = await srv.get(user.id) + assert result == User.from_orm(user) async def test_user_exists_by_id__user_does_not_exist(session: AsyncSession, uuid_zero: uuid.UUID): @@ -25,12 +24,12 @@ async def test_user_exists_by_id__user_does_not_exist(session: AsyncSession, uui async def test_get_user_by_email( session: AsyncSession, - tom: UserSchema, - tom_create: UserCreate, + user: User, + user_create: UserCreate, ): srv = UserService(session) - result = await srv.get_by_email(tom_create.email) - assert result == User.from_orm(tom) + result = await srv.get_by_email(user_create.email) + assert result == User.from_orm(user) async def test_create_super_user_admin__created_only_once(