Skip to content

Commit ab23a55

Browse files
committed
test: parametrize base URL resolution tests
Collapse the per-case sync/async base-URL resolution tests into pytest.mark.parametrize cases with descriptive ids, covering the same behavior (and a little more, since sync and async now share every case). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bXf84xVdv32VQAt916Ygj
1 parent 09ed654 commit ab23a55

1 file changed

Lines changed: 182 additions & 131 deletions

File tree

Lines changed: 182 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,172 +1,223 @@
11
from __future__ import annotations
22

3-
from typing import TYPE_CHECKING
3+
import pytest
44

55
from apify_client import ApifyClient, ApifyClientAsync
66
from apify_client._consts import DEFAULT_API_PUBLIC_URL, DEFAULT_API_URL
77
from apify_client.http_clients import ImpitHttpClient, ImpitHttpClientAsync
88

9-
if TYPE_CHECKING:
10-
import pytest
9+
# Both clients resolve base URLs identically; construction is synchronous for both.
10+
CLIENT_CLASSES = [
11+
pytest.param(ApifyClient, id='sync'),
12+
pytest.param(ApifyClientAsync, id='async'),
13+
]
14+
15+
# Scenarios for the `with_custom_http_client` tests: (env_var, api_url, api_public_url, attr, expected).
16+
WITH_CUSTOM_HTTP_CLIENT_SCENARIOS = [
17+
pytest.param(
18+
'APIFY_API_BASE_URL',
19+
None,
20+
None,
21+
'_base_url',
22+
'http://localhost:8080/v2',
23+
id='api-base-env-var-resolved',
24+
),
25+
pytest.param(
26+
'APIFY_API_BASE_URL',
27+
'http://example.test',
28+
None,
29+
'_base_url',
30+
'http://example.test/v2',
31+
id='explicit-api-url-wins',
32+
),
33+
pytest.param(
34+
'APIFY_API_PUBLIC_BASE_URL',
35+
None,
36+
None,
37+
'_public_base_url',
38+
'http://localhost:8080/v2',
39+
id='public-base-env-var-resolved',
40+
),
41+
]
42+
1143

1244
# ============================================================================
1345
# API base URL (`APIFY_API_BASE_URL`) — criteria 1-4
1446
# ============================================================================
1547

1648

17-
def test_api_url_defaults_to_production_when_unset_sync(monkeypatch: pytest.MonkeyPatch) -> None:
18-
"""No env var and no argument: resolves to the production default."""
19-
monkeypatch.delenv('APIFY_API_BASE_URL', raising=False)
20-
client = ApifyClient(token='dummy-token')
21-
assert client._base_url == f'{DEFAULT_API_URL}/v2'
22-
23-
24-
async def test_api_url_defaults_to_production_when_unset_async(monkeypatch: pytest.MonkeyPatch) -> None:
25-
"""No env var and no argument: resolves to the production default (async)."""
26-
monkeypatch.delenv('APIFY_API_BASE_URL', raising=False)
27-
client = ApifyClientAsync(token='dummy-token')
28-
assert client._base_url == f'{DEFAULT_API_URL}/v2'
29-
30-
31-
def test_api_url_env_var_used_when_no_argument_sync(monkeypatch: pytest.MonkeyPatch) -> None:
32-
"""`APIFY_API_BASE_URL` is used when no explicit `api_url` argument is given."""
33-
monkeypatch.setenv('APIFY_API_BASE_URL', 'http://localhost:8080')
34-
client = ApifyClient(token='dummy-token')
35-
assert client._base_url == 'http://localhost:8080/v2'
36-
37-
38-
async def test_api_url_env_var_used_when_no_argument_async(monkeypatch: pytest.MonkeyPatch) -> None:
39-
"""`APIFY_API_BASE_URL` is used when no explicit `api_url` argument is given (async)."""
40-
monkeypatch.setenv('APIFY_API_BASE_URL', 'http://localhost:8080')
41-
client = ApifyClientAsync(token='dummy-token')
42-
assert client._base_url == 'http://localhost:8080/v2'
43-
44-
45-
def test_explicit_api_url_wins_over_env_var_sync(monkeypatch: pytest.MonkeyPatch) -> None:
46-
"""An explicit `api_url` argument wins over `APIFY_API_BASE_URL`."""
47-
monkeypatch.setenv('APIFY_API_BASE_URL', 'http://localhost:8080')
48-
client = ApifyClient(token='dummy-token', api_url='http://example.test')
49-
assert client._base_url == 'http://example.test/v2'
50-
51-
52-
async def test_explicit_api_url_wins_over_env_var_async(monkeypatch: pytest.MonkeyPatch) -> None:
53-
"""An explicit `api_url` argument wins over `APIFY_API_BASE_URL` (async)."""
54-
monkeypatch.setenv('APIFY_API_BASE_URL', 'http://localhost:8080')
55-
client = ApifyClientAsync(token='dummy-token', api_url='http://example.test')
56-
assert client._base_url == 'http://example.test/v2'
57-
58-
59-
def test_api_url_custom_port_from_env_needs_no_special_handling(monkeypatch: pytest.MonkeyPatch) -> None:
60-
"""A custom port supplied via the env var works with no special handling."""
61-
monkeypatch.setenv('APIFY_API_BASE_URL', 'http://localhost:9999')
62-
client = ApifyClient(token='dummy-token')
63-
assert client._base_url == 'http://localhost:9999/v2'
49+
@pytest.mark.parametrize('client_class', CLIENT_CLASSES)
50+
@pytest.mark.parametrize(
51+
('env_value', 'explicit_arg', 'expected'),
52+
[
53+
pytest.param(None, None, f'{DEFAULT_API_URL}/v2', id='defaults-to-production-when-unset'),
54+
pytest.param('http://localhost:8080', None, 'http://localhost:8080/v2', id='env-var-used-when-no-argument'),
55+
pytest.param(
56+
'http://localhost:8080',
57+
'http://example.test',
58+
'http://example.test/v2',
59+
id='explicit-arg-wins-over-env-var',
60+
),
61+
pytest.param(
62+
'http://localhost:9999',
63+
None,
64+
'http://localhost:9999/v2',
65+
id='custom-port-needs-no-special-handling',
66+
),
67+
],
68+
)
69+
def test_api_url_resolution(
70+
client_class: type[ApifyClient | ApifyClientAsync],
71+
env_value: str | None,
72+
explicit_arg: str | None,
73+
expected: str,
74+
monkeypatch: pytest.MonkeyPatch,
75+
) -> None:
76+
"""API base URL resolves as explicit arg > `APIFY_API_BASE_URL` > default, for both clients."""
77+
if env_value is None:
78+
monkeypatch.delenv('APIFY_API_BASE_URL', raising=False)
79+
else:
80+
monkeypatch.setenv('APIFY_API_BASE_URL', env_value)
81+
client = client_class(token='dummy-token', api_url=explicit_arg)
82+
assert client._base_url == expected
6483

