From 0799c769a9b07dd47f407f9368e350a5269bd036 Mon Sep 17 00:00:00 2001 From: wookie184 Date: Tue, 2 Apr 2024 18:52:59 +0100 Subject: Improve accuracy (and efficiency) of MockContext --- tests/helpers.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'tests') diff --git a/tests/helpers.py b/tests/helpers.py index 580848c25..c51a82a9d 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -500,10 +500,12 @@ class MockContext(CustomMockMixin, unittest.mock.MagicMock): super().__init__(**kwargs) self.me = kwargs.get("me", MockMember()) self.bot = kwargs.get("bot", MockBot()) - self.guild = kwargs.get("guild", MockGuild()) - self.author = kwargs.get("author", MockMember()) - self.channel = kwargs.get("channel", MockTextChannel()) - self.message = kwargs.get("message", MockMessage()) + + self.message = kwargs.get("message", MockMessage(guild=self.guild)) + self.author = kwargs.get("author", self.message.author) + self.channel = kwargs.get("channel", self.message.channel) + self.guild = kwargs.get("guild", self.channel.guild) + self.invoked_from_error_handler = kwargs.get("invoked_from_error_handler", False) @@ -519,10 +521,12 @@ class MockInteraction(CustomMockMixin, unittest.mock.MagicMock): super().__init__(**kwargs) self.me = kwargs.get("me", MockMember()) self.client = kwargs.get("client", MockBot()) - self.guild = kwargs.get("guild", MockGuild()) - self.user = kwargs.get("user", MockMember()) - self.channel = kwargs.get("channel", MockTextChannel()) - self.message = kwargs.get("message", MockMessage()) + + self.message = kwargs.get("message", MockMessage(guild=self.guild)) + self.user = kwargs.get("user", self.message.author) + self.channel = kwargs.get("channel", self.message.channel) + self.guild = kwargs.get("guild", self.channel.guild) + self.invoked_from_error_handler = kwargs.get("invoked_from_error_handler", False) -- cgit v1.2.3 From 7909349bc77a93031995d52c70163911b0f11c98 Mon Sep 17 00:00:00 2001 From: wookie184 Date: Tue, 2 Apr 2024 19:08:09 +0100 Subject: Reply to eval commands instead of using a mention where possible --- bot/exts/utils/snekbox/_cog.py | 18 ++++++++++++++++-- tests/bot/exts/utils/snekbox/test_snekbox.py | 15 ++++----------- 2 files changed, 20 insertions(+), 13 deletions(-) (limited to 'tests') diff --git a/bot/exts/utils/snekbox/_cog.py b/bot/exts/utils/snekbox/_cog.py index eedac810a..0b96e78d3 100644 --- a/bot/exts/utils/snekbox/_cog.py +++ b/bot/exts/utils/snekbox/_cog.py @@ -393,7 +393,7 @@ class Snekbox(Cog): output, paste_link = await self.format_output(output) status_msg = result.get_status_message(job) - msg = f"{ctx.author.mention} {result.status_emoji} {status_msg}.\n" + msg = f"{result.status_emoji} {status_msg}.\n" # This is done to make sure the last line of output contains the error # and the error is not manually printed by the author with a syntax error. @@ -435,7 +435,21 @@ class Snekbox(Cog): files = [f.to_file() for f in allowed if f not in text_files] allowed_mentions = AllowedMentions(everyone=False, roles=False, users=[ctx.author]) view = self.build_python_version_switcher_view(job.version, ctx, job) - response = await ctx.send(msg, allowed_mentions=allowed_mentions, view=view, files=files) + + if ctx.message.channel == ctx.channel: + # Don't fail if the command invoking message was deleted. + message = ctx.message.to_reference(fail_if_not_exists=False) + response = await ctx.send( + msg, + allowed_mentions=allowed_mentions, + view=view, + files=files, + reference=message + ) + else: + # The command was directed so a reply wont work, send a normal message with a mention. + msg = f"{ctx.author.mention} {msg}" + response = await ctx.send(msg, allowed_mentions=allowed_mentions, view=view, files=files) view.message = response log.info(f"{ctx.author}'s {job.name} job had a return code of {result.returncode}") diff --git a/tests/bot/exts/utils/snekbox/test_snekbox.py b/tests/bot/exts/utils/snekbox/test_snekbox.py index d057b284d..08925afaa 100644 --- a/tests/bot/exts/utils/snekbox/test_snekbox.py +++ b/tests/bot/exts/utils/snekbox/test_snekbox.py @@ -292,7 +292,6 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase): async def test_send_job(self): """Test the send_job function.""" ctx = MockContext() - ctx.message = MockMessage() ctx.send = AsyncMock() ctx.author = MockUser(mention="@LemonLemonishBeard#0042") @@ -311,7 +310,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase): ctx.send.assert_called_once() self.assertEqual( ctx.send.call_args.args[0], - "@LemonLemonishBeard#0042 :warning: Your 3.12 eval job has completed " + ":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"] @@ -325,9 +324,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase): async def test_send_job_with_paste_link(self): """Test the send_job function with a too long output that generate a paste link.""" ctx = MockContext() - ctx.message = MockMessage() ctx.send = AsyncMock() - ctx.author.mention = "@LemonLemonishBeard#0042" eval_result = EvalResult("Way too long beard", 0) self.cog.post_job = AsyncMock(return_value=eval_result) @@ -343,7 +340,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase): ctx.send.assert_called_once() self.assertEqual( ctx.send.call_args.args[0], - "@LemonLemonishBeard#0042 :white_check_mark: Your 3.12 eval job " + ":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" ) @@ -354,9 +351,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase): async def test_send_job_with_non_zero_eval(self): """Test the send_job function with a code returning a non-zero code.""" ctx = MockContext() - ctx.message = MockMessage() ctx.send = AsyncMock() - ctx.author.mention = "@LemonLemonishBeard#0042" eval_result = EvalResult("ERROR", 127) self.cog.post_job = AsyncMock(return_value=eval_result) @@ -372,7 +367,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase): ctx.send.assert_called_once() self.assertEqual( ctx.send.call_args.args[0], - "@LemonLemonishBeard#0042 :x: Your 3.12 eval job has completed with return code 127." + ":x: Your 3.12 eval job has completed with return code 127." "\n\n```\nERROR\n```" ) @@ -382,9 +377,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase): async def test_send_job_with_disallowed_file_ext(self): """Test send_job with disallowed file extensions.""" ctx = MockContext() - ctx.message = MockMessage() ctx.send = AsyncMock() - ctx.author.mention = "@user#7700" files = [ FileAttachment("test.disallowed2", b"test"), @@ -407,7 +400,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase): ctx.send.assert_called_once() res = ctx.send.call_args.args[0] self.assertTrue( - res.startswith("@user#7700 :white_check_mark: Your 3.12 eval job has completed with return code 0.") + res.startswith(":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, .disallowed2, ...**", res) -- cgit v1.2.3 From 5b209b1c68d6f688477a81d1cdfacac4053f6586 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Mon, 13 May 2024 13:50:20 +0100 Subject: Move from sentry_sdk.push_scope to sentry_sdk.new_scope --- bot/bot.py | 4 ++-- bot/exts/backend/error_handler.py | 4 ++-- tests/bot/exts/backend/test_error_handler.py | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'tests') diff --git a/bot/bot.py b/bot/bot.py index fa3617f1b..35dbd1ba4 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -6,7 +6,7 @@ import aiohttp from discord.errors import Forbidden from pydis_core import BotBase from pydis_core.utils.error_handling import handle_forbidden_from_block -from sentry_sdk import push_scope, start_transaction +from sentry_sdk import new_scope, start_transaction from bot import constants, exts from bot.log import get_logger @@ -71,7 +71,7 @@ class Bot(BotBase): self.stats.incr(f"errors.event.{event}") - with push_scope() as scope: + with new_scope() as scope: scope.set_tag("event", event) scope.set_extra("args", args) scope.set_extra("kwargs", kwargs) diff --git a/bot/exts/backend/error_handler.py b/bot/exts/backend/error_handler.py index 5cf07613d..352be313d 100644 --- a/bot/exts/backend/error_handler.py +++ b/bot/exts/backend/error_handler.py @@ -7,7 +7,7 @@ from discord.ext.commands import ChannelNotFound, Cog, Context, TextChannelConve from pydis_core.site_api import ResponseCodeError from pydis_core.utils.error_handling import handle_forbidden_from_block from pydis_core.utils.interactions import DeleteMessageButton, ViewWithUserAndRoleCheck -from sentry_sdk import push_scope +from sentry_sdk import new_scope from bot.bot import Bot from bot.constants import Colours, Icons, MODERATION_ROLES @@ -400,7 +400,7 @@ class ErrorHandler(Cog): ctx.bot.stats.incr("errors.unexpected") - with push_scope() as scope: + with new_scope() as scope: scope.user = { "id": ctx.author.id, "username": str(ctx.author) diff --git a/tests/bot/exts/backend/test_error_handler.py b/tests/bot/exts/backend/test_error_handler.py index dbc62270b..85dc33999 100644 --- a/tests/bot/exts/backend/test_error_handler.py +++ b/tests/bot/exts/backend/test_error_handler.py @@ -495,26 +495,26 @@ class IndividualErrorHandlerTests(unittest.IsolatedAsyncioTestCase): else: log_mock.debug.assert_called_once() - @patch("bot.exts.backend.error_handler.push_scope") + @patch("bot.exts.backend.error_handler.new_scope") @patch("bot.exts.backend.error_handler.log") - async def test_handle_unexpected_error(self, log_mock, push_scope_mock): + async def test_handle_unexpected_error(self, log_mock, new_scope_mock): """Should `ctx.send` this error, error log this and sent to Sentry.""" for case in (None, MockGuild()): with self.subTest(guild=case): self.ctx.reset_mock() log_mock.reset_mock() - push_scope_mock.reset_mock() + new_scope_mock.reset_mock() scope_mock = Mock() # Mock `with push_scope_mock() as scope:` - push_scope_mock.return_value.__enter__.return_value = scope_mock + new_scope_mock.return_value.__enter__.return_value = scope_mock self.ctx.guild = case await self.cog.handle_unexpected_error(self.ctx, errors.CommandError()) self.ctx.send.assert_awaited_once() log_mock.error.assert_called_once() - push_scope_mock.assert_called_once() + new_scope_mock.assert_called_once() set_tag_calls = [ call("command", self.ctx.command.qualified_name), -- cgit v1.2.3 From d7f158bb477bc7b8bfc42180a1a73c8d6b1bd8fc Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Sat, 18 May 2024 04:07:02 +0100 Subject: Update tests for new autonomination threshold logic --- .../bot/exts/recruitment/talentpool/test_review.py | 40 +++++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) (limited to 'tests') diff --git a/tests/bot/exts/recruitment/talentpool/test_review.py b/tests/bot/exts/recruitment/talentpool/test_review.py index 25622e91f..8ec384bb2 100644 --- a/tests/bot/exts/recruitment/talentpool/test_review.py +++ b/tests/bot/exts/recruitment/talentpool/test_review.py @@ -3,7 +3,7 @@ from datetime import UTC, datetime, timedelta from unittest.mock import AsyncMock, Mock, patch from bot.exts.recruitment.talentpool import _review -from tests.helpers import MockBot, MockMember, MockMessage, MockTextChannel +from tests.helpers import MockBot, MockMember, MockMessage, MockReaction, MockTextChannel class AsyncIterator: @@ -63,8 +63,10 @@ class ReviewerTests(unittest.IsolatedAsyncioTestCase): """Tests for the `is_ready_for_review` function.""" too_recent = datetime.now(UTC) - timedelta(hours=1) not_too_recent = datetime.now(UTC) - timedelta(days=7) + ticket_reaction = MockReaction(users=[self.bot_user], emoji="\N{TICKET}") + cases = ( - # Only one review, and not too recent, so ready. + # Only one active review, and not too recent, so ready. ( [ MockMessage(author=self.bot_user, content="wookie for Helper!", created_at=not_too_recent), @@ -75,7 +77,7 @@ class ReviewerTests(unittest.IsolatedAsyncioTestCase): True, ), - # Three reviews, so not ready. + # Three active reviews, so not ready. ( [ MockMessage(author=self.bot_user, content="Chrisjl for Helper!", created_at=not_too_recent), @@ -86,7 +88,7 @@ class ReviewerTests(unittest.IsolatedAsyncioTestCase): False, ), - # Only one review, but too recent, so not ready. + # Only one active review, but too recent, so not ready. ( [ MockMessage(author=self.bot_user, content="Chrisjl for Helper!", created_at=too_recent), @@ -95,7 +97,7 @@ class ReviewerTests(unittest.IsolatedAsyncioTestCase): False, ), - # Only two reviews, and not too recent, so ready. + # Only two active reviews, and not too recent, so ready. ( [ MockMessage(author=self.bot_user, content="Not a review", created_at=too_recent), @@ -107,6 +109,34 @@ class ReviewerTests(unittest.IsolatedAsyncioTestCase): True, ), + # Over the active threshold, but below the total threshold + ( + [ + MockMessage( + author=self.bot_user, + content="joe for Helper!", + created_at=not_too_recent, + reactions=[ticket_reaction] + ) + ] * 6, + not_too_recent.timestamp(), + True + ), + + # Over the total threshold + ( + [ + MockMessage( + author=self.bot_user, + content="joe for Helper!", + created_at=not_too_recent, + reactions=[ticket_reaction] + ) + ] * 11, + not_too_recent.timestamp(), + False + ), + # No messages, so ready. ([], None, True), ) -- cgit v1.2.3