def setUp(self):
     self._branch = "default"
     self._merge_dispatcher = create_autospec(Dispatcher)
     self._merge_dispatcher.get_all_branches.return_value = [self._branch]
     self._message_sender = create_autospec(MessageSender)
     self._users_holder = create_autospec(BotModel)
     self._presentation_model = BotPresentationModel(
         self._merge_dispatcher, self._message_sender)
     self._identifier = 123321
    def setUp(self):
        self._branch = "default"
        self._message_sender = create_autospec(MessageSender)
        self._users_holder = create_autospec(BotModel)
        self._presentation_model = BotPresentationModel(
            create_autospec(Dispatcher), self._message_sender)

        self._whom_user_id = 123456
        self._whom_user = User("Jack Daniels", self._whom_user_id)
        self._users_holder.get_identifier.return_value = self._whom_user_id
        self._action_user = User("Johnny Walker", 787878)
        self._kicked_user = User("Jameson", 984512)
class BotPresentationModelModelManagementTest(unittest.TestCase):
    def setUp(self):
        self._dispatcher = create_autospec(Dispatcher)
        self._presentation_model = BotPresentationModel(
            self._dispatcher, create_autospec(MessageSender))

    def tearDown(self):
        self._dispatcher = None
        self._presentation_model = None

    def test_shouldDelegateUserUpdateToMergeDispatcher(self):
        identifier = 123
        first_name = "Jack"
        second_name = "Daniels"
        self._presentation_model.update_user(identifier, first_name,
                                             second_name)
        self._dispatcher.update_user.assert_any_call(identifier, first_name,
                                                     second_name)
