From 7ec536e4c64ad46d8319340709e9c5e7ac7a59e5 Mon Sep 17 00:00:00 2001 From: Vadim Nifadev <36514612+nifadyev@users.noreply.github.com> Date: Wed, 6 Nov 2024 09:04:59 +0300 Subject: [PATCH] #94: Remove permissions field from response schemas (#95) * Change zoneinfo importing to fix type hints * Remove field email from PUT me integration test to avoid flaky test * Fix flaky project update test by removing check for old and new values inequality * Fix invalid timeframe format in Project's integration tests --- tests/factories/base.py | 8 +++++--- tests/factories/project.py | 16 ++++++++-------- tests/factories/time_entry.py | 8 ++++---- tests/factories/workspace.py | 8 ++++---- tests/integration/test_project.py | 8 +++----- tests/integration/test_report_time_entry.py | 8 +++++--- tests/integration/test_time_entry.py | 10 ++++++---- tests/integration/test_user.py | 3 +-- tests/responses/project_get.py | 1 - tests/responses/time_entry_get.py | 1 - tests/responses/workspace_get.py | 1 - toggl_python/schemas/project.py | 1 - toggl_python/schemas/time_entry.py | 1 - toggl_python/schemas/workspace.py | 1 - 14 files changed, 36 insertions(+), 39 deletions(-) diff --git a/tests/factories/base.py b/tests/factories/base.py index 3b80f98..9bbe0f7 100644 --- a/tests/factories/base.py +++ b/tests/factories/base.py @@ -1,5 +1,6 @@ from __future__ import annotations +import sys from typing import TYPE_CHECKING, Dict, List, Union from tests.conftest import fake @@ -10,10 +11,11 @@ from pydantic_core import TzInfo -try: - import zoneinfo -except ImportError: +if sys.version_info < (3, 9): from backports import zoneinfo +else: + import zoneinfo + def datetime_repr_factory(timezone: Union[ZoneInfo, TzInfo, None] = None) -> str: diff --git a/tests/factories/project.py b/tests/factories/project.py index 75033b6..bb71589 100644 --- a/tests/factories/project.py +++ b/tests/factories/project.py @@ -1,29 +1,30 @@ from __future__ import annotations +import sys from typing import Dict, Optional, Union from tests.conftest import fake from tests.factories.base import datetime_repr_factory -try: - import zoneinfo -except ImportError: +if sys.version_info < (3, 9): from backports import zoneinfo +else: + import zoneinfo -def project_request_factory() -> Dict[str, Union[str, bool, int, None]]: - start_date = fake.past_date() +def project_request_factory() -> Dict[str, Union[str, bool, int]]: + start_date = fake.future_date() request_body = { "active": fake.boolean(), "auto_estimates": fake.boolean(), "currency": fake.currency_code(), - "end_date": fake.date_between(start_date=start_date).isoformat(), + "end_date": fake.date_between(start_date=start_date, end_date="+90d").isoformat(), "estimated_hours": fake.random_int(), "is_private": fake.boolean(), "is_shared": fake.boolean(), - "name": fake.uuid4(), + "name": str(fake.uuid4()), "start_date": start_date.isoformat(), "template": fake.boolean(), } @@ -63,7 +64,6 @@ def project_response_factory( "is_private": fake.boolean(), "is_shared": fake.boolean(), "name": fake.word(), - "permissions": None, "rate": fake.random_int() if fake.boolean() else None, "rate_last_updated": datetime_repr_factory(timezone) if fake.boolean() else None, "recurring": fake.boolean(), diff --git a/tests/factories/time_entry.py b/tests/factories/time_entry.py index 815268f..b07e24b 100644 --- a/tests/factories/time_entry.py +++ b/tests/factories/time_entry.py @@ -1,5 +1,6 @@ from __future__ import annotations +import sys from datetime import datetime, timedelta from typing import TYPE_CHECKING, Dict, List, Optional, Union @@ -12,10 +13,10 @@ from pydantic_core import TzInfo -try: - import zoneinfo -except ImportError: +if sys.version_info < (3, 9): from backports import zoneinfo +else: + import zoneinfo def _stop_datetime_repr_factory( @@ -88,7 +89,6 @@ def time_entry_response_factory( "duration": duration or fake.random_int(), "duronly": fake.boolean(), "id": fake.random_number(digits=11, fix_len=True), - "permissions": None, "project_id": project_id or fake.random_int(), "server_deleted_at": ( fake.date_time_this_month(tzinfo=tz).isoformat(timespec="seconds") diff --git a/tests/factories/workspace.py b/tests/factories/workspace.py index 15fbfaf..ea93c24 100644 --- a/tests/factories/workspace.py +++ b/tests/factories/workspace.py @@ -1,15 +1,16 @@ from __future__ import annotations +import sys from typing import Dict, List, Optional, Set, Union from tests.conftest import fake from tests.factories.base import datetime_repr_factory -try: - import zoneinfo -except ImportError: +if sys.version_info < (3, 9): from backports import zoneinfo +else: + import zoneinfo def workspace_request_factory( @@ -55,7 +56,6 @@ def workspace_response_factory( "only_admins_see_billable_rates": fake.boolean(), "only_admins_see_team_dashboard": fake.boolean(), "organization_id": 8364520, - "permissions": None, "premium": fake.boolean(), "projects_billable_by_default": fake.boolean(), "projects_enforce_billable": fake.boolean(), diff --git a/tests/integration/test_project.py b/tests/integration/test_project.py index e33e611..d723dcf 100644 --- a/tests/integration/test_project.py +++ b/tests/integration/test_project.py @@ -27,7 +27,7 @@ def test_create_project__without_query_params(i_authed_workspace: Workspace) -> optional_fields = {"end_date", "status"} expected_result = set(ProjectResponse.model_fields.keys()) - optional_fields - result = i_authed_workspace.create_project(workspace_id, name=fake.uuid4()) + result = i_authed_workspace.create_project(workspace_id, name=str(fake.uuid4())) assert result.model_fields_set == expected_result @@ -52,7 +52,7 @@ def test_create_project__all_params(i_authed_workspace: Workspace) -> None: def test_get_projects__without_query_params(i_authed_workspace: Workspace) -> None: workspace_id = int(os.environ["WORKSPACE_ID"]) - project = i_authed_workspace.create_project(workspace_id, name=fake.uuid4()) + project = i_authed_workspace.create_project(workspace_id, name=str(fake.uuid4())) # Field `status` is set to `archived` after first fetch request, `end_date` is still absent optional_fields = {"end_date"} expected_result = set(ProjectResponse.model_fields.keys()) - optional_fields @@ -411,18 +411,16 @@ def test_me_get_paginated_projects__per_page( def test_update_project(i_authed_workspace: Workspace) -> None: workspace_id = int(os.environ["WORKSPACE_ID"]) - project = i_authed_workspace.create_project(workspace_id, name=fake.uuid4()) + project = i_authed_workspace.create_project(workspace_id, name=str(fake.uuid4())) full_request_body = project_request_factory() random_param = fake.random_element(full_request_body.keys()) request_body = {random_param: full_request_body[random_param]} - old_param_value = getattr(project, random_param) optional_fields = {"end_date"} expected_result = set(ProjectResponse.model_fields.keys()) - optional_fields result = i_authed_workspace.update_project(workspace_id, project.id, **request_body) assert result.model_fields_set == expected_result - assert getattr(result, random_param) != old_param_value _ = i_authed_workspace.delete_project(workspace_id, project.id) diff --git a/tests/integration/test_report_time_entry.py b/tests/integration/test_report_time_entry.py index a3f777c..84430c9 100644 --- a/tests/integration/test_report_time_entry.py +++ b/tests/integration/test_report_time_entry.py @@ -1,6 +1,7 @@ from __future__ import annotations import os +import sys from datetime import timedelta from typing import TYPE_CHECKING @@ -20,10 +21,11 @@ from toggl_python.entities.workspace import Workspace -try: - import zoneinfo -except ImportError: +if sys.version_info < (3, 9): from backports import zoneinfo +else: + import zoneinfo + @pytest.mark.parametrize( diff --git a/tests/integration/test_time_entry.py b/tests/integration/test_time_entry.py index 31b7555..b0308a6 100644 --- a/tests/integration/test_time_entry.py +++ b/tests/integration/test_time_entry.py @@ -1,6 +1,7 @@ from __future__ import annotations import os +import sys from datetime import timedelta from typing import TYPE_CHECKING @@ -16,10 +17,11 @@ from tests.integration import pytestmark # noqa: F401 - imported but unused -try: - import zoneinfo -except ImportError: +if sys.version_info < (3, 9): from backports import zoneinfo +else: + import zoneinfo + if TYPE_CHECKING: @@ -52,7 +54,7 @@ def test_create_time_entry__all_fields(i_authed_workspace: Workspace) -> None: workspace_id = int(os.environ["WORKSPACE_ID"]) request_body = time_entry_extended_request_factory(workspace_id) expected_result = set(MeTimeEntryResponse.model_fields.keys()) - project = i_authed_workspace.create_project(workspace_id, name=fake.uuid4()) + project = i_authed_workspace.create_project(workspace_id, name=str(fake.uuid4())) result = i_authed_workspace.create_time_entry( workspace_id, diff --git a/tests/integration/test_user.py b/tests/integration/test_user.py index e06f8b4..4eb8ad7 100644 --- a/tests/integration/test_user.py +++ b/tests/integration/test_user.py @@ -66,14 +66,12 @@ def test_me__with_related_data(i_authed_user: CurrentUser) -> None: argvalues=[ ("beginning_of_week", fake.random_int(min=0, max=6)), ("country_id", fake.random_int(min=100, max=200)), - ("email", fake.email()), ("fullname", fake.name()), ("timezone", fake.timezone()), ], ids=( "beginning_of_week", "country_id", - "email", "fullname", "timezone", ), @@ -85,6 +83,7 @@ def test_update_me__ok( field_value: Union[str, int], ) -> None: # default_workspace_id is not tested because it requires method to create and delete workspace + # `email` is skipped because changing it leads to flaky tests update_body = {field_name: field_value} current_state_body = {field_name: getattr(me_response, field_name)} diff --git a/tests/responses/project_get.py b/tests/responses/project_get.py index c2ad9f1..d3a3285 100644 --- a/tests/responses/project_get.py +++ b/tests/responses/project_get.py @@ -23,7 +23,6 @@ "is_private": True, "is_shared": False, "name": "test project", - "permissions": None, "rate": None, "rate_last_updated": None, "recurring": False, diff --git a/tests/responses/time_entry_get.py b/tests/responses/time_entry_get.py index 246508a..6dc1f34 100644 --- a/tests/responses/time_entry_get.py +++ b/tests/responses/time_entry_get.py @@ -29,7 +29,6 @@ "duration": 22, "duronly": True, "id": 3544298808, - "permissions": None, "project_id": None, "server_deleted_at": None, "start": "2024-07-29T12:28:33+00:00", diff --git a/tests/responses/workspace_get.py b/tests/responses/workspace_get.py index 766f8eb..c072a7c 100644 --- a/tests/responses/workspace_get.py +++ b/tests/responses/workspace_get.py @@ -23,7 +23,6 @@ "only_admins_see_billable_rates": False, "only_admins_see_team_dashboard": False, "organization_id": 8364520, - "permissions": None, "premium": False, "profile": 0, "projects_billable_by_default": True, diff --git a/toggl_python/schemas/project.py b/toggl_python/schemas/project.py index 19ac5be..66ecec0 100644 --- a/toggl_python/schemas/project.py +++ b/toggl_python/schemas/project.py @@ -30,7 +30,6 @@ class ProjectResponse(BaseSchema): is_private: bool is_shared: bool name: str - permissions: Optional[str] rate: Optional[int] rate_last_updated: Optional[datetime] recurring: bool diff --git a/toggl_python/schemas/time_entry.py b/toggl_python/schemas/time_entry.py index 428de98..8444933 100644 --- a/toggl_python/schemas/time_entry.py +++ b/toggl_python/schemas/time_entry.py @@ -45,7 +45,6 @@ class MeTimeEntryResponse(MeTimeEntryResponseBase): duration: int duronly: bool id: int - permissions: Optional[List] server_deleted_at: Optional[datetime] start: datetime stop: Optional[datetime] diff --git a/toggl_python/schemas/workspace.py b/toggl_python/schemas/workspace.py index 260eec1..9819218 100644 --- a/toggl_python/schemas/workspace.py +++ b/toggl_python/schemas/workspace.py @@ -27,7 +27,6 @@ class WorkspaceResponseBase(BaseSchema): only_admins_see_billable_rates: bool only_admins_see_team_dashboard: bool organization_id: int - permissions: Optional[List[str]] premium: bool projects_billable_by_default: bool projects_enforce_billable: bool