6584

6685
# ============================================================================
6786
# Public API base URL (`APIFY_API_PUBLIC_BASE_URL`) — criteria 5-8
6887
# ============================================================================
6988

7089

71-
def test_api_public_url_defaults_to_production_when_unset_sync(monkeypatch: pytest.MonkeyPatch) -> None:
72-
"""No env var and no argument: the public base URL resolves to the production default."""
73-
monkeypatch.delenv('APIFY_API_PUBLIC_BASE_URL', raising=False)
74-
client = ApifyClient(token='dummy-token')
75-
assert client._public_base_url == f'{DEFAULT_API_PUBLIC_URL}/v2'
76-
77-
78-
async def test_api_public_url_defaults_to_production_when_unset_async(monkeypatch: pytest.MonkeyPatch) -> None:
79-
"""No env var and no argument: the public base URL resolves to the production default (async)."""
80-
monkeypatch.delenv('APIFY_API_PUBLIC_BASE_URL', raising=False)
81-
client = ApifyClientAsync(token='dummy-token')
82-
assert client._public_base_url == f'{DEFAULT_API_PUBLIC_URL}/v2'
83-
84-
85-
def test_api_public_url_env_var_used_when_no_argument(monkeypatch: pytest.MonkeyPatch) -> None:
86-
"""`APIFY_API_PUBLIC_BASE_URL` is used when no explicit `api_public_url` argument is given."""
87-
monkeypatch.setenv('APIFY_API_PUBLIC_BASE_URL', 'http://localhost:8080')
88-
client = ApifyClient(token='dummy-token')
89-
assert client._public_base_url == 'http://localhost:8080/v2'
90-
91-
92-
def test_explicit_api_public_url_wins_over_env_var(monkeypatch: pytest.MonkeyPatch) -> None:
93-
"""An explicit `api_public_url` argument wins over `APIFY_API_PUBLIC_BASE_URL`."""
94-
monkeypatch.setenv('APIFY_API_PUBLIC_BASE_URL', 'http://localhost:8080')
95-
client = ApifyClient(token='dummy-token', api_public_url='http://example.test')
96-
assert client._public_base_url == 'http://example.test/v2'
97-
98-
99-
def test_api_base_and_public_base_env_vars_are_independent(monkeypatch: pytest.MonkeyPatch) -> None:
100-
"""Setting only `APIFY_API_BASE_URL` leaves the public base URL at its default."""
101-
monkeypatch.delenv('APIFY_API_PUBLIC_BASE_URL', raising=False)
102-
monkeypatch.setenv('APIFY_API_BASE_URL', 'http://localhost:8080')
103-
client = ApifyClient(token='dummy-token')
104-
assert client._base_url == 'http://localhost:8080/v2'
105-
assert client._public_base_url == f'{DEFAULT_API_PUBLIC_URL}/v2'
106-
107-
108-
def test_api_base_and_public_base_env_vars_are_independent_other_direction(monkeypatch: pytest.MonkeyPatch) -> None:
109-
"""Setting only `APIFY_API_PUBLIC_BASE_URL` leaves the API base URL at its default."""
90+
@pytest.mark.parametrize('client_class', CLIENT_CLASSES)
91+
@pytest.mark.parametrize(
92+
('env_value', 'explicit_arg', 'expected'),
93+
[
94+
pytest.param(None, None, f'{DEFAULT_API_PUBLIC_URL}/v2', id='defaults-to-production-when-unset'),
95+
pytest.param('http://localhost:8080', None, 'http://localhost:8080/v2', id='env-var-used-when-no-argument'),
96+
pytest.param(
97+
'http://localhost:8080',
98+
'http://example.test',
99+
'http://example.test/v2',
100+
id='explicit-arg-wins-over-env-var',
101+
),
102+
],
103+
)
104+
def test_api_public_url_resolution(
105+
client_class: type[ApifyClient | ApifyClientAsync],
106+
env_value: str | None,
107+
explicit_arg: str | None,
108+
expected: str,
109+
monkeypatch: pytest.MonkeyPatch,
110+
) -> None:
111+
"""Public API base URL resolves as explicit arg > `APIFY_API_PUBLIC_BASE_URL` > default, for both clients."""
112+
if env_value is None:
113+
monkeypatch.delenv('APIFY_API_PUBLIC_BASE_URL', raising=False)
114+
else:
115+
monkeypatch.setenv('APIFY_API_PUBLIC_BASE_URL', env_value)
116+
client = client_class(token='dummy-token', api_public_url=explicit_arg)
117+
assert client._public_base_url == expected
118+
119+
120+
@pytest.mark.parametrize(
121+
('env_var', 'expected_base', 'expected_public'),
122+
[
123+
pytest.param(
124+
'APIFY_API_BASE_URL',
125+
'http://localhost:8080/v2',
126+
f'{DEFAULT_API_PUBLIC_URL}/v2',
127+
id='only-api-base-set-leaves-public-at-default',
128+
),
129+
pytest.param(
130+
'APIFY_API_PUBLIC_BASE_URL',
131+
f'{DEFAULT_API_URL}/v2',
132+
'http://localhost:8080/v2',
133+
id='only-public-set-leaves-api-base-at-default',
134+
),
135+
],
136+
)
137+
def test_api_base_and_public_base_env_vars_are_independent(
138+
env_var: str,
139+
expected_base: str,
140+
expected_public: str,
141+
monkeypatch: pytest.MonkeyPatch,
142+
) -> None:
143+
"""Setting only one of the two env vars leaves the other at its default."""
110144
monkeypatch.delenv('APIFY_API_BASE_URL', raising=False)
111-
monkeypatch.setenv('APIFY_API_PUBLIC_BASE_URL', 'http://localhost:8080')
145+
monkeypatch.delenv('APIFY_API_PUBLIC_BASE_URL', raising=False)
146+
monkeypatch.setenv(env_var, 'http://localhost:8080')
112147
client = ApifyClient(token='dummy-token')
113-
assert client._public_base_url == 'http://localhost:8080/v2'
114-
assert client._base_url == f'{DEFAULT_API_URL}/v2'
148+
assert client._base_url == expected_base
149+
assert client._public_base_url == expected_public
115150

