test_giveaway_commands.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. from __future__ import annotations
  2. import asyncio
  3. import sys
  4. import types
  5. from datetime import UTC, datetime, timedelta
  6. from types import SimpleNamespace
  7. from unittest.mock import AsyncMock
  8. import pytest
  9. @pytest.fixture
  10. def giveaway_module(app_modules, monkeypatch):
  11. permissions = types.ModuleType("wbb.core.decorators.permissions")
  12. permissions.adminsOnly = lambda *_args, **_kwargs: lambda function: function
  13. functions = types.ModuleType("wbb.utils.functions")
  14. async def extract_user_and_reason(_message):
  15. return None, ""
  16. functions.extract_user_and_reason = extract_user_and_reason
  17. monkeypatch.setitem(
  18. sys.modules, "wbb.core.decorators.permissions", permissions
  19. )
  20. monkeypatch.setitem(sys.modules, "wbb.utils.functions", functions)
  21. def no_running_loop():
  22. raise RuntimeError
  23. with monkeypatch.context() as scoped:
  24. scoped.setattr(asyncio, "get_running_loop", no_running_loop)
  25. return app_modules.load("wbb.modules.giveaway")
  26. async def _giveaway_with_participants(
  27. app_modules, count: int = 12, winner_count: int = 1
  28. ):
  29. giveaway_db = app_modules.load("wbb.utils.dbgiveaway")
  30. giveaway = await giveaway_db.create_giveaway(
  31. chat_id=-100,
  32. creator_id=1,
  33. creator_name="Admin",
  34. title="每周抽奖",
  35. description="",
  36. prizes=[{"name": "Winner", "count": winner_count}],
  37. ends_at=datetime.now(UTC) + timedelta(hours=1),
  38. )
  39. for user_id in range(1, count + 1):
  40. assert (
  41. await giveaway_db.add_participant(
  42. giveaway_id=giveaway["giveaway_id"],
  43. user_id=user_id,
  44. username=f"user{user_id}",
  45. first_name=f"User {user_id}",
  46. )
  47. == "ok"
  48. )
  49. return giveaway
  50. async def test_giveaway_keyword_lists_draw_and_participant_button(
  51. app_modules, giveaway_module
  52. ):
  53. giveaway = await _giveaway_with_participants(app_modules)
  54. message = SimpleNamespace(
  55. chat=SimpleNamespace(id=-100),
  56. reply_text=AsyncMock(return_value=SimpleNamespace(id=1)),
  57. )
  58. await giveaway_module.giveaway_keyword_command(None, message)
  59. text = message.reply_text.await_args.args[0]
  60. markup = message.reply_text.await_args.kwargs["reply_markup"]
  61. assert "每周抽奖" in text
  62. assert "12 人参与" in text
  63. callback_data = [button.callback_data for row in markup.inline_keyboard for button in row]
  64. assert f"giveaway_join:{giveaway['giveaway_id']}" in callback_data
  65. assert f"giveaway_participants:{giveaway['giveaway_id']}" in callback_data
  66. async def test_participant_callback_paginates_ten_users_per_page(
  67. app_modules, giveaway_module
  68. ):
  69. giveaway = await _giveaway_with_participants(app_modules)
  70. callback_message = SimpleNamespace(
  71. chat=SimpleNamespace(id=-100),
  72. reply_text=AsyncMock(return_value=SimpleNamespace(id=2)),
  73. edit_text=AsyncMock(),
  74. )
  75. open_query = SimpleNamespace(
  76. data=f"giveaway_participants:{giveaway['giveaway_id']}",
  77. message=callback_message,
  78. answer=AsyncMock(),
  79. )
  80. await giveaway_module.giveaway_participants_callback(None, open_query)
  81. first_page = callback_message.reply_text.await_args.args[0]
  82. first_markup = callback_message.reply_text.await_args.kwargs["reply_markup"]
  83. assert "第 1/2 页 · 共 12 人" in first_page
  84. assert "User 1" in first_page
  85. assert "User 10" in first_page
  86. assert "User 11" not in first_page
  87. assert any(
  88. button.callback_data
  89. == f"giveaway_participants_page:{giveaway['giveaway_id']}:2"
  90. for row in first_markup.inline_keyboard
  91. for button in row
  92. )
  93. page_query = SimpleNamespace(
  94. data=f"giveaway_participants_page:{giveaway['giveaway_id']}:2",
  95. message=callback_message,
  96. answer=AsyncMock(),
  97. )
  98. await giveaway_module.giveaway_participants_page_callback(None, page_query)
  99. second_page = callback_message.edit_text.await_args.args[0]
  100. assert "第 2/2 页 · 共 12 人" in second_page
  101. assert "11. " in second_page
  102. assert "User 11" in second_page
  103. assert "User 12" in second_page
  104. async def test_draw_keyword_shows_latest_winners_with_pagination(
  105. app_modules, giveaway_module
  106. ):
  107. giveaway = await _giveaway_with_participants(
  108. app_modules, count=12, winner_count=12
  109. )
  110. service = app_modules.load("wbb.services.giveaways")
  111. ok, _, _ = await service.finish_and_publish_giveaway(
  112. giveaway["giveaway_id"], publish=False
  113. )
  114. assert ok is True
  115. message = SimpleNamespace(
  116. chat=SimpleNamespace(id=-100),
  117. reply_text=AsyncMock(return_value=SimpleNamespace(id=3)),
  118. )
  119. await giveaway_module.giveaway_winners_keyword_command(None, message)
  120. first_page = message.reply_text.await_args.args[0]
  121. first_markup = message.reply_text.await_args.kwargs["reply_markup"]
  122. assert "抽奖结果" in first_page
  123. assert "第 1/2 页 · 共 12 位中奖者" in first_page
  124. assert any(
  125. button.callback_data
  126. == f"giveaway_winners_page:{giveaway['giveaway_id']}:2"
  127. for row in first_markup.inline_keyboard
  128. for button in row
  129. )
  130. callback_message = SimpleNamespace(
  131. chat=SimpleNamespace(id=-100),
  132. edit_text=AsyncMock(),
  133. )
  134. page_query = SimpleNamespace(
  135. data=f"giveaway_winners_page:{giveaway['giveaway_id']}:2",
  136. message=callback_message,
  137. answer=AsyncMock(),
  138. )
  139. await giveaway_module.giveaway_winners_page_callback(None, page_query)
  140. second_page = callback_message.edit_text.await_args.args[0]
  141. assert "第 2/2 页 · 共 12 位中奖者" in second_page
  142. assert "11. Winner" in second_page
  143. assert "12. Winner" in second_page