コード例 #1
0
    async def test__on_member_remove(self, mmj_patch):
        """Unit tests for bot._on_member_remove function."""
        # async def _on_member_remove(bot, member)
        _on_member_remove = bot._on_member_remove

        # bad guild
        member = mock.MagicMock(discord.Member, guild=3)
        await _on_member_remove(config.bot, member)
        config.Channel.logs.send.assert_not_called()
        mmj_patch.assert_not_called()

        # good guild
        member = mock.MagicMock(discord.Member, guild=config.guild)
        await _on_member_remove(config.bot, member)
        mock_discord.assert_sent(config.Channel.logs,
                                 [mmj_patch.return_value, "ALERTE",
                                  member.display_name])
コード例 #2
0
    async def test_interact(self, bloc_patch, aic_patch):
        """Unit tests for RealShell.interact method."""
        # async def interact(self, banner=None, exitmsg="Byebye!")
        interact = realshell.RealShell.interact
        bloc_patch.side_effect = lambda data: f"<!<{data}>!>"

        # simple
        channel = mock_discord.chan("tezt")
        slf = mock.Mock(realshell.RealShell, channel=channel)
        await interact(slf)
        mock_discord.assert_sent(channel, "Launching Python shell")
        aic_patch.assert_called_once_with(mock.ANY, "Byebye!")
        banner = aic_patch.call_args.args[0]
        self.assertIn("Discord implementation", banner)
        slf.message.clear_reactions.assert_called_once()
        aic_patch.reset_mock()

        # complex
        channel = mock_discord.chan("tezt")
        slf = mock.Mock(realshell.RealShell, channel=channel)
        await interact(slf, banner="LULZ", exitmsg="allo?")
        mock_discord.assert_sent(channel, "Launching Python shell")
        aic_patch.assert_called_once_with("LULZ", "allo?")
        slf.message.clear_reactions.assert_called_once()
        aic_patch.reset_mock()

        # simple, exited
        aic_patch.side_effect = SystemExit
        channel = mock_discord.chan("tezt")
        slf = mock.Mock(realshell.RealShell, channel=channel)
        with self.assertRaises(realshell.RealShellExit):
            await interact(slf)
        mock_discord.assert_sent(channel, "Launching Python shell")
        aic_patch.assert_called_once_with(mock.ANY, "Byebye!")
        slf.write.assert_called_once_with(f"\nByebye!",
                                          refresh=True,
                                          show_caret=False)
        slf.message.clear_reactions.assert_called_once()
        aic_patch.reset_mock()

        # complex, exited
        channel = mock_discord.chan("tezt")
        slf = mock.Mock(realshell.RealShell, channel=channel)
        aic_patch.side_effect = SystemExit
        with self.assertRaises(realshell.RealShellExit):
            await interact(slf, banner="LULZ", exitmsg="allo?")
        mock_discord.assert_sent(channel, "Launching Python shell")
        aic_patch.assert_called_once_with("LULZ", "allo?")
        slf.write.assert_called_once_with(f"\nallo?",
                                          refresh=True,
                                          show_caret=False)
        slf.message.clear_reactions.assert_called_once()
コード例 #3
0
    async def test__on_error(self):
        """Unit tests for bot._on_error function."""
        # async def _on_error(bot, event, *args, **kwargs)
        _on_error = bot._on_error

        # SQLAlchemyError
        exc = bdd.SQLAlchemyError("bzzt")
        with self.assertRaises(bdd.SQLAlchemyError):    # re-raised
            try:
                raise exc
            except bdd.SQLAlchemyError:
                # called within a running except block
                await _on_error(config.bot, "event")
        mock_discord.assert_sent(
            config.Channel.logs, "Rollback session",
            [f"{config.Role.mj.mention} ALED : Exception Python",
             "Traceback", "SQLAlchemyError", "bzzt"])
        config.Channel.logs.send.reset_mock()
        config.session.rollback.assert_called_once()
        config.session.rollback.reset_mock()

        # DriverOperationalError
        exc = bdd.DriverOperationalError("koook")
        with self.assertRaises(bdd.DriverOperationalError):    # re-raised
            try:
                raise exc
            except bdd.DriverOperationalError:
                # called within a running except block
                await _on_error(config.bot, "event")
        mock_discord.assert_sent(
            config.Channel.logs, "Rollback session",
            [f"{config.Role.mj.mention} ALED : Exception Python",
             "Traceback", bdd.DriverOperationalError.__name__, "koook"])
        config.Channel.logs.send.reset_mock()
        config.session.rollback.assert_called_once()
        config.session.rollback.reset_mock()

        # BDD error - session not ready : on vérifie juste que pas d'erreur
        exc = bdd.SQLAlchemyError("bzzt")
        _session = config.session
        del config.session
        with self.assertRaises(bdd.SQLAlchemyError):    # re-raised
            try:
                raise exc
            except bdd.SQLAlchemyError:
                # called within a running except block
                await _on_error(config.bot, "event")
        mock_discord.assert_sent(
            config.Channel.logs,
            [f"{config.Role.mj.mention} ALED : Exception Python",
             "Traceback", "SQLAlchemyError", "bzzt"])
        config.Channel.logs.send.reset_mock()
        config.session = _session

        # other exception
        class SomeException(Exception):
            pass
        with self.assertRaises(SomeException):    # re-raised
            try:
                raise SomeException("!a!", "@b@", "^c^")
            except SomeException:
                # called within a running except block
                await _on_error(config.bot, "event")
        mock_discord.assert_sent(
            config.Channel.logs,
            [f"{config.Role.mj.mention} ALED : Exception Python",
             "Traceback", "SomeException", "!a!", "@b@", "^c^"])
        config.Channel.logs.send.reset_mock()