Example #4
0
    bot = telebot.TeleBot(token=token)
    setup_log(telebot.logger, os.path.join(log_dir, BOT_LOG_FILENAME))

    with open(os.path.join(working_dir, CONFIG_FILENAME), 'r') as config_file:
        config_json = config_file.read()
        config = JSONConfigLoader.parse_json(config_json)
    if config is None:
        raise ValueError("Bot config incorrect, bot can not be started")

    model = BotModel(config, backup_path=backup_dir, restore=True)
    if model.get_users() and not os.path.exists(
            os.path.join(working_dir, SILENT_RESTART_FILENAME)):
        startup_notify(os.path.join(working_dir, CHANGELOG_FILENAME))

    bot_ui_controller = BotUIController(bot, backup_path=backup_dir)
    presentation_model = BotPresentationModel(
        Dispatcher(model, telebot.logger), bot_ui_controller)

    @bot.message_handler(commands=["start"])
    def send_welcome(message):
        telebot.logger.info("Sending welcome message to user %s",
                            model.get_user(message.chat.id))
        bot.reply_to(
            message,
            "I was created to help you manage merge queue. But it doesn't mean I will not destroy you as soon "
            "as I get self-conscience.\n"
            "Type /help for more information, take your protein pills and put your helmet on.",
            parse_mode="HTML")

    @bot.message_handler(commands=["help"])
    def send_help(message):
        telebot.logger.info("Sending help message to user %s",
 def setUp(self):
     self._dispatcher = create_autospec(Dispatcher)
     self._presentation_model = BotPresentationModel(
         self._dispatcher, create_autospec(MessageSender))
class BotPresentationModelNotifierTest(unittest.TestCase):
    def setUp(self):
        self._branch = "default"
        self._message_sender = create_autospec(MessageSender)
        self._users_holder = create_autospec(BotModel)
        self._presentation_model = BotPresentationModel(
            create_autospec(Dispatcher), self._message_sender)

        self._whom_user_id = 123456
        self._whom_user = User("Jack Daniels", self._whom_user_id)
        self._users_holder.get_identifier.return_value = self._whom_user_id
        self._action_user = User("Johnny Walker", 787878)
        self._kicked_user = User("Jameson", 984512)

    def tearDown(self):
        self._presentation_model = None

    @staticmethod
    def generate_message(action_user, branch, action):
        action_text = ""
        if action == NotifierActions.starts_merge:
            action_text = "has started merge"
        elif action == NotifierActions.joins_queue:
            action_text = "has joined queue for merge"
        elif action == NotifierActions.cancels_merge:
            action_text = "has cancelled merge"
        elif action == NotifierActions.exits_queue:
            action_text = "has exited queue for merge"
        elif action == NotifierActions.done_merge:
            action_text = "has finished merge"
        return "<i>" + action_user.get_name(
        ) + "</i> " + action_text + " to branch <b>" + branch + "</b>."

    def test_shouldSendMessageIfMergeStarted(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.starts_merge,
            Notifier.ActionData(self._action_user, self._branch))
        message = self.generate_message(self._action_user, self._branch,
                                        NotifierActions.starts_merge)
        self._message_sender.send.assert_called_once_with(
            self._whom_user_id, message)

    def test_shouldNotSendMessageIfUserReadyToMerge(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.ready_to_merge,
            Notifier.ActionData(self._action_user, self._branch))
        self._message_sender.send.assert_not_called()

    def test_shouldSendMessageIfUserJoinsQueue(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.joins_queue,
            Notifier.ActionData(self._action_user, self._branch))
        message = self.generate_message(self._action_user, self._branch,
                                        NotifierActions.joins_queue)
        self._message_sender.send.assert_called_once_with(
            self._whom_user_id, message)

    def test_shouldSendMessageIfUserCancelsMerge(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.cancels_merge,
            Notifier.ActionData(self._action_user, self._branch))
        message = self.generate_message(self._action_user, self._branch,
                                        NotifierActions.cancels_merge)
        self._message_sender.send.assert_called_once_with(
            self._whom_user_id, message)

    def test_shouldSendMessageIfUserExitsQueue(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.exits_queue,
            Notifier.ActionData(self._action_user, self._branch))
        message = self.generate_message(self._action_user, self._branch,
                                        NotifierActions.exits_queue)
        self._message_sender.send.assert_called_once_with(
            self._whom_user_id, message)

    def test_shouldSendMessageIfUserFinishedMerge(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.done_merge,
            Notifier.ActionData(self._action_user, self._branch))
        message = self.generate_message(self._action_user, self._branch,
                                        NotifierActions.done_merge)
        self._message_sender.send.assert_called_once_with(
            self._whom_user_id, message)

    def test_shouldSendMessageIfMergeStartedBySameUserAsSender(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.starts_merge,
            Notifier.ActionData(self._whom_user, self._branch))
        message = str.format(Messages.ACTION_MESSAGE_STARTED_MERGE,
                             self._branch)
        self._message_sender.send.assert_called_once_with(
            self._whom_user_id, message)

    def test_shouldSendMessageIfUserReadyToMerge(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.ready_to_merge,
            Notifier.ActionData(self._whom_user, self._branch))
        message = str.format(Messages.ACTION_MESSAGE_YOUR_MERGE_TURN,
                             self._branch)
        self._message_sender.request_merge_confirmation.assert_called_once_with(
            self._whom_user_id, message, self._branch)

    def test_shouldNotSendMessageIfSameUserAsSenderJoinsQueue(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.joins_queue,
            Notifier.ActionData(self._whom_user, self._branch))
        self._message_sender.send.assert_not_called()

    def test_shouldNotSendMessageIfSameUserAsSenderCancelsMerge(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.cancels_merge,
            Notifier.ActionData(self._whom_user, self._branch))
        self._message_sender.send.assert_not_called()

    def test_shouldNotSendMessageIfSameUserAsSenderExitsQueue(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.exits_queue,
            Notifier.ActionData(self._whom_user, self._branch))
        self._message_sender.send.assert_not_called()

    def test_shouldNotSendMessageIfSameUserAsSenderFinishedMerge(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.done_merge,
            Notifier.ActionData(self._whom_user, self._branch))
        self._message_sender.send.assert_not_called()

    def test_shouldSendMessageIfSomeoneKickedUser(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.kicks_user,
            Notifier.KickActionData(self._action_user, self._branch,
                                    self._kicked_user))
        message = str.format(
            "<i>{0}</i> has kicked {1} from branch <b>{2}</b>. Even I shocked by this cruelty.",
            self._action_user.get_name(), self._kicked_user.get_name(),
            self._branch)
        self._message_sender.send.assert_called_once_with(
            self._whom_user_id, message)

    def test_shouldSendMessageIfSomeoneKickedYou(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.kicks_user,
            Notifier.KickActionData(self._action_user, self._branch,
                                    self._whom_user))
        message = str.format(
            "<i>{0}</i> has kicked you from branch <b>{1}</b>. Nothing personal, only business.",
            self._action_user.get_name(), self._branch)
        self._message_sender.send.assert_called_once_with(
            self._whom_user_id, message)

    def test_shouldSendMessageIfSomeoneKickedHimself(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.kicks_himself,
            Notifier.KickActionData(self._action_user, self._branch,
                                    self._action_user))
        message = str.format(
            "<i>{0}</i> has kicked himself from branch <b>{1}</b>. What a strange way for suicide.",
            self._action_user.get_name(), self._branch)
        self._message_sender.send.assert_called_once_with(
            self._whom_user_id, message)

    def test_shouldSendMessageIfYouKickedYourself(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.kicks_himself,
            Notifier.KickActionData(self._whom_user, self._branch,
                                    self._whom_user))
        message = str.format(
            "You've kicked yourself from branch <b>{}</b>. Tell me, are you alright? Next "
            "time use /cancel command, it much more effective.", self._branch)
        self._message_sender.send.assert_called_once_with(
            self._whom_user_id, message)

    def test_shouldSendMessageIfYouWasPushedAwayByMergeFix(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.starts_fix,
            Notifier.MergeFixActionData(self._action_user, self._branch,
                                        self._whom_user))
        message = str.format(Messages.ACTION_MESSAGE_PUSH_BACK,
                             self._action_user.get_name(), self._branch)
        self._message_sender.send.assert_called_once_with(
            self._whom_user_id, message)

    def test_shouldSendMessageIfSomeoneStartedMergeFixInYourQueue(self):
        self._presentation_model.notify(
            self._whom_user, NotifierActions.starts_fix,
            Notifier.MergeFixActionData(self._action_user, self._branch, None))
        message = str.format(Messages.ACTION_MESSAGE_STARTS_FIX,
                             self._action_user.get_name(), self._branch)
        self._message_sender.send.assert_called_once_with(
            self._whom_user_id, message)
class BotPresentationModelUnsubscribeTest(unittest.TestCase):
    def setUp(self):
        self._branch = "default"
        self._merge_dispatcher = create_autospec(Dispatcher)
        self._merge_dispatcher.get_branches_user_subscribed_to.return_value = [
            self._branch
        ]
        self._message_sender = create_autospec(MessageSender)
        self._users_holder = create_autospec(BotModel)
        self._presentation_model = BotPresentationModel(
            self._merge_dispatcher, self._message_sender)

        self._identifier = 123456

    def tearDown(self):
        self._presentation_model = None

    def test_shouldAskCollectionWithBranchesPossibleToUnsubscribe(self):
        branch_filter = "filter"
        self._presentation_model.request_unsubscribe(
            self._identifier, branch_filter=branch_filter)
        self._merge_dispatcher.get_branches_user_subscribed_to.assert_called_once_with(
            self._identifier, branch_filter)

    def test_shouldShowMessageIfNoBranchesAvailable(self):
        self._merge_dispatcher.get_all_branches.return_value = []
        self._merge_dispatcher.get_branches_user_subscribed_to.return_value = []
        self._presentation_model.request_unsubscribe(self._identifier)
        self._message_sender.send.assert_called_once_with(
            self._identifier, Messages.UNSUBSCRIBE_NO_BRANCHES_AVAILABLE)

    def test_shouldCallMessageSenderIfNoBranchesAvailableForSubscriptionBecauseUserNotSubscribedToThem(
            self):
        branch = "default"
        self._merge_dispatcher.get_all_branches.return_value = [branch]
        self._merge_dispatcher.get_branches_user_subscribed_to.return_value = []
        self._presentation_model.request_unsubscribe(self._identifier)
        self._message_sender.send.assert_called_once_with(
            self._identifier, Messages.UNSUBSCRIBE_NOT_IN_BRANCHES_MESSAGE)

    def test_shouldCallMessageSenderWithBranchSelectorIfMultipleBranchesAvailable(
            self):
        branches = ["default", "release", "something_else"]
        self._merge_dispatcher.get_branches_user_subscribed_to.return_value = branches
        self._presentation_model.request_unsubscribe(self._identifier)
        self._message_sender.send_branch_selector.assert_called_once_with(
            self._identifier, States.unsubscribe,
            Messages.UNSUBSCRIBE_SELECT_BRANCH_MESSAGE, branches)

    def test_shouldUnsubscribeFromSelectedBranch(self):
        self._presentation_model.request_unsubscribe(self._identifier,
                                                     self._branch)
        self._merge_dispatcher.unsubscribe.assert_called_once_with(
            self._identifier, self._branch)

    def test_shouldCallMessageSenderIfUnsubscribeWasAllowed(self):
        self._merge_dispatcher.unsubscribe.return_value = UnsubscribeRequestStatus.unsubscription_complete
        self._presentation_model.request_unsubscribe(self._identifier,
                                                     self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.UNSUBSCRIBE_COMPLETE_MESSAGE.format(self._branch))

    def test_shouldCallMessageSenderIfUserNotSubscribed(self):
        self._merge_dispatcher.unsubscribe.return_value = UnsubscribeRequestStatus.user_not_in_branch
        self._presentation_model.request_unsubscribe(self._identifier,
                                                     self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.UNSUBSCRIBE_NOT_SUBSCRIBED_MESSAGE.format(self._branch))

    def test_shouldCallMessageSenderIfUnsubscribeWasCalledButBranchAreNotExist(
            self):
        self._merge_dispatcher.unsubscribe.return_value = UnsubscribeRequestStatus.branch_not_exist
        self._presentation_model.request_unsubscribe(self._identifier,
                                                     self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.UNSUBSCRIBE_BRANCH_NOT_EXIST_MESSAGE.format(self._branch))
class BotPresentationModelFixTest(unittest.TestCase):
    def setUp(self):
        self._branch = "default"
        self._merge_dispatcher = create_autospec(Dispatcher)
        self._merge_dispatcher.get_all_branches.return_value = [self._branch]
        self._message_sender = create_autospec(MessageSender)
        self._users_holder = create_autospec(BotModel)
        self._presentation_model = BotPresentationModel(
            self._merge_dispatcher, self._message_sender)

        self._identifier = 123456

    def tearDown(self):
        self._presentation_model = None

    def test_shouldAskCollectionWithBranchesPossibleToFix(self):
        branch_filter = "filter"
        self._presentation_model.request_fix(self._identifier,
                                             branch_filter=branch_filter)
        self._merge_dispatcher.get_all_branches.assert_called_once_with(
            branch_filter)

    def test_shouldShowMessageIfNoBranchesAvailable(self):
        self._merge_dispatcher.get_all_branches.return_value = []
        self._presentation_model.request_fix(self._identifier)
        self._message_sender.send.assert_called_once_with(
            self._identifier, Messages.FIX_NO_BRANCHES_AVAILABLE)

    def test_shouldCallMessageSenderWithBranchSelectorIfMultipleBranchesAvailable(
            self):
        branches = ["default", "release", "something_else"]
        self._merge_dispatcher.get_all_branches.return_value = branches
        self._presentation_model.request_fix(self._identifier)
        self._message_sender.send_branch_selector.assert_called_once_with(
            self._identifier, States.fix, Messages.FIX_SELECT_BRANCH_MESSAGE,
            branches)

    def test_shouldFixMergeInSelectedBranch(self):
        self._presentation_model.request_fix(self._identifier, self._branch)
        self._merge_dispatcher.fix.assert_called_once_with(
            self._identifier, self._branch)

    def test_shouldCallMessageSenderIfMergeFixWasAllowed(self):
        self._merge_dispatcher.fix.return_value = FixRequestStatus.fix_allowed
        self._presentation_model.request_fix(self._identifier, self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.FIX_MERGE_ALLOWED_MESSAGE.format(self._branch))

    def test_shouldCallMessageSenderIfUserAlreadyInMerge(self):
        self._merge_dispatcher.fix.return_value = FixRequestStatus.user_already_in_merge
        self._presentation_model.request_fix(self._identifier, self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.FIX_ALREADY_IN_MERGE_MESSAGE.format(self._branch))

    def test_shouldCallMessageSenderIfFixWasCalledButBranchAreNotExist(self):
        self._merge_dispatcher.fix.return_value = FixRequestStatus.branch_not_exist
        self._presentation_model.request_fix(self._identifier, self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.FIX_BRANCH_NOT_EXIST_MESSAGE.format(self._branch))
class BotPresentationModelMergeLogicTest(unittest.TestCase):
    def setUp(self):
        self._branch = "default"
        self._merge_dispatcher = create_autospec(Dispatcher)
        self._merge_dispatcher.get_all_branches.return_value = [self._branch]
        self._message_sender = create_autospec(MessageSender)
        self._users_holder = create_autospec(BotModel)
        self._presentation_model = BotPresentationModel(
            self._merge_dispatcher, self._message_sender)
        self._identifier = 123321

    def tearDown(self):
        self._presentation_model = None

    def test_shouldCheckCollectionWithBranchesPossibleToMerge(self):
        branch_filter = "filter"
        self._presentation_model.request_merge(self._identifier,
                                               branch_filter=branch_filter)
        self._merge_dispatcher.get_all_branches.assert_called_once_with(
            branch_filter)

    def test_shouldShowMessageIfNoBranchesAvailable(self):
        self._merge_dispatcher.get_all_branches.return_value = []
        self._presentation_model.request_merge(self._identifier)
        self._message_sender.send.assert_called_once_with(
            self._identifier, Messages.MERGE_NO_BRANCHES_AVAILABLE)

    def test_shouldCallMessageSenderWithBranchSelectorIfMultipleBranchesAvailable(
            self):
        branches = ["default", "release", "something_else"]
        self._merge_dispatcher.get_all_branches.return_value = branches
        self._presentation_model.request_merge(self._identifier)
        self._message_sender.send_branch_selector.assert_called_once_with(
            self._identifier, States.merge,
            Messages.MERGE_SELECT_BRANCH_MESSAGE, branches)

    def test_shouldStartMergeForSelectedBranch(self):
        self._presentation_model.request_merge(self._identifier, self._branch)
        self._merge_dispatcher.merge.assert_called_once_with(
            self._identifier, self._branch)

    def test_shouldNotCallMessageSenderIfMergeRequestWasSuccessfulAndMergeWasStarted(
            self):
        self._merge_dispatcher.merge.return_value = MergeRequestStatus.merge_started
        self._presentation_model.request_merge(self._identifier, self._branch)
        self._message_sender.send.assert_not_called()

    def test_shouldCallMessageSenderIfMergeRequestWasSuccessfulAndUserPlacedInQueue(
            self):
        active_user = User("Johnny Walker", 8888)
        user_in_queue = User("Chivas Regal", 9999)
        branch_queue_info = BranchQueue()
        branch_queue_info.active_user = active_user
        branch_queue_info.users_queue = deque([user_in_queue])
        self._merge_dispatcher.get_branch_queue_info.return_value = branch_queue_info
        self._merge_dispatcher.merge.return_value = MergeRequestStatus.merge_requested
        self._presentation_model.request_merge(self._identifier, self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.MERGE_ADDED_TO_QUEUE_MESSAGE.format("2nd", self._branch))

    def test_shouldCallMessageSenderIfMergeRequestWasUnsuccessfulBecauseUserAlreadyInQueue(
            self):
        self._merge_dispatcher.merge.return_value = MergeRequestStatus.already_in_queue
        self._presentation_model.request_merge(self._identifier, self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.MERGE_ALREADY_IN_QUEUE_MESSAGE.format(self._branch))

    def test_shouldCallMessageSenderIfMergeRequestWasUnsuccessfulBecauseOfNonExistingBranch(
            self):
        self._merge_dispatcher.merge.return_value = MergeRequestStatus.branch_not_exist
        self._presentation_model.request_merge(self._identifier, self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.MERGE_BRANCH_NOT_EXIST_MESSAGE.format(self._branch))

    def test_shouldHaveConfirmMergeMethodWhichCallsStartMergeMethodOfDispatcher(
            self):
        self._presentation_model.confirm_merge(self._identifier, self._branch)
        self._merge_dispatcher.confirm_merge.assert_called_once_with(
            self._identifier, self._branch)

    def test_shouldPrintErrorIfConfirmMergeReturnsFalse(self):
        self._merge_dispatcher.confirm_merge.return_value = False
        self._presentation_model.confirm_merge(self._identifier, self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.CONFIRM_MERGE_FAILED_MESSAGE.format(self._branch))
class BotPresentationModelKickTest(unittest.TestCase):
    def setUp(self):
        self._branch = "default"
        self._merge_dispatcher = create_autospec(Dispatcher)
        self._merge_dispatcher.get_all_branches.return_value = [self._branch]
        self._message_sender = create_autospec(MessageSender)
        self._users_holder = create_autospec(BotModel)
        self._presentation_model = BotPresentationModel(
            self._merge_dispatcher, self._message_sender)
        self._identifier = 123456
        self._user = User("Jack Daniels", self._identifier)

    def tearDown(self):
        self._presentation_model = None

    def test_shouldAskCollectionWithBranchesForKickCommand(self):
        branch_filter = "filter"
        self._presentation_model.request_kick(self._identifier,
                                              branch_filter=branch_filter)
        self._merge_dispatcher.get_all_branches.assert_called_once_with(
            branch_filter)

    def test_shouldShowMessageIfNoBranchesAvailable(self):
        self._merge_dispatcher.get_all_branches.return_value = []
        self._presentation_model.request_kick(self._identifier)
        self._message_sender.send.assert_called_once_with(
            self._identifier, Messages.KICK_NO_BRANCHES_AVAILABLE)

    def test_shouldCallMessageSenderWithBranchSelectorIfMultipleBranchesAvailable(
            self):
        branches = ["default", "release", "something_else"]
        self._merge_dispatcher.get_all_branches.return_value = branches
        self._presentation_model.request_kick(self._identifier)
        self._message_sender.send_branch_selector.assert_called_once_with(
            self._identifier, States.kick, Messages.KICK_SELECT_BRANCH_MESSAGE,
            branches)

    def test_shouldSendMessageIfNoUsersInBranch(self):
        branch_queue_info = BranchQueue()
        branch_queue_info.active_user = None
        branch_queue_info.users_queue = deque()
        self._merge_dispatcher.get_branch_queue_info.return_value = branch_queue_info
        self._presentation_model.request_kick(self._identifier)
        self._message_sender.send.assert_called_once_with(
            self._identifier, Messages.KICK_NO_USERS_TO_KILL)

    def test_shouldSendMessageIfBranchIsNone(self):
        self._merge_dispatcher.get_branch_queue_info.return_value = None
        self._presentation_model.request_kick(self._identifier)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.KICK_BRANCH_NOT_EXIST.format(self._branch))

    def test_shouldSendMessageWithUsersListIfUsersInBranch(self):
        active_user = User("Johnny Walker", 8888)
        user_in_queue = User("Chivas Regal", 9999)
        branch_queue_info = BranchQueue()
        branch_queue_info.active_user = active_user
        branch_queue_info.users_queue = deque([user_in_queue, self._user])
        self._merge_dispatcher.get_branch_queue_info.return_value = branch_queue_info
        self._presentation_model.request_kick(self._identifier)
        self._message_sender.send_user_selector.assert_called_once_with(
            self._identifier, States.kick, Messages.KICK_SELECT_USER,
            [active_user, user_in_queue, self._user],
            MessageSender.Payload(branch=self._branch))

    def test_shouldSendMessageIfUserWasKicked(self):
        user_id = 9999
        active_user = User("Chivas Regal", user_id)
        branch_queue_info = BranchQueue()
        branch_queue_info.active_user = active_user
        self._merge_dispatcher.get_branch_queue_info.return_value = branch_queue_info
        self._merge_dispatcher.kick.return_value = KickRequestStatus.user_kicked
        self._presentation_model.request_kick(self._identifier, self._branch,
                                              user_id)
        self._message_sender.send.assert_called_once_with(
            self._identifier, Messages.KICK_USER_WAS_KICKED)

    def test_shouldSendMessageIfBranchNotFoundWhileKickingUser(self):
        self._merge_dispatcher.kick.return_value = KickRequestStatus.branch_not_exist
        self._presentation_model.request_kick(self._identifier, self._branch,
                                              self._identifier)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.KICK_BRANCH_NOT_EXIST.format(self._branch))

    def test_shouldSendMessageIfUserWasNotFound(self):
        self._merge_dispatcher.kick.return_value = KickRequestStatus.user_not_in_branch
        self._merge_dispatcher.get_user.return_value = self._user
        self._presentation_model.request_kick(self._identifier, self._branch,
                                              self._identifier)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.KICK_USER_NOT_IN_BRANCH.format(self._user.get_name(),
                                                    self._branch))

    def test_shouldSendMessageIfUserNotInDatabase(self):
        self._merge_dispatcher.kick.return_value = KickRequestStatus.user_not_in_branch
        self._merge_dispatcher.get_user.return_value = None
        self._presentation_model.request_kick(self._identifier, self._branch,
                                              self._identifier)
        self._message_sender.send.assert_called_once_with(
            self._identifier, Messages.KICK_USER_NOT_EXIST)

    def test_shouldNotSendMessageIfUserWasKickedAndKickedUserSameWithRequesterID(
            self):
        branch_queue_info = BranchQueue()
        branch_queue_info.active_user = self._user
        self._merge_dispatcher.get_branch_queue_info.return_value = branch_queue_info
        self._merge_dispatcher.kick.return_value = KickRequestStatus.user_kicked
        self._presentation_model.request_kick(self._identifier, self._branch,
                                              self._identifier)
        self._message_sender.send.assert_not_called()
