2020-05-26 07:16:25 +02:00
|
|
|
from unittest.mock import patch
|
2017-10-25 17:18:43 +02:00
|
|
|
|
2020-08-07 01:09:47 +02:00
|
|
|
import orjson
|
2023-10-12 19:43:45 +02:00
|
|
|
from typing_extensions import override
|
2020-06-11 00:54:34 +02:00
|
|
|
|
2022-11-17 09:30:48 +01:00
|
|
|
from zerver.lib.bot_lib import EmbeddedBotQuitError
|
2023-12-15 03:04:08 +01:00
|
|
|
from zerver.lib.display_recipient import get_display_recipient
|
2017-10-25 17:18:43 +02:00
|
|
|
from zerver.lib.test_classes import ZulipTestCase
|
2023-12-15 21:00:29 +01:00
|
|
|
from zerver.models import UserProfile
|
|
|
|
from zerver.models.bots import get_service_profile
|
2023-12-15 02:14:24 +01:00
|
|
|
from zerver.models.realms import get_realm
|
2023-12-15 01:16:00 +01:00
|
|
|
from zerver.models.users import get_user
|
2017-10-25 17:18:43 +02:00
|
|
|
|
2018-01-30 17:05:14 +01:00
|
|
|
|
2017-10-25 17:18:43 +02:00
|
|
|
class TestEmbeddedBotMessaging(ZulipTestCase):
|
2023-10-12 19:43:45 +02:00
|
|
|
@override
|
2017-11-05 10:51:25 +01:00
|
|
|
def setUp(self) -> None:
|
2019-10-19 20:47:00 +02:00
|
|
|
super().setUp()
|
2017-10-25 17:18:43 +02:00
|
|
|
self.user_profile = self.example_user("othello")
|
2021-02-12 08:19:30 +01:00
|
|
|
self.bot_profile = self.create_test_bot(
|
2021-02-12 08:20:45 +01:00
|
|
|
"embedded",
|
2021-02-12 08:19:30 +01:00
|
|
|
self.user_profile,
|
2021-02-12 08:20:45 +01:00
|
|
|
full_name="Embedded bot",
|
2021-02-12 08:19:30 +01:00
|
|
|
bot_type=UserProfile.EMBEDDED_BOT,
|
2021-02-12 08:20:45 +01:00
|
|
|
service_name="helloworld",
|
|
|
|
config_data=orjson.dumps({"foo": "bar"}).decode(),
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2017-10-25 17:18:43 +02:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_pm_to_embedded_bot(self) -> None:
|
2018-06-17 07:12:51 +02:00
|
|
|
assert self.bot_profile is not None
|
2021-02-12 08:19:30 +01:00
|
|
|
self.send_personal_message(self.user_profile, self.bot_profile, content="help")
|
2017-10-25 17:18:43 +02:00
|
|
|
last_message = self.get_last_message()
|
|
|
|
self.assertEqual(last_message.content, "beep boop")
|
|
|
|
self.assertEqual(last_message.sender_id, self.bot_profile.id)
|
|
|
|
display_recipient = get_display_recipient(last_message.recipient)
|
2020-06-23 07:20:47 +02:00
|
|
|
assert isinstance(display_recipient, list)
|
|
|
|
self.assert_length(display_recipient, 1)
|
2021-02-12 08:20:45 +01:00
|
|
|
self.assertEqual(display_recipient[0]["email"], self.user_profile.email)
|
2017-10-25 17:18:43 +02:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_stream_message_to_embedded_bot(self) -> None:
|
2018-06-17 07:12:51 +02:00
|
|
|
assert self.bot_profile is not None
|
2021-02-12 08:19:30 +01:00
|
|
|
self.send_stream_message(
|
|
|
|
self.user_profile,
|
|
|
|
"Denmark",
|
|
|
|
content=f"@**{self.bot_profile.full_name}** foo",
|
|
|
|
topic_name="bar",
|
|
|
|
)
|
2017-10-25 17:18:43 +02:00
|
|
|
last_message = self.get_last_message()
|
|
|
|
self.assertEqual(last_message.content, "beep boop")
|
|
|
|
self.assertEqual(last_message.sender_id, self.bot_profile.id)
|
2018-11-10 16:11:12 +01:00
|
|
|
self.assertEqual(last_message.topic_name(), "bar")
|
2023-07-16 12:08:57 +02:00
|
|
|
self.assert_message_stream_name(last_message, "Denmark")
|
2017-10-25 17:18:43 +02:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_stream_message_not_to_embedded_bot(self) -> None:
|
2021-02-12 08:19:30 +01:00
|
|
|
self.send_stream_message(self.user_profile, "Denmark", content="foo", topic_name="bar")
|
2017-10-25 17:18:43 +02:00
|
|
|
last_message = self.get_last_message()
|
|
|
|
self.assertEqual(last_message.content, "foo")
|
2017-11-03 21:08:34 +01:00
|
|
|
|
2018-02-25 20:25:48 +01:00
|
|
|
def test_message_to_embedded_bot_with_initialize(self) -> None:
|
2018-06-17 07:12:51 +02:00
|
|
|
assert self.bot_profile is not None
|
tests: Ensure stream senders get a UserMessage row.
We now complain if a test author sends a stream message
that does not result in the sender getting a
UserMessage row for the message.
This is basically 100% equivalent to complaining that
the author failed to subscribe the sender to the stream
as part of the test setup, as far as I can tell, so the
AssertionError instructs the author to subscribe the
sender to the stream.
We exempt bots from this check, although it is
plausible we should only exempt the system bots like
the notification bot.
I considered auto-subscribing the sender to the stream,
but that can be a little more expensive than the
current check, and we generally want test setup to be
explicit.
If there is some legitimate way than a subscribed human
sender can't get a UserMessage, then we probably want
an explicit test for that, or we may want to change the
backend to just write a UserMessage row in that
hypothetical situation.
For most tests, including almost all the ones fixed
here, the author just wants their test setup to
realistically reflect normal operation, and often devs
may not realize that Cordelia is not subscribed to
Denmark or not realize that Hamlet is not subscribed to
Scotland.
Some of us don't remember our Shakespeare from high
school, and our stream subscriptions don't even
necessarily reflect which countries the Bard placed his
characters in.
There may also be some legitimate use case where an
author wants to simulate sending a message to an
unsubscribed stream, but for those edge cases, they can
always set allow_unsubscribed_sender to True.
2021-12-10 13:55:48 +01:00
|
|
|
self.subscribe(self.user_profile, "Denmark")
|
2021-02-12 08:19:30 +01:00
|
|
|
with patch(
|
2021-02-12 08:20:45 +01:00
|
|
|
"zulip_bots.bots.helloworld.helloworld.HelloWorldHandler.initialize", create=True
|
2021-02-12 08:19:30 +01:00
|
|
|
) as mock_initialize:
|
|
|
|
self.send_stream_message(
|
|
|
|
self.user_profile,
|
|
|
|
"Denmark",
|
|
|
|
content=f"@**{self.bot_profile.full_name}** foo",
|
|
|
|
topic_name="bar",
|
|
|
|
)
|
2018-02-25 20:25:48 +01:00
|
|
|
mock_initialize.assert_called_once()
|
|
|
|
|
2018-02-08 15:51:38 +01:00
|
|
|
def test_embedded_bot_quit_exception(self) -> None:
|
2018-06-17 07:12:51 +02:00
|
|
|
assert self.bot_profile is not None
|
2024-07-14 20:30:42 +02:00
|
|
|
with (
|
|
|
|
patch(
|
|
|
|
"zulip_bots.bots.helloworld.helloworld.HelloWorldHandler.handle_message",
|
|
|
|
side_effect=EmbeddedBotQuitError("I'm quitting!"),
|
|
|
|
),
|
|
|
|
self.assertLogs(level="WARNING") as m,
|
2021-02-12 08:19:30 +01:00
|
|
|
):
|
2024-07-14 20:30:42 +02:00
|
|
|
self.send_stream_message(
|
|
|
|
self.user_profile,
|
|
|
|
"Denmark",
|
|
|
|
content=f"@**{self.bot_profile.full_name}** foo",
|
|
|
|
topic_name="bar",
|
|
|
|
)
|
|
|
|
self.assertEqual(m.output, ["WARNING:root:I'm quitting!"])
|
2018-02-08 15:51:38 +01:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-11-03 21:08:34 +01:00
|
|
|
class TestEmbeddedBotFailures(ZulipTestCase):
|
2018-02-25 19:33:49 +01:00
|
|
|
def test_message_embedded_bot_with_invalid_service(self) -> None:
|
2017-11-03 21:08:34 +01:00
|
|
|
user_profile = self.example_user("othello")
|
2021-02-12 08:19:30 +01:00
|
|
|
self.create_test_bot(
|
2021-02-12 08:20:45 +01:00
|
|
|
short_name="embedded",
|
2021-02-12 08:19:30 +01:00
|
|
|
user_profile=user_profile,
|
|
|
|
bot_type=UserProfile.EMBEDDED_BOT,
|
2021-02-12 08:20:45 +01:00
|
|
|
service_name="helloworld",
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2021-02-12 08:20:45 +01:00
|
|
|
bot_profile = get_user("embedded-bot@zulip.testserver", get_realm("zulip"))
|
|
|
|
service_profile = get_service_profile(bot_profile.id, "helloworld")
|
|
|
|
service_profile.name = "invalid"
|
2018-02-25 19:33:49 +01:00
|
|
|
service_profile.save()
|
2021-02-12 08:20:45 +01:00
|
|
|
with self.assertLogs(level="ERROR") as m:
|
2021-02-12 08:19:30 +01:00
|
|
|
self.send_stream_message(
|
|
|
|
user_profile,
|
|
|
|
"Denmark",
|
|
|
|
content=f"@**{bot_profile.full_name}** foo",
|
|
|
|
topic_name="bar",
|
|
|
|
)
|
2021-02-04 11:20:53 +01:00
|
|
|
self.assertEqual(
|
2021-02-12 08:19:30 +01:00
|
|
|
m.output[0],
|
2021-02-04 11:20:53 +01:00
|
|
|
f"ERROR:root:Error: User {bot_profile.id} has bot with invalid embedded bot service invalid",
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|