コード例 #4
0
    async def test__on_command_error(self):
        """Unit tests for bot._on_command_error function."""
        # async def _on_command_error(bot, ctx, exc)
        _on_command_error = bot._on_command_error

        # mauvais serveur
        ctx = mock.NonCallableMock(commands.Context, guild=10)
        await _on_command_error(config.bot, ctx, None)
        ctx.send.assert_not_called()

        # STOP
        ctx = mock_discord.get_ctx()
        exc = commands.CommandInvokeError(blocs.tools.CommandExit())
        await _on_command_error(config.bot, ctx, exc)
        ctx.assert_sent("Mission aborted")

        # STOP custom message
        ctx = mock_discord.get_ctx()
        exc = commands.CommandInvokeError(blocs.tools.CommandExit("cust0m"))
        await _on_command_error(config.bot, ctx, exc)
        ctx.assert_sent("cust0m")

        # BDD error - MJ
        ctx = mock_discord.get_ctx()
        ctx.author.top_role = mock.MagicMock(discord.Role,
                                             __ge__=lambda s, o: True) # >= MJ
        exc = commands.CommandInvokeError(bdd.SQLAlchemyError("bzzt"))
        try: raise exc.original      # creating traceback
        except bdd.SQLAlchemyError: pass
        await _on_command_error(config.bot, ctx, exc)
        mock_discord.assert_sent(config.Channel.logs, "Rollback session")
        config.Channel.logs.send.reset_mock()
        config.session.rollback.assert_called_once()
        config.session.rollback.reset_mock()
        ctx.assert_sent(["Un problème est survenu", "Traceback",
                         "SQLAlchemyError", "bzzt"])

        # BDD error - not MJ
        ctx = mock_discord.get_ctx()
        ctx.author.top_role = mock.MagicMock(discord.Role,
                                             __ge__=lambda s, o: False) # < MJ
        exc = commands.CommandInvokeError(bdd.DriverOperationalError("bzoozt"))
        try: raise exc.original      # creating traceback
        except bdd.DriverOperationalError: pass
        await _on_command_error(config.bot, ctx, exc)
        mock_discord.assert_sent(config.Channel.logs, "Rollback session")
        config.Channel.logs.send.reset_mock()
        config.session.rollback.assert_called_once()
        config.session.rollback.reset_mock()
        ctx.assert_sent(["Un problème est survenu",
                         bdd.DriverOperationalError.__name__, "bzoozt"])
        ctx.assert_not_sent("Traceback")

        # BDD error - session not ready : on vérifie juste que pas d'erreur
        ctx = mock_discord.get_ctx()
        _session = config.session
        del config.session
        ctx.author.top_role = mock.MagicMock(discord.Role,
                                             __ge__=lambda s, o: True) # >= MJ
        exc = commands.CommandInvokeError(bdd.SQLAlchemyError("bzzt"))
        await _on_command_error(config.bot, ctx, exc)
        mock_discord.assert_sent(config.Channel.logs)   # nothing
        config.Channel.logs.send.reset_mock()
        ctx.assert_sent(["Un problème est survenu", "SQLAlchemyError", "bzzt"])
        config.session = _session

        # CommandNotFound
        ctx = mock_discord.get_ctx()
        await _on_command_error(config.bot, ctx, commands.CommandNotFound())
        ctx.assert_sent("je ne connais pas cette commande")

        # DisabledCommand
        ctx = mock_discord.get_ctx()
        await _on_command_error(config.bot, ctx, commands.DisabledCommand())
        ctx.assert_sent("Cette commande est désactivée")

        # ConversionError
        command = mock.Mock()
        ctx = mock_discord.get_ctx(command)
        exc = commands.ConversionError("bkrkr", "kak")
        await _on_command_error(config.bot, ctx, exc)
        ctx.assert_sent(["ce n'est pas comme ça qu'on utilise cette commande",
                         "ConversionError", "bkrkr", "kak"])
        config.bot.get_context.assert_called_with(ctx.message)
        self.assertEqual(ctx.message.content, f"!help {command.name}")
        config.bot.get_context.return_value.reinvoke.assert_called()

        # UserInputError
        command = mock.Mock()
        ctx = mock_discord.get_ctx(command)
        exc = commands.UserInputError("bakaka")
        await _on_command_error(config.bot, ctx, exc)
        ctx.assert_sent(["ce n'est pas comme ça qu'on utilise cette commande",
                         "UserInputError", "bakaka"])
        config.bot.get_context.assert_called_with(ctx.message)
        self.assertEqual(ctx.message.content, f"!help {command.name}")
        config.bot.get_context.return_value.reinvoke.assert_called()

        # UserInputError derivate
        command = mock.Mock()
        ctx = mock_discord.get_ctx(command)
        exc = commands.BadArgument("bakaka")
        await _on_command_error(config.bot, ctx, exc)
        ctx.assert_sent(["ce n'est pas comme ça qu'on utilise cette commande",
                         "BadArgument", "bakaka"])
        config.bot.get_context.assert_called_with(ctx.message)
        self.assertEqual(ctx.message.content, f"!help {command.name}")
        config.bot.get_context.return_value.reinvoke.assert_called()

        # CheckAnyFailure
        ctx = mock_discord.get_ctx()
        exc = commands.CheckAnyFailure(mock.ANY, mock.ANY)
        await _on_command_error(config.bot, ctx, exc)
        ctx.assert_sent("cette commande est réservée aux MJs")

        # MissingAnyRole
        ctx = mock_discord.get_ctx()
        exc = commands.MissingAnyRole([mock.ANY])
        await _on_command_error(config.bot, ctx, exc)
        ctx.assert_sent("Cette commande est réservée aux joueurs")

        # MissingRole
        ctx = mock_discord.get_ctx()
        exc = commands.MissingRole(mock.ANY)
        await _on_command_error(config.bot, ctx, exc)
        ctx.assert_sent("cette commande est réservée aux joueurs en vie")

        # one_command.AlreadyInCommand, not addIA/modifIA
        command = mock.Mock()
        command.configure_mock(name="blabla")
        ctx = mock_discord.get_ctx(command)
        exc = blocs.one_command.AlreadyInCommand()
        await _on_command_error(config.bot, ctx, exc)
        ctx.assert_sent("Impossible d'utiliser une commande pendant")

        # one_command.AlreadyInCommand, addIA
        command = mock.Mock()
        command.configure_mock(name="addIA")
        ctx = mock_discord.get_ctx(command)
        exc = blocs.one_command.AlreadyInCommand()
        await _on_command_error(config.bot, ctx, exc)
        ctx.assert_sent()

        # one_command.AlreadyInCommand, modifIA
        command = mock.Mock()
        command.configure_mock(name="modifIA")
        ctx = mock_discord.get_ctx(command)
        exc = blocs.one_command.AlreadyInCommand()
        await _on_command_error(config.bot, ctx, exc)
        ctx.assert_sent()

        # CheckFailure (autre check erreur)
        ctx = mock_discord.get_ctx()
        exc = commands.CheckFailure("jojo")
        with mock.patch("lgrez.blocs.tools.mention_MJ") as mmj_patch:
            await _on_command_error(config.bot, ctx, exc)
        mmj_patch.assert_called_once_with(ctx)
        ctx.assert_sent(["cette commande ne puisse pas être exécutée",
                         "CheckFailure", "jojo"])

        # other exception
        ctx = mock_discord.get_ctx()
        exc = AttributeError("oh")
        with mock.patch("lgrez.blocs.tools.mention_MJ") as mmj_patch:
            await _on_command_error(config.bot, ctx, exc)
        mmj_patch.assert_called_once_with(ctx)
        ctx.assert_sent(["Une erreur inattendue est survenue",
                         "AttributeError", "oh"])

        # other exception
        ctx = mock_discord.get_ctx()
        class SomeException(Exception):
            pass
        exc = SomeException("p!wet")
        with mock.patch("lgrez.blocs.tools.mention_MJ") as mmj_patch:
            await _on_command_error(config.bot, ctx, exc)
        mmj_patch.assert_called_once_with(ctx)
        ctx.assert_sent(["Une erreur inattendue est survenue",
                         "SomeException", "p!wet"])
