Skip to content

Commit 7b0d8bc

Browse files
committed
unit and smoke tests for base api changes
1 parent 95af66e commit 7b0d8bc

3 files changed

Lines changed: 617 additions & 0 deletions

File tree

tests/api_resources/devboxes/test_disk_snapshots.py

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import os
66
from typing import Any, cast
7+
from unittest.mock import patch
78

89
import pytest
910

@@ -14,6 +15,8 @@
1415
from runloop_api_client.types.devboxes import (
1516
DevboxSnapshotAsyncStatusView,
1617
)
18+
from runloop_api_client._exceptions import RunloopError
19+
from runloop_api_client.lib.polling import PollingConfig, PollingTimeout
1720

1821
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
1922

@@ -181,6 +184,112 @@ def test_path_params_query_status(self, client: Runloop) -> None:
181184
"",
182185
)
183186

187+
# Polling method tests
188+
@parametrize
189+
def test_method_await_completed_success(self, client: Runloop) -> None:
190+
"""Test await_completed with successful polling to complete state"""
191+
192+
# Mock the query_status calls - first returns in_progress, then complete
193+
mock_status_in_progress = DevboxSnapshotAsyncStatusView(
194+
status="in_progress",
195+
error_message=None,
196+
)
197+
198+
mock_status_complete = DevboxSnapshotAsyncStatusView(
199+
status="complete",
200+
error_message=None,
201+
)
202+
203+
with patch.object(client.devboxes.disk_snapshots, "query_status") as mock_query:
204+
mock_query.side_effect = [mock_status_in_progress, mock_status_complete]
205+
206+
result = client.devboxes.disk_snapshots.await_completed("test_id")
207+
208+
assert result.status == "complete"
209+
assert mock_query.call_count == 2
210+
211+
@parametrize
212+
def test_method_await_completed_immediate_success(self, client: Runloop) -> None:
213+
"""Test await_completed when snapshot is already complete"""
214+
215+
mock_status_complete = DevboxSnapshotAsyncStatusView(
216+
status="complete",
217+
error_message=None,
218+
)
219+
220+
with patch.object(client.devboxes.disk_snapshots, "query_status") as mock_query:
221+
mock_query.return_value = mock_status_complete
222+
223+
result = client.devboxes.disk_snapshots.await_completed("test_id")
224+
225+
assert result.status == "complete"
226+
assert mock_query.call_count == 1
227+
228+
@parametrize
229+
def test_method_await_completed_error_state(self, client: Runloop) -> None:
230+
"""Test await_completed when snapshot status becomes error"""
231+
232+
mock_status_error = DevboxSnapshotAsyncStatusView(
233+
status="error",
234+
error_message="Snapshot creation failed",
235+
)
236+
237+
with patch.object(client.devboxes.disk_snapshots, "query_status") as mock_query:
238+
mock_query.return_value = mock_status_error
239+
240+
with pytest.raises(RunloopError, match="Snapshot test_id failed: Snapshot creation failed"):
241+
client.devboxes.disk_snapshots.await_completed("test_id")
242+
243+
@parametrize
244+
def test_method_await_completed_error_state_no_message(self, client: Runloop) -> None:
245+
"""Test await_completed when snapshot status becomes error without error message"""
246+
247+
mock_status_error = DevboxSnapshotAsyncStatusView(
248+
status="error",
249+
error_message=None,
250+
)
251+
252+
with patch.object(client.devboxes.disk_snapshots, "query_status") as mock_query:
253+
mock_query.return_value = mock_status_error
254+
255+
with pytest.raises(RunloopError, match="Snapshot test_id failed: Unknown error"):
256+
client.devboxes.disk_snapshots.await_completed("test_id")
257+
258+
@parametrize
259+
def test_method_await_completed_with_config(self, client: Runloop) -> None:
260+
"""Test await_completed with custom polling configuration"""
261+
262+
mock_status_complete = DevboxSnapshotAsyncStatusView(
263+
status="complete",
264+
error_message=None,
265+
)
266+
267+
config = PollingConfig(interval_seconds=0.1, max_attempts=10)
268+
269+
with patch.object(client.devboxes.disk_snapshots, "query_status") as mock_query:
270+
mock_query.return_value = mock_status_complete
271+
272+
result = client.devboxes.disk_snapshots.await_completed("test_id", polling_config=config)
273+
274+
assert result.status == "complete"
275+
276+
@parametrize
277+
def test_method_await_completed_polling_timeout(self, client: Runloop) -> None:
278+
"""Test await_completed raises PollingTimeout when max attempts exceeded"""
279+
280+
mock_status_in_progress = DevboxSnapshotAsyncStatusView(
281+
status="in_progress",
282+
error_message=None,
283+
)
284+
285+
config = PollingConfig(interval_seconds=0.01, max_attempts=2)
286+
287+
with patch.object(client.devboxes.disk_snapshots, "query_status") as mock_query:
288+
mock_query.return_value = mock_status_in_progress
289+
290+
with pytest.raises(PollingTimeout):
291+
client.devboxes.disk_snapshots.await_completed("test_id", polling_config=config)
292+
184293

