Skip to content

Commit a716e9c

Browse files
committed
Switch tests to declarative respx request lookups
Use declarative respx lookups (params__eq, headers__contains, json__eq) via mock_route request_* arguments and response_* payload arguments. Set API fixtures to deterministic request IDs so request-header assertions remain fully declarative and consistent across sync and async tests.
1 parent af93217 commit a716e9c

11 files changed

Lines changed: 249 additions & 395 deletions

tests/conftest.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
DEFAULT_LABELS_RESPONSE,
1616
DEFAULT_PROJECT_RESPONSE,
1717
DEFAULT_PROJECTS_RESPONSE,
18+
DEFAULT_REQUEST_ID,
1819
DEFAULT_SECTION_RESPONSE,
1920
DEFAULT_SECTIONS_RESPONSE,
2021
DEFAULT_TASK_META_RESPONSE,
@@ -42,13 +43,19 @@
4243

4344
@pytest.fixture
4445
def todoist_api() -> Iterator[TodoistAPI]:
45-
with TodoistAPI(DEFAULT_TOKEN) as api:
46+
with TodoistAPI(
47+
DEFAULT_TOKEN,
48+
request_id_fn=lambda: DEFAULT_REQUEST_ID,
49+
) as api:
4650
yield api
4751

4852

4953
@pytest_asyncio.fixture
5054
async def todoist_api_async() -> AsyncIterator[TodoistAPIAsync]:
51-
async with TodoistAPIAsync(DEFAULT_TOKEN) as api:
55+
async with TodoistAPIAsync(
56+
DEFAULT_TOKEN,
57+
request_id_fn=lambda: DEFAULT_REQUEST_ID,
58+
) as api:
5259
yield api
5360

5461

tests/test_api_comments.py

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,7 @@
88
DEFAULT_API_URL,
99
PaginatedResults,
1010
)
11-
from tests.utils.test_utils import (
12-
auth_matcher,
13-
data_matcher,
14-
enumerate_async,
15-
mock_route,
16-
request_id_matcher,
17-
)
11+
from tests.utils.test_utils import api_headers, enumerate_async, mock_route
1812
from todoist_api_python.models import Attachment
1913

2014
if TYPE_CHECKING:
@@ -41,9 +35,9 @@ async def test_get_comment(
4135
respx_mock,
4236
method="GET",
4337
url=endpoint,
44-
json=default_comment_response,
45-
status=200,
46-
matchers=[auth_matcher(), request_id_matcher()],
38+
request_headers=api_headers(),
39+
response_json=default_comment_response,
40+
response_status=200,
4741
)
4842

4943
comment = todoist_api.get_comment(comment_id)
@@ -74,13 +68,11 @@ async def test_get_comments(
7468
respx_mock,
7569
method="GET",
7670
url=endpoint,
77-
json=page,
78-
status=200,
79-
params={"task_id": task_id} | ({"cursor": cursor} if cursor else {}),
80-
matchers=[
81-
auth_matcher(),
82-
request_id_matcher(),
83-
],
71+
request_params={"task_id": task_id}
72+
| ({"cursor": cursor} if cursor else {}),
73+
request_headers=api_headers(),
74+
response_json=page,
75+
response_status=200,
8476
)
8577
cursor = page["next_cursor"]
8678

@@ -122,19 +114,14 @@ async def test_add_comment(
122114
respx_mock,
123115
method="POST",
124116
url=f"{DEFAULT_API_URL}/comments",
125-
json=default_comment_response,
126-
status=200,
127-
matchers=[
128-
auth_matcher(),
129-
request_id_matcher(),
130-
data_matcher(
131-
{
132-
"content": content,
133-
"project_id": project_id,
134-
"attachment": attachment.to_dict(),
135-
}
136-
),
137-
],
117+
request_headers=api_headers(),
118+
request_json={
119+
"content": content,
120+
"project_id": project_id,
121+
"attachment": attachment.to_dict(),
122+
},
123+
response_json=default_comment_response,
124+
response_status=200,
138125
)
139126

