Skip to content

Commit 89ab112

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 0921833 commit 89ab112

11 files changed

Lines changed: 253 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: 25 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+
response_json=default_comment_response,
39+
response_status=200,
40+
request_headers=api_headers(),
4741
)
4842

4943
comment = todoist_api.get_comment(comment_id)
@@ -74,13 +68,13 @@ 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+
response_json=page,
72+
response_status=200,
73+
request_params={
74+
"task_id": task_id,
75+
}
76+
| ({"cursor": cursor} if cursor else {}),
77+
request_headers=api_headers(),
8478
)
8579
cursor = page["next_cursor"]
8680

@@ -122,19 +116,14 @@ async def test_add_comment(
122116
respx_mock,
123117
method="POST",
124118
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-
],
119+
response_json=default_comment_response,
120+
response_status=200,
121+
request_headers=api_headers(),
122+
request_json={
123+
"content": content,
124+
"project_id": project_id,
125+
"attachment": attachment.to_dict(),
126+
},
138127
)
139128

140129
new_comment = todoist_api.add_comment(
@@ -172,9 +161,10 @@ async def test_update_comment(
172161
respx_mock,
173162
method="POST",
174163
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)],
164+
response_json=updated_comment_dict,
165+
response_status=200,
166+
request_headers=api_headers(),
167+
request_json=args,
178168
)
179169

180170
response = todoist_api.update_comment(comment_id=default_comment.id, **args)
@@ -203,8 +193,8 @@ async def test_delete_comment(
203193
respx_mock,
204194
method="DELETE",
205195
url=endpoint,
206-
status=204,
207-
matchers=[auth_matcher(), request_id_matcher()],
196+
response_status=204,
197+
request_headers=api_headers(),
208198
)
209199

210200
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+
response_json=page,
55+
response_status=200,
56+
request_params=params | ({"cursor": cursor} if cursor else {}),
57+
request_headers=api_headers(),
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+
response_json=page,
117+
response_status=200,
118+
request_params=params | ({"cursor": cursor} if cursor else {}),
119+
request_headers=api_headers(),
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+
response_json=default_label_response,
34+
response_status=200,
35+
request_headers=api_headers(),
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+
response_json=page,
66+
response_status=200,
67+
request_params={"cursor": cursor} if cursor else {},
68+
request_headers=api_headers(),
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+
response_json=page,
107+
response_status=200,
108+
request_params={"query": query} | ({"cursor": cursor} if cursor else {}),
109+
request_headers=api_headers(),
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+
response_json=default_label_response,
145+
response_status=200,
146+
request_headers=api_headers(),
147+
request_json={"name": label_name},
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+
response_json=default_label_response,
181+
response_status=200,
182+
request_headers=api_headers(),
183+
request_json={"name": label_name} | args,
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+
response_json=updated_label_dict,
214+
response_status=200,
215+
request_headers=api_headers(),
216+
request_json=args,
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+
response_status=204,
244+
request_headers=api_headers(),
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)