Skip to content

Commit 35fb731

Browse files
committed
Add more integration tests
1 parent bbf4e8e commit 35fb731

26 files changed

Lines changed: 545 additions & 113 deletions

scripts/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ def get_published_package_versions() -> list:
5959
package_data = json.load(urlopen(package_info_url)) # noqa: S310
6060
published_versions = list(package_data['releases'].keys())
6161
# If the URL returns 404, it means the package has no releases yet (which is okay in our case)
62-
except HTTPError as e:
63-
if e.code != 404:
62+
except HTTPError as exc:
63+
if exc.code != 404:
6464
raise
6565
published_versions = []
6666
return published_versions

src/apify_client/_http_client.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,10 @@ def _make_request(stop_retrying: Callable, attempt: int) -> impit.Response:
189189
if response.status_code == HTTPStatus.TOO_MANY_REQUESTS:
190190
self.stats.add_rate_limit_error(attempt)
191191

192-
except Exception as e:
193-
logger.debug('Request threw exception', exc_info=e)
194-
if not is_retryable_error(e):
195-
logger.debug('Exception is not retryable', exc_info=e)
192+
except Exception as exc:
193+
logger.debug('Request threw exception', exc_info=exc)
194+
if not is_retryable_error(exc):
195+
logger.debug('Exception is not retryable', exc_info=exc)
196196
stop_retrying()
197197
raise
198198

@@ -265,10 +265,10 @@ async def _make_request(stop_retrying: Callable, attempt: int) -> impit.Response
265265
if response.status_code == HTTPStatus.TOO_MANY_REQUESTS:
266266
self.stats.add_rate_limit_error(attempt)
267267

268-
except Exception as e:
269-
logger.debug('Request threw exception', exc_info=e)
270-
if not is_retryable_error(e):
271-
logger.debug('Exception is not retryable', exc_info=e)
268+
except Exception as exc:
269+
logger.debug('Request threw exception', exc_info=exc)
270+
if not is_retryable_error(exc):
271+
logger.debug('Exception is not retryable', exc_info=exc)
272272
stop_retrying()
273273
raise
274274

src/apify_client/_resource_clients/actor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ def runs(self) -> RunCollectionClient:
463463
"""Retrieve a client for the runs of this Actor."""
464464
return RunCollectionClient(**self._sub_resource_init_options(resource_path='runs'))
465465

