Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@
DEFAULT_COMPLETED_TASKS_RESPONSE,
DEFAULT_LABEL_RESPONSE,
DEFAULT_LABELS_RESPONSE,
DEFAULT_LOCATION_REMINDER_RESPONSE,
DEFAULT_LOCATION_REMINDERS_RESPONSE,
DEFAULT_PROJECT_RESPONSE,
DEFAULT_PROJECTS_RESPONSE,
DEFAULT_REMINDER_RESPONSE,
DEFAULT_REMINDERS_RESPONSE,
DEFAULT_REQUEST_ID,
DEFAULT_SECTION_RESPONSE,
DEFAULT_SECTIONS_RESPONSE,
Expand All @@ -32,7 +36,9 @@
Collaborator,
Comment,
Label,
LocationReminder,
Project,
Reminder,
Section,
Task,
)
Expand Down Expand Up @@ -210,6 +216,52 @@ def default_labels_list() -> list[list[Label]]:
]


@pytest.fixture
def default_reminder_response() -> dict[str, Any]:
return DEFAULT_REMINDER_RESPONSE


@pytest.fixture
def default_reminder() -> Reminder:
return Reminder.from_dict(DEFAULT_REMINDER_RESPONSE)


@pytest.fixture
def default_reminders_response() -> list[PaginatedResults]:
return DEFAULT_REMINDERS_RESPONSE


@pytest.fixture
def default_reminders_list() -> list[list[Reminder]]:
return [
[Reminder.from_dict(result) for result in response["results"]]
for response in DEFAULT_REMINDERS_RESPONSE
]


@pytest.fixture
def default_location_reminder_response() -> dict[str, Any]:
return DEFAULT_LOCATION_REMINDER_RESPONSE


@pytest.fixture
def default_location_reminder() -> LocationReminder:
return LocationReminder.from_dict(DEFAULT_LOCATION_REMINDER_RESPONSE)


@pytest.fixture
def default_location_reminders_response() -> list[PaginatedResults]:
return DEFAULT_LOCATION_REMINDERS_RESPONSE


@pytest.fixture
def default_location_reminders_list() -> list[list[LocationReminder]]:
return [
[LocationReminder.from_dict(result) for result in response["results"]]
for response in DEFAULT_LOCATION_REMINDERS_RESPONSE
]


@pytest.fixture
def default_quick_add_response() -> dict[str, Any]:
return DEFAULT_TASK_RESPONSE
Expand Down
63 changes: 63 additions & 0 deletions tests/data/test_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,69 @@ class PaginatedItems(TypedDict):
},
]

DEFAULT_REMINDER_RESPONSE: dict[str, Any] = {
"id": "6X7rM8997g3RQmvh",
"item_id": "6Jf8VQXxpwv56VQ7",
"notify_uid": "34567",
"type": "relative",
"is_deleted": False,
"is_urgent": False,
"minute_offset": 30,
"due": DEFAULT_DUE_RESPONSE,
"service": "push",
}

DEFAULT_REMINDER_RESPONSE_2 = dict(DEFAULT_REMINDER_RESPONSE)
DEFAULT_REMINDER_RESPONSE_2["id"] = "6X7rfFVPjhvv84XG"

DEFAULT_REMINDER_RESPONSE_3 = dict(DEFAULT_REMINDER_RESPONSE)
DEFAULT_REMINDER_RESPONSE_3["id"] = "6X7rfEVP8hvv25ZQ"

DEFAULT_REMINDERS_RESPONSE: list[PaginatedResults] = [
{
"results": [DEFAULT_REMINDER_RESPONSE, DEFAULT_REMINDER_RESPONSE_2],
"next_cursor": "next",
},
{
"results": [DEFAULT_REMINDER_RESPONSE_3],
"next_cursor": None,
},
]

DEFAULT_LOCATION_REMINDER_RESPONSE: dict[str, Any] = {
"id": "6X7rM8997g3RQmvh",
"item_id": "6Jf8VQXxpwv56VQ7",
"project_id": "6Jf8VQXxpwv56VQ7",
"notify_uid": "34567",
"name": "Office",
"loc_lat": "51.5074",
"loc_long": "-0.1278",
"loc_trigger": "on_enter",
"radius": 100,
"type": "location",
"is_deleted": False,
}

DEFAULT_LOCATION_REMINDER_RESPONSE_2 = dict(DEFAULT_LOCATION_REMINDER_RESPONSE)
DEFAULT_LOCATION_REMINDER_RESPONSE_2["id"] = "6X7rfFVPjhvv84XG"

DEFAULT_LOCATION_REMINDER_RESPONSE_3 = dict(DEFAULT_LOCATION_REMINDER_RESPONSE)
DEFAULT_LOCATION_REMINDER_RESPONSE_3["id"] = "6X7rfEVP8hvv25ZQ"

DEFAULT_LOCATION_REMINDERS_RESPONSE: list[PaginatedResults] = [
{
"results": [
DEFAULT_LOCATION_REMINDER_RESPONSE,
DEFAULT_LOCATION_REMINDER_RESPONSE_2,
],
"next_cursor": "next",
},
{
"results": [DEFAULT_LOCATION_REMINDER_RESPONSE_3],
"next_cursor": None,
},
]