コード例 #5
0
    async def test__on_ready(self, emo_patch, role_patch, ch_patch, ppatch):
        """Unit tests for bot._on_ready function."""
        # async def _on_ready(bot)
        _on_ready = bot._on_ready

        # guild not found
        config.bot.get_guild.return_value = None
        with self.assertRaises(RuntimeError) as cm:
            await _on_ready(config.bot)
        self.assertEqual(config.loop, config.bot.loop)
        config.bot.i_am_alive.assert_not_called()
        config.bot.get_guild.assert_called_once_with(config.bot.GUILD_ID)
        self.assertIn(str(config.bot.GUILD_ID), cm.exception.args[0])
        ppatch.assert_not_called()
        config.bot.get_guild.reset_mock(return_value=True)
        config.bot.reset_mock()

        # guild found, everything ok
        config.output_liveness = False
        ch_patch.side_effect=functools.partial(mock.Mock, discord.TextChannel)
        role_patch.side_effect=functools.partial(mock.Mock, discord.Role)
        emo_patch.side_effect=functools.partial(mock.Mock, discord.Emoji)
        await _on_ready(config.bot)
        guild = config.bot.get_guild.return_value
        self.assertEqual(config.loop, config.bot.loop)
        config.bot.i_am_alive.assert_not_called()
        config.bot.get_guild.assert_called_once_with(config.bot.GUILD_ID)
        self.assertEqual(config.guild, guild)
        printed = "\n".join(call.args[0] for call in ppatch.call_args_list)
        self.assertIn("Connected", printed)
        self.assertIn(str(guild.name), printed)
        self.assertIn("Initialization", printed)
        self.assertIn("Initialization", printed)
        self.assertIn("Initialization complete", printed)
        self.assertIn("Listening for events", printed)
        mock_discord.assert_sent(config.Channel.logs, "Just rebooted")
        mock_discord.assert_not_sent(config.Channel.logs,
                                     ["tâches planifiées", "ERREURS"])
        ppatch.reset_mock()
        try:
            for name in config.Channel:
                getattr(config.Channel, name)
            for name in config.Role:
                getattr(config.Role, name)
            for name in config.Emoji:
                getattr(config.Emoji, name)
            config.private_chan_category_name
        except ready_check.NotReadyError as e:
            raise AssertionError from e
        config.bot.change_presence.assert_called_once()
        config.bot.reset_mock()

        mock_discord._unprepare_attributes(config.Role)
        mock_discord._unprepare_attributes(config.Channel)
        mock_discord._unprepare_attributes(config.Emoji)

        # guild found, some missing Discord elements (not #logs / @MJ)
        def _channel(name):
            if name in ["rôles", "débats", config.private_chan_category_name]:
                raise ValueError
            else:
                return mock.NonCallableMock(discord.TextChannel)
        def _role(name):
            if name in ["Joueur en vie", "Maire"]:
                raise ValueError
            else:
                return mock.NonCallableMock(discord.Role)
        def _emoji(name):
            if name == "ro":
                raise ValueError
            else:
                return mock.NonCallableMock(discord.Emoji)
        ch_patch.side_effect = _channel
        role_patch.side_effect = _role
        emo_patch.side_effect = _emoji
        await _on_ready(config.bot)
        guild = config.bot.get_guild.return_value
        self.assertEqual(config.loop, config.bot.loop)
        config.bot.i_am_alive.assert_not_called()
        config.bot.get_guild.assert_called_once_with(config.bot.GUILD_ID)
        self.assertEqual(config.guild, guild)
        printed = "\n".join(call.args[0] for call in ppatch.call_args_list)
        self.assertIn("Connected", printed)
        self.assertIn(str(guild.name), printed)
        self.assertIn("Initialization", printed)
        self.assertIn("Initialization complete", printed)
        self.assertIn("Listening for events", printed)
        mock_discord.assert_sent(
            config.Channel.logs,
            ["ERREURS", "6 errors", 'config.Channel.roles = "rôles"',
             'config.Channel.debats = "débats"', str(config.Role.mj.mention),
             'catégorie config.private_chan_category_name = '
             f'"{config.private_chan_category_name}"',
             'config.Role.joueur_en_vie = "Joueur en vie"',
             'config.Role.maire = "Maire"', 'config.Emoji.ro = "ro"'],
            "Just rebooted")
        mock_discord.assert_not_sent(config.Channel.logs, "tâches planifiées",
                                     "tâches planifiées")
        ppatch.reset_mock()
        try:
            for attr in config.Channel:
                if attr not in ["roles", "debats"]:
                    getattr(config.Channel, attr)
            for attr in config.Role:
                if attr not in ["joueur_en_vie", "maire"]:
                    getattr(config.Role, attr)
            for attr in config.Emoji:
                if attr != "ro":
                    getattr(config.Emoji, attr)
            config.private_chan_category_name
        except ready_check.NotReadyError as e:
            raise AssertionError from e
        config.bot.change_presence.assert_called_once()
        config.bot.reset_mock()

        mock_discord._unprepare_attributes(config.Role)
        mock_discord._unprepare_attributes(config.Channel)
        mock_discord._unprepare_attributes(config.Emoji)

        # guild found, missing @MJ
        def _channel(name):
            return mock.NonCallableMock(discord.TextChannel)
        def _role(name):
            if name == "MJ":
                raise ValueError
            else:
                return mock.NonCallableMock(discord.Role)
        def _emoji(name):
            return mock.NonCallableMock(discord.Emoji)
        ch_patch.side_effect = _channel
        role_patch.side_effect = _role
        emo_patch.side_effect = _emoji
        await _on_ready(config.bot)
        guild = config.bot.get_guild.return_value
        self.assertEqual(config.loop, config.bot.loop)
        config.bot.i_am_alive.assert_not_called()
        config.bot.get_guild.assert_called_once_with(config.bot.GUILD_ID)
        self.assertEqual(config.guild, guild)
        printed = "\n".join(call.args[0] for call in ppatch.call_args_list)
        self.assertIn("Connected", printed)
        self.assertIn(str(guild.name), printed)
        self.assertIn("Initialization", printed)
        self.assertIn("Initialization complete", printed)
        self.assertIn("Listening for events", printed)
        mock_discord.assert_sent(
            config.Channel.logs,
            ["ERREURS", "1 error", 'config.Role.mj = "MJ"',
             "@everyone"],
            "Just rebooted")
        mock_discord.assert_not_sent(config.Channel.logs, "tâches planifiées",
                                     "tâches planifiées")
        ppatch.reset_mock()
        try:
            for attr in config.Channel:
                getattr(config.Channel, attr)
            for attr in config.Role:
                if attr != "mj":
                    getattr(config.Role, attr)
            for attr in config.Emoji:
                getattr(config.Emoji, attr)
            config.private_chan_category_name
        except ready_check.NotReadyError as e:
            raise AssertionError from e
        config.bot.change_presence.assert_called_once()
        config.bot.reset_mock()

        mock_discord._unprepare_attributes(config.Role)
        mock_discord._unprepare_attributes(config.Channel)
        mock_discord._unprepare_attributes(config.Emoji)

        # guild found, missing @MJ / #logs
        def _channel(name):
            if name == "logs":
                raise ValueError
            else:
                return mock.NonCallableMock(discord.TextChannel)
        def _role(name):
            return mock.NonCallableMock(discord.Role)
        def _emoji(name):
            return mock.NonCallableMock(discord.Emoji)
        ch_patch.side_effect = _channel
        role_patch.side_effect = _role
        emo_patch.side_effect = _emoji
        defchan = mock.NonCallableMock(discord.TextChannel)
        config.guild.text_channels.__getitem__.return_value = defchan
        await _on_ready(config.bot)
        guild = config.bot.get_guild.return_value
        self.assertEqual(config.loop, config.bot.loop)
        config.bot.i_am_alive.assert_not_called()
        config.bot.get_guild.assert_called_once_with(config.bot.GUILD_ID)
        self.assertEqual(config.guild, guild)
        printed = "\n".join(call.args[0] for call in ppatch.call_args_list)
        self.assertIn("Connected", printed)
        self.assertIn(str(guild.name), printed)
        self.assertIn("Initialization", printed)
        self.assertIn("Initialization complete", printed)
        self.assertIn("Listening for events", printed)
        mock_discord.assert_sent(
            defchan,
            ["ERREURS", "1 error", 'config.Channel.logs = "logs"',
             "Routing logs", str(config.Role.mj.mention)],
            "Just rebooted")
        ppatch.reset_mock()
        try:
            for attr in config.Channel:
                if attr != "logs":
                    getattr(config.Channel, attr)
            for attr in config.Role:
                getattr(config.Role, attr)
            for attr in config.Emoji:
                getattr(config.Emoji, attr)
            config.private_chan_category_name
        except ready_check.NotReadyError as e:
            raise AssertionError from e
        config.bot.change_presence.assert_called_once()
        config.bot.reset_mock()

        mock_discord._unprepare_attributes(config.Role)
        mock_discord._unprepare_attributes(config.Channel)
        mock_discord._unprepare_attributes(config.Emoji)

        # guild found, missing @MJ / #logs
        def _channel(name):
            return mock.NonCallableMock(discord.TextChannel)
        def _role(name):
            return mock.NonCallableMock(discord.Role)
        def _emoji(name):
            return mock.NonCallableMock(discord.Emoji)
        taches = [
            bdd.Tache(timestamp=datetime.datetime.now(), commande="cmdz"),
            bdd.Tache(timestamp=datetime.datetime.now(), commande="cmd2"),
            bdd.Tache(timestamp=datetime.datetime.now(), commande="cmd3"),
        ]
        bdd.Tache.add(*taches)
        ch_patch.side_effect = _channel
        role_patch.side_effect = _role
        emo_patch.side_effect = _emoji
        await _on_ready(config.bot)
        guild = config.bot.get_guild.return_value
        self.assertEqual(config.loop, config.bot.loop)
        config.bot.i_am_alive.assert_not_called()
        config.bot.get_guild.assert_called_once_with(config.bot.GUILD_ID)
        self.assertEqual(config.guild, guild)
        printed = "\n".join(call.args[0] for call in ppatch.call_args_list)
        self.assertIn("Connected", printed)
        self.assertIn(str(guild.name), printed)
        self.assertIn("Initialization", printed)
        self.assertIn("Initialization complete", printed)
        self.assertIn("Listening for events", printed)
        mock_discord.assert_sent(config.Channel.logs, "Just rebooted",
                                 "3 tâches planifiées")
        ppatch.reset_mock()
        try:
            for attr in config.Channel:
                if attr != "logs":
                    getattr(config.Channel, attr)
            for attr in config.Role:
                getattr(config.Role, attr)
            for attr in config.Emoji:
                getattr(config.Emoji, attr)
            config.private_chan_category_name
        except ready_check.NotReadyError as e:
            raise AssertionError from e
        config.bot.change_presence.assert_called_once()
        config.loop.call_later.assert_has_calls(
            [mock.call(mock.ANY, tache.execute) for tache in taches]
        )
