예제 #1
0
    async def test_relay_message_correctly_relays_content_and_attachments(
            self):
        """The `relay_message` method should correctly relay message content and attachments."""
        send_webhook_path = f"{MODULE_PATH}.DuckPond.send_webhook"
        send_attachments_path = f"{MODULE_PATH}.send_attachments"

        self.cog.webhook = helpers.MockAsyncWebhook()

        test_values = (
            (helpers.MockMessage(clean_content="",
                                 attachments=[]), False, False),
            (helpers.MockMessage(clean_content="message",
                                 attachments=[]), True, False),
            (helpers.MockMessage(clean_content="",
                                 attachments=["attachment"]), False, True),
            (helpers.MockMessage(clean_content="message",
                                 attachments=["attachment"]), True, True),
        )

        for message, expect_webhook_call, expect_attachment_call in test_values:
            with patch(send_webhook_path,
                       new_callable=helpers.AsyncMock) as send_webhook:
                with patch(send_attachments_path,
                           new_callable=helpers.AsyncMock) as send_attachments:
                    with self.subTest(clean_content=message.clean_content,
                                      attachments=message.attachments):
                        await self.cog.relay_message(message)

                        self.assertEqual(expect_webhook_call,
                                         send_webhook.called)
                        self.assertEqual(expect_attachment_call,
                                         send_attachments.called)

                        message.add_reaction.assert_called_once_with(
                            self.checkmark_emoji)
예제 #2
0
    async def test_has_green_checkmark_correctly_detects_presence_of_green_checkmark_emoji(
            self):
        """The `has_green_checkmark` method should only return `True` if one is present."""
        test_cases = (
            ("No reactions", helpers.MockMessage(),
             False), ("No green check mark reactions",
                      helpers.MockMessage(reactions=[
                          helpers.MockReaction(emoji=self.unicode_duck_emoji,
                                               users=[self.bot.user]),
                          helpers.MockReaction(emoji=self.thumbs_up_emoji,
                                               users=[self.bot.user])
                      ]), False),
            ("Green check mark reaction, but not from our bot",
             helpers.MockMessage(reactions=[
                 helpers.MockReaction(emoji=self.unicode_duck_emoji,
                                      users=[self.bot.user]),
                 helpers.MockReaction(emoji=self.checkmark_emoji,
                                      users=[self.staff_member])
             ]), False),
            ("Green check mark reaction, with one from the bot",
             helpers.MockMessage(reactions=[
                 helpers.MockReaction(emoji=self.unicode_duck_emoji,
                                      users=[self.bot.user]),
                 helpers.MockReaction(emoji=self.checkmark_emoji,
                                      users=[self.staff_member, self.bot.user])
             ]), True))

        for description, message, expected_return in test_cases:
            actual_return = await self.cog.has_green_checkmark(message)
            with self.subTest(test_case=description,
                              expected_return=expected_return,
                              actual_return=actual_return):
                self.assertEqual(expected_return, actual_return)
예제 #3
0
    async def test_sync_confirmation_context_redirect(self):
        """If ctx is given, a new message should be sent and author should be ctx's author."""
        mock_member = helpers.MockMember()
        subtests = (
            (None, self.bot.user, None),
            (helpers.MockContext(author=mock_member), mock_member,
             helpers.MockMessage()),
        )

        for ctx, author, message in subtests:
            with self.subTest(ctx=ctx, author=author, message=message):
                if ctx is not None:
                    ctx.send.return_value = message

                # Make sure `_get_diff` returns a MagicMock, not an AsyncMock
                self.syncer._get_diff.return_value = mock.MagicMock()

                self.syncer._get_confirmation_result = mock.AsyncMock(
                    return_value=(False, None))

                guild = helpers.MockGuild()
                await self.syncer.sync(guild, ctx)

                if ctx is not None:
                    ctx.send.assert_called_once()

                self.syncer._get_confirmation_result.assert_called_once()
                self.assertEqual(
                    self.syncer._get_confirmation_result.call_args[0][1],
                    author)
                self.assertEqual(
                    self.syncer._get_confirmation_result.call_args[0][2],
                    message)
예제 #4
0
 def test_bot_latency_correct_context(self, create_embed, constants):
     """Ping should return correct ping responses dependent on message sent."""
     ctx = helpers.MockContext()
     ctx.message = helpers.MockMessage()
     ctx.message.created_at = "D"
     coroutine = self.cog.ping.callback(self.cog, ctx)
     self.assertFalse(asyncio.run(coroutine))