116151

117152
# ============================================================================
118153
# `with_custom_http_client` resolves URLs by the same precedence — criterion 9
119154
# ============================================================================
120155

121156

122-
def test_with_custom_http_client_resolves_env_var_sync(monkeypatch: pytest.MonkeyPatch) -> None:
123-
monkeypatch.setenv('APIFY_API_BASE_URL', 'http://localhost:8080')
124-
client = ApifyClient.with_custom_http_client(token='dummy-token', http_client=ImpitHttpClient())
125-
assert client._base_url == 'http://localhost:8080/v2'
126-
127-
128-
async def test_with_custom_http_client_resolves_env_var_async(monkeypatch: pytest.MonkeyPatch) -> None:
129-
monkeypatch.setenv('APIFY_API_BASE_URL', 'http://localhost:8080')
130-
client = ApifyClientAsync.with_custom_http_client(token='dummy-token', http_client=ImpitHttpClientAsync())
131-
assert client._base_url == 'http://localhost:8080/v2'
132-
133-
134-
def test_with_custom_http_client_explicit_arg_wins_sync(monkeypatch: pytest.MonkeyPatch) -> None:
135-
monkeypatch.setenv('APIFY_API_BASE_URL', 'http://localhost:8080')
157+
@pytest.mark.parametrize(
158+
('env_var', 'api_url', 'api_public_url', 'attr', 'expected'), WITH_CUSTOM_HTTP_CLIENT_SCENARIOS
159+
)
160+
def test_with_custom_http_client_resolution_sync(
161+
env_var: str,
162+
api_url: str | None,
163+
api_public_url: str | None,
164+
attr: str,
165+
expected: str,
166+
monkeypatch: pytest.MonkeyPatch,
167+
) -> None:
168+
"""`with_custom_http_client` resolves URLs by the same precedence as the constructor (sync)."""
169+
monkeypatch.setenv(env_var, 'http://localhost:8080')
136170
client = ApifyClient.with_custom_http_client(
137171
token='dummy-token',
138-
api_url='http://example.test',
139172
http_client=ImpitHttpClient(),
173+
api_url=api_url,
174+
api_public_url=api_public_url,
140175
)
141-
assert client._base_url == 'http://example.test/v2'
142-
143-
144-
def test_with_custom_http_client_public_url_env_var(monkeypatch: pytest.MonkeyPatch) -> None:
145-
monkeypatch.setenv('APIFY_API_PUBLIC_BASE_URL', 'http://localhost:8080')
146-
client = ApifyClient.with_custom_http_client(token='dummy-token', http_client=ImpitHttpClient())
147-
assert client._public_base_url == 'http://localhost:8080/v2'
148-
149-
150-
async def test_with_custom_http_client_public_url_env_var_async(monkeypatch: pytest.MonkeyPatch) -> None:
151-
monkeypatch.setenv('APIFY_API_PUBLIC_BASE_URL', 'http://localhost:8080')
152-
client = ApifyClientAsync.with_custom_http_client(token='dummy-token', http_client=ImpitHttpClientAsync())
153-
assert client._public_base_url == 'http://localhost:8080/v2'
176+
assert getattr(client, attr) == expected
177+
178+
179+
@pytest.mark.parametrize(
180+
('env_var', 'api_url', 'api_public_url', 'attr', 'expected'), WITH_CUSTOM_HTTP_CLIENT_SCENARIOS
181+
)
182+
async def test_with_custom_http_client_resolution_async(
183+
env_var: str,
184+
api_url: str | None,
185+
api_public_url: str | None,
186+
attr: str,
187+
expected: str,
188+
monkeypatch: pytest.MonkeyPatch,
189+
) -> None:
190+
"""`with_custom_http_client` resolves URLs by the same precedence as the constructor (async)."""
191+
monkeypatch.setenv(env_var, 'http://localhost:8080')
192+
client = ApifyClientAsync.with_custom_http_client(
193+
token='dummy-token',
194+
http_client=ImpitHttpClientAsync(),
195+
api_url=api_url,
196+
api_public_url=api_public_url,
197+
)
198+
assert getattr(client, attr) == expected
154199