DEFAULT_AUTH_RESPONSE = {
"access_token": "123456789",
"state": "somestate",
Expand Down
211 changes: 211 additions & 0 deletions tests/test_api_location_reminders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
from __future__ import annotations

from typing import TYPE_CHECKING, Any

import pytest

from tests.data.test_defaults import (
DEFAULT_API_URL,
PaginatedResults,
)
from tests.utils.test_utils import api_headers, enumerate_async, mock_route
from todoist_api_python.models import LocationReminder

if TYPE_CHECKING:
import respx

from todoist_api_python.api import TodoistAPI
from todoist_api_python.api_async import TodoistAPIAsync


@pytest.mark.asyncio
async def test_get_location_reminder(
todoist_api: TodoistAPI,
todoist_api_async: TodoistAPIAsync,
respx_mock: respx.MockRouter,
default_location_reminder_response: dict[str, Any],
default_location_reminder: LocationReminder,
) -> None:
location_reminder_id = "6X7rM8997g3RQmvh"
endpoint = f"{DEFAULT_API_URL}/location_reminders/{location_reminder_id}"

mock_route(
respx_mock,
method="GET",
url=endpoint,
request_headers=api_headers(),
response_json=default_location_reminder_response,
response_status=200,
)

reminder = todoist_api.get_location_reminder(location_reminder_id)

assert len(respx_mock.calls) == 1
assert reminder == default_location_reminder

reminder = await todoist_api_async.get_location_reminder(location_reminder_id)

assert len(respx_mock.calls) == 2
assert reminder == default_location_reminder


@pytest.mark.asyncio
async def test_get_location_reminders(
todoist_api: TodoistAPI,
todoist_api_async: TodoistAPIAsync,
respx_mock: respx.MockRouter,
default_location_reminders_response: list[PaginatedResults],
default_location_reminders_list: list[list[LocationReminder]],
) -> None:
task_id = "6X7rM8997g3RQmvh"
endpoint = f"{DEFAULT_API_URL}/location_reminders"

cursor: str | None = None
for page in default_location_reminders_response:
mock_route(
respx_mock,
method="GET",
url=endpoint,
request_params={"task_id": task_id}
| ({"cursor": cursor} if cursor else {}),
request_headers=api_headers(),
response_json=page,
response_status=200,
)
cursor = page["next_cursor"]

count = 0

reminders_iter = todoist_api.get_location_reminders(task_id=task_id)

for i, reminders in enumerate(reminders_iter):
assert len(respx_mock.calls) == count + 1
assert reminders == default_location_reminders_list[i]
count += 1

reminders_async_iter = await todoist_api_async.get_location_reminders(
task_id=task_id
)

async for i, reminders in enumerate_async(reminders_async_iter):
assert len(respx_mock.calls) == count + 1
assert reminders == default_location_reminders_list[i]
count += 1


@pytest.mark.asyncio
async def test_add_location_reminder(
todoist_api: TodoistAPI,
todoist_api_async: TodoistAPIAsync,
respx_mock: respx.MockRouter,
default_location_reminder_response: dict[str, Any],
default_location_reminder: LocationReminder,
) -> None:
task_id = "6X7rM8997g3RQmvh"

mock_route(
respx_mock,
method="POST",
url=f"{DEFAULT_API_URL}/location_reminders",
request_headers=api_headers(),
request_json={
"task_id": task_id,
"name": "Office",
"loc_lat": "51.5074",
"loc_long": "-0.1278",
"loc_trigger": "on_enter",
"radius": 200,
},
response_json=default_location_reminder_response,
response_status=200,
)

new_reminder = todoist_api.add_location_reminder(
task_id=task_id,
name="Office",
loc_lat="51.5074",
loc_long="-0.1278",
loc_trigger="on_enter",
radius=200,
)

assert len(respx_mock.calls) == 1
assert new_reminder == default_location_reminder

new_reminder = await todoist_api_async.add_location_reminder(
task_id=task_id,
name="Office",
loc_lat="51.5074",
loc_long="-0.1278",
loc_trigger="on_enter",
radius=200,
)

assert len(respx_mock.calls) == 2
assert new_reminder == default_location_reminder


@pytest.mark.asyncio
async def test_update_location_reminder(
todoist_api: TodoistAPI,
todoist_api_async: TodoistAPIAsync,
respx_mock: respx.MockRouter,
default_location_reminder: LocationReminder,
) -> None:
args = {
"name": "Home Office",
"radius": 150,
}
updated_dict = default_location_reminder.to_dict() | args

mock_route(
respx_mock,
method="POST",
url=f"{DEFAULT_API_URL}/location_reminders/{default_location_reminder.id}",
request_headers=api_headers(),
request_json=args,
response_json=updated_dict,
response_status=200,
)

response = todoist_api.update_location_reminder(
location_reminder_id=default_location_reminder.id, **args
)

assert len(respx_mock.calls) == 1
assert response == LocationReminder.from_dict(updated_dict)

response = await todoist_api_async.update_location_reminder(
location_reminder_id=default_location_reminder.id, **args
)

assert len(respx_mock.calls) == 2
assert response == LocationReminder.from_dict(updated_dict)


@pytest.mark.asyncio
async def test_delete_location_reminder(
todoist_api: TodoistAPI,
todoist_api_async: TodoistAPIAsync,
respx_mock: respx.MockRouter,
) -> None:
location_reminder_id = "6X7rM8997g3RQmvh"
endpoint = f"{DEFAULT_API_URL}/location_reminders/{location_reminder_id}"

mock_route(
respx_mock,
method="DELETE",
url=endpoint,
request_headers=api_headers(),
response_status=204,
)

response = todoist_api.delete_location_reminder(location_reminder_id)

assert len(respx_mock.calls) == 1
assert response is True

response = await todoist_api_async.delete_location_reminder(location_reminder_id)

assert len(respx_mock.calls) == 2
assert response is True
Loading
Loading