예제 #5
0
    async def test_confirmation_result_large_diff(self):
        """Should return True if confirmed and False if _send_prompt fails or aborted."""
        author = helpers.MockMember()
        mock_message = helpers.MockMessage()

        subtests = (
            (True, mock_message, True, "confirmed"),
            (False, None, False, "_send_prompt failed"),
            (False, mock_message, False, "aborted"),
        )

        for expected_result, expected_message, confirmed, msg in subtests:  # pragma: no cover
            with self.subTest(msg=msg):
                self.syncer._send_prompt = mock.AsyncMock(
                    return_value=expected_message)
                self.syncer._wait_for_confirmation = mock.AsyncMock(
                    return_value=confirmed)

                coro = self.syncer._get_confirmation_result(4, author)
                actual_result, actual_message = await coro

                self.syncer._send_prompt.assert_called_once_with(
                    None)  # message defaults to None
                self.assertIs(actual_result, expected_result)
                self.assertEqual(actual_message, expected_message)

                if expected_message:
                    self.syncer._wait_for_confirmation.assert_called_once_with(
                        author, expected_message)
예제 #6
0
    async def test_sync_respects_confirmation_result(self):
        """The sync should abort if confirmation fails and continue if confirmed."""
        mock_message = helpers.MockMessage()
        subtests = (
            (True, mock_message),
            (False, None),
        )

        for confirmed, message in subtests:
            with self.subTest(confirmed=confirmed):
                self.syncer._sync.reset_mock()
                self.syncer._get_diff.reset_mock()

                diff = _Diff({1, 2, 3}, {4, 5}, None)
                self.syncer._get_diff.return_value = diff
                self.syncer._get_confirmation_result = mock.AsyncMock(
                    return_value=(confirmed, message))

                guild = helpers.MockGuild()
                await self.syncer.sync(guild)

                self.syncer._get_diff.assert_called_once_with(guild)
                self.syncer._get_confirmation_result.assert_called_once()

                if confirmed:
                    self.syncer._sync.assert_called_once_with(diff)
                else:
                    self.syncer._sync.assert_not_called()
예제 #7
0
    async def test_relay_message_handles_attachment_http_error(
            self, send_attachments, send_webhook):
        """The `relay_message` method should handle irretrievable attachments."""
        message = helpers.MockMessage(clean_content="message",
                                      attachments=["attachment"])

        self.cog.webhook = helpers.MockAsyncWebhook()
        log = logging.getLogger("bot.cogs.duck_pond")

        side_effect = discord.HTTPException(MagicMock(), "")
        send_attachments.side_effect = side_effect
        with self.subTest(side_effect=type(side_effect).__name__):
            with self.assertLogs(logger=log,
                                 level=logging.ERROR) as log_watcher:
                await self.cog.relay_message(message)

            send_webhook.assert_called_once_with(
                content=message.clean_content,
                username=message.author.display_name,
                avatar_url=message.author.avatar_url)

            self.assertEqual(len(log_watcher.records), 1)

            record = log_watcher.records[0]
            self.assertEqual(record.levelno, logging.ERROR)
예제 #8
0
    async def test_send_prompt_edits_and_returns_message(self):
        """The given message should be edited to display the prompt and then should be returned."""
        msg = helpers.MockMessage()
        ret_val = await self.syncer._send_prompt(msg)

        msg.edit.assert_called_once()
        self.assertIn("content", msg.edit.call_args[1])
        self.assertEqual(ret_val, msg)
예제 #9
0
 def test_bot_latency_correct_time(self, create_embed, constants):
     """Ping should return correct ping responses dependent on message sent."""
     ctx = helpers.MockContext()
     ctx.message = helpers.MockMessage()
     timestamp = 1587263832
     ctx.message.created_at = datetime.fromtimestamp(timestamp)
     self.assertEqual(
         information.time_difference_milliseconds(datetime.fromtimestamp(1587263836), ctx.message), 4000)
