mirror of
https://github.com/vibe-existing/pyfragment.git
synced 2026-07-25 06:54:31 +00:00
feat: Add gift and number search functionality to FragmentClient
- Implemented `search_gifts` method for searching gifts in the Fragment marketplace. - Implemented `search_numbers` method for searching anonymous Telegram numbers. - Added new example scripts for searching gifts, numbers, and usernames. - Updated HTML parsing logic to handle gift items and number listings. - Added unit tests for the new search methods and updated existing tests for usernames and numbers. - Removed obsolete test file for auction searches.
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
"""Unit tests for search_usernames — Fragment marketplace username search."""
|
||||
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from pyfragment import FragmentClient
|
||||
from pyfragment.types import UsernamesResult
|
||||
from tests.shared import FAKE_HASH
|
||||
|
||||
FAKE_HTML = """
|
||||
<tr class="tm-row-selectable">
|
||||
<td><a href="/username/coolname" class="table-cell">
|
||||
<div class="table-cell-value tm-value">@coolname</div>
|
||||
<div class="table-cell-status-thin thin-only tm-status-avail">On auction</div>
|
||||
</a></td>
|
||||
<td><div class="table-cell-value tm-value icon-before icon-ton">5</div>
|
||||
<time datetime="2026-06-01T12:00:00+00:00" data-relative="text">2 days</time>
|
||||
</td>
|
||||
<td><div class="table-cell-value tm-value tm-status-avail">On auction</div></td>
|
||||
</tr>
|
||||
"""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_usernames_basic(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_usernames.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_usernames.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_HTML}),
|
||||
),
|
||||
):
|
||||
result = await client.search_usernames("coolname")
|
||||
|
||||
assert isinstance(result, UsernamesResult)
|
||||
assert len(result.items) == 1
|
||||
assert result.items[0]["slug"] == "username/coolname"
|
||||
assert result.items[0]["name"] == "@coolname"
|
||||
assert result.items[0]["date"] == "2026-06-01T12:00:00+00:00"
|
||||
assert result.next_offset_id is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_usernames_empty_html(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_usernames.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_usernames.fragment_request",
|
||||
AsyncMock(return_value={"ok": True}),
|
||||
),
|
||||
):
|
||||
result = await client.search_usernames("zzz_no_results")
|
||||
|
||||
assert isinstance(result, UsernamesResult)
|
||||
assert result.items == []
|
||||
assert result.next_offset_id is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_usernames_with_sort_and_filter(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_usernames.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_usernames.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_HTML}),
|
||||
) as mock_request,
|
||||
):
|
||||
result = await client.search_usernames("durov", sort="price_desc", filter="auction")
|
||||
|
||||
assert isinstance(result, UsernamesResult)
|
||||
call_data = mock_request.call_args[0][3]
|
||||
assert call_data["type"] == "usernames"
|
||||
assert call_data["method"] == "searchAuctions"
|
||||
assert call_data["sort"] == "price_desc"
|
||||
assert call_data["filter"] == "auction"
|
||||
assert call_data["query"] == "durov"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_usernames_with_offset_id(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_usernames.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_usernames.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_HTML, "next_offset_id": "offset_99"}),
|
||||
) as mock_request,
|
||||
):
|
||||
result = await client.search_usernames("durov", offset_id="offset_10")
|
||||
|
||||
assert isinstance(result, UsernamesResult)
|
||||
assert result.next_offset_id == "offset_99"
|
||||
call_data = mock_request.call_args[0][3]
|
||||
assert call_data["offset_id"] == "offset_10"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_usernames_default_query(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_usernames.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_usernames.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_HTML}),
|
||||
) as mock_request,
|
||||
):
|
||||
result = await client.search_usernames()
|
||||
|
||||
assert isinstance(result, UsernamesResult)
|
||||
call_data = mock_request.call_args[0][3]
|
||||
assert call_data["query"] == ""
|
||||
assert call_data["type"] == "usernames"
|
||||
@@ -0,0 +1,111 @@
|
||||
"""Unit tests for search_numbers — Fragment marketplace number search."""
|
||||
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from pyfragment import FragmentClient
|
||||
from pyfragment.types import NumbersResult
|
||||
from tests.shared import FAKE_HASH
|
||||
|
||||
FAKE_HTML = """
|
||||
<tr class="tm-row-selectable">
|
||||
<td><a href="/number/8880000888" class="table-cell">
|
||||
<div class="table-cell-value tm-value">+888 0000 888</div>
|
||||
<div class="table-cell-status-thin thin-only tm-status-avail">For sale</div>
|
||||
</a></td>
|
||||
<td><div class="table-cell-value tm-value icon-before icon-ton">150</div>
|
||||
<time datetime="2026-05-15T10:00:00+00:00" data-relative="short-text">May 15</time>
|
||||
</td>
|
||||
<td><div class="table-cell-value tm-value tm-status-avail">For sale</div></td>
|
||||
</tr>
|
||||
"""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_numbers_basic(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_numbers.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_numbers.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_HTML}),
|
||||
),
|
||||
):
|
||||
result = await client.search_numbers("888")
|
||||
|
||||
assert isinstance(result, NumbersResult)
|
||||
assert len(result.items) == 1
|
||||
assert result.items[0]["slug"] == "number/8880000888"
|
||||
assert result.items[0]["name"] == "+888 0000 888"
|
||||
assert result.items[0]["date"] == "2026-05-15T10:00:00+00:00"
|
||||
assert result.next_offset_id is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_numbers_empty_html(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_numbers.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_numbers.fragment_request",
|
||||
AsyncMock(return_value={"ok": True}),
|
||||
),
|
||||
):
|
||||
result = await client.search_numbers("zzz_no_results")
|
||||
|
||||
assert isinstance(result, NumbersResult)
|
||||
assert result.items == []
|
||||
assert result.next_offset_id is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_numbers_with_sort_and_filter(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_numbers.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_numbers.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_HTML}),
|
||||
) as mock_request,
|
||||
):
|
||||
result = await client.search_numbers("888", sort="price_asc", filter="sale")
|
||||
|
||||
assert isinstance(result, NumbersResult)
|
||||
call_data = mock_request.call_args[0][3]
|
||||
assert call_data["type"] == "numbers"
|
||||
assert call_data["method"] == "searchAuctions"
|
||||
assert call_data["sort"] == "price_asc"
|
||||
assert call_data["filter"] == "sale"
|
||||
assert call_data["query"] == "888"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_numbers_with_offset_id(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_numbers.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_numbers.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_HTML, "next_offset_id": "offset_50"}),
|
||||
) as mock_request,
|
||||
):
|
||||
result = await client.search_numbers("888", offset_id="offset_50")
|
||||
|
||||
assert isinstance(result, NumbersResult)
|
||||
assert result.next_offset_id == "offset_50"
|
||||
call_data = mock_request.call_args[0][3]
|
||||
assert call_data["offset_id"] == "offset_50"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_numbers_default_query(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_numbers.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_numbers.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_HTML}),
|
||||
) as mock_request,
|
||||
):
|
||||
result = await client.search_numbers()
|
||||
|
||||
assert isinstance(result, NumbersResult)
|
||||
call_data = mock_request.call_args[0][3]
|
||||
assert call_data["query"] == ""
|
||||
assert call_data["type"] == "numbers"
|
||||
@@ -1,124 +0,0 @@
|
||||
"""Unit tests for search_auctions — Fragment marketplace search."""
|
||||
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from pyfragment import FragmentClient
|
||||
from pyfragment.types import AuctionsResult
|
||||
from tests.shared import FAKE_HASH
|
||||
|
||||
FAKE_HTML = """
|
||||
<tr class="tm-row-selectable">
|
||||
<td><a href="/username/coolname" class="table-cell">
|
||||
<div class="table-cell-value tm-value">@coolname</div>
|
||||
<div class="table-cell-status-thin thin-only tm-status-avail">On auction</div>
|
||||
</a></td>
|
||||
<td><div class="table-cell-value tm-value icon-before icon-ton">5</div>
|
||||
<time datetime="2026-06-01T12:00:00+00:00" data-relative="text">2 days</time>
|
||||
</td>
|
||||
<td><div class="table-cell-value tm-value tm-status-avail">On auction</div></td>
|
||||
</tr>
|
||||
"""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_auctions_basic(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_auctions.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_auctions.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_HTML}),
|
||||
),
|
||||
):
|
||||
result = await client.search_auctions("coolname")
|
||||
|
||||
assert isinstance(result, AuctionsResult)
|
||||
assert len(result.items) == 1
|
||||
assert result.items[0]["slug"] == "username/coolname"
|
||||
assert result.items[0]["name"] == "@coolname"
|
||||
assert result.next_offset_id is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_auctions_with_type(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_auctions.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_auctions.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_HTML, "next_offset_id": "offset_99"}),
|
||||
),
|
||||
):
|
||||
result = await client.search_auctions("coolname", type="usernames")
|
||||
|
||||
assert isinstance(result, AuctionsResult)
|
||||
assert len(result.items) == 1
|
||||
assert result.next_offset_id == "offset_99"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_auctions_numbers(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_auctions.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_auctions.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_HTML}),
|
||||
),
|
||||
):
|
||||
result = await client.search_auctions("888", type="numbers")
|
||||
|
||||
assert isinstance(result, AuctionsResult)
|
||||
assert isinstance(result.items, list)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_auctions_empty_html(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_auctions.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_auctions.fragment_request",
|
||||
AsyncMock(return_value={"ok": True}),
|
||||
),
|
||||
):
|
||||
result = await client.search_auctions("zzz_no_results")
|
||||
|
||||
assert isinstance(result, AuctionsResult)
|
||||
assert result.items == []
|
||||
assert result.next_offset_id is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_auctions_with_sort_and_filter(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_auctions.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_auctions.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_HTML}),
|
||||
) as mock_request,
|
||||
):
|
||||
result = await client.search_auctions("durov", type="usernames", sort="price_desc", filter="auction")
|
||||
|
||||
assert isinstance(result, AuctionsResult)
|
||||
call_data = mock_request.call_args[0][3]
|
||||
assert call_data["sort"] == "price_desc"
|
||||
assert call_data["filter"] == "auction"
|
||||
assert call_data["type"] == "usernames"
|
||||
assert call_data["query"] == "durov"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_auctions_with_offset_id(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_auctions.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_auctions.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_HTML}),
|
||||
) as mock_request,
|
||||
):
|
||||
result = await client.search_auctions("durov", type="usernames", offset_id="offset_10")
|
||||
|
||||
assert isinstance(result, AuctionsResult)
|
||||
call_data = mock_request.call_args[0][3]
|
||||
assert call_data["offset_id"] == "offset_10"
|
||||
assert call_data["type"] == "usernames"
|
||||
assert call_data["query"] == "durov"
|
||||
@@ -0,0 +1,188 @@
|
||||
"""Unit tests for search_gifts — Fragment gifts marketplace search."""
|
||||
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from pyfragment import FragmentClient
|
||||
from pyfragment.types import GiftsResult
|
||||
from tests.shared import FAKE_HASH
|
||||
|
||||
FAKE_GIFTS_HTML = """
|
||||
<div class="tm-catalog-grid">
|
||||
<a href="/gift/plushpepe-1821?collection=all" class="tm-grid-item">
|
||||
<div class="tm-grid-item-thumb">
|
||||
<img src="https://nft.fragment.com/gift/plushpepe-1821.medium.jpg" class="tm-grid-thumb"/>
|
||||
</div>
|
||||
<div class="tm-grid-item-content">
|
||||
<div class="tm-grid-item-name wide-only">
|
||||
<span class="item-name">Plush Pepe</span>
|
||||
<span class="item-num"> #1821</span>
|
||||
</div>
|
||||
<div class="tm-grid-item-desc wide-only">
|
||||
<time datetime="2026-02-05T14:41:27+00:00" class="short">Feb 5 at 16:41</time>
|
||||
</div>
|
||||
<div class="tm-grid-item-values">
|
||||
<div class="tm-grid-item-value tm-value icon-before icon-ton">88,888</div>
|
||||
<div class="tm-grid-item-status tm-status-unavail">Sold</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/gift/swisswatch-7799?collection=all" class="tm-grid-item">
|
||||
<div class="tm-grid-item-content">
|
||||
<div class="tm-grid-item-name wide-only">
|
||||
<span class="item-name">Swiss Watch</span>
|
||||
<span class="item-num"> #7799</span>
|
||||
</div>
|
||||
<div class="tm-grid-item-desc wide-only">
|
||||
<time datetime="2026-01-10T04:52:59+00:00" class="short">Jan 10 at 06:52</time>
|
||||
</div>
|
||||
<div class="tm-grid-item-values">
|
||||
<div class="tm-grid-item-value tm-value icon-before icon-ton">13,588</div>
|
||||
<div class="tm-grid-item-status tm-status-unavail">Sold</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a class="tm-catalog-grid-more js-load-more" data-next-offset="60">Show more</a>
|
||||
</div>
|
||||
"""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_gifts_basic(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_gifts.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_gifts.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_GIFTS_HTML}),
|
||||
),
|
||||
):
|
||||
result = await client.search_gifts()
|
||||
|
||||
assert isinstance(result, GiftsResult)
|
||||
assert len(result.items) == 2
|
||||
assert result.items[0]["slug"] == "gift/plushpepe-1821"
|
||||
assert result.items[0]["name"] == "Plush Pepe #1821"
|
||||
assert result.items[0]["status"] == "Sold"
|
||||
assert result.items[0]["price"] == "88888.00"
|
||||
assert result.items[0]["date"] == "2026-02-05T14:41:27+00:00"
|
||||
assert result.items[1]["slug"] == "gift/swisswatch-7799"
|
||||
assert result.items[1]["price"] == "13588.00"
|
||||
assert result.next_offset == 60
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_gifts_empty(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_gifts.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_gifts.fragment_request",
|
||||
AsyncMock(return_value={"ok": True}),
|
||||
),
|
||||
):
|
||||
result = await client.search_gifts(query="zzz_no_results")
|
||||
|
||||
assert isinstance(result, GiftsResult)
|
||||
assert result.items == []
|
||||
assert result.next_offset is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_gifts_with_collection_and_sort(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_gifts.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_gifts.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_GIFTS_HTML}),
|
||||
) as mock_request,
|
||||
):
|
||||
result = await client.search_gifts(collection="plushpepe", sort="price_desc", filter="sold")
|
||||
|
||||
assert isinstance(result, GiftsResult)
|
||||
call_data = mock_request.call_args[0][3]
|
||||
assert call_data["collection"] == "plushpepe"
|
||||
assert call_data["sort"] == "price_desc"
|
||||
assert call_data["filter"] == "sold"
|
||||
assert call_data["type"] == "gifts"
|
||||
assert call_data["method"] == "searchAuctions"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_gifts_with_offset(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_gifts.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_gifts.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_GIFTS_HTML}),
|
||||
) as mock_request,
|
||||
):
|
||||
result = await client.search_gifts(offset=60)
|
||||
|
||||
assert isinstance(result, GiftsResult)
|
||||
call_data = mock_request.call_args[0][3]
|
||||
assert call_data["offset"] == 60
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_gifts_with_view(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_gifts.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_gifts.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_GIFTS_HTML}),
|
||||
) as mock_request,
|
||||
):
|
||||
result = await client.search_gifts(collection="artisanbrick", view="Model")
|
||||
|
||||
assert isinstance(result, GiftsResult)
|
||||
call_data = mock_request.call_args[0][3]
|
||||
assert call_data["view"] == "Model"
|
||||
assert call_data["collection"] == "artisanbrick"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_gifts_with_attr(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_gifts.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_gifts.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_GIFTS_HTML}),
|
||||
) as mock_request,
|
||||
):
|
||||
result = await client.search_gifts(
|
||||
collection="artisanbrick",
|
||||
sort="listed",
|
||||
filter="auction",
|
||||
attr={
|
||||
"Model": ["Delicate Wash", "Foosball", "Chocolate"],
|
||||
"Backdrop": ["Celtic Blue", "Carrot Juice", "Orange"],
|
||||
"Symbol": ["Crystal Ball", "Tetsubin", "Acorn"],
|
||||
},
|
||||
)
|
||||
|
||||
assert isinstance(result, GiftsResult)
|
||||
call_data = mock_request.call_args[0][3]
|
||||
assert call_data["attr[Model]"] == ["Delicate Wash", "Foosball", "Chocolate"]
|
||||
assert call_data["attr[Backdrop]"] == ["Celtic Blue", "Carrot Juice", "Orange"]
|
||||
assert call_data["attr[Symbol]"] == ["Crystal Ball", "Tetsubin", "Acorn"]
|
||||
assert call_data["collection"] == "artisanbrick"
|
||||
assert call_data["sort"] == "listed"
|
||||
assert call_data["filter"] == "auction"
|
||||
assert call_data["type"] == "gifts"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_gifts_attr_not_in_data_when_none(client: FragmentClient) -> None:
|
||||
with (
|
||||
patch("pyfragment.methods.search_gifts.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)),
|
||||
patch(
|
||||
"pyfragment.methods.search_gifts.fragment_request",
|
||||
AsyncMock(return_value={"ok": True, "html": FAKE_GIFTS_HTML}),
|
||||
) as mock_request,
|
||||
):
|
||||
result = await client.search_gifts()
|
||||
|
||||
assert isinstance(result, GiftsResult)
|
||||
call_data = mock_request.call_args[0][3]
|
||||
assert "view" not in call_data
|
||||
assert not any(k.startswith("attr[") for k in call_data)
|
||||
Reference in New Issue
Block a user