Example #1
0
    def test_multiple_calls_with_same_word(self):
        msg = CommandMessage(original_text='.count ham',
                             text='ham',
                             sender='U06TXXXXX')
        assert_that(slack_count(msg, {})) \
            .described_as("First count returns 1") \
            .is_equal_to('1')

        other_msg = CommandMessage(original_text='.count ham',
                                   text='ham',
                                   sender='U06TYYYYYY')
        assert_that(slack_count(other_msg, {})) \
            .described_as("Different counter for different message") \
            .is_equal_to('1')

        assert_that(slack_count(msg, {})) \
            .described_as("Same message results in incremented count") \
            .is_equal_to('2')

        reset_msg = CommandMessage(original_text='.reset_count',
                                   text='',
                                   sender='U06TXXXXX')
        assert_that(slack_reset_count(reset_msg, {})) \
            .described_as(".reset_count command resets current count") \
            .is_equal_to("restart counting")

        assert_that(slack_count(msg, {})) \
            .described_as("Count restarts") \
            .is_equal_to('1')
Example #2
0
    def test_init(self):
        msg = CommandMessage(original_text='.count foo',
                             text='foo',
                             sender='123_homer@localhost/Oklahomer')
        assert_that(msg) \
            .has_original_text('.count foo') \
            .has_text('foo') \
            .has_sender('123_homer@localhost/Oklahomer')

        # Can't change
        msg.__original_text = 'foo'
        assert_that(msg).has_original_text('.count foo')
Example #3
0
    def test_multiple_calls_with_different_word(self):
        msg = CommandMessage(original_text='.count ham',
                             text='ham',
                             sender='U06TXXXXX')
        assert_that(slack_count(msg, {})) \
            .described_as("First count message returns 1") \
            .is_equal_to('1')

        other_msg = CommandMessage(original_text='.count spam',
                                   text='spam',
                                   sender='U06TXXXXX')
        assert_that(slack_count(other_msg, {})) \
            .described_as("Second message with different content returns 1") \
            .is_equal_to('1')
Example #4
0
 def test_valid(self):
     msg = CommandMessage(original_text='.count ham',
                          text='ham',
                          sender='U06TXXXXX')
     assert_that(slack_count(msg, {})) \
         .described_as(".count command increments count") \
         .is_equal_to('1')
Example #5
0
 def test_valid(self):
     msg = CommandMessage(original_text='.count ham',
                          text='ham',
                          sender='123_homer@localhost/Oklahomer')
     assert_that(hipchat_count(msg, {})) \
         .described_as(".count command increments count") \
         .is_equal_to('1')
Example #6
0
    def test__init(self):
        msg = CommandMessage(original_text='.hello',
                             text='',
                             sender='spam@localhost/ham')
        response = hipchat_hello(msg, {})

        assert_that(response) \
            .described_as(".hello initiates conversation.") \
            .is_instance_of(UserContext) \
            .has_message("Hello. How are you feeling today?")

        assert_that(response.input_options) \
            .described_as("User has two options to respond.") \
            .is_length(2)

        assert_that([o.next_step.__name__ for o in response.input_options]) \
            .described_as("Those options include 'Good' and 'Bad'") \
            .contains(hipchat_user_feeling_good.__name__,
                      hipchat_user_feeling_bad.__name__)

        assert_that(response.input_options[0].next_step("Good", {})) \
            .described_as("When 'Good,' just return text.") \
            .is_equal_to("Good to hear that.")

        assert_that(response.input_options[1].next_step("Bad", {})) \
            .described_as("When 'Bad,' continue to ask health status") \
            .is_instance_of(UserContext)
Example #7
0
    def test_decorator(self):
        self.passed_command_message = None
        self.passed_config = None

        def func(message: CommandMessage, config: Dict[str, Any]) -> str:
            self.passed_command_message = message
            self.passed_config = config
            return "spam"

        wrapper = Base.command(".command_name",
                               [".command_name spam", ".command_name ham"])
        wrapped_function = wrapper(func)
        ret = wrapped_function(
            CommandMessage("original message", "message", "homer"),
            {'ham': "egg"})

        assert_that(ret).is_equal_to("spam")

        assert_that(self.passed_command_message).is_not_none()
        assert_that(self.passed_command_message).is_instance_of(CommandMessage)
        assert_that(getattr(self.passed_command_message, "original_text")) \
            .is_equal_to("original message")

        assert_that(self.passed_config).is_not_none()
        assert_that(self.passed_config).is_instance_of(dict)
Example #8
0
    def test_valid(self):
        response = slack_echo(
            CommandMessage(original_text='.echo spam ham',
                           text='spam ham',
                           sender='U06TXXXXX'), {})

        assert_that(response) \
            .described_as(".echo returns user inputs") \
            .is_equal_to("spam ham")
Example #9
0
    def test_valid(self):
        response = hipchat_echo(
            CommandMessage(original_text='.echo spam ham',
                           text='spam ham',
                           sender='123_homer@localhost/Oklahomer'),
            {})

        assert_that(response) \
            .described_as(".echo returns user inputs") \
            .is_equal_to("spam ham")