466-
async def default_build(
466+
def default_build(
467467
self,
468468
*,
469469
wait_for_finish: int | None = None,

tests/integration/test_actor.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,53 @@ def test_actor_create_update_delete(apify_client: ApifyClient) -> None:
113113
# Verify deletion
114114
deleted_actor = actor_client.get()
115115
assert deleted_actor is None
116+
117+
118+
def test_actor_default_build(apify_client: ApifyClient) -> None:
119+
"""Test getting an actor's default build."""
120+
# Use a public actor that has builds
121+
actor_client = apify_client.actor('apify/hello-world')
122+
123+
# Get default build client
124+
build_client = actor_client.default_build()
125+
assert build_client is not None
126+
127+
# Use the returned client to get the build
128+
build = build_client.get()
129+
assert build is not None
130+
assert build.id is not None
131+
assert build.status is not None
132+
133+
134+
def test_actor_last_run(apify_client: ApifyClient) -> None:
135+
"""Test getting an actor's last run."""
136+
# First run an actor to ensure there is a last run
137+
actor_client = apify_client.actor('apify/hello-world')
138+
run = actor_client.call()
139+
assert run is not None
140+
141+
try:
142+
# Get last run client
143+
last_run_client = actor_client.last_run()
144+
assert last_run_client is not None
145+
146+
# Use the returned client to get the run
147+
last_run = last_run_client.get()
148+
assert last_run is not None
149+
assert last_run.id is not None
150+
# The last run should be the one we just created
151+
assert last_run.id == run.id
152+
153+
finally:
154+
# Cleanup
155+
apify_client.run(run.id).delete()
156+
157+
158+
def test_actor_validate_input(apify_client: ApifyClient) -> None:
159+
"""Test validating actor input."""
160+
# Use a public actor with an input schema
161+
actor_client = apify_client.actor('apify/hello-world')
162+
163+
# Valid input (hello-world accepts empty input or simple input)
164+
is_valid = actor_client.validate_input({})
165+
assert is_valid is True

tests/integration/test_actor_async.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,53 @@ async def test_actor_create_update_delete(apify_client_async: ApifyClientAsync)
113113
# Verify deletion
114114
deleted_actor = await actor_client.get()
115115
assert deleted_actor is None
116+
117+
118+
async def test_actor_default_build(apify_client_async: ApifyClientAsync) -> None:
119+
"""Test getting an actor's default build."""
120+
# Use a public actor that has builds
121+
actor_client = apify_client_async.actor('apify/hello-world')
122+
123+
# Get default build client
124+
build_client = await actor_client.default_build()
125+
assert build_client is not None
126+
127+
# Use the returned client to get the build
128+
build = await build_client.get()
129+
assert build is not None
130+
assert build.id is not None
131+
assert build.status is not None
132+
133+
134+
async def test_actor_last_run(apify_client_async: ApifyClientAsync) -> None:
135+
"""Test getting an actor's last run."""
136+
# First run an actor to ensure there is a last run
137+
actor_client = apify_client_async.actor('apify/hello-world')
138+
run = await actor_client.call()
139+
assert run is not None
140+
141+
try:
142+
# Get last run client
143+
last_run_client = actor_client.last_run()
144+
assert last_run_client is not None
145+
146+
# Use the returned client to get the run
147+
last_run = await last_run_client.get()
148+
assert last_run is not None
149+
assert last_run.id is not None
150+
# The last run should be the one we just created
151+
assert last_run.id == run.id
152+
153+
finally:
154+
# Cleanup
155+
await apify_client_async.run(run.id).delete()
156+
157+
158+
async def test_actor_validate_input(apify_client_async: ApifyClientAsync) -> None:
159+
"""Test validating actor input."""
160+
# Use a public actor with an input schema
161+
actor_client = apify_client_async.actor('apify/hello-world')
162+
163+
# Valid input (hello-world accepts empty input or simple input)
164+
is_valid = await actor_client.validate_input({})
165+
assert is_valid is True

tests/integration/test_build_async.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
from typing import TYPE_CHECKING
44

5-
import pytest
6-
75
from .utils import get_random_resource_name
86

97
if TYPE_CHECKING:
@@ -13,7 +11,6 @@
1311
HELLO_WORLD_ACTOR = 'apify/hello-world'
1412

1513

16-
@pytest.mark.asyncio
1714
async def test_build_list_for_actor(apify_client_async: ApifyClientAsync) -> None:
1815
"""Test listing builds for a public actor."""
1916
# Get builds for hello-world actor
@@ -30,7 +27,6 @@ async def test_build_list_for_actor(apify_client_async: ApifyClientAsync) -> Non
3027
assert first_build.act_id is not None
3128

3229

33-
@pytest.mark.asyncio
3430
async def test_build_get(apify_client_async: ApifyClientAsync) -> None:
3531
"""Test getting a specific build."""
3632
# First list builds to get a build ID
@@ -48,7 +44,6 @@ async def test_build_get(apify_client_async: ApifyClientAsync) -> None:
4844
assert build.status is not None
4945

5046

51-
@pytest.mark.asyncio
5247
async def test_user_builds_list(apify_client_async: ApifyClientAsync) -> None:
5348
"""Test listing all user builds."""
5449
# List user's builds (may be empty if user has no actors)

tests/integration/test_dataset.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,9 @@ def test_get_items_as_bytes_signature(apify_client: ApifyClient, test_dataset_of
151151
assert test_dataset_of_another_user.expected_content == json.loads(raw_data.decode('utf-8'))
152152

153153

154-
##################################################
155-
# NEW TESTS - Basic CRUD operations without mocks
156-
##################################################
154+
#############
155+
# NEW TESTS #
156+
#############
157157

158158

159159
def test_dataset_get_or_create_and_get(apify_client: ApifyClient) -> None:
@@ -368,3 +368,36 @@ def test_dataset_get_statistics(apify_client: ApifyClient) -> None:
368368
finally:
369369
# Cleanup
370370
dataset_client.delete()
371+
372+
373+
def test_dataset_stream_items(apify_client: ApifyClient) -> None:
374+
"""Test streaming dataset items."""
375+
dataset_name = get_random_resource_name('dataset')
376+
377+
created_dataset = apify_client.datasets().get_or_create(name=dataset_name)
378+
dataset_client = apify_client.dataset(created_dataset.id)
379+
380+
try:
381+
# Push some items
382+
items_to_push = [
383+
{'id': 1, 'name': 'Item 1', 'value': 100},
384+
{'id': 2, 'name': 'Item 2', 'value': 200},
385+
{'id': 3, 'name': 'Item 3', 'value': 300},
386+
]
387+
dataset_client.push_items(items_to_push)
388+
389+
# Wait briefly for eventual consistency
390+
time.sleep(1)
391+
392+
# Stream items using context manager
393+
with dataset_client.stream_items(item_format='json') as response:
394+
assert response is not None
395+
assert response.status_code == 200
396+
content = response.read()
397+
items = json.loads(content)
398+
assert len(items) == 3
399+
assert items[0]['id'] == 1
400+
401+
finally:
402+
# Cleanup
403+
dataset_client.delete()

tests/integration/test_dataset_async.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,9 @@ async def test_get_items_as_bytes_signature(
159159
assert test_dataset_of_another_user.expected_content == json.loads(raw_data.decode('utf-8'))
160160

161161

162-
##################################################
163-
# NEW TESTS - Basic CRUD operations without mocks
164-
##################################################
162+
#############
163+
# NEW TESTS #
164+
#############
165165

166166

167167
async def test_dataset_get_or_create_and_get(apify_client_async: ApifyClientAsync) -> None:
@@ -376,3 +376,36 @@ async def test_dataset_get_statistics(apify_client_async: ApifyClientAsync) -> N
376376
finally:
377377
# Cleanup
378378
await dataset_client.delete()
379+
380+
381+
async def test_dataset_stream_items(apify_client_async: ApifyClientAsync) -> None:
382+
"""Test streaming dataset items."""
383+
dataset_name = get_random_resource_name('dataset')
384+
385+
created_dataset = await apify_client_async.datasets().get_or_create(name=dataset_name)
386+
dataset_client = apify_client_async.dataset(created_dataset.id)
387+
388+
try:
389+
# Push some items
390+
items_to_push = [
391+
{'id': 1, 'name': 'Item 1', 'value': 100},
392+
{'id': 2, 'name': 'Item 2', 'value': 200},
393+
{'id': 3, 'name': 'Item 3', 'value': 300},
394+
]
395+
await dataset_client.push_items(items_to_push)
396+
397+
# Wait briefly for eventual consistency
398+
await asyncio.sleep(1)
399+
400+
# Stream items using async context manager
401+
async with dataset_client.stream_items(item_format='json') as response:
402+
assert response is not None
403+
assert response.status_code == 200
404+
content = await response.aread()
405+
items = json.loads(content)
406+
assert len(items) == 3
407+
assert items[0]['id'] == 1
408+
409+
finally:
410+
# Cleanup
411+
await dataset_client.delete()

tests/integration/test_dataset_collection_async.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,10 @@
33
import uuid
44
from typing import TYPE_CHECKING
55

6-
import pytest
7-
86
if TYPE_CHECKING:
97
from apify_client import ApifyClientAsync
108

119

12-
@pytest.mark.asyncio
1310
async def test_datasets_list(apify_client_async: ApifyClientAsync) -> None:
1411
"""Test listing datasets."""
1512
datasets_page = await apify_client_async.datasets().list(limit=10)
@@ -19,7 +16,6 @@ async def test_datasets_list(apify_client_async: ApifyClientAsync) -> None:
1916
assert isinstance(datasets_page.items, list)
2017

2118

22-
@pytest.mark.asyncio
2319
async def test_datasets_list_pagination(apify_client_async: ApifyClientAsync) -> None:
2420
"""Test listing datasets with pagination."""
2521
datasets_page = await apify_client_async.datasets().list(limit=5, offset=0)
@@ -29,7 +25,6 @@ async def test_datasets_list_pagination(apify_client_async: ApifyClientAsync) ->
2925
assert isinstance(datasets_page.items, list)
3026

3127

32-
@pytest.mark.asyncio
3328
async def test_datasets_get_or_create(apify_client_async: ApifyClientAsync) -> None:
3429
"""Test get_or_create for datasets."""
3530
unique_name = f'test-dataset-{uuid.uuid4().hex[:8]}'

tests/integration/test_key_value_store.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,9 @@ def test_stream_record_signature(apify_client: ApifyClient, test_kvs_of_another_
207207
assert test_kvs_of_another_user.expected_content[key] == value
208208

209209

210-
##################################################
211-
# NEW TESTS - Basic CRUD operations without mocks
212-
##################################################
210+
#############
211+
# NEW TESTS #
212+
#############
213213

214214

215215
def test_key_value_store_get_or_create_and_get(apify_client: ApifyClient) -> None:

0 commit comments

Comments
 (0)