コード例 #6
0
    async def test_close_action(self, da_patch):
        """Unit tests for gestion_actions.close_action function."""
        # async def close_action(action)
        close_action = gestion_actions.close_action
        mock_bdd.add_campsroles()
        j1 = bdd.Joueur(discord_id=1, chan_id_=11, nom="Joueur1")
        j1.add()

        # pas de décision, no base_cooldown, no temporel/perma
        ba1 = bdd.BaseAction(slug="ba1", instant=False, base_cooldown=0,
                             trigger_debut=bdd.ActionTrigger.open_cond)
        ba1.add()
        act1 = bdd.Action(base=ba1, joueur=j1, decision_="rien")
        act1.add()
        await close_action(act1)
        self.assertIsNone(act1.decision_)
        self.assertEqual(bdd.Tache.query.all(), [])
        da_patch.assert_not_called()

        # pas de décision, base_cooldown = 4, no temporel/perma
        ba2 = bdd.BaseAction(slug="ba2", instant=False, base_cooldown=4,
                             trigger_debut=bdd.ActionTrigger.open_cond)
        ba2.add()
        act2 = bdd.Action(base=ba2, joueur=j1, cooldown=0, decision_="rien")
        act2.add()
        await close_action(act2)
        self.assertIsNone(act2.decision_)
        self.assertEqual(act2.cooldown, 4)
        self.assertEqual(bdd.Tache.query.all(), [])
        da_patch.assert_not_called()

        # pas de décision, no base_cooldown, temporel
        ba3 = bdd.BaseAction(slug="ba3", instant=False, base_cooldown=0,
                             trigger_debut=bdd.ActionTrigger.temporel,
                             heure_debut=datetime.time(15, 2))
        ba3.add()
        act3 = bdd.Action(id=3, base=ba3, joueur=j1, decision_="rien")
        act3.add()
        with mock.patch("lgrez.blocs.tools.next_occurence") as no_patch:
            no_patch.return_value = datetime.datetime(1, 1, 1, 15, 2)
            await close_action(act3)
        no_patch.assert_called_once_with(datetime.time(15, 2))
        self.assertIsNone(act3.decision_)
        self.assertEqual(len(bdd.Tache.query.all()), 1)
        tache = bdd.Tache.query.one()
        self.assertEqual(tache.timestamp, no_patch.return_value)
        self.assertEqual(tache.commande, "!open 3")
        self.assertEqual(tache.action, act3)
        tache.delete()
        da_patch.assert_not_called()

        # pas de décision, no base_cooldown, perma
        ba4 = bdd.BaseAction(slug="ba4", instant=False, base_cooldown=0,
                             trigger_debut=bdd.ActionTrigger.perma)
        ba4.add()
        act4 = bdd.Action(id=4, base=ba4, joueur=j1, decision_="rien")
        act4.add()
        with mock.patch("lgrez.blocs.tools.fin_pause") as fp_patch:
            fp_patch.return_value = datetime.datetime(1, 1, 1, 10, 4)
            await close_action(act4)
        fp_patch.assert_called_once()
        self.assertIsNone(act4.decision_)
        self.assertEqual(len(bdd.Tache.query.all()), 1)
        tache = bdd.Tache.query.one()
        self.assertEqual(tache.timestamp, fp_patch.return_value)
        self.assertEqual(tache.commande, "!open 4")
        self.assertEqual(tache.action, act4)
        tache.delete()
        da_patch.assert_not_called()

        # décision, no base_cooldown, no temporel/perma, no charges ==> no diff
        act11 = bdd.Action(base=ba1, joueur=j1, decision_="ach ja",
                           charges=None)
        act11.add()
        await close_action(act11)
        self.assertIsNone(act11.decision_)
        self.assertIsNone(act11.charges)
        self.assertEqual(bdd.Tache.query.all(), [])
        da_patch.assert_not_called()

        # décision, no base_cooldown, no temporel/perma, 4 charges
        act12 = bdd.Action(base=ba1, joueur=j1, decision_="ach ja", charges=4)
        act12.add()
        with mock_discord.mock_members_and_chans(j1):
            chan = j1.private_chan
            await close_action(act12)
        self.assertIsNone(act12.decision_)
        self.assertEqual(act12.charges, 3)
        mock_discord.assert_sent(chan, "Il te reste 3 charge")
        mock_discord.assert_not_sent(chan, "pour cette semaine")
        self.assertEqual(bdd.Tache.query.all(), [])
        da_patch.assert_not_called()

        # décision, no base_cooldown, no temporel/perma, 4 charges, refill WE
        ba1b = bdd.BaseAction(slug="ba1b", instant=False, base_cooldown=0,
                              trigger_debut=bdd.ActionTrigger.open_cond,
                              refill="weekends, other")
        ba1b.add()
        act13 = bdd.Action(base=ba1b, joueur=j1, decision_="ach ja", charges=4)
        act13.add()
        with mock_discord.mock_members_and_chans(j1):
            chan = j1.private_chan
            await close_action(act13)
        self.assertIsNone(act13.decision_)
        self.assertEqual(act13.charges, 3)
        mock_discord.assert_sent(chan, "Il te reste 3 charge")
        mock_discord.assert_sent(chan, "pour cette semaine")
        self.assertEqual(bdd.Tache.query.all(), [])
        da_patch.assert_not_called()

        # décision, no base_cooldown, no temporel/perma, 1 charge
        act14 = bdd.Action(id=37, base=ba1, joueur=j1, decision_="ach ja",
                           charges=1)
        act14.add()
        with mock_discord.mock_members_and_chans(j1):
            chan = j1.private_chan
            await close_action(act14)
        da_patch.assert_called_once_with(act14)     # deleted
        mock_discord.assert_sent(chan, "Il te reste 0 charge")
        mock_discord.assert_not_sent(chan, "pour cette semaine")
        self.assertEqual(bdd.Tache.query.all(), [])
        da_patch.reset_mock()

        # décision, no base_cooldown, no temporel/perma, 1 charge, refill WE
        act13 = bdd.Action(base=ba1b, joueur=j1, decision_="ach ja", charges=1)
        act13.add()
        with mock_discord.mock_members_and_chans(j1):
            chan = j1.private_chan
            await close_action(act13)
        self.assertIsNone(act13.decision_)
        self.assertEqual(act13.charges, 0)      # not deleted
        mock_discord.assert_sent(chan, "Il te reste 0 charge")
        mock_discord.assert_sent(chan, "pour cette semaine")
        self.assertEqual(bdd.Tache.query.all(), [])
        da_patch.assert_not_called()

        # décision, no base_cooldown, no temporel/perma, 1 charge, refill autre
        ba1c = bdd.BaseAction(slug="ba1c", instant=False, base_cooldown=0,
                              trigger_debut=bdd.ActionTrigger.open_cond,
                              refill="brzzz")
        ba1c.add()
        act13 = bdd.Action(base=ba1c, joueur=j1, decision_="ach ja", charges=1)
        act13.add()
        with mock_discord.mock_members_and_chans(j1):
            chan = j1.private_chan
            await close_action(act13)
        self.assertIsNone(act13.decision_)
        self.assertEqual(act13.charges, 0)      # not deleted
        mock_discord.assert_sent(chan, "Il te reste 0 charge")
        mock_discord.assert_not_sent(chan, "pour cette semaine")
        self.assertEqual(bdd.Tache.query.all(), [])
        da_patch.assert_not_called()

        # deleted et plein d'autre trucs
        batro = bdd.BaseAction(slug="batro", instant=False, base_cooldown=2,
                              trigger_debut=bdd.ActionTrigger.perma,
                              refill="brzzz")
        act14 = bdd.Action(base=ba1, joueur=j1, decision_="ach ja", charges=1)
        act14.add()
        with mock_discord.mock_members_and_chans(j1):
            chan = j1.private_chan
            await close_action(act14)
        da_patch.assert_called_once_with(act14)     # deleted
        mock_discord.assert_sent(chan, "Il te reste 0 charge")
        mock_discord.assert_not_sent(chan, "pour cette semaine")
        self.assertEqual(bdd.Tache.query.all(), [])
        da_patch.reset_mock()