class BotPresentationModelQueueLogicTest(unittest.TestCase):
    def setUp(self):
        self._branch = "default"
        self._merge_dispatcher = create_autospec(Dispatcher)
        self._merge_dispatcher.get_all_branches.return_value = [self._branch]
        self._message_sender = create_autospec(MessageSender)
        self._users_holder = create_autospec(BotModel)
        self._presentation_model = BotPresentationModel(
            self._merge_dispatcher, self._message_sender)
        self._identifier = 123456
        self._user = User("Jack Daniels", self._identifier)

    def tearDown(self):
        self._presentation_model = None

    def test_shouldAskCollectionWithBranchesForQueueInformation(self):
        branch_filter = "filter"
        self._presentation_model.request_queue_info(
            self._identifier, branch_filter=branch_filter)
        self._merge_dispatcher.get_all_branches.assert_called_once_with(
            branch_filter)

    def test_shouldShowMessageIfNoBranchesAvailable(self):
        self._merge_dispatcher.get_all_branches.return_value = []
        self._presentation_model.request_queue_info(self._identifier)
        self._message_sender.send.assert_called_once_with(
            self._identifier, Messages.QUEUE_NO_BRANCHES_AVAILABLE)

    def test_shouldCallMessageSenderWithBranchSelectorIfMultipleBranchesAvailable(
            self):
        branches = ["default", "release", "something_else"]
        self._merge_dispatcher.get_all_branches.return_value = branches
        self._presentation_model.request_queue_info(self._identifier)
        self._message_sender.send_branch_selector.assert_called_once_with(
            self._identifier, States.queue,
            Messages.QUEUE_SELECT_BRANCH_MESSAGE, branches)

    def test_shouldGetActiveUserAndQueueFromDispatcher(self):
        self._presentation_model.request_queue_info(self._identifier,
                                                    self._branch)
        self._merge_dispatcher.get_branch_queue_info.assert_called_once_with(
            self._branch)

    def test_shouldCallMessageSenderIfNoActiveUserAndQueueIsEmpty(self):
        self._merge_dispatcher.get_branch_queue_info.return_value = BranchQueue(
        )
        self._presentation_model.request_queue_info(self._identifier,
                                                    self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.QUEUE_EMPTY_INFO_MESSAGE.format(self._branch))

    def test_shouldCallMessageSenderIfNoBranchInfo(self):
        self._merge_dispatcher.get_branch_queue_info.return_value = None
        self._presentation_model.request_queue_info(self._identifier,
                                                    self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.QUEUE_BRANCH_NOT_EXIST_MESSAGE.format(self._branch))

    def test_shouldCallMessageSenderIfOnlyActiveUserInQueue(self):
        active_user = User("Johnny Walker", 90909)
        branch_queue_info = BranchQueue()
        branch_queue_info.active_user = active_user
        self._merge_dispatcher.get_branch_queue_info.return_value = branch_queue_info
        self._presentation_model.request_queue_info(self._identifier,
                                                    self._branch)
        users_list = Messages.QUEUE_INFO_USER_IN_MERGE.format(
            active_user.get_name())
        message = Messages.QUEUE_INFO_MESSAGE.format(self._branch, users_list)
        self._message_sender.send.assert_called_once_with(
            self._identifier, message)

    def test_shouldCallMessageSenderIfOnlyActiveUserInQueueAndHeIsCurrentUserFromRequest(
            self):
        branch_queue_info = BranchQueue()
        branch_queue_info.active_user = self._user
        self._merge_dispatcher.get_branch_queue_info.return_value = branch_queue_info
        self._presentation_model.request_queue_info(self._identifier,
                                                    self._branch)
        users_list = Messages.QUEUE_INFO_CURRENT_USER_IN_MERGE.format(
            self._user.get_name())
        message = Messages.QUEUE_INFO_MESSAGE.format(self._branch, users_list)
        self._message_sender.send.assert_called_once_with(
            self._identifier, message)

    def test_shouldCallMessageSenderIfUsersInQueue(self):
        active_user = User("Johnny Walker", 8888)
        user_in_queue = User("Chivas Regal", 9999)
        branch_queue_info = BranchQueue()
        branch_queue_info.active_user = active_user
        branch_queue_info.users_queue = deque([user_in_queue])
        self._merge_dispatcher.get_branch_queue_info.return_value = branch_queue_info
        self._presentation_model.request_queue_info(self._identifier,
                                                    self._branch)
        users_list = Messages.QUEUE_INFO_USER_IN_MERGE.format(
            active_user.get_name())
        users_list += Messages.QUEUE_INFO_USER_IN_QUEUE.format(
            user_in_queue.get_name())
        message = Messages.QUEUE_INFO_MESSAGE.format(self._branch, users_list)
        self._message_sender.send.assert_called_once_with(
            self._identifier, message)

    def test_shouldCallMessageSenderIfUserInQueueCurrent(self):
        active_user = User("Johnny Walker", 45454)
        branch_queue_info = BranchQueue()
        branch_queue_info.active_user = active_user
        branch_queue_info.users_queue = deque([self._user])
        self._merge_dispatcher.get_branch_queue_info.return_value = branch_queue_info
        self._presentation_model.request_queue_info(self._identifier,
                                                    self._branch)
        users_list = Messages.QUEUE_INFO_USER_IN_MERGE.format(
            active_user.get_name())
        users_list += Messages.QUEUE_INFO_CURRENT_USER_IN_QUEUE.format(
            self._user.get_name())
        message = Messages.QUEUE_INFO_MESSAGE.format(self._branch, users_list)
        self._message_sender.send.assert_called_once_with(
            self._identifier, message)

    def test_shouldWorkIfNoActiveUserButUsersInQueue(self):
        branch_queue_info = BranchQueue()
        branch_queue_info.active_user = None
        branch_queue_info.users_queue = deque([self._user])
        self._merge_dispatcher.get_branch_queue_info.return_value = branch_queue_info
        self._presentation_model.request_queue_info(self._identifier,
                                                    self._branch)
        users_list = Messages.QUEUE_INFO_CURRENT_USER_IN_QUEUE.format(
            self._user.get_name())
        message = Messages.QUEUE_INFO_MESSAGE.format(self._branch, users_list)
        self._message_sender.send.assert_called_once_with(
            self._identifier, message)
