mirror of
https://github.com/bohd4nx/FragmentAPI.git
synced 2026-07-25 14:24:31 +00:00
164 lines
6.0 KiB
Python
164 lines
6.0 KiB
Python
"""Unit tests for anonymous number methods — login codes and session management."""
|
|
|
|
from unittest.mock import AsyncMock, patch
|
|
|
|
import pytest
|
|
|
|
from pyfragment import AnonymousNumberError, FragmentClient, LoginCodeResult, TerminateSessionsResult
|
|
from tests.shared import FAKE_HASH, FAKE_HTML_NO_CODE, FAKE_HTML_WITH_CODE, FAKE_TERMINATE_HASH
|
|
|
|
# get_login_code tests
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_login_code_returns_code(client: FragmentClient) -> None:
|
|
with (
|
|
patch("pyfragment.methods.anonymous_number.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
|
patch(
|
|
"pyfragment.methods.anonymous_number.fragment_request",
|
|
AsyncMock(return_value={"html": FAKE_HTML_WITH_CODE}),
|
|
),
|
|
):
|
|
result = await client.get_login_code("+1234567890")
|
|
|
|
assert isinstance(result, LoginCodeResult)
|
|
assert result.number == "+1234567890"
|
|
assert result.code == "12345"
|
|
assert result.active_sessions == 2 # 2 <tr> in the HTML
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_login_code_no_pending_code(client: FragmentClient) -> None:
|
|
with (
|
|
patch("pyfragment.methods.anonymous_number.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
|
patch(
|
|
"pyfragment.methods.anonymous_number.fragment_request",
|
|
AsyncMock(return_value={"html": FAKE_HTML_NO_CODE}),
|
|
),
|
|
):
|
|
result = await client.get_login_code("1234567890")
|
|
|
|
assert result.code is None
|
|
assert result.active_sessions == 1
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_login_code_no_html_returns_none(client: FragmentClient) -> None:
|
|
with (
|
|
patch("pyfragment.methods.anonymous_number.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
|
patch("pyfragment.methods.anonymous_number.fragment_request", AsyncMock(return_value={})),
|
|
):
|
|
result = await client.get_login_code("+1234567890")
|
|
|
|
assert result.code is None
|
|
assert result.active_sessions == 0
|
|
|
|
|
|
# terminate_sessions tests
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_terminate_sessions_success(client: FragmentClient) -> None:
|
|
with (
|
|
patch("pyfragment.methods.anonymous_number.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
|
patch(
|
|
"pyfragment.methods.anonymous_number.fragment_request",
|
|
AsyncMock(
|
|
side_effect=[
|
|
{"terminate_hash": FAKE_TERMINATE_HASH}, # step 1: confirmation
|
|
{"msg": "All sessions terminated"}, # step 2: confirmed
|
|
]
|
|
),
|
|
),
|
|
):
|
|
result = await client.terminate_sessions("+1234567890")
|
|
|
|
assert isinstance(result, TerminateSessionsResult)
|
|
assert result.number == "+1234567890"
|
|
assert result.message == "All sessions terminated"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_terminate_sessions_not_owned_raises(client: FragmentClient) -> None:
|
|
with (
|
|
patch("pyfragment.methods.anonymous_number.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
|
patch("pyfragment.methods.anonymous_number.fragment_request", AsyncMock(return_value={})),
|
|
):
|
|
with pytest.raises(AnonymousNumberError, match="not associated"):
|
|
await client.terminate_sessions("+1234567890")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_terminate_sessions_api_error_raises(client: FragmentClient) -> None:
|
|
with (
|
|
patch("pyfragment.methods.anonymous_number.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
|
patch(
|
|
"pyfragment.methods.anonymous_number.fragment_request",
|
|
AsyncMock(return_value={"error": "SESSION_ALREADY_TERMINATED"}),
|
|
),
|
|
):
|
|
with pytest.raises(AnonymousNumberError, match="SESSION_ALREADY_TERMINATED"):
|
|
await client.terminate_sessions("+1234567890")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_terminate_sessions_confirm_error_raises(client: FragmentClient) -> None:
|
|
with (
|
|
patch("pyfragment.methods.anonymous_number.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
|
patch(
|
|
"pyfragment.methods.anonymous_number.fragment_request",
|
|
AsyncMock(
|
|
side_effect=[
|
|
{"terminate_hash": FAKE_TERMINATE_HASH},
|
|
{"error": "INTERNAL_ERROR"},
|
|
]
|
|
),
|
|
),
|
|
):
|
|
with pytest.raises(AnonymousNumberError, match="INTERNAL_ERROR"):
|
|
await client.terminate_sessions("+1234567890")
|
|
|
|
|
|
# toggle_login_codes tests
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_toggle_login_codes_enable(client: FragmentClient) -> None:
|
|
with (
|
|
patch("pyfragment.methods.anonymous_number.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
|
patch("pyfragment.methods.anonymous_number.fragment_request", AsyncMock(return_value={"ok": True})) as mock_req,
|
|
):
|
|
await client.toggle_login_codes("+1234567890", can_receive=True)
|
|
|
|
call_data = mock_req.call_args[0][3]
|
|
assert call_data["can_receive"] == 1
|
|
assert call_data["method"] == "toggleLoginCodes"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_toggle_login_codes_disable(client: FragmentClient) -> None:
|
|
with (
|
|
patch("pyfragment.methods.anonymous_number.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
|
patch("pyfragment.methods.anonymous_number.fragment_request", AsyncMock(return_value={"ok": True})) as mock_req,
|
|
):
|
|
await client.toggle_login_codes("+1234567890", can_receive=False)
|
|
|
|
call_data = mock_req.call_args[0][3]
|
|
assert call_data["can_receive"] == 0
|
|
|
|
|
|
# strip_plus tests
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_login_code_strips_plus(client: FragmentClient) -> None:
|
|
"""Number passed with '+' is stripped before the API call."""
|
|
with (
|
|
patch("pyfragment.methods.anonymous_number.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
|
patch("pyfragment.methods.anonymous_number.fragment_request", AsyncMock(return_value={})) as mock_req,
|
|
):
|
|
await client.get_login_code("+1234567890")
|
|
|
|
call_data = mock_req.call_args[0][3]
|
|
assert call_data["number"] == "1234567890"
|