155200

156201
# ============================================================================
157202
# The `/v2` suffix invariant — criterion 19
158203
# ============================================================================
159204

160205

161-
def test_v2_suffix_applied_to_env_supplied_api_url(monkeypatch: pytest.MonkeyPatch) -> None:
162-
monkeypatch.setenv('APIFY_API_BASE_URL', 'http://localhost:8080')
163-
client = ApifyClient(token='dummy-token')
164-
assert client._base_url.endswith('/v2')
165-
assert client._base_url == 'http://localhost:8080/v2'
166-
167-
168-
def test_v2_suffix_applied_to_env_supplied_public_url(monkeypatch: pytest.MonkeyPatch) -> None:
169-
monkeypatch.setenv('APIFY_API_PUBLIC_BASE_URL', 'http://localhost:8080')
206+
@pytest.mark.parametrize(
207+
('env_var', 'attr'),
208+
[
209+
pytest.param('APIFY_API_BASE_URL', '_base_url', id='api-base'),
210+
pytest.param('APIFY_API_PUBLIC_BASE_URL', '_public_base_url', id='public-base'),
211+
],
212+
)
213+
def test_v2_suffix_applied_to_env_supplied_url(
214+
env_var: str,
215+
attr: str,
216+
monkeypatch: pytest.MonkeyPatch,
217+
) -> None:
218+
"""The `/v2` version suffix is appended to an env-supplied base URL that lacks it."""
219+
monkeypatch.setenv(env_var, 'http://localhost:8080')
170220
client = ApifyClient(token='dummy-token')
171-
assert client._public_base_url.endswith('/v2')
172-
assert client._public_base_url == 'http://localhost:8080/v2'
221+
value = getattr(client, attr)
222+
assert value.endswith('/v2')
223+
assert value == 'http://localhost:8080/v2'

0 commit comments

Comments
 (0)