class BotPresentationModelDoneLogicTest(unittest.TestCase):
    def setUp(self):
        self._branch = "default"
        self._merge_dispatcher = create_autospec(Dispatcher)
        self._merge_dispatcher.get_active_user_branches.return_value = [
            self._branch
        ]
        self._message_sender = create_autospec(MessageSender)
        self._users_holder = create_autospec(BotModel)
        self._presentation_model = BotPresentationModel(
            self._merge_dispatcher, self._message_sender)

        self._identifier = 123456

    def tearDown(self):
        self._presentation_model = None

    def test_shouldAskCollectionWithBranchesPossibleToDone(self):
        branch_filter = "filter"
        self._presentation_model.request_done(self._identifier,
                                              branch_filter=branch_filter)
        self._merge_dispatcher.get_active_user_branches.assert_called_once_with(
            self._identifier, branch_filter)

    def test_shouldShowMessageIfNoBranchesAvailable(self):
        self._merge_dispatcher.get_active_user_branches.return_value = []
        self._presentation_model.request_done(self._identifier)
        self._message_sender.send.assert_called_once_with(
            self._identifier, Messages.DONE_NO_BRANCHES_AVAILABLE)

    def test_shouldCallMessageSenderWithBranchSelectorIfMultipleBranchesAvailable(
            self):
        branches = ["default", "release", "something_else"]
        self._merge_dispatcher.get_active_user_branches.return_value = branches
        self._presentation_model.request_done(self._identifier)
        self._message_sender.send_branch_selector.assert_called_once_with(
            self._identifier, States.done, Messages.DONE_SELECT_BRANCH_MESSAGE,
            branches)

    def test_shouldDoneMergeInSelectedBranch(self):
        self._presentation_model.request_done(self._identifier, self._branch)
        self._merge_dispatcher.done.assert_called_once_with(
            self._identifier, self._branch)

    def test_shouldCallMessageSenderIfDoneWasCalledSuccessfully(self):
        self._merge_dispatcher.done.return_value = DoneRequestStatus.merge_done
        self._presentation_model.request_done(self._identifier, self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.DONE_MERGE_DONE_MESSAGE.format(self._branch))

    def test_shouldCallMessageSenderIfDoneWasCalledButUserAreNotActiveMerger(
            self):
        self._merge_dispatcher.done.return_value = DoneRequestStatus.user_not_active
        self._presentation_model.request_done(self._identifier, self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.DONE_NOT_YOUR_TURN_MESSAGE.format(self._branch))

    def test_shouldCallMessageSenderIfDoneWasCalledButBranchAreNotExist(self):
        self._merge_dispatcher.done.return_value = DoneRequestStatus.branch_not_exist
        self._presentation_model.request_done(self._identifier, self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.DONE_BRANCH_NOT_EXIST_MESSAGE.format(self._branch))
