DEVX-93: fix: force pip upgrade in setup-image to install new dependencies
This commit is contained in:
@@ -6,7 +6,7 @@ from unittest.mock import MagicMock, patch
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
from devx.api_clients import GiteaClient, VikunjaClient, _is_retryable, _parse_error
|
||||
from devx.api_clients import GiteaClient, VikunjaClient, _parse_error
|
||||
from devx.config import (
|
||||
DEFAULT_PER_PAGE,
|
||||
DEFAULT_TIMEOUT,
|
||||
@@ -507,7 +507,7 @@ class TestGiteaClient:
|
||||
assert result["id"] == 1
|
||||
assert client._session.request.call_count == 2
|
||||
|
||||
@patch("devx.api_clients.time.sleep")
|
||||
@patch("time.sleep")
|
||||
def test_request_retries_on_429(self, mock_sleep: MagicMock) -> None:
|
||||
"""Should retry on 429 rate limit with exponential backoff."""
|
||||
client = GiteaClient("https://git.example.com", "tok", "owner", "repo")
|
||||
@@ -520,7 +520,7 @@ class TestGiteaClient:
|
||||
assert client._session.request.call_count == 3
|
||||
assert mock_sleep.call_count == 2
|
||||
|
||||
@patch("devx.api_clients.time.sleep")
|
||||
@patch("time.sleep")
|
||||
def test_request_retries_on_503(self, mock_sleep: MagicMock) -> None:
|
||||
"""Should retry on 503 service unavailable."""
|
||||
client = GiteaClient("https://git.example.com", "tok", "owner", "repo")
|
||||
@@ -532,7 +532,7 @@ class TestGiteaClient:
|
||||
assert result.json() == {"ok": True}
|
||||
assert client._session.request.call_count == 2
|
||||
|
||||
@patch("devx.api_clients.time.sleep")
|
||||
@patch("time.sleep")
|
||||
def test_request_no_retry_on_404(self, mock_sleep: MagicMock) -> None:
|
||||
"""Should NOT retry on 404 — it's not a transient error."""
|
||||
client = GiteaClient("https://git.example.com", "tok", "owner", "repo")
|
||||
@@ -545,7 +545,7 @@ class TestGiteaClient:
|
||||
assert client._session.request.call_count == 1
|
||||
mock_sleep.assert_not_called()
|
||||
|
||||
@patch("devx.api_clients.time.sleep")
|
||||
@patch("time.sleep")
|
||||
def test_request_retries_on_connection_error(self, mock_sleep: MagicMock) -> None:
|
||||
"""Should retry on connection errors."""
|
||||
client = GiteaClient("https://git.example.com", "tok", "owner", "repo")
|
||||
@@ -555,7 +555,7 @@ class TestGiteaClient:
|
||||
assert result.json() == {"ok": True}
|
||||
assert client._session.request.call_count == 2
|
||||
|
||||
@patch("devx.api_clients.time.sleep")
|
||||
@patch("time.sleep")
|
||||
def test_request_max_retries_exhausted(self, mock_sleep: MagicMock) -> None:
|
||||
"""Should raise APIError after max retries on persistent 503."""
|
||||
client = GiteaClient("https://git.example.com", "tok", "owner", "repo")
|
||||
@@ -567,7 +567,7 @@ class TestGiteaClient:
|
||||
assert exc_info.value.status == 503
|
||||
assert client._session.request.call_count == 3 # MAX_RETRIES
|
||||
|
||||
@patch("devx.api_clients.time.sleep")
|
||||
@patch("time.sleep")
|
||||
def test_request_connection_error_exhausted(self, mock_sleep: MagicMock) -> None:
|
||||
"""Should raise APIError after max retries on persistent connection errors."""
|
||||
client = GiteaClient("https://git.example.com", "tok", "owner", "repo")
|
||||
@@ -691,7 +691,7 @@ class TestVikunjaClient:
|
||||
json={"id": 42, "title": "My task", "done": True},
|
||||
)
|
||||
|
||||
@patch("devx.api_clients.time.sleep")
|
||||
@patch("time.sleep")
|
||||
def test_http_error_raises_api_error(self, mock_sleep: MagicMock) -> None:
|
||||
client = VikunjaClient("https://work.example.com", "tok")
|
||||
mock_resp = MagicMock()
|
||||
@@ -713,7 +713,7 @@ class TestVikunjaClient:
|
||||
client.list_tasks()
|
||||
assert "connection failed" in str(exc_info.value)
|
||||
|
||||
@patch("devx.api_clients.time.sleep")
|
||||
@patch("time.sleep")
|
||||
def test_vikunja_retries_on_503(self, mock_sleep: MagicMock) -> None:
|
||||
"""VikunjaClient should also retry on 503."""
|
||||
client = VikunjaClient("https://work.example.com", "tok")
|
||||
@@ -725,7 +725,7 @@ class TestVikunjaClient:
|
||||
assert len(result) == 1
|
||||
assert client._session.request.call_count == 2
|
||||
|
||||
@patch("devx.api_clients.time.sleep")
|
||||
@patch("time.sleep")
|
||||
def test_vikunja_retries_on_connection_error(self, mock_sleep: MagicMock) -> None:
|
||||
"""VikunjaClient should retry on connection errors."""
|
||||
client = VikunjaClient("https://work.example.com", "tok")
|
||||
@@ -735,7 +735,7 @@ class TestVikunjaClient:
|
||||
assert len(result) == 1
|
||||
assert client._session.request.call_count == 2
|
||||
|
||||
@patch("devx.api_clients.time.sleep")
|
||||
@patch("time.sleep")
|
||||
def test_vikunja_max_retries_exhausted(self, mock_sleep: MagicMock) -> None:
|
||||
"""VikunjaClient should raise APIError after max retries on persistent 503."""
|
||||
client = VikunjaClient("https://work.example.com", "tok")
|
||||
@@ -747,7 +747,7 @@ class TestVikunjaClient:
|
||||
assert exc_info.value.status == 503
|
||||
assert client._session.request.call_count == 3 # MAX_RETRIES
|
||||
|
||||
@patch("devx.api_clients.time.sleep")
|
||||
@patch("time.sleep")
|
||||
def test_vikunja_connection_error_exhausted(self, mock_sleep: MagicMock) -> None:
|
||||
"""VikunjaClient should raise APIError after max retries on persistent connection errors."""
|
||||
client = VikunjaClient("https://work.example.com", "tok")
|
||||
@@ -818,22 +818,6 @@ class TestVikunjaClient:
|
||||
assert result["title"] == "Found on page 2"
|
||||
|
||||
|
||||
class TestIsRetryable:
|
||||
def test_connection_error_is_retryable(self) -> None:
|
||||
assert _is_retryable(requests.ConnectionError("refused")) is True
|
||||
|
||||
def test_timeout_is_retryable(self) -> None:
|
||||
assert _is_retryable(requests.Timeout("timed out")) is True
|
||||
|
||||
def test_429_is_retryable(self) -> None:
|
||||
err = _mock_http_error(429, "rate limited")
|
||||
assert _is_retryable(err) is True
|
||||
|
||||
def test_404_is_not_retryable(self) -> None:
|
||||
err = _mock_http_error(404, "not found")
|
||||
assert _is_retryable(err) is False
|
||||
|
||||
|
||||
class TestGiteaClientPrLabels:
|
||||
def test_add_pr_label(self) -> None:
|
||||
client = GiteaClient("https://git.example.com", "tok", "owner", "repo")
|
||||
@@ -913,8 +897,3 @@ class TestGiteaClientActions:
|
||||
"https://git.example.com/repos/owner/repo/actions/jobs/10026/logs",
|
||||
timeout=DEFAULT_TIMEOUT,
|
||||
)
|
||||
|
||||
|
||||
class TestIsRetryableGeneric:
|
||||
def test_generic_exception_is_not_retryable(self) -> None:
|
||||
assert _is_retryable(ValueError("oops")) is False
|
||||
|
||||
Reference in New Issue
Block a user