예제 #10
0
    def test_reaction_check_for_invalid_reactions(self):
        """Should return False for invalid reaction events."""
        valid_emoji = self.syncer._REACTION_EMOJIS[0]
        subtests = (
            (
                helpers.MockMember(id=77),
                *self.get_message_reaction(valid_emoji),
                helpers.MockMember(id=43, roles=[self.core_dev_role]),
                "users are not identical",
            ),
            (
                helpers.MockMember(id=77, bot=True),
                *self.get_message_reaction(valid_emoji),
                helpers.MockMember(id=43),
                "reactor lacks the core-dev role",
            ),
            (
                helpers.MockMember(id=77, bot=True,
                                   roles=[self.core_dev_role]),
                *self.get_message_reaction(valid_emoji),
                helpers.MockMember(id=77, bot=True,
                                   roles=[self.core_dev_role]),
                "reactor is a bot",
            ),
            (
                helpers.MockMember(id=77),
                helpers.MockMessage(id=95),
                helpers.MockReaction(emoji=valid_emoji,
                                     message=helpers.MockMessage(id=26)),
                helpers.MockMember(id=77),
                "messages are not identical",
            ),
            (
                helpers.MockMember(id=77),
                *self.get_message_reaction("InVaLiD"),
                helpers.MockMember(id=77),
                "emoji is invalid",
            ),
        )

        for *args, msg in subtests:
            kwargs = dict(zip(("author", "message", "reaction", "user"), args))
            with self.subTest(**kwargs, msg=msg):
                ret_val = self.syncer._reaction_check(*args)
                self.assertFalse(ret_val)
예제 #11
0
    async def test_embedjson_command(self):
        context = helpers.MockContext()

        await self.cog.embed_json(self.cog, context, message=helpers.MockMessage())

        self.assertEqual(
            context.send.call_args.kwargs["embed"].description[:61],
            '```json\n<MagicMock name="mock.embeds.__getitem__().to_dict()"',
        )
예제 #12
0
    async def test_sync_message_edited(self):
        """The message should be edited if one was sent, even if the sync has an API error."""
        subtests = (
            (None, None, False),
            (helpers.MockMessage(), None, True),
            (helpers.MockMessage(), ResponseCodeError(mock.MagicMock()), True),
        )

        for message, side_effect, should_edit in subtests:
            with self.subTest(message=message, side_effect=side_effect, should_edit=should_edit):
                TestSyncer._sync.side_effect = side_effect
                ctx = helpers.MockContext()
                ctx.send.return_value = message

                await TestSyncer.sync(self.guild, ctx)

                if should_edit:
                    message.edit.assert_called_once()
                    self.assertIn("content", message.edit.call_args[1])
예제 #13
0
    def mock_get_channel(self):
        """Fixture to return a mock channel and message for when `get_channel` is used."""
        self.bot.reset_mock()

        mock_channel = helpers.MockTextChannel()
        mock_message = helpers.MockMessage()

        mock_channel.send.return_value = mock_message
        self.bot.get_channel.return_value = mock_channel

        return mock_channel, mock_message
예제 #14
0
    async def test_sync_message_edited(self):
        """The message should be edited if one was sent, even if the sync has an API error."""
        subtests = (
            (None, None, False),
            (helpers.MockMessage(), None, True),
            (helpers.MockMessage(), ResponseCodeError(mock.MagicMock()), True),
        )

        for message, side_effect, should_edit in subtests:
            with self.subTest(message=message,
                              side_effect=side_effect,
                              should_edit=should_edit):
                self.syncer._sync.side_effect = side_effect
                self.syncer._get_confirmation_result = mock.AsyncMock(
                    return_value=(True, message))

                guild = helpers.MockGuild()
                await self.syncer.sync(guild)

                if should_edit:
                    message.edit.assert_called_once()
                    self.assertIn("content", message.edit.call_args[1])
예제 #15
0
    async def test_sync_message_sent(self):
        """If ctx is given, a new message should be sent."""
        subtests = (
            (None, None),
            (helpers.MockContext(), helpers.MockMessage()),
        )

        for ctx, message in subtests:
            with self.subTest(ctx=ctx, message=message):
                await TestSyncer.sync(self.guild, ctx)

                if ctx is not None:
                    ctx.send.assert_called_once()
예제 #16
0
    def _raw_reaction_mocks(self, channel_id, message_id, user_id):
        """Sets up mocks for tests of the `on_raw_reaction_add` event listener."""
        channel = helpers.MockTextChannel(id=channel_id)
        self.bot.get_all_channels.return_value = (channel,)

        message = helpers.MockMessage(id=message_id)

        channel.fetch_message.return_value = message

        member = helpers.MockMember(id=user_id, roles=[self.staff_role])
        message.guild.members = (member,)

        payload = MagicMock(channel_id=channel_id, message_id=message_id, user_id=user_id)

        return channel, message, member, payload