コード例 #7
0
    async def test_open_action(self, log_patch, ca_patch):
        """Unit tests for gestion_actions.open_action function."""
        # async def open_action(action)
        open_action = gestion_actions.open_action
        mock_bdd.add_campsroles()
        j1 = bdd.Joueur(discord_id=1, chan_id_=11, nom="Joueur1",
                        role_actif=True)
        j1.add()

        # test préliminaire 1 - en cooldown, non temporel
        ba1 = bdd.BaseAction(slug="ba1")
        ba1.add()
        act1 = bdd.Action(base=ba1, joueur=j1, cooldown=3)
        act1.add()
        with mock_discord.mock_members_and_chans(j1):
            await open_action(act1)
        self.assertEqual(act1.cooldown, 2)
        log_patch.assert_called_once()
        self.assertIn(repr(act1), log_patch.call_args.args[0])
        self.assertIn("en cooldown", log_patch.call_args.args[0])
        self.assertEqual(bdd.Tache.query.all(), [])
        ca_patch.assert_not_called()
        log_patch.reset_mock()

        # test préliminaire 2 - en cooldown, temporel
        ba2 = bdd.BaseAction(slug="ba2",
                             trigger_debut=bdd.ActionTrigger.temporel,
                             heure_debut=datetime.time(15, 2))
        ba2.add()
        act2 = bdd.Action(id=23, base=ba2, joueur=j1, cooldown=3)
        act2.add()
        with mock_discord.mock_members_and_chans(j1):
            await open_action(act2)
        self.assertEqual(act2.cooldown, 2)
        log_patch.assert_called_once()
        self.assertIn(repr(act2), log_patch.call_args.args[0])
        self.assertIn("en cooldown", log_patch.call_args.args[0])
        self.assertEqual(len(bdd.Tache.query.all()), 1)
        tache = bdd.Tache.query.one()
        self.assertEqual(tache.timestamp.time(), datetime.time(15, 2))
        self.assertEqual(tache.commande, "!open 23")
        self.assertEqual(tache.action, act2)
        log_patch.reset_mock()
        ca_patch.assert_not_called()
        tache.delete()

        # test préliminaire 3 - role non actif, non temporel
        j2 = bdd.Joueur(discord_id=2, chan_id_=21, nom="Joueur2",
                        role_actif=False)
        j2.add()
        act3 = bdd.Action(id=24, base=ba1, joueur=j2, cooldown=0)
        act3.add()
        with mock_discord.mock_members_and_chans(j2):
            await open_action(act3)
        self.assertEqual(act3.cooldown, 0)
        log_patch.assert_called_once()
        self.assertIn(repr(act3), log_patch.call_args.args[0])
        self.assertIn("role_actif == False", log_patch.call_args.args[0])
        self.assertEqual(bdd.Tache.query.all(), [])
        ca_patch.assert_not_called()
        log_patch.reset_mock()

        # test préliminaire 4 - role non actif, temporel
        act4 = bdd.Action(id=25, base=ba2, joueur=j2, cooldown=0)
        act4.add()
        with mock_discord.mock_members_and_chans(j2):
            await open_action(act4)
        self.assertEqual(act4.cooldown, 0)
        log_patch.assert_called_once()
        self.assertIn(repr(act4), log_patch.call_args.args[0])
        self.assertIn("role_actif == False", log_patch.call_args.args[0])
        self.assertEqual(len(bdd.Tache.query.all()), 1)
        tache = bdd.Tache.query.one()
        self.assertEqual(tache.timestamp.time(), datetime.time(15, 2))
        self.assertEqual(tache.commande, "!open 25")
        self.assertEqual(tache.action, act4)
        log_patch.reset_mock()
        ca_patch.assert_not_called()
        tache.delete()

        # test préliminaire 5 - action automatique, non temporelle
        ba3 = bdd.BaseAction(slug="ba3",
                             trigger_debut=bdd.ActionTrigger.perma,
                             trigger_fin=bdd.ActionTrigger.auto)
        ba3.add()
        act5 = bdd.Action(id=27, base=ba3, joueur=j1, cooldown=0)
        act5.add()
        with mock_discord.mock_members_and_chans(j1):
            await open_action(act5)
        self.assertEqual(act5.cooldown, 0)
        log_patch.assert_called_once()
        self.assertIn(repr(act5), log_patch.call_args.args[0])
        self.assertIn("automatique", log_patch.call_args.args[0])
        self.assertEqual(bdd.Tache.query.all(), [])
        ca_patch.assert_called_once_with(act5)
        log_patch.reset_mock()
        ca_patch.reset_mock()

        # test préliminaire 6 - action automatique, temporelle
        ba4 = bdd.BaseAction(slug="ba4",
                             trigger_debut=bdd.ActionTrigger.temporel,
                             heure_debut=datetime.time(15, 2),
                             trigger_fin=bdd.ActionTrigger.auto)
        ba4.add()
        act6 = bdd.Action(id=28, base=ba4, joueur=j1, cooldown=0)
        act6.add()
        with mock_discord.mock_members_and_chans(j1):
            chan = j1.private_chan
            await open_action(act6)
        self.assertEqual(act6.cooldown, 0)
        log_patch.assert_called_once()
        self.assertIn("ba4", log_patch.call_args.args[0])
        self.assertIn("Joueur1", log_patch.call_args.args[0])
        self.assertIn("pas vraiment automatique", log_patch.call_args.args[0])
        self.assertIn(str(config.Role.mj.mention), log_patch.call_args.args[0])
        self.assertIn(str(chan.mention), log_patch.call_args.args[0])
        self.assertEqual(bdd.Tache.query.all(), [])
        ca_patch.assert_called_once_with(act6)
        log_patch.reset_mock()
        ca_patch.reset_mock()


        # --- fin des tests préliminaires
        # fin hors temp/delta/perma, déjà ouverte
        ba5 = bdd.BaseAction(slug="ba5",
                             trigger_debut=bdd.ActionTrigger.open_cond,
                             trigger_fin=bdd.ActionTrigger.close_cond)
        ba5.add()
        act7 = bdd.Action(base=ba5, joueur=j1, decision_="rien")
        act7.add()
        with mock_discord.mock_members_and_chans(j1):
            chan = j1.private_chan
            await open_action(act7)
        mock_discord.assert_sent(chan, [
            "tu peux utiliser quand tu le souhaites", "ba5", "!action",
        ])
        mock_discord.assert_not_sent(chan, "tu as jusqu'à")
        self.assertEqual(act7.decision_, "rien")
        chan.send.return_value.add_reaction.assert_called_once_with(
            config.Emoji.action
        )
        self.assertEqual(bdd.Tache.query.all(), [])
        log_patch.assert_not_called()
        ca_patch.assert_not_called()

        # fin hors temp/delta/perma, fermée
        ba6 = bdd.BaseAction(slug="ba6",
                             trigger_debut=bdd.ActionTrigger.open_cond,
                             trigger_fin=bdd.ActionTrigger.close_cond)
        ba6.add()
        act8 = bdd.Action(id=30, base=ba6, joueur=j1, decision_=None)
        act8.add()
        with mock_discord.mock_members_and_chans(j1):
            chan = j1.private_chan
            await open_action(act8)
        mock_discord.assert_sent(chan, [
            "Tu peux maintenant utiliser", "ba6", "!action",
        ])
        mock_discord.assert_not_sent(chan, "tu as jusqu'à")
        chan.send.return_value.add_reaction.assert_called_once_with(
            config.Emoji.action
        )
        self.assertEqual(act8.decision_, "rien")
        self.assertEqual(bdd.Tache.query.all(), [])
        log_patch.assert_not_called()
        ca_patch.assert_not_called()


        # fin temp, déjà ouverte
        ba7 = bdd.BaseAction(slug="ba7",
                             trigger_debut=bdd.ActionTrigger.open_cond,
                             trigger_fin=bdd.ActionTrigger.temporel,
                             heure_fin=datetime.time(15, 2))
        ba7.add()
        act9 = bdd.Action(id=31, base=ba7, joueur=j1, decision_="rien")
        act9.add()
        with mock_discord.mock_members_and_chans(j1):
            chan = j1.private_chan
            await open_action(act9)
        mock_discord.assert_sent(chan, [
            "tu peux utiliser quand tu le souhaites", "ba7", "!action",
            f"Tu as jusqu'à {datetime.time(15, 2)}"
        ])
        chan.send.return_value.add_reaction.assert_called_once_with(
            config.Emoji.action
        )
        self.assertEqual(act9.decision_, "rien")
        taches = bdd.Tache.query.all()
        self.assertEqual(len(taches), 2)
        self.assertEqual([tache.action for tache in taches], [act9]*2)
        self.assertEqual(
            {(tache.commande, tache.timestamp.time()) for tache in taches},
            {("!close 31", datetime.time(15, 2)),
             ("!remind 31", datetime.time(14, 32))}
        )
        bdd.Tache.delete(*taches)
        log_patch.assert_not_called()
        ca_patch.assert_not_called()

        # fin temp, fermée
        ba8 = bdd.BaseAction(slug="ba8",
                             trigger_debut=bdd.ActionTrigger.open_cond,
                             trigger_fin=bdd.ActionTrigger.temporel,
                             heure_fin=datetime.time(15, 2))
        ba8.add()
        act10 = bdd.Action(id=32, base=ba8, joueur=j1, decision_=None)
        act10.add()
        with mock_discord.mock_members_and_chans(j1):
            chan = j1.private_chan
            await open_action(act10)
        mock_discord.assert_sent(chan, [
            "Tu peux maintenant utiliser", "ba8", "!action",
            f"Tu as jusqu'à {datetime.time(15, 2)}"
        ])
        self.assertEqual(act10.decision_, "rien")
        chan.send.return_value.add_reaction.assert_called_once_with(
            config.Emoji.action
        )
        taches = bdd.Tache.query.all()
        self.assertEqual(len(taches), 2)
        self.assertEqual([tache.action for tache in taches], [act10]*2)
        self.assertEqual(
            {(tache.commande, tache.timestamp.time()) for tache in taches},
            {("!close 32", datetime.time(15, 2)),
             ("!remind 32", datetime.time(14, 32))}
        )
        bdd.Tache.delete(*taches)
        log_patch.assert_not_called()
        ca_patch.assert_not_called()


        # fin delta (fermée)
        ba9 = bdd.BaseAction(slug="ba9",
                             trigger_debut=bdd.ActionTrigger.open_cond,
                             trigger_fin=bdd.ActionTrigger.delta,
                             heure_fin=datetime.time(1, 10, 7))
        ba9.add()
        act11 = bdd.Action(id=33, base=ba9, joueur=j1, decision_=None)
        act11.add()
        with mock_discord.mock_members_and_chans(j1):
            chan = j1.private_chan
            with freezegun.freeze_time(datetime.datetime(1, 1, 1, 16, 28, 4)):
                await open_action(act11)
        mock_discord.assert_sent(chan, [
            "Tu peux maintenant utiliser", "ba9", "!action",
            f"Tu as jusqu'à {datetime.time(17, 38, 11)}"
        ])
        self.assertEqual(act11.decision_, "rien")
        chan.send.return_value.add_reaction.assert_called_once_with(
            config.Emoji.action
        )
        taches = bdd.Tache.query.all()
        self.assertEqual(len(taches), 2)
        self.assertEqual([tache.action for tache in taches], [act11]*2)
        self.assertEqual(
            {(tache.commande, tache.timestamp.time()) for tache in taches},
            {("!close 33", datetime.time(17, 38, 11)),
             ("!remind 33", datetime.time(17, 8, 11))}
        )
        bdd.Tache.delete(*taches)
        log_patch.assert_not_called()
        ca_patch.assert_not_called()


        # fin perma (fermée) - WE d'abord
        ba10 = bdd.BaseAction(slug="ba10",
                             trigger_debut=bdd.ActionTrigger.open_cond,
                             trigger_fin=bdd.ActionTrigger.perma)
        ba10.add()
        act12 = bdd.Action(id=34, base=ba10, joueur=j1, decision_=None)
        act12.add()
        with mock.patch("lgrez.blocs.tools.next_occurence",
                        return_value=datetime.datetime(1, 1, 1, 16, 28, 4)), \
             mock.patch("lgrez.blocs.tools.debut_pause",
                        return_value=datetime.datetime(1, 1, 1, 15, 28, 4)), \
             mock_discord.mock_members_and_chans(j1):
            chan = j1.private_chan
            await open_action(act12)
        mock_discord.assert_sent(chan, [
            "Tu peux maintenant utiliser", "ba10", "!action",
        ])
        self.assertEqual(act12.decision_, "rien")
        mock_discord.assert_not_sent(chan, "Tu as jusqu'à",)
        chan.send.return_value.add_reaction.assert_called_once_with(
            config.Emoji.action
        )
        self.assertEqual(len(bdd.Tache.query.all()), 1)
        tache = bdd.Tache.query.one()
        self.assertEqual(tache.action, act12)
        self.assertEqual(tache.commande, "!close 34")
        self.assertEqual(tache.timestamp.time(), datetime.time(15, 28, 4))
        tache.delete()
        log_patch.assert_not_called()
        ca_patch.assert_not_called()

        # fin perma (fermée) - prochaine ouverture d'abord
        ba11 = bdd.BaseAction(slug="ba11",
                             trigger_debut=bdd.ActionTrigger.open_cond,
                             trigger_fin=bdd.ActionTrigger.perma)
        ba11.add()
        act13 = bdd.Action(id=35, base=ba11, joueur=j1, decision_=None)
        act13.add()
        with mock.patch("lgrez.blocs.tools.next_occurence",
                        return_value=datetime.datetime(1, 1, 1, 16, 28, 4)), \
             mock.patch("lgrez.blocs.tools.debut_pause",
                        return_value=datetime.datetime(1, 1, 1, 17, 28, 4)), \
             mock_discord.mock_members_and_chans(j1):
            chan = j1.private_chan
            await open_action(act13)
        mock_discord.assert_sent(chan, [
            "Tu peux maintenant utiliser", "ba11", "!action",
        ])
        self.assertEqual(act13.decision_, "rien")
        mock_discord.assert_not_sent(chan, "Tu as jusqu'à",)
        chan.send.return_value.add_reaction.assert_called_once_with(
            config.Emoji.action
        )
        self.assertEqual(len(bdd.Tache.query.all()), 1)
        tache = bdd.Tache.query.one()
        self.assertEqual(tache.action, act13)
        self.assertEqual(tache.commande, "!open 35")
        self.assertEqual(tache.timestamp.time(), datetime.time(16, 28, 4))
        tache.delete()
        log_patch.assert_not_called()
        ca_patch.assert_not_called()