140127
new_comment = todoist_api.add_comment(
@@ -172,9 +159,10 @@ async def test_update_comment(
172159
respx_mock,
173160
method="POST",
174161
url=f"{DEFAULT_API_URL}/comments/{default_comment.id}",
175-
json=updated_comment_dict,
176-
status=200,
177-
matchers=[auth_matcher(), request_id_matcher(), data_matcher(args)],
162+
request_headers=api_headers(),
163+
request_json=args,
164+
response_json=updated_comment_dict,
165+
response_status=200,
178166
)
179167

180168
response = todoist_api.update_comment(comment_id=default_comment.id, **args)
@@ -203,8 +191,8 @@ async def test_delete_comment(
203191
respx_mock,
204192
method="DELETE",
205193
url=endpoint,
206-
status=204,
207-
matchers=[auth_matcher(), request_id_matcher()],
194+
request_headers=api_headers(),
195+
response_status=204,
208196
)
209197

210198
response = todoist_api.delete_comment(comment_id)

tests/test_api_completed_tasks.py

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,7 @@
1212
import pytest
1313

1414
from tests.data.test_defaults import DEFAULT_API_URL, PaginatedItems
15-
from tests.utils.test_utils import (
16-
auth_matcher,
17-
enumerate_async,
18-
mock_route,
19-
request_id_matcher,
20-
)
15+
from tests.utils.test_utils import api_headers, enumerate_async, mock_route
2116
from todoist_api_python._core.utils import format_datetime
2217

2318
if TYPE_CHECKING:
@@ -56,13 +51,10 @@ async def test_get_completed_tasks_by_due_date(
5651
respx_mock,
5752
method="GET",
5853
url=endpoint,
59-
json=page,
60-
status=200,
61-
params=params | ({"cursor": cursor} if cursor else {}),
62-
matchers=[
63-
auth_matcher(),
64-
request_id_matcher(),
65-
],
54+
request_params=params | ({"cursor": cursor} if cursor else {}),
55+
request_headers=api_headers(),
56+
response_json=page,
57+
response_status=200,
6658
)
6759
cursor = page["next_cursor"]
6860

@@ -121,13 +113,10 @@ async def test_get_completed_tasks_by_completion_date(
121113
respx_mock,
122114
method="GET",
123115
url=endpoint,
124-
json=page,
125-
status=200,
126-
params=params | ({"cursor": cursor} if cursor else {}),
127-
matchers=[
128-
auth_matcher(),
129-
request_id_matcher(),
130-
],
116+
request_params=params | ({"cursor": cursor} if cursor else {}),
117+
request_headers=api_headers(),
118+
response_json=page,
119+
response_status=200,
131120
)
132121
cursor = page["next_cursor"]
133122

tests/test_api_labels.py

Lines changed: 26 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,7 @@
55
import pytest
66

77
from tests.data.test_defaults import DEFAULT_API_URL, PaginatedResults
8-
from tests.utils.test_utils import (
9-
auth_matcher,
10-
data_matcher,
11-
enumerate_async,
12-
mock_route,
13-
request_id_matcher,
14-
)
8+
from tests.utils.test_utils import api_headers, enumerate_async, mock_route
159

1610
if TYPE_CHECKING:
1711
import respx
@@ -36,9 +30,9 @@ async def test_get_label(
3630
respx_mock,
3731
method="GET",
3832
url=endpoint,
39-
json=default_label_response,
40-
status=200,
41-
matchers=[auth_matcher()],
33+
request_headers=api_headers(),
34+
response_json=default_label_response,
35+
response_status=200,
4236
)
4337

4438
label = todoist_api.get_label(label_id)
@@ -68,10 +62,10 @@ async def test_get_labels(
6862
respx_mock,
6963
method="GET",
7064
url=endpoint,
71-
json=page,
72-
status=200,
73-
params={"cursor": cursor} if cursor else {},
74-
matchers=[auth_matcher(), request_id_matcher()],
65+
request_params={"cursor": cursor} if cursor else {},
66+
request_headers=api_headers(),
67+
response_json=page,
68+
response_status=200,
7569
)
7670
cursor = page["next_cursor"]
7771

@@ -109,13 +103,10 @@ async def test_search_labels(
109103
respx_mock,
110104
method="GET",
111105
url=endpoint,
112-
json=page,
113-
status=200,
114-
params={"query": query} | ({"cursor": cursor} if cursor else {}),
115-
matchers=[
116-
auth_matcher(),
117-
request_id_matcher(),
118-
],
106+
request_params={"query": query} | ({"cursor": cursor} if cursor else {}),
107+
request_headers=api_headers(),
108+
response_json=page,
109+
response_status=200,
119110
)
120111
cursor = page["next_cursor"]
121112

@@ -150,13 +141,10 @@ async def test_add_label_minimal(
150141
respx_mock,
151142
method="POST",
152143
url=f"{DEFAULT_API_URL}/labels",
153-
json=default_label_response,
154-
status=200,
155-
matchers=[
156-
auth_matcher(),
157-
request_id_matcher(),
158-
data_matcher({"name": label_name}),
159-
],
144+
request_headers=api_headers(),
145+
request_json={"name": label_name},
146+
response_json=default_label_response,
147+
response_status=200,
160148
)
161149

162150
new_label = todoist_api.add_label(name=label_name)
@@ -189,13 +177,10 @@ async def test_add_label_full(
189177
respx_mock,
190178
method="POST",
191179
url=f"{DEFAULT_API_URL}/labels",
192-
json=default_label_response,
193-
status=200,
194-
matchers=[
195-
auth_matcher(),
196-
request_id_matcher(),
197-
data_matcher({"name": label_name} | args),
198-
],
180+
request_headers=api_headers(),
181+
request_json={"name": label_name} | args,
182+
response_json=default_label_response,
183+
response_status=200,
199184
)
200185

201186
new_label = todoist_api.add_label(name=label_name, **args)
@@ -225,9 +210,10 @@ async def test_update_label(
225210
respx_mock,
226211
method="POST",
227212
url=f"{DEFAULT_API_URL}/labels/{default_label.id}",
228-
json=updated_label_dict,
229-
status=200,
230-
matchers=[auth_matcher(), request_id_matcher(), data_matcher(args)],
213+
request_headers=api_headers(),
214+
request_json=args,
215+
response_json=updated_label_dict,
216+
response_status=200,
231217
)
232218

233219
response = todoist_api.update_label(label_id=default_label.id, **args)
@@ -254,8 +240,8 @@ async def test_delete_label(
254240
respx_mock,
255241
method="DELETE",
256242
url=endpoint,
257-
status=204,
258-
matchers=[auth_matcher(), request_id_matcher()],
243+
request_headers=api_headers(),
244+
response_status=204,
259245
)
260246

261247
response = todoist_api.delete_label(label_id)
@@ -267,5 +253,3 @@ async def test_delete_label(
267253

268254
assert len(respx_mock.calls) == 2
269255
assert response is True
270-
271-

0 commit comments

Comments
 (0)