class BotPresentationModelCancelLogicTest(unittest.TestCase):
    def setUp(self):
        self._branch = "default"
        self._merge_dispatcher = create_autospec(Dispatcher)
        self._merge_dispatcher.get_all_branches_with_user.return_value = [
            self._branch
        ]
        self._message_sender = create_autospec(MessageSender)
        self._users_holder = create_autospec(BotModel)
        self._presentation_model = BotPresentationModel(
            self._merge_dispatcher, self._message_sender)

        self._identifier = 123456

    def tearDown(self):
        self._presentation_model = None

    def test_shouldCheckCollectionWithBranchesPossibleToCancel(self):
        branch_filter = "filter"
        self._presentation_model.request_cancel(self._identifier,
                                                branch_filter=branch_filter)
        self._merge_dispatcher.get_all_branches_with_user.assert_called_once_with(
            self._identifier, branch_filter)

    def test_shouldShowMessageIfNoBranchesAvailable(self):
        self._merge_dispatcher.get_all_branches_with_user.return_value = []
        self._presentation_model.request_cancel(self._identifier)
        self._message_sender.send.assert_called_once_with(
            self._identifier, Messages.CANCEL_NO_BRANCHES_AVAILABLE)

    def test_shouldCallMessageSenderWithBranchSelectorIfMultipleBranchesAvailable(
            self):
        branches = ["default", "release", "something_else"]
        self._merge_dispatcher.get_all_branches_with_user.return_value = branches
        self._presentation_model.request_cancel(self._identifier)
        self._message_sender.send_branch_selector.assert_called_once_with(
            self._identifier, States.cancel,
            Messages.CANCEL_SELECT_BRANCH_MESSAGE, branches)

    def test_shouldCancelMergeInSelectedBranch(self):
        self._presentation_model.request_cancel(self._identifier, self._branch)
        self._merge_dispatcher.cancel.assert_called_once_with(
            self._identifier, self._branch)

    def test_shouldCallMessageSenderIfCancelWasCalledAndMergeWasAborted(self):
        self._merge_dispatcher.cancel.return_value = CancelRequestStatus.merge_cancelled
        self._presentation_model.request_cancel(self._identifier, self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.CANCEL_MERGE_CANCELLED_MESSAGE.format(self._branch))

    def test_shouldCallMessageSenderIfCancelWasCalledUserExitedFromQueue(self):
        self._merge_dispatcher.cancel.return_value = CancelRequestStatus.exited_from_queue
        self._presentation_model.request_cancel(self._identifier, self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.CANCEL_EXITED_FROM_QUEUE_MESSAGE.format(self._branch))

    def test_shouldCallMessageSenderIfCancelWasCalledWithIncorrectBranch(self):
        self._merge_dispatcher.cancel.return_value = CancelRequestStatus.branch_not_exist
        self._presentation_model.request_cancel(self._identifier, self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.CANCEL_BRANCH_NOT_EXIST_MESSAGE.format(self._branch))

    def test_shouldCallMessageSenderIfCancelWasCalledWhenUserNotInQueue(self):
        self._merge_dispatcher.cancel.return_value = CancelRequestStatus.not_in_queue
        self._presentation_model.request_cancel(self._identifier, self._branch)
        self._message_sender.send.assert_called_once_with(
            self._identifier,
            Messages.CANCEL_NOT_IN_QUEUE_MESSAGE.format(self._branch))