Example #10
0
    def test_valid(self):
        command_name = ".answer"
        command = Command(command_name, DummyClass.answer, DummyClass.__name__,
                          {'spam': "ham"}, ["example", "input"])

        assert_that(command.name).is_equal_to(command_name)
        assert_that(command.function).is_equal_to(DummyClass.answer)
        assert_that(command.module_name).is_equal_to(DummyClass.__name__)
        assert_that(command.config).is_equal_to({'spam': "ham"})
        assert_that(command.examples).is_equal_to(["example", "input"])
        assert_that(command.help) \
            .is_equal_to("%s: %s" % (command_name, "example, input"))

        # is callable
        message = CommandMessage(".hello sarah", "sarah", "homer")
        assert_that(command(message)).is_equal_to(".hello sarah")
Example #11
0
    def test_with_instance(self):
        # Concrete class is initialized
        base_impl = create_concrete_class()()

        # Plugin module is loaded while/after initialization
        class BaseImplPlugin(object):
            @staticmethod
            @base_impl.__class__.command(".target", ["spam", "ham"])
            def target_command(msg: CommandMessage, _: Dict) -> str:
                return msg.original_text

        # Then the command provided by plugin module is registered
        registered = base_impl.commands
        assert_that(registered).is_length(1)
        assert_that(registered[0]).is_instance_of(Command)
        assert_that(registered[0](CommandMessage("original message",
                                                 "message",
                                                 "homer"))) \
            .is_equal_to("original message")
Example #12
0
    def test_valid(self):
        command_message = CommandMessage(".hello sarah", "sarah", "homer")

        assert_that(command_message.original_text).is_equal_to(".hello sarah")
        assert_that(command_message.text).is_equal_to("sarah")
        assert_that(command_message.sender).is_equal_to("homer")
Example #13
0
 def test_valid(self):
     msg = CommandMessage(original_text='.bmw', text='', sender='U06TXXXXX')
     # assert_that(slack_quote(msg, {})).is_instance_of(SlackMessage)
     assert_that(isinstance(slack_quote(msg, {}), SlackMessage)).is_true()
Example #14
0
 def test_valid(self):
     msg = CommandMessage(original_text='.bmw',
                          text='',
                          sender='123_homer@localhost/Oklahomer')
     assert_that(hipchat_quote(msg, {})).is_type_of(str)
Example #15
0
    def respond(self, user_key: str,
                user_input: str) -> Optional[Union[RichMessage, str]]:
        """Receive user input and respond to it.

        It checks if any UserContext is stored with the given user_key. If
        found, consider this user is in a middle of "conversation" with a
        plugin module. Then the user input is passed to the next_step of that
        UserContext and proceed.

        If there is no UserContext stored, see if any registered command is
        applicable. If found, pass the user input to given plugin module
        command and receive response.

        Command response can be one of UserContext, RichMessage, or string.
        When UserContext is returned, register this context with the user key
        so the next input from the same user can proceed to next step.

        :param user_key: Stringified unique user key. Format varies depending
            on each bot implementation.
        :param user_input: User input text.
        :return: One of RichMessage, string, or None.
        """
        user_context = self.user_context_map.get(user_key, None)

        if user_input == '.help':
            return self.help()

        ret = None  # type: Optional[Union[RichMessage, UserContext, str]]
        error = []  # type: List[Tuple[str, str]]
        if user_context:
            # User is in the middle of conversation

            if user_input == '.abort':
                # If user wishes, abort the current conversation, and remove
                # context data.
                self.user_context_map.pop(user_key)
                return 'Abort current conversation'

            # Check if we can proceed conversation. If user input is irrelevant
            # return help message.
            next_step = user_context.find_next_step(user_input)
            if next_step is None:
                return user_context.help_message

            try:
                config = self.plugin_config.get(next_step.__module__, {})
                ret = next_step(
                    CommandMessage(original_text=user_input,
                                   text=user_input,
                                   sender=user_key), config)

                # Only when command is successfully executed, remove current
                # context. To forcefully abort the conversation, use ".abort"
                # command
                self.user_context_map.pop(user_key)
            except Exception as e:
                error.append((next_step.__name__, str(e)))

        else:
            # If user is not in the middle of conversation, see if the input
            # text contains command.
            command = self.find_command(user_input)
            if command is None:
                # If it doesn't match any command, leave it.
                return None

            try:
                text = re.sub(r'{0}\s+'.format(command.name), '', user_input)
                ret = command(
                    CommandMessage(original_text=user_input,
                                   text=text,
                                   sender=user_key))
            except Exception as e:
                error.append((command.name, str(e)))

        if error:
            logging.error('Error occurred. '
                          'command: %s. input: %s. error: %s.' %
                          (error[0][0], user_input, error[0][1]))
            return 'Something went wrong with "%s"' % user_input

        elif not ret:
            logging.error('command should return UserContext or text'
                          'to let user know the result or next move')
            return 'Something went wrong with "%s"' % user_input

        elif isinstance(ret, UserContext):
            self.user_context_map[user_key] = ret
            return ret.message

        else:
            # String or RichMessage
            return ret