From ebd45d29917acc681e896ecc707ccf538c89296f Mon Sep 17 00:00:00 2001 From: bohd4nx Date: Tue, 14 Apr 2026 00:22:48 +0300 Subject: [PATCH] Add unit tests for FragmentClient methods - Implement tests for Stars methods: purchase_stars and giveaway_stars, including validation and success scenarios. - Add tests for Premium methods: purchase_premium and giveaway_premium, covering validation and success cases. - Create tests for topup_ton functionality, validating input and mocking successful operations. - Introduce wallet tests to verify get_wallet() functionality, ensuring correct wallet info retrieval. - Add tests for FragmentClient.call() method, validating API response handling and data merging. - Implement tests for anonymous number methods, including login codes and session management. - Create recharge_ads tests for self-service Telegram Ads recharge, validating input and success scenarios. - Add username search tests for the Fragment marketplace, ensuring correct result parsing and parameter forwarding. - Implement number search tests for the Fragment marketplace, validating result parsing and parameter handling. - Create gift search tests for the Fragment gifts marketplace, ensuring correct result parsing and parameter forwarding. - Add cookie extraction tests for get_cookies_from_browser(), validating successful extraction and error handling. --- examples/auctions/search_gifts.py | 6 ++++++ examples/auctions/search_numbers.py | 6 ++++++ examples/auctions/search_usernames.py | 6 ++++++ examples/client/raw_api_call.py | 6 ++++++ examples/client/wallet_info.py | 6 ++++++ examples/numbers/manage_number.py | 6 ++++++ examples/purchase/recharge_ads_balance.py | 6 ++++++ examples/purchase/run_premium_giveaway.py | 6 ++++++ examples/purchase/run_stars_giveaway.py | 6 ++++++ examples/purchase/send_premium.py | 6 ++++++ examples/purchase/send_stars.py | 6 ++++++ examples/purchase/topup_ton_balance.py | 12 +++++++++--- pyfragment/__init__.py | 2 -- pyfragment/client.py | 6 +++--- pyfragment/methods/topup_ton.py | 4 ++-- ...004_test_balance.py => 003_test_balance.py} | 0 tests/003_test_hash.py | 18 ------------------ tests/{005_test_stars.py => 004_test_stars.py} | 0 ...006_test_premium.py => 005_test_premium.py} | 0 tests/{007_test_topup.py => 006_test_topup.py} | 0 .../{008_test_wallet.py => 007_test_wallet.py} | 0 tests/{009_test_call.py => 008_test_call.py} | 0 .../{010_test_number.py => 009_test_number.py} | 0 ...echarge_ads.py => 010_test_recharge_ads.py} | 0 ...test_usernames.py => 011_test_usernames.py} | 0 ...013_test_numbers.py => 012_test_numbers.py} | 0 tests/{014_test_gifts.py => 013_test_gifts.py} | 0 ...015_test_cookies.py => 014_test_cookies.py} | 2 +- 28 files changed, 81 insertions(+), 29 deletions(-) rename tests/{004_test_balance.py => 003_test_balance.py} (100%) delete mode 100644 tests/003_test_hash.py rename tests/{005_test_stars.py => 004_test_stars.py} (100%) rename tests/{006_test_premium.py => 005_test_premium.py} (100%) rename tests/{007_test_topup.py => 006_test_topup.py} (100%) rename tests/{008_test_wallet.py => 007_test_wallet.py} (100%) rename tests/{009_test_call.py => 008_test_call.py} (100%) rename tests/{010_test_number.py => 009_test_number.py} (100%) rename tests/{011_test_recharge_ads.py => 010_test_recharge_ads.py} (100%) rename tests/{012_test_usernames.py => 011_test_usernames.py} (100%) rename tests/{013_test_numbers.py => 012_test_numbers.py} (100%) rename tests/{014_test_gifts.py => 013_test_gifts.py} (100%) rename tests/{015_test_cookies.py => 014_test_cookies.py} (98%) diff --git a/examples/auctions/search_gifts.py b/examples/auctions/search_gifts.py index 70ad338..4eb31ac 100644 --- a/examples/auctions/search_gifts.py +++ b/examples/auctions/search_gifts.py @@ -11,9 +11,15 @@ import asyncio import json from pyfragment import FragmentClient, GiftsResult +from pyfragment.utils import get_cookies_from_browser # noqa: F401 SEED = "word1 word2 ... word24" API_KEY = "YOUR_TONAPI_KEY" + +# Option A: extract cookies directly from your browser (no manual copy-paste needed) +# COOKIES = get_cookies_from_browser("chrome") # or "firefox", "edge", "brave", ... + +# Option B: provide cookies manually COOKIES = { "stel_ssid": "YOUR_STEL_SSID", "stel_dt": "YOUR_STEL_DT", diff --git a/examples/auctions/search_numbers.py b/examples/auctions/search_numbers.py index 9a98a27..f8d55ba 100644 --- a/examples/auctions/search_numbers.py +++ b/examples/auctions/search_numbers.py @@ -10,9 +10,15 @@ import asyncio import json from pyfragment import FragmentClient, NumbersResult +from pyfragment.utils import get_cookies_from_browser # noqa: F401 SEED = "word1 word2 ... word24" API_KEY = "YOUR_TONAPI_KEY" + +# Option A: extract cookies directly from your browser (no manual copy-paste needed) +# COOKIES = get_cookies_from_browser("chrome") # or "firefox", "edge", "brave", ... + +# Option B: provide cookies manually COOKIES = { "stel_ssid": "YOUR_STEL_SSID", "stel_dt": "YOUR_STEL_DT", diff --git a/examples/auctions/search_usernames.py b/examples/auctions/search_usernames.py index 68e5ea1..f478b03 100644 --- a/examples/auctions/search_usernames.py +++ b/examples/auctions/search_usernames.py @@ -10,9 +10,15 @@ import asyncio import json from pyfragment import FragmentClient, UsernamesResult +from pyfragment.utils import get_cookies_from_browser # noqa: F401 SEED = "word1 word2 ... word24" API_KEY = "YOUR_TONAPI_KEY" + +# Option A: extract cookies directly from your browser (no manual copy-paste needed) +# COOKIES = get_cookies_from_browser("chrome") # or "firefox", "edge", "brave", ... + +# Option B: provide cookies manually COOKIES = { "stel_ssid": "YOUR_STEL_SSID", "stel_dt": "YOUR_STEL_DT", diff --git a/examples/client/raw_api_call.py b/examples/client/raw_api_call.py index 6bd9594..070ee7a 100644 --- a/examples/client/raw_api_call.py +++ b/examples/client/raw_api_call.py @@ -12,9 +12,15 @@ Defaults to the Fragment base URL. import asyncio from pyfragment import FragmentClient +from pyfragment.utils import get_cookies_from_browser # noqa: F401 SEED = "word1 word2 ... word24" API_KEY = "YOUR_TONAPI_KEY" + +# Option A: extract cookies directly from your browser (no manual copy-paste needed) +# COOKIES = get_cookies_from_browser("chrome") # or "firefox", "edge", "brave", ... + +# Option B: provide cookies manually COOKIES = { "stel_ssid": "YOUR_STEL_SSID", "stel_dt": "YOUR_STEL_DT", diff --git a/examples/client/wallet_info.py b/examples/client/wallet_info.py index 84c8db4..4b4f14f 100644 --- a/examples/client/wallet_info.py +++ b/examples/client/wallet_info.py @@ -8,9 +8,15 @@ wallet_version defaults to "V5R1" — change to "V4R2" for older wallets. import asyncio from pyfragment import FragmentClient +from pyfragment.utils import get_cookies_from_browser # noqa: F401 SEED = "word1 word2 ... word24" API_KEY = "YOUR_TONAPI_KEY" + +# Option A: extract cookies directly from your browser (no manual copy-paste needed) +# COOKIES = get_cookies_from_browser("chrome") # or "firefox", "edge", "brave", ... + +# Option B: provide cookies manually COOKIES = { "stel_ssid": "YOUR_STEL_SSID", "stel_dt": "YOUR_STEL_DT", diff --git a/examples/numbers/manage_number.py b/examples/numbers/manage_number.py index 3355b22..8251c2e 100644 --- a/examples/numbers/manage_number.py +++ b/examples/numbers/manage_number.py @@ -9,9 +9,15 @@ Use terminate_sessions() to forcefully end all active Telegram sessions. import asyncio from pyfragment import AnonymousNumberError, FragmentClient +from pyfragment.utils import get_cookies_from_browser # noqa: F401 SEED = "word1 word2 ... word24" API_KEY = "YOUR_TONAPI_KEY" + +# Option A: extract cookies directly from your browser (no manual copy-paste needed) +# COOKIES = get_cookies_from_browser("chrome") # or "firefox", "edge", "brave", ... + +# Option B: provide cookies manually COOKIES = { "stel_ssid": "YOUR_STEL_SSID", "stel_dt": "YOUR_STEL_DT", diff --git a/examples/purchase/recharge_ads_balance.py b/examples/purchase/recharge_ads_balance.py index 6ec6121..56dde7a 100644 --- a/examples/purchase/recharge_ads_balance.py +++ b/examples/purchase/recharge_ads_balance.py @@ -13,9 +13,15 @@ from pyfragment import ( FragmentClient, WalletError, ) +from pyfragment.utils import get_cookies_from_browser # noqa: F401 SEED = "word1 word2 ... word24" API_KEY = "YOUR_TONAPI_KEY" + +# Option A: extract cookies directly from your browser (no manual copy-paste needed) +# COOKIES = get_cookies_from_browser("chrome") # or "firefox", "edge", "brave", ... + +# Option B: provide cookies manually COOKIES = { "stel_ssid": "YOUR_STEL_SSID", "stel_dt": "YOUR_STEL_DT", diff --git a/examples/purchase/run_premium_giveaway.py b/examples/purchase/run_premium_giveaway.py index e2a5818..c152af9 100644 --- a/examples/purchase/run_premium_giveaway.py +++ b/examples/purchase/run_premium_giveaway.py @@ -8,9 +8,15 @@ months (Premium duration per winner) must be 3, 6, or 12. import asyncio from pyfragment import ConfigurationError, FragmentClient, UserNotFoundError +from pyfragment.utils import get_cookies_from_browser # noqa: F401 SEED = "word1 word2 ... word24" API_KEY = "YOUR_TONAPI_KEY" + +# Option A: extract cookies directly from your browser (no manual copy-paste needed) +# COOKIES = get_cookies_from_browser("chrome") # or "firefox", "edge", "brave", ... + +# Option B: provide cookies manually COOKIES = { "stel_ssid": "YOUR_STEL_SSID", "stel_dt": "YOUR_STEL_DT", diff --git a/examples/purchase/run_stars_giveaway.py b/examples/purchase/run_stars_giveaway.py index 400a707..a9188ba 100644 --- a/examples/purchase/run_stars_giveaway.py +++ b/examples/purchase/run_stars_giveaway.py @@ -8,9 +8,15 @@ amount (stars per winner) must be an integer between 500 and 1 000 000. import asyncio from pyfragment import ConfigurationError, FragmentClient, UserNotFoundError +from pyfragment.utils import get_cookies_from_browser # noqa: F401 SEED = "word1 word2 ... word24" API_KEY = "YOUR_TONAPI_KEY" + +# Option A: extract cookies directly from your browser (no manual copy-paste needed) +# COOKIES = get_cookies_from_browser("chrome") # or "firefox", "edge", "brave", ... + +# Option B: provide cookies manually COOKIES = { "stel_ssid": "YOUR_STEL_SSID", "stel_dt": "YOUR_STEL_DT", diff --git a/examples/purchase/send_premium.py b/examples/purchase/send_premium.py index fc90f3b..cd12734 100644 --- a/examples/purchase/send_premium.py +++ b/examples/purchase/send_premium.py @@ -8,9 +8,15 @@ Set show_sender=False to send anonymously. import asyncio from pyfragment import ConfigurationError, FragmentClient, UserNotFoundError +from pyfragment.utils import get_cookies_from_browser # noqa: F401 SEED = "word1 word2 ... word24" API_KEY = "YOUR_TONAPI_KEY" + +# Option A: extract cookies directly from your browser (no manual copy-paste needed) +# COOKIES = get_cookies_from_browser("chrome") # or "firefox", "edge", "brave", ... + +# Option B: provide cookies manually COOKIES = { "stel_ssid": "YOUR_STEL_SSID", "stel_dt": "YOUR_STEL_DT", diff --git a/examples/purchase/send_stars.py b/examples/purchase/send_stars.py index 594f883..73d77eb 100644 --- a/examples/purchase/send_stars.py +++ b/examples/purchase/send_stars.py @@ -8,9 +8,15 @@ Set show_sender=False to send anonymously. import asyncio from pyfragment import ConfigurationError, FragmentClient, UserNotFoundError +from pyfragment.utils import get_cookies_from_browser # noqa: F401 SEED = "word1 word2 ... word24" API_KEY = "YOUR_TONAPI_KEY" + +# Option A: extract cookies directly from your browser (no manual copy-paste needed) +# COOKIES = get_cookies_from_browser("chrome") # or "firefox", "edge", "brave", ... + +# Option B: provide cookies manually COOKIES = { "stel_ssid": "YOUR_STEL_SSID", "stel_dt": "YOUR_STEL_DT", diff --git a/examples/purchase/topup_ton_balance.py b/examples/purchase/topup_ton_balance.py index 10681ad..49900b7 100644 --- a/examples/purchase/topup_ton_balance.py +++ b/examples/purchase/topup_ton_balance.py @@ -1,10 +1,10 @@ """ -Example: Topup ton to recipient's Telegram balance. +Example: top up TON to a recipient's Telegram balance. -For adding TON to Telegram Ads account, use recharge_ads() instead. +For adding TON to a Telegram Ads account, use recharge_ads() instead. Amount must be an integer between 1 and 1 000 000 000 TON. -Your wallet must hold at least the topup amount + ~0.056 TON for gas. +Your wallet must hold at least the top-up amount + ~0.056 TON for gas. """ import asyncio @@ -15,9 +15,15 @@ from pyfragment import ( UserNotFoundError, WalletError, ) +from pyfragment.utils import get_cookies_from_browser # noqa: F401 SEED = "word1 word2 ... word24" API_KEY = "YOUR_TONAPI_KEY" + +# Option A: extract cookies directly from your browser (no manual copy-paste needed) +# COOKIES = get_cookies_from_browser("chrome") # or "firefox", "edge", "brave", ... + +# Option B: provide cookies manually COOKIES = { "stel_ssid": "YOUR_STEL_SSID", "stel_dt": "YOUR_STEL_DT", diff --git a/pyfragment/__init__.py b/pyfragment/__init__.py index 53073f7..495897d 100644 --- a/pyfragment/__init__.py +++ b/pyfragment/__init__.py @@ -34,14 +34,12 @@ from pyfragment.types import ( WalletError, WalletInfo, ) -from pyfragment.utils.cookies import get_cookies_from_browser __version__: str = version("pyfragment") __all__ = [ "__version__", "FragmentClient", - "get_cookies_from_browser", "AdsRechargeResult", "AdsTopupResult", "GiftsResult", diff --git a/pyfragment/client.py b/pyfragment/client.py index 08bd9ab..d5f7e68 100644 --- a/pyfragment/client.py +++ b/pyfragment/client.py @@ -123,7 +123,7 @@ class FragmentClient: return f"FragmentClient(wallet_version='{self.wallet_version}', cookies={len(self.cookies)} keys)" async def purchase_premium(self, username: str, months: int, show_sender: bool = True) -> PremiumResult: - """Purchase Telegram Premium for a user. + """Gift Telegram Premium to a user. Args: username: Recipient's Telegram username (with or without ``@``). @@ -136,7 +136,7 @@ class FragmentClient: return await purchase_premium(self, username, months, show_sender) async def purchase_stars(self, username: str, amount: int, show_sender: bool = True) -> StarsResult: - """Purchase Telegram Stars for a user. + """Send Telegram Stars to a user. Args: username: Recipient's Telegram username (with or without ``@``). @@ -149,7 +149,7 @@ class FragmentClient: return await purchase_stars(self, username, amount, show_sender) async def topup_ton(self, username: str, amount: int, show_sender: bool = True) -> AdsTopupResult: - """Topup ton to recipient's Telegram balance. + """Top up TON to a recipient's Telegram balance. Args: username: Recipient's Telegram username (with or without ``@``). diff --git a/pyfragment/methods/topup_ton.py b/pyfragment/methods/topup_ton.py index e503872..f19e342 100644 --- a/pyfragment/methods/topup_ton.py +++ b/pyfragment/methods/topup_ton.py @@ -18,7 +18,7 @@ if TYPE_CHECKING: async def topup_ton(client: "FragmentClient", username: str, amount: int, show_sender: bool = True) -> AdsTopupResult: - """Topup ton to recipient's Telegram balance. + """Top up TON to a recipient's Telegram balance. Args: client: Authenticated :class:`FragmentClient` instance. @@ -31,7 +31,7 @@ async def topup_ton(client: "FragmentClient", username: str, amount: int, show_s Raises: ConfigurationError: If ``amount`` is not an integer between 1 and 1 000 000 000. - UserNotFoundError: If the recipient is not found on Fragment. + UserNotFoundError: If the recipient is not found on Telegram. FragmentAPIError: If the Fragment API returns an error. UnexpectedError: For any other unexpected failure. """ diff --git a/tests/004_test_balance.py b/tests/003_test_balance.py similarity index 100% rename from tests/004_test_balance.py rename to tests/003_test_balance.py diff --git a/tests/003_test_hash.py b/tests/003_test_hash.py deleted file mode 100644 index 2b72758..0000000 --- a/tests/003_test_hash.py +++ /dev/null @@ -1,18 +0,0 @@ -"""Tests for get_fragment_hash() — API hash extraction from Fragment page source.""" - -import re - -import pytest - -from pyfragment.types.constants import BASE_HEADERS, STARS_PAGE -from pyfragment.utils import get_fragment_hash - -# Hash integration tests - - -@pytest.mark.asyncio -async def test_hash_is_valid_hex(cookies: dict) -> None: - result = await get_fragment_hash(cookies, BASE_HEADERS, STARS_PAGE) - assert isinstance(result, str) - assert len(result) >= 10, f"hash too short: {result!r}" - assert re.fullmatch(r"[a-f0-9]+", result), f"not a hex string: {result!r}" diff --git a/tests/005_test_stars.py b/tests/004_test_stars.py similarity index 100% rename from tests/005_test_stars.py rename to tests/004_test_stars.py diff --git a/tests/006_test_premium.py b/tests/005_test_premium.py similarity index 100% rename from tests/006_test_premium.py rename to tests/005_test_premium.py diff --git a/tests/007_test_topup.py b/tests/006_test_topup.py similarity index 100% rename from tests/007_test_topup.py rename to tests/006_test_topup.py diff --git a/tests/008_test_wallet.py b/tests/007_test_wallet.py similarity index 100% rename from tests/008_test_wallet.py rename to tests/007_test_wallet.py diff --git a/tests/009_test_call.py b/tests/008_test_call.py similarity index 100% rename from tests/009_test_call.py rename to tests/008_test_call.py diff --git a/tests/010_test_number.py b/tests/009_test_number.py similarity index 100% rename from tests/010_test_number.py rename to tests/009_test_number.py diff --git a/tests/011_test_recharge_ads.py b/tests/010_test_recharge_ads.py similarity index 100% rename from tests/011_test_recharge_ads.py rename to tests/010_test_recharge_ads.py diff --git a/tests/012_test_usernames.py b/tests/011_test_usernames.py similarity index 100% rename from tests/012_test_usernames.py rename to tests/011_test_usernames.py diff --git a/tests/013_test_numbers.py b/tests/012_test_numbers.py similarity index 100% rename from tests/013_test_numbers.py rename to tests/012_test_numbers.py diff --git a/tests/014_test_gifts.py b/tests/013_test_gifts.py similarity index 100% rename from tests/014_test_gifts.py rename to tests/013_test_gifts.py diff --git a/tests/015_test_cookies.py b/tests/014_test_cookies.py similarity index 98% rename from tests/015_test_cookies.py rename to tests/014_test_cookies.py index bb45a36..e0b7d94 100644 --- a/tests/015_test_cookies.py +++ b/tests/014_test_cookies.py @@ -4,9 +4,9 @@ from unittest.mock import MagicMock, patch import pytest -from pyfragment import get_cookies_from_browser from pyfragment.types import CookieError from pyfragment.types.constants import REQUIRED_COOKIE_KEYS +from pyfragment.utils import get_cookies_from_browser FAKE_JAR = [ {"name": "stel_ssid", "value": "abc123", "domain": "fragment.com"},