feat: add unit tests for balance checks, giveaway stars, and premium methods; validate float inputs for winners and amounts

This commit is contained in:
bohd4nx
2026-03-21 17:18:56 +02:00
parent b55cd00205
commit ab8d463d54
3 changed files with 55 additions and 0 deletions
+37
View File
@@ -4,11 +4,17 @@ from contextlib import contextmanager
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from tonutils.exceptions import ProviderResponseError
from pyfragment.types import TransactionError, WalletError
from pyfragment.utils.wallet import process_transaction
from tests.shared import VALID_SEED
def _provider_error(code: int, message: str = "error") -> ProviderResponseError:
return ProviderResponseError(code=code, message=message, endpoint="api.tonapi.io")
TRANSACTION_DATA = {
"transaction": {
"messages": [
@@ -94,3 +100,34 @@ async def test_one_nanoton_below_minimum_raises() -> None:
async def test_invalid_payload_raises() -> None:
with pytest.raises(TransactionError):
await process_transaction(_make_client(), {"transaction": {}})
@pytest.mark.asyncio
async def test_balance_check_failed_raises_wallet_error() -> None:
wallet = _make_wallet(balance_nanotons=1_000_000_000)
wallet.refresh = AsyncMock(side_effect=RuntimeError("network timeout"))
with _patch_wallet(wallet):
with pytest.raises(WalletError, match="balance"):
await process_transaction(_make_client(), TRANSACTION_DATA)
wallet.transfer.assert_not_called()
@pytest.mark.asyncio
async def test_rate_limit_retries_and_succeeds() -> None:
wallet = _make_wallet(balance_nanotons=1_000_000_000)
wallet.transfer = AsyncMock(side_effect=[_provider_error(429, "rate limited"), MagicMock(normalized_hash="abc123")])
with _patch_wallet(wallet), patch("pyfragment.utils.wallet.clean_decode", return_value=""):
result = await process_transaction(_make_client(), TRANSACTION_DATA)
assert result == "abc123"
assert wallet.transfer.call_count == 2
@pytest.mark.asyncio
async def test_duplicate_seqno_raises_after_retries() -> None:
wallet = _make_wallet(balance_nanotons=1_000_000_000)
err = _provider_error(406, "Duplicate msg_seqno")
wallet.transfer = AsyncMock(side_effect=[err, err, err])
with _patch_wallet(wallet), patch("pyfragment.utils.wallet.clean_decode", return_value=""):
with pytest.raises(TransactionError, match="seqno"):
await process_transaction(_make_client(), TRANSACTION_DATA)
assert wallet.transfer.call_count == 3
+12
View File
@@ -90,6 +90,18 @@ async def test_giveaway_stars_amount_too_high(client: FragmentClient) -> None:
await client.giveaway_stars("@channel", winners=1, amount=1_000_001)
@pytest.mark.asyncio
async def test_giveaway_stars_float_winners(client: FragmentClient) -> None:
with pytest.raises(ConfigurationError):
await client.giveaway_stars("@channel", winners=1.5, amount=500) # type: ignore[arg-type]
@pytest.mark.asyncio
async def test_giveaway_stars_float_amount(client: FragmentClient) -> None:
with pytest.raises(ConfigurationError):
await client.giveaway_stars("@channel", winners=1, amount=500.5) # type: ignore[arg-type]
# Stars giveaway mocked tests
+6
View File
@@ -78,6 +78,12 @@ async def test_giveaway_premium_winners_too_high(client: FragmentClient) -> None
await client.giveaway_premium("@channel", winners=24_001, months=3)
@pytest.mark.asyncio
async def test_giveaway_premium_float_winners(client: FragmentClient) -> None:
with pytest.raises(ConfigurationError):
await client.giveaway_premium("@channel", winners=2.5, months=3) # type: ignore[arg-type]
@pytest.mark.asyncio
async def test_giveaway_premium_invalid_months(client: FragmentClient) -> None:
with pytest.raises(ConfigurationError):