aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorGravatar mbaruh <[email protected]>2024-03-17 23:14:26 +0200
committerGravatar mbaruh <[email protected]>2024-03-17 23:14:26 +0200
commitd4d8e6d0af376e32112512a3726df8f1449deb01 (patch)
treee3f4c4f53ca17c6129b586e167dfa83e1c2cf51d /tests
parentMake the moderator the author of the compban for phishing attempts (diff)
parentMerge pull request #2953 from python-discord/dependabot/pip/pytest-8.1.1 (diff)
Merge branch 'main' into phishing_button
Diffstat (limited to 'tests')
-rw-r--r--tests/_autospec.py2
-rw-r--r--tests/bot/exts/backend/test_error_handler.py36
-rw-r--r--tests/bot/exts/backend/test_logging.py5
-rw-r--r--tests/bot/exts/filtering/test_settings_entries.py8
-rw-r--r--tests/bot/exts/moderation/infraction/test_utils.py10
-rw-r--r--tests/bot/exts/moderation/test_incidents.py22
-rw-r--r--tests/bot/exts/moderation/test_modlog.py4
-rw-r--r--tests/bot/exts/moderation/test_silence.py9
-rw-r--r--tests/bot/exts/test_cogs.py3
-rw-r--r--tests/bot/exts/utils/snekbox/test_snekbox.py45
-rw-r--r--tests/bot/test_pagination.py46
-rw-r--r--tests/bot/utils/test_services.py90
-rw-r--r--tests/helpers.py10
-rw-r--r--tests/test_helpers.py1
14 files changed, 83 insertions, 208 deletions
diff --git a/tests/_autospec.py b/tests/_autospec.py
index 6f990a580..a9cd59dc0 100644
--- a/tests/_autospec.py
+++ b/tests/_autospec.py
@@ -51,7 +51,7 @@ def autospec(target, *attributes: str, pass_mocks: bool = True, **patch_kwargs)
# Import the target if it's a string.
# This is to support both object and string targets like patch.multiple.
- if type(target) is str:
+ if isinstance(target, str):
target = pkgutil.resolve_name(target)
def decorator(func):
diff --git a/tests/bot/exts/backend/test_error_handler.py b/tests/bot/exts/backend/test_error_handler.py
index 0ba2fcf11..9670d42a0 100644
--- a/tests/bot/exts/backend/test_error_handler.py
+++ b/tests/bot/exts/backend/test_error_handler.py
@@ -1,5 +1,5 @@
import unittest
-from unittest.mock import AsyncMock, MagicMock, call, patch
+from unittest.mock import AsyncMock, MagicMock, Mock, call, patch
from discord.ext.commands import errors
from pydis_core.site_api import ResponseCodeError
@@ -54,12 +54,15 @@ class ErrorHandlerTests(unittest.IsolatedAsyncioTestCase):
self.ctx.reset_mock()
self.cog.try_silence.reset_mock(return_value=True)
self.cog.try_get_tag.reset_mock()
+ self.ctx.invoked_from_error_handler = False
self.cog.try_silence.return_value = case["try_silence_return"]
self.ctx.channel.id = 1234
self.assertIsNone(await self.cog.on_command_error(self.ctx, error))
+ self.assertTrue(self.ctx.invoked_from_error_handler)
+
if case["try_silence_return"]:
self.cog.try_get_tag.assert_not_awaited()
self.cog.try_silence.assert_awaited_once()
@@ -203,13 +206,6 @@ class TrySilenceTests(unittest.IsolatedAsyncioTestCase):
self.ctx = MockContext(bot=self.bot, guild=self.guild)
self.cog = error_handler.ErrorHandler(self.bot)
- async def test_try_silence_context_invoked_from_error_handler(self):
- """Should set `Context.invoked_from_error_handler` to `True`."""
- self.ctx.invoked_with = "foo"
- await self.cog.try_silence(self.ctx)
- self.assertTrue(hasattr(self.ctx, "invoked_from_error_handler"))
- self.assertTrue(self.ctx.invoked_from_error_handler)
-
async def test_try_silence_get_command(self):
"""Should call `get_command` with `silence`."""
self.ctx.invoked_with = "foo"
@@ -342,26 +338,12 @@ class TryGetTagTests(unittest.IsolatedAsyncioTestCase):
await self.cog.try_get_tag(self.ctx)
self.bot.get_cog.assert_called_once_with("Tags")
- async def test_try_get_tag_invoked_from_error_handler(self):
- """`self.ctx` should have `invoked_from_error_handler` `True`."""
- self.ctx.invoked_from_error_handler = False
- await self.cog.try_get_tag(self.ctx)
- self.assertTrue(self.ctx.invoked_from_error_handler)
-
async def test_try_get_tag_no_permissions(self):
"""Test how to handle checks failing."""
self.bot.can_run = AsyncMock(return_value=False)
self.ctx.invoked_with = "foo"
self.assertIsNone(await self.cog.try_get_tag(self.ctx))
- async def test_try_get_tag_command_error(self):
- """Should call `on_command_error` when `CommandError` raised."""
- err = errors.CommandError()
- self.bot.can_run = AsyncMock(side_effect=err)
- self.cog.on_command_error = AsyncMock()
- self.assertIsNone(await self.cog.try_get_tag(self.ctx))
- self.cog.on_command_error.assert_awaited_once_with(self.ctx, err)
-
async def test_dont_call_suggestion_tag_sent(self):
"""Should never call command suggestion if tag is already sent."""
self.ctx.message = MagicMock(content="foo")
@@ -375,7 +357,7 @@ class TryGetTagTests(unittest.IsolatedAsyncioTestCase):
async def test_dont_call_suggestion_if_user_mod(self):
"""Should not call command suggestion if user is a mod."""
self.ctx.invoked_with = "foo"
- self.ctx.invoke = AsyncMock(return_value=False)
+ self.tag.get_command_ctx = AsyncMock(return_value=False)
self.ctx.author.roles = [MockRole(id=1234)]
self.cog.send_command_suggestion = AsyncMock()
@@ -521,6 +503,10 @@ class IndividualErrorHandlerTests(unittest.IsolatedAsyncioTestCase):
self.ctx.reset_mock()
log_mock.reset_mock()
push_scope_mock.reset_mock()
+ scope_mock = Mock()
+
+ # Mock `with push_scope_mock() as scope:`
+ push_scope_mock.return_value.__enter__.return_value = scope_mock
self.ctx.guild = case
await self.cog.handle_unexpected_error(self.ctx, errors.CommandError())
@@ -544,8 +530,8 @@ class IndividualErrorHandlerTests(unittest.IsolatedAsyncioTestCase):
)
set_extra_calls.append(call("jump_to", url))
- push_scope_mock.set_tag.has_calls(set_tag_calls)
- push_scope_mock.set_extra.has_calls(set_extra_calls)
+ scope_mock.set_tag.assert_has_calls(set_tag_calls)
+ scope_mock.set_extra.assert_has_calls(set_extra_calls)
class ErrorHandlerSetupTests(unittest.IsolatedAsyncioTestCase):
diff --git a/tests/bot/exts/backend/test_logging.py b/tests/bot/exts/backend/test_logging.py
index 466f207d9..3a41220ad 100644
--- a/tests/bot/exts/backend/test_logging.py
+++ b/tests/bot/exts/backend/test_logging.py
@@ -3,7 +3,7 @@ from unittest.mock import patch
from bot import constants
from bot.exts.backend.logging import Logging
-from tests.helpers import MockBot, MockTextChannel
+from tests.helpers import MockBot, MockTextChannel, no_create_task
class LoggingTests(unittest.IsolatedAsyncioTestCase):
@@ -11,7 +11,8 @@ class LoggingTests(unittest.IsolatedAsyncioTestCase):
def setUp(self):
self.bot = MockBot()
- self.cog = Logging(self.bot)
+ with no_create_task():
+ self.cog = Logging(self.bot)
self.dev_log = MockTextChannel(id=1234, name="dev-log")
@patch("bot.exts.backend.logging.DEBUG_MODE", False)
diff --git a/tests/bot/exts/filtering/test_settings_entries.py b/tests/bot/exts/filtering/test_settings_entries.py
index 3ae0b5ab5..f12b2caa5 100644
--- a/tests/bot/exts/filtering/test_settings_entries.py
+++ b/tests/bot/exts/filtering/test_settings_entries.py
@@ -2,7 +2,9 @@ import unittest
from bot.exts.filtering._filter_context import Event, FilterContext
from bot.exts.filtering._settings_types.actions.infraction_and_notification import (
- Infraction, InfractionAndNotification, InfractionDuration
+ Infraction,
+ InfractionAndNotification,
+ InfractionDuration,
)
from bot.exts.filtering._settings_types.validations.bypass_roles import RoleBypass
from bot.exts.filtering._settings_types.validations.channel_scope import ChannelScope
@@ -173,7 +175,7 @@ class FilterTests(unittest.TestCase):
result = infraction1.union(infraction2)
self.assertDictEqual(
- result.dict(),
+ result.model_dump(),
{
"infraction_type": Infraction.TIMEOUT,
"infraction_reason": "there",
@@ -206,7 +208,7 @@ class FilterTests(unittest.TestCase):
result = infraction1.union(infraction2)
self.assertDictEqual(
- result.dict(),
+ result.model_dump(),
{
"infraction_type": Infraction.BAN,
"infraction_reason": "",
diff --git a/tests/bot/exts/moderation/infraction/test_utils.py b/tests/bot/exts/moderation/infraction/test_utils.py
index 25337673e..e2a7bad9f 100644
--- a/tests/bot/exts/moderation/infraction/test_utils.py
+++ b/tests/bot/exts/moderation/infraction/test_utils.py
@@ -142,7 +142,7 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):
),
"expected_output": Embed(
title=utils.INFRACTION_TITLE,
- description=utils.INFRACTION_DESCRIPTION_TEMPLATE.format(
+ description=utils.INFRACTION_DESCRIPTION_NOT_WARNING_TEMPLATE.format(
type="Ban",
expires="2020-02-26 09:20 (23 hours and 59 minutes)",
reason="No reason provided."
@@ -160,7 +160,7 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):
"args": (dict(id=0, type="warning", reason="Test reason.", expires_at=None), self.user),
"expected_output": Embed(
title=utils.INFRACTION_TITLE,
- description=utils.INFRACTION_DESCRIPTION_TEMPLATE.format(
+ description=utils.INFRACTION_DESCRIPTION_NOT_WARNING_TEMPLATE.format(
type="Warning",
expires="N/A",
reason="Test reason."
@@ -180,7 +180,7 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):
"args": (dict(id=0, type="note", reason=None, expires_at=None), self.user),
"expected_output": Embed(
title=utils.INFRACTION_TITLE,
- description=utils.INFRACTION_DESCRIPTION_TEMPLATE.format(
+ description=utils.INFRACTION_DESCRIPTION_NOT_WARNING_TEMPLATE.format(
type="Note",
expires="N/A",
reason="No reason provided."
@@ -201,7 +201,7 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):
),
"expected_output": Embed(
title=utils.INFRACTION_TITLE,
- description=utils.INFRACTION_DESCRIPTION_TEMPLATE.format(
+ description=utils.INFRACTION_DESCRIPTION_NOT_WARNING_TEMPLATE.format(
type="Mute",
expires="2020-02-26 09:20 (23 hours and 59 minutes)",
reason="Test"
@@ -219,7 +219,7 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):
"args": (dict(id=0, type="mute", reason="foo bar" * 4000, expires_at=None), self.user),
"expected_output": Embed(
title=utils.INFRACTION_TITLE,
- description=utils.INFRACTION_DESCRIPTION_TEMPLATE.format(
+ description=utils.INFRACTION_DESCRIPTION_NOT_WARNING_TEMPLATE.format(
type="Mute",
expires="N/A",
reason="foo bar" * 4000
diff --git a/tests/bot/exts/moderation/test_incidents.py b/tests/bot/exts/moderation/test_incidents.py
index bb337aeba..444bb1142 100644
--- a/tests/bot/exts/moderation/test_incidents.py
+++ b/tests/bot/exts/moderation/test_incidents.py
@@ -16,8 +16,16 @@ from bot.utils.messages import format_user
from bot.utils.time import TimestampFormats, discord_timestamp
from tests.base import RedisTestCase
from tests.helpers import (
- MockAsyncWebhook, MockAttachment, MockBot, MockMember, MockMessage, MockReaction, MockRole, MockTextChannel,
- MockUser
+ MockAsyncWebhook,
+ MockAttachment,
+ MockBot,
+ MockMember,
+ MockMessage,
+ MockReaction,
+ MockRole,
+ MockTextChannel,
+ MockUser,
+ no_create_task,
)
CURRENT_TIME = datetime.datetime(2022, 1, 1, tzinfo=datetime.UTC)
@@ -306,7 +314,8 @@ class TestIncidents(RedisTestCase):
Note that this will not schedule `crawl_incidents` in the background, as everything
is being mocked. The `crawl_task` attribute will end up being None.
"""
- self.cog_instance = incidents.Incidents(MockBot())
+ with no_create_task():
+ self.cog_instance = incidents.Incidents(MockBot())
@patch("asyncio.sleep", AsyncMock()) # Prevent the coro from sleeping to speed up the test
@@ -458,7 +467,8 @@ class TestMakeConfirmationTask(TestIncidents):
If this function begins to fail, first check that `created_check` is being retrieved
correctly. It should be the function that is built locally in the tested method.
"""
- self.cog_instance.make_confirmation_task(MockMessage(id=123))
+ with no_create_task():
+ self.cog_instance.make_confirmation_task(MockMessage(id=123))
self.cog_instance.bot.wait_for.assert_called_once()
created_check = self.cog_instance.bot.wait_for.call_args.kwargs["check"]
@@ -547,7 +557,7 @@ class TestProcessEvent(TestIncidents):
exception should it propagate out of `process_event`. This is so that we can then manually
fail the test with a more informative message than just the plain traceback.
"""
- mock_task = AsyncMock(side_effect=asyncio.TimeoutError())
+ mock_task = AsyncMock(side_effect=TimeoutError())
try:
with patch("bot.exts.moderation.incidents.Incidents.make_confirmation_task", mock_task):
@@ -556,7 +566,7 @@ class TestProcessEvent(TestIncidents):
incident=MockMessage(id=123, created_at=CURRENT_TIME),
member=MockMember(roles=[MockRole(id=1)])
)
- except asyncio.TimeoutError:
+ except TimeoutError:
self.fail("TimeoutError was not handled gracefully, and propagated out of `process_event`!")
diff --git a/tests/bot/exts/moderation/test_modlog.py b/tests/bot/exts/moderation/test_modlog.py
index 79e04837d..f2b02bd1b 100644
--- a/tests/bot/exts/moderation/test_modlog.py
+++ b/tests/bot/exts/moderation/test_modlog.py
@@ -3,6 +3,7 @@ import unittest
import discord
from bot.exts.moderation.modlog import ModLog
+from bot.utils.modlog import send_log_message
from tests.helpers import MockBot, MockTextChannel
@@ -17,7 +18,8 @@ class ModLogTests(unittest.IsolatedAsyncioTestCase):
async def test_log_entry_description_truncation(self):
"""Test that embed description for ModLog entry is truncated."""
self.bot.get_channel.return_value = self.channel
- await self.cog.send_log_message(
+ await send_log_message(
+ self.bot,
icon_url="foo",
colour=discord.Colour.blue(),
title="bar",
diff --git a/tests/bot/exts/moderation/test_silence.py b/tests/bot/exts/moderation/test_silence.py
index ec0b3bf43..a7f239d7f 100644
--- a/tests/bot/exts/moderation/test_silence.py
+++ b/tests/bot/exts/moderation/test_silence.py
@@ -10,7 +10,14 @@ from bot.constants import Channels, Guild, MODERATION_ROLES, Roles
from bot.exts.moderation import silence
from tests.base import RedisTestCase
from tests.helpers import (
- MockBot, MockContext, MockGuild, MockMember, MockRole, MockTextChannel, MockVoiceChannel, autospec
+ MockBot,
+ MockContext,
+ MockGuild,
+ MockMember,
+ MockRole,
+ MockTextChannel,
+ MockVoiceChannel,
+ autospec,
)
diff --git a/tests/bot/exts/test_cogs.py b/tests/bot/exts/test_cogs.py
index 99bc87120..0c117b3e6 100644
--- a/tests/bot/exts/test_cogs.py
+++ b/tests/bot/exts/test_cogs.py
@@ -62,8 +62,7 @@ class CommandNameTests(unittest.TestCase):
"""Yield all commands for all cogs in all extensions."""
for module in self.walk_modules():
for cog in self.walk_cogs(module):
- for cmd in self.walk_commands(cog):
- yield cmd
+ yield from self.walk_commands(cog)
def test_names_dont_shadow(self):
"""Names and aliases of commands should be unique."""
diff --git a/tests/bot/exts/utils/snekbox/test_snekbox.py b/tests/bot/exts/utils/snekbox/test_snekbox.py
index fa28aade8..8ee0f46ff 100644
--- a/tests/bot/exts/utils/snekbox/test_snekbox.py
+++ b/tests/bot/exts/utils/snekbox/test_snekbox.py
@@ -5,6 +5,7 @@ from unittest.mock import AsyncMock, MagicMock, Mock, call, create_autospec, pat
from discord import AllowedMentions
from discord.ext import commands
+from pydis_core.utils.paste_service import MAX_PASTE_SIZE
from bot import constants
from bot.errors import LockedResourceError
@@ -54,21 +55,15 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
)
resp.json.assert_awaited_once()
+ @patch(
+ "bot.exts.utils.snekbox._cog.paste_service._lexers_supported_by_pastebin",
+ {"https://paste.pythondiscord.com": ["text"]},
+ )
async def test_upload_output_reject_too_long(self):
"""Reject output longer than MAX_PASTE_LENGTH."""
- result = await self.cog.upload_output("-" * (snekbox._cog.MAX_PASTE_LENGTH + 1))
+ result = await self.cog.upload_output("-" * (MAX_PASTE_SIZE + 1))
self.assertEqual(result, "too long to upload")
- @patch("bot.exts.utils.snekbox._cog.send_to_paste_service")
- async def test_upload_output(self, mock_paste_util):
- """Upload the eval output to the URLs.paste_service.format(key="documents") endpoint."""
- await self.cog.upload_output("Test output.")
- mock_paste_util.assert_called_once_with(
- "Test output.",
- extension="txt",
- max_length=snekbox._cog.MAX_PASTE_LENGTH
- )
-
async def test_codeblock_converter(self):
ctx = MockContext()
cases = (
@@ -108,9 +103,9 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
def test_eval_result_message(self):
"""EvalResult.get_message(), should return message."""
cases = (
- ("ERROR", None, ("Your 3.11 eval job has failed", "ERROR", "")),
- ("", 128 + snekbox._eval.SIGKILL, ("Your 3.11 eval job timed out or ran out of memory", "", "")),
- ("", 255, ("Your 3.11 eval job has failed", "A fatal NsJail error occurred", ""))
+ ("ERROR", None, ("Your 3.12 eval job has failed", "ERROR", "")),
+ ("", 128 + snekbox._eval.SIGKILL, ("Your 3.12 eval job timed out or ran out of memory", "", "")),
+ ("", 255, ("Your 3.12 eval job has failed", "A fatal NsJail error occurred", ""))
)
for stdout, returncode, expected in cases:
exp_msg, exp_err, exp_files_err = expected
@@ -182,8 +177,8 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
mock_signals.return_value.name = "SIGTEST"
result = EvalResult(stdout="", returncode=127)
self.assertEqual(
- result.get_message(EvalJob([], version="3.11")),
- "Your 3.11 eval job has completed with return code 127 (SIGTEST)"
+ result.get_message(EvalJob([], version="3.12")),
+ "Your 3.12 eval job has completed with return code 127 (SIGTEST)"
)
def test_eval_result_status_emoji(self):
@@ -257,7 +252,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
self.cog.send_job = AsyncMock(return_value=response)
self.cog.continue_job = AsyncMock(return_value=None)
- await self.cog.eval_command(self.cog, ctx=ctx, python_version="3.11", code=["MyAwesomeCode"])
+ await self.cog.eval_command(self.cog, ctx=ctx, python_version="3.12", code=["MyAwesomeCode"])
job = EvalJob.from_code("MyAwesomeCode")
self.cog.send_job.assert_called_once_with(ctx, job)
self.cog.continue_job.assert_called_once_with(ctx, response, "eval")
@@ -271,7 +266,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
self.cog.continue_job = AsyncMock()
self.cog.continue_job.side_effect = (EvalJob.from_code("MyAwesomeFormattedCode"), None)
- await self.cog.eval_command(self.cog, ctx=ctx, python_version="3.11", code=["MyAwesomeCode"])
+ await self.cog.eval_command(self.cog, ctx=ctx, python_version="3.12", code=["MyAwesomeCode"])
expected_job = EvalJob.from_code("MyAwesomeFormattedCode")
self.cog.send_job.assert_called_with(ctx, expected_job)
@@ -316,7 +311,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
ctx.send.assert_called_once()
self.assertEqual(
ctx.send.call_args.args[0],
- "@LemonLemonishBeard#0042 :warning: Your 3.11 eval job has completed "
+ "@LemonLemonishBeard#0042 :warning: Your 3.12 eval job has completed "
"with return code 0.\n\n```\n[No output]\n```"
)
allowed_mentions = ctx.send.call_args.kwargs["allowed_mentions"]
@@ -342,13 +337,13 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
mocked_filter_cog.filter_snekbox_output = AsyncMock(return_value=(False, []))
self.bot.get_cog.return_value = mocked_filter_cog
- job = EvalJob.from_code("MyAwesomeCode").as_version("3.11")
+ job = EvalJob.from_code("MyAwesomeCode").as_version("3.12")
await self.cog.send_job(ctx, job),
ctx.send.assert_called_once()
self.assertEqual(
ctx.send.call_args.args[0],
- "@LemonLemonishBeard#0042 :white_check_mark: Your 3.11 eval job "
+ "@LemonLemonishBeard#0042 :white_check_mark: Your 3.12 eval job "
"has completed with return code 0."
"\n\n```\nWay too long beard\n```\nFull output: lookatmybeard.com"
)
@@ -371,13 +366,13 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
mocked_filter_cog.filter_snekbox_output = AsyncMock(return_value=(False, []))
self.bot.get_cog.return_value = mocked_filter_cog
- job = EvalJob.from_code("MyAwesomeCode").as_version("3.11")
+ job = EvalJob.from_code("MyAwesomeCode").as_version("3.12")
await self.cog.send_job(ctx, job),
ctx.send.assert_called_once()
self.assertEqual(
ctx.send.call_args.args[0],
- "@LemonLemonishBeard#0042 :x: Your 3.11 eval job has completed with return code 127."
+ "@LemonLemonishBeard#0042 :x: Your 3.12 eval job has completed with return code 127."
"\n\n```\nERROR\n```"
)
@@ -399,13 +394,13 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
mocked_filter_cog.filter_snekbox_output = AsyncMock(return_value=(False, [".disallowed"]))
self.bot.get_cog.return_value = mocked_filter_cog
- job = EvalJob.from_code("MyAwesomeCode").as_version("3.11")
+ job = EvalJob.from_code("MyAwesomeCode").as_version("3.12")
await self.cog.send_job(ctx, job),
ctx.send.assert_called_once()
res = ctx.send.call_args.args[0]
self.assertTrue(
- res.startswith("@user#7700 :white_check_mark: Your 3.11 eval job has completed with return code 0.")
+ res.startswith("@user#7700 :white_check_mark: Your 3.12 eval job has completed with return code 0.")
)
self.assertIn("Files with disallowed extensions can't be uploaded: **.disallowed**", res)
diff --git a/tests/bot/test_pagination.py b/tests/bot/test_pagination.py
deleted file mode 100644
index cf23f1948..000000000
--- a/tests/bot/test_pagination.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from unittest import TestCase
-
-from bot import pagination
-
-
-class LinePaginatorTests(TestCase):
- """Tests functionality of the `LinePaginator`."""
-
- def setUp(self):
- """Create a paginator for the test method."""
- self.paginator = pagination.LinePaginator(prefix="", suffix="", max_size=30,
- scale_to_size=50)
-
- def test_add_line_works_on_small_lines(self):
- """`add_line` should allow small lines to be added."""
- self.paginator.add_line("x" * (self.paginator.max_size - 3))
- # Note that the page isn't added to _pages until it's full.
- self.assertEqual(len(self.paginator._pages), 0)
-
- def test_add_line_works_on_long_lines(self):
- """After additional lines after `max_size` is exceeded should go on the next page."""
- self.paginator.add_line("x" * self.paginator.max_size)
- self.assertEqual(len(self.paginator._pages), 0)
-
- # Any additional lines should start a new page after `max_size` is exceeded.
- self.paginator.add_line("x")
- self.assertEqual(len(self.paginator._pages), 1)
-
- def test_add_line_continuation(self):
- """When `scale_to_size` is exceeded, remaining words should be split onto the next page."""
- self.paginator.add_line("zyz " * (self.paginator.scale_to_size//4 + 1))
- self.assertEqual(len(self.paginator._pages), 1)
-
- def test_add_line_no_continuation(self):
- """If adding a new line to an existing page would exceed `max_size`, it should start a new
- page rather than using continuation.
- """
- self.paginator.add_line("z" * (self.paginator.max_size - 3))
- self.paginator.add_line("z")
- self.assertEqual(len(self.paginator._pages), 1)
-
- def test_add_line_truncates_very_long_words(self):
- """`add_line` should truncate if a single long word exceeds `scale_to_size`."""
- self.paginator.add_line("x" * (self.paginator.scale_to_size + 1))
- # Note: item at index 1 is the truncated line, index 0 is prefix
- self.assertEqual(self.paginator._current_page[1], "x" * self.paginator.scale_to_size)
diff --git a/tests/bot/utils/test_services.py b/tests/bot/utils/test_services.py
deleted file mode 100644
index 3c9e037ce..000000000
--- a/tests/bot/utils/test_services.py
+++ /dev/null
@@ -1,90 +0,0 @@
-import logging
-import unittest
-from unittest.mock import AsyncMock, MagicMock, Mock, patch
-
-from aiohttp import ClientConnectorError
-
-from bot.utils.services import (
- FAILED_REQUEST_ATTEMPTS, MAX_PASTE_LENGTH, PasteTooLongError, PasteUploadError, send_to_paste_service
-)
-from tests.helpers import MockBot
-
-
-class PasteTests(unittest.IsolatedAsyncioTestCase):
- def setUp(self) -> None:
- patcher = patch("bot.instance", new=MockBot())
- self.bot = patcher.start()
- self.addCleanup(patcher.stop)
-
- @patch("bot.utils.services.URLs.paste_service", "https://paste_service.com/{key}")
- async def test_url_and_sent_contents(self):
- """Correct url was used and post was called with expected data."""
- response = MagicMock(
- json=AsyncMock(return_value={"key": ""})
- )
- self.bot.http_session.post.return_value.__aenter__.return_value = response
- self.bot.http_session.post.reset_mock()
- await send_to_paste_service("Content")
- self.bot.http_session.post.assert_called_once_with("https://paste_service.com/documents", data="Content")
-
- @patch("bot.utils.services.URLs.paste_service", "https://paste_service.com/{key}")
- async def test_paste_returns_correct_url_on_success(self):
- """Url with specified extension is returned on successful requests."""
- key = "paste_key"
- test_cases = (
- (f"https://paste_service.com/{key}.txt?noredirect", "txt"),
- (f"https://paste_service.com/{key}.py", "py"),
- (f"https://paste_service.com/{key}?noredirect", ""),
- )
- response = MagicMock(
- json=AsyncMock(return_value={"key": key})
- )
- self.bot.http_session.post.return_value.__aenter__.return_value = response
-
- for expected_output, extension in test_cases:
- with self.subTest(msg=f"Send contents with extension {extension!r}"):
- self.assertEqual(
- await send_to_paste_service("", extension=extension),
- expected_output
- )
-
- async def test_request_repeated_on_json_errors(self):
- """Json with error message and invalid json are handled as errors and requests repeated."""
- test_cases = ({"message": "error"}, {"unexpected_key": None}, {})
- self.bot.http_session.post.return_value.__aenter__.return_value = response = MagicMock()
- self.bot.http_session.post.reset_mock()
-
- for error_json in test_cases:
- with self.subTest(error_json=error_json):
- response.json = AsyncMock(return_value=error_json)
- with self.assertRaises(PasteUploadError):
- await send_to_paste_service("")
- self.assertEqual(self.bot.http_session.post.call_count, FAILED_REQUEST_ATTEMPTS)
-
- self.bot.http_session.post.reset_mock()
-
- async def test_request_repeated_on_connection_errors(self):
- """Requests are repeated in the case of connection errors."""
- self.bot.http_session.post = MagicMock(side_effect=ClientConnectorError(Mock(), Mock()))
- with self.assertRaises(PasteUploadError):
- await send_to_paste_service("")
- self.assertEqual(self.bot.http_session.post.call_count, FAILED_REQUEST_ATTEMPTS)
-
- async def test_general_error_handled_and_request_repeated(self):
- """All `Exception`s are handled, logged and request repeated."""
- self.bot.http_session.post = MagicMock(side_effect=Exception)
- with self.assertRaises(PasteUploadError):
- await send_to_paste_service("")
- self.assertEqual(self.bot.http_session.post.call_count, FAILED_REQUEST_ATTEMPTS)
- self.assertLogs("bot.utils", logging.ERROR)
-
- async def test_raises_error_on_too_long_input(self):
- """Ensure PasteTooLongError is raised if `contents` is longer than `MAX_PASTE_LENGTH`."""
- contents = "a" * (MAX_PASTE_LENGTH + 1)
- with self.assertRaises(PasteTooLongError):
- await send_to_paste_service(contents)
-
- async def test_raises_on_too_large_max_length(self):
- """Ensure ValueError is raised if `max_length` passed is greater than `MAX_PASTE_LENGTH`."""
- with self.assertRaises(ValueError):
- await send_to_paste_service("Hello World!", max_length=MAX_PASTE_LENGTH + 1)
diff --git a/tests/helpers.py b/tests/helpers.py
index 26ac42697..580848c25 100644
--- a/tests/helpers.py
+++ b/tests/helpers.py
@@ -6,6 +6,7 @@ import logging
import unittest.mock
from asyncio import AbstractEventLoop
from collections.abc import Iterable
+from contextlib import contextmanager
from functools import cached_property
import discord
@@ -664,3 +665,12 @@ class MockAsyncWebhook(CustomMockMixin, unittest.mock.MagicMock):
"""
spec_set = webhook_instance
additional_spec_asyncs = ("send", "edit", "delete", "execute")
+
+@contextmanager
+def no_create_task():
+ def side_effect(coro, *_, **__):
+ coro.close()
+
+ with unittest.mock.patch("pydis_core.utils.scheduling.create_task") as create_task:
+ create_task.side_effect = side_effect
+ yield
diff --git a/tests/test_helpers.py b/tests/test_helpers.py
index fa7d0eb44..3d4cb09e7 100644
--- a/tests/test_helpers.py
+++ b/tests/test_helpers.py
@@ -316,7 +316,6 @@ class MockObjectTests(unittest.TestCase):
class MyMock(helpers.CustomMockMixin, unittest.mock.MagicMock):
child_mock_type = unittest.mock.MagicMock
- pass
mock = MyMock()
unittest.mock.seal(mock)