예제 #17
0
    async def test_on_raw_reaction_remove_prevents_removal_of_green_checkmark_depending_on_the_duck_count(
            self):
        """The `on_raw_reaction_remove` listener prevents removal of the check mark on messages with enough ducks."""
        checkmark = helpers.MockPartialEmoji(name=self.checkmark_emoji)

        message = helpers.MockMessage(id=1234)

        channel = helpers.MockTextChannel(id=98765)
        channel.fetch_message.return_value = message

        self.bot.get_all_channels.return_value = (channel, )

        payload = MagicMock(channel_id=channel.id,
                            message_id=message.id,
                            emoji=checkmark)

        test_cases = (
            (constants.DuckPond.threshold - 1, False),
            (constants.DuckPond.threshold, True),
            (constants.DuckPond.threshold + 1, True),
        )
        for duck_count, should_re_add_checkmark in test_cases:
            with patch(f"{MODULE_PATH}.DuckPond.count_ducks",
                       new_callable=helpers.AsyncMock) as count_ducks:
                count_ducks.return_value = duck_count
                with self.subTest(
                        duck_count=duck_count,
                        should_re_add_checkmark=should_re_add_checkmark):
                    await self.cog.on_raw_reaction_remove(payload)

                    # Check if we fetched the message
                    channel.fetch_message.assert_called_once_with(message.id)

                    # Check if we actually counted the number of ducks
                    count_ducks.assert_called_once_with(message)

                    has_re_added_checkmark = message.add_reaction.called
                    self.assertEqual(should_re_add_checkmark,
                                     has_re_added_checkmark)

                    if should_re_add_checkmark:
                        message.add_reaction.assert_called_once_with(
                            self.checkmark_emoji)
                        message.add_reaction.reset_mock()

                    # reset mocks
                    channel.fetch_message.reset_mock()
                    message.reset_mock()
예제 #18
0
파일: test_helpers.py 프로젝트: sapanz/bot
    def test_mocks_rejects_access_to_attributes_not_part_of_spec(self):
        """Accessing attributes that are invalid for the objects they mock should fail."""
        mocks = (
            helpers.MockGuild(),
            helpers.MockRole(),
            helpers.MockMember(),
            helpers.MockBot(),
            helpers.MockContext(),
            helpers.MockTextChannel(),
            helpers.MockMessage(),
        )

        for mock in mocks:
            with self.subTest(mock=mock):
                with self.assertRaises(AttributeError):
                    mock.the_cake_is_a_lie
예제 #19
0
    async def test_relay_message_handles_irretrievable_attachment_exceptions(self, send_attachments):
        """The `relay_message` method should handle irretrievable attachments."""
        message = helpers.MockMessage(clean_content="message", attachments=["attachment"])
        side_effects = (discord.errors.Forbidden(MagicMock(), ""), discord.errors.NotFound(MagicMock(), ""))

        self.cog.webhook = helpers.MockAsyncWebhook()
        log = logging.getLogger("bot.cogs.duck_pond")

        for side_effect in side_effects:  # pragma: no cover
            send_attachments.side_effect = side_effect
            with patch(f"{MODULE_PATH}.DuckPond.send_webhook", new_callable=AsyncMock) as send_webhook:
                with self.subTest(side_effect=type(side_effect).__name__):
                    with self.assertNotLogs(logger=log, level=logging.ERROR):
                        await self.cog.relay_message(message)

                    self.assertEqual(send_webhook.call_count, 2)
