diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/bot/exts/utils/snekbox/test_snekbox.py | 38 | ||||
| -rw-r--r-- | tests/bot/exts/utils/test_utils.py | 94 |
2 files changed, 116 insertions, 16 deletions
diff --git a/tests/bot/exts/utils/snekbox/test_snekbox.py b/tests/bot/exts/utils/snekbox/test_snekbox.py index 9cfd75df8..69262bf61 100644 --- a/tests/bot/exts/utils/snekbox/test_snekbox.py +++ b/tests/bot/exts/utils/snekbox/test_snekbox.py @@ -1,6 +1,7 @@ import asyncio import unittest from base64 import b64encode +from typing import get_args from unittest.mock import AsyncMock, MagicMock, Mock, call, create_autospec, patch from discord import AllowedMentions @@ -10,7 +11,7 @@ from pydis_core.utils.paste_service import MAX_PASTE_SIZE from bot import constants from bot.errors import LockedResourceError from bot.exts.utils import snekbox -from bot.exts.utils.snekbox import EvalJob, EvalResult, Snekbox +from bot.exts.utils.snekbox import EvalJob, EvalResult, Snekbox, SupportedPythonVersions from bot.exts.utils.snekbox._io import FileAttachment from tests.helpers import MockBot, MockContext, MockMember, MockMessage, MockReaction, MockUser @@ -21,6 +22,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase): self.bot = MockBot() self.cog = Snekbox(bot=self.bot) self.job = EvalJob.from_code("import random") + self.default_version = get_args(SupportedPythonVersions)[0] @staticmethod def code_args(code: str) -> tuple[EvalJob]: @@ -35,7 +37,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase): context_manager = MagicMock() context_manager.__aenter__.return_value = resp self.bot.http_session.post.return_value = context_manager - py_version = "3.12" + py_version = self.default_version job = EvalJob.from_code("import random").as_version(py_version) self.assertEqual(await self.cog.post_job(job), EvalResult("Hi", 137)) @@ -104,9 +106,13 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase): def test_eval_result_message(self): """EvalResult.get_message(), should return message.""" cases = ( - ("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", "")) + ("ERROR", None, (f"Your {self.default_version} eval job has failed", "ERROR", "")), + ( + "", + 128 + snekbox._eval.SIGKILL, + (f"Your {self.default_version} eval job timed out or ran out of memory", "", "") + ), + ("", 255, (f"Your {self.default_version} eval job has failed", "A fatal NsJail error occurred", "")) ) for stdout, returncode, expected in cases: exp_msg, exp_err, exp_files_err = expected @@ -178,8 +184,8 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase): mock_signals.return_value.name = "SIGTEST" result = EvalResult(stdout="", returncode=127) self.assertEqual( - result.get_status_message(EvalJob([], version="3.12")), - "Your 3.12 eval job has completed with return code 127 (SIGTEST)" + result.get_status_message(EvalJob([])), + f"Your {self.default_version} eval job has completed with return code 127 (SIGTEST)" ) def test_eval_result_status_emoji(self): @@ -253,7 +259,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.12", code=["MyAwesomeCode"]) + await self.cog.eval_command(self.cog, ctx=ctx, python_version=self.default_version, 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") @@ -267,7 +273,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.12", code=["MyAwesomeCode"]) + await self.cog.eval_command(self.cog, ctx=ctx, python_version=self.default_version, code=["MyAwesomeCode"]) expected_job = EvalJob.from_code("MyAwesomeFormattedCode") self.cog.send_job.assert_called_with(ctx, expected_job) @@ -311,7 +317,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase): ctx.send.assert_called_once() self.assertEqual( ctx.send.call_args.args[0], - ":warning: Your 3.12 eval job has completed " + f":warning: Your {self.default_version} eval job has completed " "with return code 0.\n\n```ansi\n[No output]\n```" ) allowed_mentions = ctx.send.call_args.kwargs["allowed_mentions"] @@ -335,13 +341,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.12") + job = EvalJob.from_code("MyAwesomeCode").as_version(self.default_version) await self.cog.send_job(ctx, job), ctx.send.assert_called_once() self.assertEqual( ctx.send.call_args.args[0], - ":white_check_mark: Your 3.12 eval job " + f":white_check_mark: Your {self.default_version} eval job " "has completed with return code 0." "\n\n```ansi\nWay too long beard\n```\nFull output: lookatmybeard.com" ) @@ -362,13 +368,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.12") + job = EvalJob.from_code("MyAwesomeCode").as_version(self.default_version) await self.cog.send_job(ctx, job), ctx.send.assert_called_once() self.assertEqual( ctx.send.call_args.args[0], - ":x: Your 3.12 eval job has completed with return code 127." + f":x: Your {self.default_version} eval job has completed with return code 127." "\n\n```ansi\nERROR\n```" ) @@ -395,13 +401,13 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase): mocked_filter_cog.filter_snekbox_output = AsyncMock(return_value=(False, disallowed_exts)) self.bot.get_cog.return_value = mocked_filter_cog - job = EvalJob.from_code("MyAwesomeCode").as_version("3.12") + job = EvalJob.from_code("MyAwesomeCode").as_version(self.default_version) await self.cog.send_job(ctx, job), ctx.send.assert_called_once() res = ctx.send.call_args.args[0] self.assertTrue( - res.startswith(":white_check_mark: Your 3.12 eval job has completed with return code 0.") + res.startswith(f":white_check_mark: Your {self.default_version} eval job has completed with return code 0.") ) self.assertIn("Files with disallowed extensions can't be uploaded: **.disallowed, .disallowed2, ...**", res) diff --git a/tests/bot/exts/utils/test_utils.py b/tests/bot/exts/utils/test_utils.py new file mode 100644 index 000000000..9b8ea4ade --- /dev/null +++ b/tests/bot/exts/utils/test_utils.py @@ -0,0 +1,94 @@ +import unittest + +from discord import Colour, Embed +from discord.ext.commands import BadArgument + +from bot.exts.utils.utils import Utils, ZEN_OF_PYTHON +from tests.helpers import MockBot, MockContext + + +class ZenTests(unittest.IsolatedAsyncioTestCase): + """ Tests for the `!zen` command. """ + + + def setUp(self): + self.bot = MockBot() + self.cog = Utils(self.bot) + self.ctx = MockContext() + + self.zen_list = ZEN_OF_PYTHON.splitlines() + self.template_embed = Embed(colour=Colour.og_blurple(), title="The Zen of Python", description=ZEN_OF_PYTHON) + + + + async def test_zen_without_arguments(self): + """ Tests if the `!zen` command reacts properly to no arguments. """ + self.template_embed.title += ", by Tim Peters" + + + await self.cog.zen.callback(self.cog,self.ctx, search_value = None) + self.ctx.send.assert_called_once_with(embed=self.template_embed) + + async def test_zen_with_valid_index(self): + """ Tests if the `!zen` command reacts properly to a valid index as an argument. """ + expected_results = { + 0: ("The Zen of Python (line 0):", "Beautiful is better than ugly."), + 10: ("The Zen of Python (line 10):", "Unless explicitly silenced."), + 18: ("The Zen of Python (line 18):", "Namespaces are one honking great idea -- let's do more of those!"), + -1: ("The Zen of Python (line 18):", "Namespaces are one honking great idea -- let's do more of those!"), + -10: ("The Zen of Python (line 9):", "Errors should never pass silently."), + -19: ("The Zen of Python (line 0):", "Beautiful is better than ugly.") + + } + + for index, (title, description) in expected_results.items(): + self.template_embed.title = title + self.template_embed.description = description + ctx = MockContext() + with self.subTest(index = index, expected_title=title, expected_description = description): + await self.cog.zen.callback(self.cog, ctx, search_value = str(index)) + ctx.send.assert_called_once_with(embed = self.template_embed) + + + + async def test_zen_with_invalid_index(self): + """ Tests if the `!zen` command reacts properly to an out-of-bounds index as an argument. """ + # Negative index + with self.subTest(index = -20), self.assertRaises(BadArgument): + await self.cog.zen.callback(self.cog, self.ctx, search_value="-20") + + # Positive index + with self.subTest(index = len(ZEN_OF_PYTHON)), self.assertRaises(BadArgument): + await self.cog.zen.callback(self.cog, self.ctx, search_value=str(len(ZEN_OF_PYTHON))) + + async def test_zen_with_valid_slices(self): + """ Tests if the `!zen` command reacts properly to valid slices for indexing as an argument. """ + + expected_results = { + "0:19": ("The Zen of Python, by Tim Peters", "\n".join(self.zen_list)), + ":": ("The Zen of Python, by Tim Peters", "\n".join(self.zen_list)), + "::": ("The Zen of Python, by Tim Peters", "\n".join(self.zen_list)), + "1:": ("The Zen of Python (lines 1-18):", "\n".join(self.zen_list[1:])), + "-2:-1": ("The Zen of Python (line 17):", self.zen_list[17]), + "0:-1": ("The Zen of Python (lines 0-17):", "\n".join(self.zen_list[0:-1])), + "10:13": ("The Zen of Python (lines 10-12):", "\n".join(self.zen_list[10:13])), + "::-1": ("The Zen of Python (step size -1):", "\n".join(self.zen_list[::-1])), + "10:5:-1": ("The Zen of Python (lines 6-10, step size -1):", "\n".join(self.zen_list[10:5:-1])), + } + + for input_slice, (title, description) in expected_results.items(): + self.template_embed.title = title + self.template_embed.description = description + + ctx = MockContext() + with self.subTest(input_slice=input_slice, expected_title=title, expected_description=description): + await self.cog.zen.callback(self.cog, ctx, search_value=input_slice) + ctx.send.assert_called_once_with(embed = self.template_embed) + + async def test_zen_with_invalid_slices(self): + """ Tests if the `!zen` command reacts properly to invalid slices for indexing as an argument. """ + slices= ["19:18", "10:9", "-1:-2", "0:-100", "::0", "1:2:-1", "-5:-4:-1"] + + for input_slice in slices: + with self.subTest(input_slice = input_slice), self.assertRaises(BadArgument): + await self.cog.zen.callback(self.cog, self.ctx, search_value=input_slice) |