Skip to content

Commit 1a7ecdf

Browse files
committed
v3.0.12
1 parent 2c91470 commit 1a7ecdf

1 file changed

Lines changed: 204 additions & 0 deletions

File tree

tests/unit/bot/tools/test_bot_utils_extra.py

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,3 +862,207 @@ async def test_pagination_stores_message(self, mock_dal_class, mock_ctx):
862862
call_kwargs = mock_ctx.send.call_args[1]
863863
view = call_kwargs["view"]
864864
assert view.message is sent_msg
865+
866+
867+
class TestEmbedPaginatorViewPersistence:
868+
"""Test EmbedPaginatorView database persistence methods."""
869+
870+
def _make_pages(self, count=3):
871+
return [discord.Embed(title=f"Page {i + 1}", description=f"Content {i + 1}") for i in range(count)]
872+
873+
def test_embed_to_dict(self):
874+
"""Test _embed_to_dict converts embed to dict."""
875+
embed = discord.Embed(title="Test", description="Desc", color=discord.Color.green())
876+
result = EmbedPaginatorView._embed_to_dict(embed)
877+
assert isinstance(result, dict)
878+
assert result["title"] == "Test"
879+
assert result["description"] == "Desc"
880+
881+
def test_dict_to_embed(self):
882+
"""Test _dict_to_embed converts dict back to embed."""
883+
data = {"title": "Test", "description": "Desc", "color": 0x00FF00}
884+
result = EmbedPaginatorView._dict_to_embed(data)
885+
assert isinstance(result, discord.Embed)
886+
assert result.title == "Test"
887+
assert result.description == "Desc"
888+
889+
def test_embed_roundtrip(self):
890+
"""Test embed -> dict -> embed preserves data."""
891+
original = discord.Embed(title="Round", description="Trip", color=discord.Color.red())
892+
original.set_footer(text="Footer")
893+
data = EmbedPaginatorView._embed_to_dict(original)
894+
restored = EmbedPaginatorView._dict_to_embed(data)
895+
assert restored.title == original.title
896+
assert restored.description == original.description
897+
assert restored.footer.text == original.footer.text
898+
899+
@pytest.mark.asyncio
900+
@patch("src.database.dal.bot.embed_pages_dal.EmbedPagesDal")
901+
async def test_send_and_save(self, mock_dal_class):
902+
"""Test send_and_save sends message and saves to DB."""
903+
mock_dal = MagicMock()
904+
mock_dal.insert_embed_pages = AsyncMock()
905+
mock_dal_class.return_value = mock_dal
906+
907+
pages = self._make_pages(2)
908+
view = EmbedPaginatorView(pages, author_id=42)
909+
910+
ctx = MagicMock()
911+
mock_msg = MagicMock()
912+
mock_msg.id = 111
913+
mock_msg.channel.id = 222
914+
ctx.send = AsyncMock(return_value=mock_msg)
915+
ctx.bot.db_session = MagicMock()
916+
ctx.bot.log = MagicMock()
917+
918+
await view.send_and_save(ctx)
919+
920+
assert view.message is mock_msg
921+
ctx.send.assert_called_once()
922+
mock_dal.insert_embed_pages.assert_awaited_once()
923+
call_args = mock_dal.insert_embed_pages.call_args
924+
assert call_args[0][0] == 111 # message_id
925+
assert call_args[0][1] == 222 # channel_id
926+
assert call_args[0][2] == 42 # author_id
927+
assert len(call_args[0][3]) == 2 # pages data
928+
929+
@pytest.mark.asyncio
930+
@patch("src.database.dal.bot.embed_pages_dal.EmbedPagesDal")
931+
async def test_load_from_db_pages_already_set(self, mock_dal_class):
932+
"""Test _load_from_db returns True immediately when pages exist."""
933+
pages = self._make_pages(2)
934+
view = EmbedPaginatorView(pages, author_id=42)
935+
interaction = MagicMock()
936+
937+
result = await view._load_from_db(interaction)
938+
939+
assert result is True
940+
mock_dal_class.assert_not_called()
941+
942+
@pytest.mark.asyncio
943+
@patch("src.database.dal.bot.embed_pages_dal.EmbedPagesDal")
944+
async def test_load_from_db_loads_from_database(self, mock_dal_class):
945+
"""Test _load_from_db loads pages from DB when not in memory."""
946+
mock_dal = MagicMock()
947+
page_data = [{"title": "P1", "description": "D1"}, {"title": "P2", "description": "D2"}]
948+
mock_dal.get_embed_pages = AsyncMock(return_value={
949+
"pages": page_data,
950+
"current_page": 1,
951+
"author_id": 42,
952+
})
953+
mock_dal_class.return_value = mock_dal
954+
955+
view = EmbedPaginatorView() # No pages
956+
interaction = MagicMock()
957+
interaction.message.id = 111
958+
interaction.client.db_session = MagicMock()
959+
interaction.client.log = MagicMock()
960+
961+
result = await view._load_from_db(interaction)
962+
963+
assert result is True
964+
assert len(view.pages) == 2
965+
assert view.current_page == 1
966+
assert view.author_id == 42
967+
968+
@pytest.mark.asyncio
969+
@patch("src.database.dal.bot.embed_pages_dal.EmbedPagesDal")
970+
async def test_load_from_db_record_not_found(self, mock_dal_class):
971+
"""Test _load_from_db returns False when record not in DB."""
972+
mock_dal = MagicMock()
973+
mock_dal.get_embed_pages = AsyncMock(return_value=None)
974+
mock_dal_class.return_value = mock_dal
975+
976+
view = EmbedPaginatorView() # No pages
977+
interaction = MagicMock()
978+
interaction.message.id = 999
979+
interaction.client.db_session = MagicMock()
980+
interaction.client.log = MagicMock()
981+
interaction.response = AsyncMock()
982+
983+
result = await view._load_from_db(interaction)
984+
985+
assert result is False
986+
interaction.response.send_message.assert_called_once_with(
987+
"This pagination has expired.", ephemeral=True
988+
)
989+
990+
@pytest.mark.asyncio
991+
@patch("src.database.dal.bot.embed_pages_dal.EmbedPagesDal")
992+
async def test_save_current_page(self, mock_dal_class):
993+
"""Test _save_current_page updates DB."""
994+
mock_dal = MagicMock()
995+
mock_dal.update_current_page = AsyncMock()
996+
mock_dal_class.return_value = mock_dal
997+
998+
pages = self._make_pages(3)
999+
view = EmbedPaginatorView(pages, author_id=42)
1000+
view.current_page = 2
1001+
1002+
interaction = MagicMock()
1003+
interaction.message.id = 111
1004+
interaction.client.db_session = MagicMock()
1005+
interaction.client.log = MagicMock()
1006+
1007+
await view._save_current_page(interaction)
1008+
1009+
mock_dal.update_current_page.assert_awaited_once_with(111, 2)
1010+
1011+
def test_init_no_pages(self):
1012+
"""Test EmbedPaginatorView with no pages defaults."""
1013+
view = EmbedPaginatorView()
1014+
assert view.pages == []
1015+
assert view.author_id == 0
1016+
assert view.page_indicator.label == "0/0"
1017+
1018+
1019+
class TestEmbedPagesDal:
1020+
"""Test EmbedPagesDal class."""
1021+
1022+
@pytest.fixture
1023+
def mock_dal(self):
1024+
db_session = MagicMock()
1025+
log = MagicMock()
1026+
with patch("src.database.dal.bot.embed_pages_dal.DBUtilsAsync") as mock_db_utils_class:
1027+
mock_db_utils = MagicMock()
1028+
mock_db_utils.insert = AsyncMock()
1029+
mock_db_utils.execute = AsyncMock()
1030+
mock_db_utils.fetchall = AsyncMock(return_value=[])
1031+
mock_db_utils_class.return_value = mock_db_utils
1032+
from src.database.dal.bot.embed_pages_dal import EmbedPagesDal
1033+
dal = EmbedPagesDal(db_session, log)
1034+
dal._mock_db_utils = mock_db_utils
1035+
return dal
1036+
1037+
@pytest.mark.asyncio
1038+
async def test_insert_embed_pages(self, mock_dal):
1039+
"""Test insert_embed_pages calls db_utils.insert."""
1040+
pages = [{"title": "P1"}]
1041+
await mock_dal.insert_embed_pages(111, 222, 42, pages)
1042+
mock_dal._mock_db_utils.insert.assert_awaited_once()
1043+
1044+
@pytest.mark.asyncio
1045+
async def test_get_embed_pages_found(self, mock_dal):
1046+
"""Test get_embed_pages returns record when found."""
1047+
mock_dal._mock_db_utils.fetchall = AsyncMock(return_value=[{"message_id": 111, "pages": []}])
1048+
result = await mock_dal.get_embed_pages(111)
1049+
assert result == {"message_id": 111, "pages": []}
1050+
1051+
@pytest.mark.asyncio
1052+
async def test_get_embed_pages_not_found(self, mock_dal):
1053+
"""Test get_embed_pages returns None when not found."""
1054+
mock_dal._mock_db_utils.fetchall = AsyncMock(return_value=[])
1055+
result = await mock_dal.get_embed_pages(999)
1056+
assert result is None
1057+
1058+
@pytest.mark.asyncio
1059+
async def test_update_current_page(self, mock_dal):
1060+
"""Test update_current_page calls db_utils.execute."""
1061+
await mock_dal.update_current_page(111, 2)
1062+
mock_dal._mock_db_utils.execute.assert_awaited_once()
1063+
1064+
@pytest.mark.asyncio
1065+
async def test_delete_embed_pages(self, mock_dal):
1066+
"""Test delete_embed_pages calls db_utils.execute."""
1067+
await mock_dal.delete_embed_pages(111)
1068+
mock_dal._mock_db_utils.execute.assert_awaited_once()

0 commit comments

Comments
 (0)