예제 #20
0
    async def test_wait_for_confirmation(self):
        """The message should always be edited and only return True if the emoji is a check mark."""
        subtests = (
            (constants.Emojis.check_mark, True, None),
            ("InVaLiD", False, None),
            (None, False, asyncio.TimeoutError),
        )

        for emoji, ret_val, side_effect in subtests:
            for bot in (True, False):
                with self.subTest(emoji=emoji,
                                  ret_val=ret_val,
                                  side_effect=side_effect,
                                  bot=bot):
                    # Set up mocks
                    message = helpers.MockMessage()
                    member = helpers.MockMember(bot=bot)

                    self.bot.wait_for.reset_mock()
                    self.bot.wait_for.return_value = (helpers.MockReaction(
                        emoji=emoji), None)
                    self.bot.wait_for.side_effect = side_effect

                    # Call the function
                    actual_return = await self.syncer._wait_for_confirmation(
                        member, message)

                    # Perform assertions
                    self.bot.wait_for.assert_called_once()
                    self.assertIn("reaction_add",
                                  self.bot.wait_for.call_args[0])

                    message.edit.assert_called_once()
                    kwargs = message.edit.call_args[1]
                    self.assertIn("content", kwargs)

                    # Core devs should only be mentioned if the author is a bot.
                    if bot:
                        self.assertIn(self.syncer._CORE_DEV_MENTION,
                                      kwargs["content"])
                    else:
                        self.assertNotIn(self.syncer._CORE_DEV_MENTION,
                                         kwargs["content"])

                    self.assertIs(actual_return, ret_val)
예제 #21
0
    async def test_confirmation_result_small_diff(self):
        """Should always return True and the given message if the diff size is too small."""
        author = helpers.MockMember()
        expected_message = helpers.MockMessage()

        for size in (3, 2):  # pragma: no cover
            with self.subTest(size=size):
                self.syncer._send_prompt = mock.AsyncMock()
                self.syncer._wait_for_confirmation = mock.AsyncMock()

                coro = self.syncer._get_confirmation_result(
                    size, author, expected_message)
                result, actual_message = await coro

                self.assertTrue(result)
                self.assertEqual(actual_message, expected_message)
                self.syncer._send_prompt.assert_not_called()
                self.syncer._wait_for_confirmation.assert_not_called()
예제 #22
0
파일: test_helpers.py 프로젝트: sapanz/bot
    def test_mocks_allows_access_to_attributes_part_of_spec(self):
        """Accessing attributes that are valid for the objects they mock should succeed."""
        mocks = (
            (helpers.MockGuild(), 'name'),
            (helpers.MockRole(), 'hoist'),
            (helpers.MockMember(), 'display_name'),
            (helpers.MockBot(), 'user'),
            (helpers.MockContext(), 'invoked_with'),
            (helpers.MockTextChannel(), 'last_message'),
            (helpers.MockMessage(), 'mention_everyone'),
        )

        for mock, valid_attribute in mocks:
            with self.subTest(mock=mock):
                try:
                    getattr(mock, valid_attribute)
                except AttributeError:
                    msg = f"accessing valid attribute `{valid_attribute}` raised an AttributeError"
                    self.fail(msg)
예제 #23
0
    async def test_send_prompt_adds_reactions(self):
        """The message should have reactions for confirmation added."""
        extant_message = helpers.MockMessage()
        subtests = (
            (extant_message, lambda: (None, extant_message)),
            (None, self.mock_get_channel),
            (None, self.mock_fetch_channel),
        )

        for message_arg, mock_ in subtests:
            subtest_msg = "Extant message" if mock_.__name__ == "<lambda>" else mock_.__name__

            with self.subTest(msg=subtest_msg):
                _, mock_message = mock_()
                await self.syncer._send_prompt(message_arg)

                calls = [
                    mock.call(emoji) for emoji in self.syncer._REACTION_EMOJIS
                ]
                mock_message.add_reaction.assert_has_calls(calls)
예제 #24
0
    def setUp(self):
        """Set up a clean environment for each test."""
        self.bot = helpers.MockMrFreeze()
        self.cog = TemperatureConverter(self.bot)

        self.msg = helpers.MockMessage()

        self.channel = self.msg.channel

        self.author = helpers.MockMember()
        self.author.bot = False
        self.msg.author = self.author

        self.ctx = helpers.MockContext()
        self.ctx.message = self.msg
        self.ctx.author = self.author
        self.ctx.channel = self.channel

        self.bot.get_context.return_value = self.ctx

        self.files: List[File] = list()