コード例 #8
0
ファイル: test_inscription.py プロジェクト: loic-simon/lg-rez
    async def test_main(self, sleep_patch, reg_patch, newchan_patch):
        """Unit tests for inscription.main function."""
        # async def main(member)
        main = inscription.main
        mock_bdd.add_campsroles()

        joueur1 = bdd.Joueur(discord_id=1, chan_id_=11, nom="Joueur 1")
        joueur1.add()

        newchan_patch.return_value = mock_discord.chan("bzzt", id=798)

        # Joueur inscrit en base
        with mock_discord.mock_members_and_chans(joueur1):
            member = joueur1.member
            chan = joueur1.private_chan
            await main(member)
        chan.set_permissions.assert_called_once_with(member,
                                                     read_messages=True,
                                                     send_messages=True)
        mock_discord.assert_sent(chan, f"{member.mention} tu es déjà inscrit")
        reg_patch.assert_not_called()
        newchan_patch.assert_not_called()
        sleep_patch.assert_not_called()
        joueur1.delete()

        # Joueur en cours d'inscription -> abort
        chan = mock_discord.chan("bzz", topic="123456")
        config.guild.text_channels = [chan]
        member = mock.Mock(discord.Member, id=123456)
        with mock_discord.interact(("yes_no", False)):
            await main(member)
        chan.set_permissions.assert_called_once_with(member,
                                                     read_messages=True,
                                                     send_messages=True)
        mock_discord.assert_sent(chan, f"{member.mention}, par ici",
                                 f"Bienvenue {member.mention}",
                                 f"finalisons ton inscription",
                                 f"C'est bon pour toi ?", "Pas de soucis")
        reg_patch.assert_not_called()
        newchan_patch.assert_not_called()
        sleep_patch.assert_called()
        sleep_patch.reset_mock()

        # Joueur arrivant -> abort
        member = mock.Mock(discord.Member, id=145)
        with mock_discord.interact(("yes_no", False)):
            await main(member)
        newchan_patch.assert_called_once_with(member)
        chan = newchan_patch.return_value
        mock_discord.assert_sent(chan, f"Bienvenue {member.mention}",
                                 f"finalisons ton inscription",
                                 f"C'est bon pour toi ?", "Pas de soucis")
        reg_patch.assert_not_called()
        newchan_patch.reset_mock()
        sleep_patch.assert_called()
        sleep_patch.reset_mock()

        # Joueur arrivant -> ok -> name -> troll -> good name
        # demande_chambre False
        config.demande_chambre = False
        member = mock.Mock(discord.Member, id=145)
        member.top_role.__lt__ = lambda s, o: True  # role < MJ
        member.display_name = "Pr-Z N0 N"
        with mock_discord.interact(
            ("yes_no", True),
            ("wait_for_message",
             mock.NonCallableMock(discord.Message, content="préz")),
            ("wait_for_message",
             mock.NonCallableMock(discord.Message, content="no n")),
            ("yes_no", False),
            ("wait_for_message",
             mock.NonCallableMock(discord.Message, content="pr-z")),
            ("wait_for_message",
             mock.NonCallableMock(discord.Message, content="n0 n")),
            ("yes_no", True),
        ):
            await main(member)
        newchan_patch.assert_called_once_with(member)
        chan = newchan_patch.return_value
        mock_discord.assert_sent(
            chan, f"Bienvenue {member.mention}", "finalisons ton inscription",
            f"C'est bon pour toi ?", ["Parfait", "prénom"], "prénom",
            "nom de famille", "Préz No N", "prénom", "nom de famille",
            "Pr-Z N0 N", "Je t'ai renommé", "Je t'inscris",
            "Tu es maintenant inscrit", "quelques dernières choses",
            "c'est tout bon")
        chan.edit.assert_any_call(
            name=f"{config.private_chan_prefix}Pr-Z N0 N")
        member.edit.assert_called_once_with(nick="Pr-Z N0 N")
        member.edit.reset_mock()
        self.assertEqual(len(bdd.Joueur.query.all()), 1)
        jr = bdd.Joueur.query.one()
        self.assertEqual([
            jr.discord_id, jr.chan_id_, jr.nom, jr.chambre, jr.statut, jr.role,
            jr.camp, jr.votant_village, jr.votant_loups, jr.role_actif
        ], [
            145, 798, "Pr-Z N0 N", None, bdd.Statut.vivant,
            bdd.Role.default(),
            bdd.Camp.default(), True, False, False
        ])
        member.add_roles.assert_called_once_with(config.Role.joueur_en_vie)
        chan.edit.assert_any_call(topic=mock.ANY)
        reg_patch.assert_called_once_with(jr)
        reg_patch.reset_mock()
        newchan_patch.reset_mock()
        sleep_patch.assert_called()
        sleep_patch.reset_mock()
        jr.delete()

        # Joueur arrivant -> ok -> name -> chambre -> pas à la Rez
        config.demande_chambre = True
        member = mock.Mock(discord.Member, id=145)
        member.top_role.__lt__ = lambda s, o: True  # role < MJ
        member.display_name = "Pr-Z N0 N"
        with mock_discord.interact(
            ("yes_no", True),
            ("wait_for_message",
             mock.NonCallableMock(discord.Message, content="pr-z")),
            ("wait_for_message",
             mock.NonCallableMock(discord.Message, content="n0 n")),
            ("yes_no", True),
            ("yes_no", False),
        ):
            await main(member)
        newchan_patch.assert_called_once_with(member)
        chan = newchan_patch.return_value
        mock_discord.assert_sent(
            chan, f"Bienvenue {member.mention}", "finalisons ton inscription",
            f"C'est bon pour toi ?", ["Parfait", "prénom"], "prénom",
            "nom de famille", "Pr-Z N0 N", "Je t'ai renommé",
            "habites-tu à la Rez", "Je t'inscris", "Tu es maintenant inscrit",
            "quelques dernières choses", "c'est tout bon")
        chan.edit.assert_any_call(
            name=f"{config.private_chan_prefix}Pr-Z N0 N")
        member.edit.assert_called_once_with(nick="Pr-Z N0 N")
        member.edit.reset_mock()
        self.assertEqual(len(bdd.Joueur.query.all()), 1)
        jr = bdd.Joueur.query.one()
        self.assertEqual([
            jr.discord_id, jr.chan_id_, jr.nom, jr.chambre, jr.statut, jr.role,
            jr.camp, jr.votant_village, jr.votant_loups, jr.role_actif
        ], [
            145, 798, "Pr-Z N0 N", config.chambre_mj, bdd.Statut.vivant,
            bdd.Role.default(),
            bdd.Camp.default(), True, False, False
        ])
        member.add_roles.assert_called_once_with(config.Role.joueur_en_vie)
        chan.edit.assert_any_call(topic=mock.ANY)
        reg_patch.assert_called_once_with(jr)
        reg_patch.reset_mock()
        newchan_patch.reset_mock()
        sleep_patch.assert_called()
        sleep_patch.reset_mock()
        jr.delete()

        # Joueur arrivant -> ok -> name -> chambre -> à la Rez
        config.demande_chambre = True
        member = mock.Mock(discord.Member, id=145)
        member.top_role.__lt__ = lambda s, o: True  # role < MJ
        member.display_name = "Pr-Z N0 N"
        with mock_discord.interact(
            ("yes_no", True),
            ("wait_for_message",
             mock.NonCallableMock(discord.Message, content="pr-z")),
            ("wait_for_message",
             mock.NonCallableMock(discord.Message, content="n0 n")),
            ("yes_no", True),
            ("yes_no", True),
            ("wait_for_message",
             mock.NonCallableMock(discord.Message, content="214")),
        ):
            await main(member)
        newchan_patch.assert_called_once_with(member)
        chan = newchan_patch.return_value
        mock_discord.assert_sent(
            chan, f"Bienvenue {member.mention}", "finalisons ton inscription",
            f"C'est bon pour toi ?", ["Parfait", "prénom"], "prénom",
            "nom de famille", "Pr-Z N0 N", "Je t'ai renommé",
            "habites-tu à la Rez", "quelle est ta chambre", "Je t'inscris",
            "Tu es maintenant inscrit", "quelques dernières choses",
            "c'est tout bon")
        chan.edit.assert_any_call(
            name=f"{config.private_chan_prefix}Pr-Z N0 N")
        member.edit.assert_called_once_with(nick="Pr-Z N0 N")
        member.edit.reset_mock()
        self.assertEqual(len(bdd.Joueur.query.all()), 1)
        jr = bdd.Joueur.query.one()
        self.assertEqual([
            jr.discord_id, jr.chan_id_, jr.nom, jr.chambre, jr.statut, jr.role,
            jr.camp, jr.votant_village, jr.votant_loups, jr.role_actif
        ], [
            145, 798, "Pr-Z N0 N", "214", bdd.Statut.vivant,
            bdd.Role.default(),
            bdd.Camp.default(), True, False, False
        ])
        member.add_roles.assert_called_once_with(config.Role.joueur_en_vie)
        chan.edit.assert_any_call(topic=mock.ANY)
        reg_patch.assert_called_once_with(jr)
        reg_patch.reset_mock()
        newchan_patch.reset_mock()
        sleep_patch.assert_called()
        sleep_patch.reset_mock()
        jr.delete()