reactions: Allow using emoji_name for removing reactions.

Given that we allow adding emoji reactions by only using the
emoji_name, we should offer the same possibility for removing
reactions to make the experience for API clients not require looking
up emoji codes.

Since this is an additional optional parameter, this also preserves
backward compatibility.
This commit is contained in:
Yago González 2018-07-09 14:18:42 +05:30 committed by Tim Abbott
parent 9244a6740e
commit e9cd0ad3d6
2 changed files with 44 additions and 1 deletions

View File

@ -494,6 +494,12 @@ class DefaultEmojiReactionTests(EmojiReactionBase):
result = self.delete_reaction(reaction_info)
self.assert_json_success(result)
def test_delete_insufficient_arguments_reaction(self) -> None:
result = self.delete_reaction({})
self.assert_json_error(result, 'At least one of the following '
'arguments must be present: emoji_name, '
'emoji_code')
def test_delete_non_existing_emoji_reaction(self) -> None:
reaction_info = {
'emoji_name': 'thumbs_up',
@ -519,6 +525,29 @@ class DefaultEmojiReactionTests(EmojiReactionBase):
result = self.delete_reaction(reaction_info)
self.assert_json_success(result)
def test_delete_reaction_by_name(self) -> None:
hamlet = self.example_user('hamlet')
message = Message.objects.get(id=1)
Reaction.objects.create(user_profile=hamlet,
message=message,
emoji_name='+1',
emoji_code='1f44d',
reaction_type='unicode_emoji',
)
reaction_info = {
'emoji_name': '+1'
}
result = self.delete_reaction(reaction_info)
self.assert_json_success(result)
self.assertFalse(
Reaction.objects.filter(user_profile=hamlet,
message=message,
emoji_name=reaction_info['emoji_name'],
emoji_code='1f44d',
reaction_type='unicode_emoji').exists()
)
def test_react_historical(self) -> None:
"""
Reacting with valid emoji on a historical message succeeds.

View File

@ -83,10 +83,24 @@ def add_reaction(request: HttpRequest, user_profile: UserProfile, message_id: in
@has_request_variables
def remove_reaction(request: HttpRequest, user_profile: UserProfile, message_id: int,
emoji_code: str=REQ(),
emoji_name: Optional[str]=REQ(default=None),
emoji_code: Optional[str]=REQ(default=None),
reaction_type: str=REQ(default="unicode_emoji")) -> HttpResponse:
message, user_message = access_message(user_profile, message_id)
if emoji_code is None:
if emoji_name is None:
raise JsonableError(_('At least one of the following arguments '
'must be present: emoji_name, emoji_code'))
# A correct full Zulip client implementation should always
# pass an emoji_code, because of the corner cases discussed in
# the long block comments elsewhere in this file. However, to
# make it easy for simple API clients to use the reactions API
# without needing the mapping between emoji names and codes,
# we allow instead passing the emoji_name and looking up the
# corresponding code using the current data.
emoji_code = emoji_name_to_emoji_code(message.sender.realm, emoji_name)[0]
if not Reaction.objects.filter(user_profile=user_profile,
message=message,
emoji_code=emoji_code,