185294
class TestAsyncDiskSnapshots:
186295
parametrize = pytest.mark.parametrize(
@@ -346,3 +455,109 @@ async def test_path_params_query_status(self, async_client: AsyncRunloop) -> Non
346455
await async_client.devboxes.disk_snapshots.with_raw_response.query_status(
347456
"",
348457
)
458+
459+
# Polling method tests
460+
@parametrize
461+
async def test_method_await_completed_success(self, async_client: AsyncRunloop) -> None:
462+
"""Test await_completed with successful polling to complete state"""
463+
464+
# Mock the query_status calls - first returns in_progress, then complete
465+
mock_status_in_progress = DevboxSnapshotAsyncStatusView(
466+
status="in_progress",
467+
error_message=None,
468+
)
469+
470+
mock_status_complete = DevboxSnapshotAsyncStatusView(
471+
status="complete",
472+
error_message=None,
473+
)
474+
475+
with patch.object(async_client.devboxes.disk_snapshots, "query_status") as mock_query:
476+
mock_query.side_effect = [mock_status_in_progress, mock_status_complete]
477+
478+
result = await async_client.devboxes.disk_snapshots.await_completed("test_id")
479+
480+
assert result.status == "complete"
481+
assert mock_query.call_count == 2
482+
483+
@parametrize
484+
async def test_method_await_completed_immediate_success(self, async_client: AsyncRunloop) -> None:
485+
"""Test await_completed when snapshot is already complete"""
486+
487+
mock_status_complete = DevboxSnapshotAsyncStatusView(
488+
status="complete",
489+
error_message=None,
490+
)
491+
492+
with patch.object(async_client.devboxes.disk_snapshots, "query_status") as mock_query:
493+
mock_query.return_value = mock_status_complete
494+
495+
result = await async_client.devboxes.disk_snapshots.await_completed("test_id")
496+
497+
assert result.status == "complete"
498+
assert mock_query.call_count == 1
499+
500+
@parametrize
501+
async def test_method_await_completed_error_state(self, async_client: AsyncRunloop) -> None:
502+
"""Test await_completed when snapshot status becomes error"""
503+
504+
mock_status_error = DevboxSnapshotAsyncStatusView(
505+
status="error",
506+
error_message="Snapshot creation failed",
507+
)
508+
509+
with patch.object(async_client.devboxes.disk_snapshots, "query_status") as mock_query:
510+
mock_query.return_value = mock_status_error
511+
512+
with pytest.raises(RunloopError, match="Snapshot test_id failed: Snapshot creation failed"):
513+
await async_client.devboxes.disk_snapshots.await_completed("test_id")
514+
515+
@parametrize
516+
async def test_method_await_completed_error_state_no_message(self, async_client: AsyncRunloop) -> None:
517+
"""Test await_completed when snapshot status becomes error without error message"""
518+
519+
mock_status_error = DevboxSnapshotAsyncStatusView(
520+
status="error",
521+
error_message=None,
522+
)
523+
524+
with patch.object(async_client.devboxes.disk_snapshots, "query_status") as mock_query:
525+
mock_query.return_value = mock_status_error
526+
527+
with pytest.raises(RunloopError, match="Snapshot test_id failed: Unknown error"):
528+
await async_client.devboxes.disk_snapshots.await_completed("test_id")
529+
530+
@parametrize
531+
async def test_method_await_completed_with_config(self, async_client: AsyncRunloop) -> None:
532+
"""Test await_completed with custom polling configuration"""
533+
534+
mock_status_complete = DevboxSnapshotAsyncStatusView(
535+
status="complete",
536+
error_message=None,
537+
)
538+
539+
config = PollingConfig(interval_seconds=0.1, max_attempts=10)
540+
541+
with patch.object(async_client.devboxes.disk_snapshots, "query_status") as mock_query:
542+
mock_query.return_value = mock_status_complete
543+
544+
result = await async_client.devboxes.disk_snapshots.await_completed("test_id", polling_config=config)
545+
546+
assert result.status == "complete"
547+
548+
@parametrize
549+
async def test_method_await_completed_polling_timeout(self, async_client: AsyncRunloop) -> None:
550+
"""Test await_completed raises PollingTimeout when max attempts exceeded"""
551+
552+
mock_status_in_progress = DevboxSnapshotAsyncStatusView(
553+
status="in_progress",
554+
error_message=None,
555+
)
556+
557+
config = PollingConfig(interval_seconds=0.01, max_attempts=2)
558+
559+
with patch.object(async_client.devboxes.disk_snapshots, "query_status") as mock_query:
560+
mock_query.return_value = mock_status_in_progress
561+
562+
with pytest.raises(PollingTimeout):
563+
await async_client.devboxes.disk_snapshots.await_completed("test_id", polling_config=config)

0 commit comments

Comments
 (0)