예제 #25
0
    async def test_count_ducks_correctly_counts_the_number_of_eligible_duck_emojis(
            self):
        """The `count_ducks` method should return the number of unique staffers who gave a duck."""
        test_cases = (
            # Simple test cases
            # A message without reactions should return 0
            ("No reactions", helpers.MockMessage(), 0),
            # A message with a non-duck reaction from a non-staffer should return 0
            ("Non-duck reaction from non-staffer",
             helpers.MockMessage(reactions=[
                 self._get_reaction(emoji=self.thumbs_up_emoji, nonstaff=1)
             ]), 0),
            # A message with a non-duck reaction from a staffer should return 0
            ("Non-duck reaction from staffer",
             helpers.MockMessage(reactions=[
                 self._get_reaction(emoji=self.non_duck_custom_emoji, staff=1)
             ]), 0),
            # A message with a non-duck reaction from a non-staffer and staffer should return 0
            ("Non-duck reaction from staffer + non-staffer",
             helpers.MockMessage(reactions=[
                 self._get_reaction(
                     emoji=self.thumbs_up_emoji, staff=1, nonstaff=1)
             ]), 0),
            # A message with a unicode duck reaction from a non-staffer should return 0
            ("Unicode Duck Reaction from non-staffer",
             helpers.MockMessage(reactions=[
                 self._get_reaction(emoji=self.unicode_duck_emoji, nonstaff=1)
             ]), 0),
            # A message with a unicode duck reaction from a staffer should return 1
            ("Unicode Duck Reaction from staffer",
             helpers.MockMessage(reactions=[
                 self._get_reaction(emoji=self.unicode_duck_emoji, staff=1)
             ]), 1),
            # A message with a unicode duck reaction from a non-staffer and staffer should return 1
            ("Unicode Duck Reaction from staffer + non-staffer",
             helpers.MockMessage(reactions=[
                 self._get_reaction(
                     emoji=self.unicode_duck_emoji, staff=1, nonstaff=1)
             ]), 1),
            # A message with a duckpond duck reaction from a non-staffer should return 0
            ("Duckpond Duck Reaction from non-staffer",
             helpers.MockMessage(reactions=[
                 self._get_reaction(emoji=self.duck_pond_emoji, nonstaff=1)
             ]), 0),
            # A message with a duckpond duck reaction from a staffer should return 1
            ("Duckpond Duck Reaction from staffer",
             helpers.MockMessage(reactions=[
                 self._get_reaction(emoji=self.duck_pond_emoji, staff=1)
             ]), 1),
            # A message with a duckpond duck reaction from a non-staffer and staffer should return 1
            ("Duckpond Duck Reaction from staffer + non-staffer",
             helpers.MockMessage(reactions=[
                 self._get_reaction(
                     emoji=self.duck_pond_emoji, staff=1, nonstaff=1)
             ]), 1),

            # Complex test cases
            # A message with duckpond duck reactions from 3 staffers and 2 non-staffers returns 3
            ("Duckpond Duck Reaction from 3 staffers + 2 non-staffers",
             helpers.MockMessage(reactions=[
                 self._get_reaction(
                     emoji=self.duck_pond_emoji, staff=3, nonstaff=2)
             ]), 3),
            # A staffer with multiple duck reactions only counts once
            ("Two different duck reactions from the same staffer",
             helpers.MockMessage(reactions=[
                 helpers.MockReaction(emoji=self.duck_pond_emoji,
                                      users=[self.staff_member]),
                 helpers.MockReaction(emoji=self.unicode_duck_emoji,
                                      users=[self.staff_member]),
             ]), 1),
            # A non-string emoji does not count (to test the `isinstance(reaction.emoji, str)` elif)
            ("Reaction with non-Emoji/str emoij from 3 staffers + 2 non-staffers",
             helpers.MockMessage(reactions=[
                 self._get_reaction(emoji=100, staff=3, nonstaff=2)
             ]), 0),
            # We correctly sum when multiple reactions are provided.
            ("Duckpond Duck Reaction from 3 staffers + 2 non-staffers",
             helpers.MockMessage(reactions=[
                 self._get_reaction(
                     emoji=self.duck_pond_emoji, staff=3, nonstaff=2),
                 self._get_reaction(
                     emoji=self.unicode_duck_emoji, staff=4, nonstaff=9),
             ]), 3 + 4),
        )

        for description, message, expected_count in test_cases:
            actual_count = await self.cog.count_ducks(message)
            with self.subTest(test_case=description,
                              expected_count=expected_count,
                              actual_count=actual_count):
                self.assertEqual(expected_count, actual_count)
예제 #26
0
    def get_message_reaction(emoji):
        """Fixture to return a mock message an reaction from the given `emoji`."""
        message = helpers.MockMessage()
        reaction = helpers.MockReaction(emoji=emoji, message=message)

        return message, reaction