2016-10-12 20:57:59 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
import ujson
|
2017-08-04 02:25:38 +02:00
|
|
|
from typing import Any, Mapping, List
|
2016-10-12 20:57:59 +02:00
|
|
|
|
2020-02-23 17:24:41 +01:00
|
|
|
from zerver.lib.test_helpers import (
|
|
|
|
tornado_redirected_to_list,
|
|
|
|
queries_captured,
|
|
|
|
)
|
2016-11-10 19:30:09 +01:00
|
|
|
from zerver.lib.test_classes import (
|
|
|
|
ZulipTestCase,
|
|
|
|
)
|
2020-02-23 18:05:29 +01:00
|
|
|
from zerver.models import (
|
|
|
|
Huddle,
|
|
|
|
get_huddle_hash,
|
|
|
|
)
|
2016-10-12 20:57:59 +02:00
|
|
|
|
2020-02-22 13:38:09 +01:00
|
|
|
class TypingValidateOperatorTest(ZulipTestCase):
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_missing_parameter(self) -> None:
|
2016-10-12 20:57:59 +02:00
|
|
|
"""
|
|
|
|
Sending typing notification without op parameter fails
|
|
|
|
"""
|
2020-02-22 13:38:09 +01:00
|
|
|
sender = self.example_user("hamlet")
|
|
|
|
params = dict(
|
|
|
|
to=ujson.dumps([sender.id]),
|
|
|
|
)
|
|
|
|
result = self.api_post(sender.email, '/api/v1/typing', params)
|
2016-10-12 20:57:59 +02:00
|
|
|
self.assert_json_error(result, 'Missing \'op\' argument')
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_invalid_parameter(self) -> None:
|
2016-10-12 20:57:59 +02:00
|
|
|
"""
|
|
|
|
Sending typing notification with invalid value for op parameter fails
|
|
|
|
"""
|
2020-02-22 13:38:09 +01:00
|
|
|
sender = self.example_user("hamlet")
|
|
|
|
params = dict(
|
|
|
|
to=ujson.dumps([sender.id]),
|
|
|
|
op='foo'
|
|
|
|
)
|
|
|
|
result = self.api_post(sender.email, '/api/v1/typing', params)
|
2016-10-12 20:57:59 +02:00
|
|
|
self.assert_json_error(result, 'Invalid \'op\' value (should be start or stop)')
|
|
|
|
|
2020-02-22 13:38:09 +01:00
|
|
|
class TypingValidateUsersTest(ZulipTestCase):
|
|
|
|
def test_empty_array(self) -> None:
|
|
|
|
"""
|
|
|
|
Sending typing notification without recipient fails
|
|
|
|
"""
|
|
|
|
sender = self.example_email("hamlet")
|
|
|
|
result = self.api_post(sender, '/api/v1/typing', {'op': 'start', 'to': '[]'})
|
|
|
|
self.assert_json_error(result, 'Missing parameter: \'to\' (recipient)')
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_missing_recipient(self) -> None:
|
2016-10-12 20:57:59 +02:00
|
|
|
"""
|
|
|
|
Sending typing notification without recipient fails
|
|
|
|
"""
|
2017-05-25 01:40:26 +02:00
|
|
|
sender = self.example_email("hamlet")
|
2017-12-14 19:02:31 +01:00
|
|
|
result = self.api_post(sender, '/api/v1/typing', {'op': 'start'})
|
2020-02-22 13:38:09 +01:00
|
|
|
self.assert_json_error(result, "Missing parameter: 'to' (recipient)")
|
2016-10-12 20:57:59 +02:00
|
|
|
|
2020-02-22 13:38:09 +01:00
|
|
|
def test_argument_to_is_not_valid_json(self) -> None:
|
2016-10-12 20:57:59 +02:00
|
|
|
"""
|
|
|
|
Sending typing notification to invalid recipient fails
|
|
|
|
"""
|
2017-05-25 01:40:26 +02:00
|
|
|
sender = self.example_email("hamlet")
|
2020-02-22 13:38:09 +01:00
|
|
|
invalid = 'bad email'
|
2017-12-14 19:02:31 +01:00
|
|
|
result = self.api_post(sender, '/api/v1/typing', {'op': 'start', 'to': invalid})
|
2020-02-22 13:38:09 +01:00
|
|
|
self.assert_json_error(result, "Invalid email 'bad email'")
|
2016-10-12 20:57:59 +02:00
|
|
|
|
2020-02-22 13:38:09 +01:00
|
|
|
def test_bogus_user_id(self) -> None:
|
2016-10-12 20:57:59 +02:00
|
|
|
"""
|
2020-02-22 13:38:09 +01:00
|
|
|
Sending typing notification to invalid recipient fails
|
2016-10-12 20:57:59 +02:00
|
|
|
"""
|
2020-02-22 13:38:09 +01:00
|
|
|
sender = self.example_email("hamlet")
|
|
|
|
invalid = '[9999999]'
|
|
|
|
result = self.api_post(sender, '/api/v1/typing', {'op': 'start', 'to': invalid})
|
|
|
|
self.assert_json_error(result, 'Invalid user ID 9999999')
|
2016-10-12 20:57:59 +02:00
|
|
|
|
2020-02-22 13:38:09 +01:00
|
|
|
class TypingHappyPathTest(ZulipTestCase):
|
|
|
|
def test_start_to_single_recipient(self) -> None:
|
2018-08-28 21:48:47 +02:00
|
|
|
sender = self.example_user('hamlet')
|
|
|
|
recipient_user = self.example_user('othello')
|
|
|
|
expected_recipients = set([sender, recipient_user])
|
|
|
|
expected_recipient_emails = set([user.email for user in expected_recipients])
|
|
|
|
expected_recipient_ids = set([user.id for user in expected_recipients])
|
|
|
|
|
2020-02-23 17:24:41 +01:00
|
|
|
params = dict(
|
|
|
|
to=ujson.dumps([recipient_user.id]),
|
|
|
|
op='start',
|
|
|
|
)
|
|
|
|
|
2018-08-28 21:48:47 +02:00
|
|
|
events = [] # type: List[Mapping[str, Any]]
|
2020-02-23 17:24:41 +01:00
|
|
|
with queries_captured() as queries:
|
|
|
|
with tornado_redirected_to_list(events):
|
|
|
|
result = self.api_post(sender.email, '/api/v1/typing', params)
|
2018-08-28 21:48:47 +02:00
|
|
|
|
|
|
|
self.assert_json_success(result)
|
|
|
|
self.assertEqual(len(events), 1)
|
2020-02-23 14:10:26 +01:00
|
|
|
self.assertEqual(len(queries), 6)
|
2018-08-28 21:48:47 +02:00
|
|
|
|
|
|
|
event = events[0]['event']
|
|
|
|
event_recipient_emails = set(user['email'] for user in event['recipients'])
|
|
|
|
event_user_ids = set(events[0]['users'])
|
|
|
|
event_recipient_user_ids = set(user['user_id'] for user in event['recipients'])
|
|
|
|
|
|
|
|
self.assertEqual(expected_recipient_ids, event_recipient_user_ids)
|
|
|
|
self.assertEqual(expected_recipient_ids, event_user_ids)
|
|
|
|
self.assertEqual(event['sender']['email'], sender.email)
|
|
|
|
self.assertEqual(event_recipient_emails, expected_recipient_emails)
|
|
|
|
self.assertEqual(event['type'], 'typing')
|
|
|
|
self.assertEqual(event['op'], 'start')
|
|
|
|
|
2020-02-22 13:38:09 +01:00
|
|
|
def test_start_to_multiple_recipients(self) -> None:
|
2018-08-28 21:48:47 +02:00
|
|
|
sender = self.example_user('hamlet')
|
|
|
|
recipient_users = [self.example_user('othello'), self.example_user('cordelia')]
|
|
|
|
expected_recipients = set(recipient_users) | set([sender])
|
|
|
|
expected_recipient_emails = set([user.email for user in expected_recipients])
|
|
|
|
expected_recipient_ids = set([user.id for user in expected_recipients])
|
2020-02-23 18:05:29 +01:00
|
|
|
|
|
|
|
huddle_hash = get_huddle_hash(list(expected_recipient_ids))
|
|
|
|
self.assertFalse(Huddle.objects.filter(huddle_hash=huddle_hash).exists())
|
|
|
|
|
2018-08-28 21:48:47 +02:00
|
|
|
events = [] # type: List[Mapping[str, Any]]
|
2020-02-23 17:24:41 +01:00
|
|
|
|
|
|
|
params = dict(
|
|
|
|
to=ujson.dumps([user.id for user in recipient_users]),
|
|
|
|
op='start',
|
|
|
|
)
|
|
|
|
|
|
|
|
with queries_captured() as queries:
|
|
|
|
with tornado_redirected_to_list(events):
|
|
|
|
result = self.api_post(sender.email, '/api/v1/typing', params)
|
2018-08-28 21:48:47 +02:00
|
|
|
self.assert_json_success(result)
|
|
|
|
self.assertEqual(len(events), 1)
|
2020-02-23 14:10:26 +01:00
|
|
|
self.assertEqual(len(queries), 7)
|
2018-08-28 21:48:47 +02:00
|
|
|
|
2020-02-23 14:10:26 +01:00
|
|
|
# We should not be adding new Huddles just because
|
|
|
|
# a user started typing in the compose box. Let's
|
|
|
|
# wait till they send an actual message.
|
|
|
|
self.assertFalse(Huddle.objects.filter(huddle_hash=huddle_hash).exists())
|
2020-02-23 18:05:29 +01:00
|
|
|
|
2018-08-28 21:48:47 +02:00
|
|
|
event = events[0]['event']
|
|
|
|
event_recipient_emails = set(user['email'] for user in event['recipients'])
|
|
|
|
event_user_ids = set(events[0]['users'])
|
|
|
|
event_recipient_user_ids = set(user['user_id'] for user in event['recipients'])
|
|
|
|
|
|
|
|
self.assertEqual(expected_recipient_ids, event_recipient_user_ids)
|
|
|
|
self.assertEqual(expected_recipient_ids, event_user_ids)
|
|
|
|
self.assertEqual(event['sender']['email'], sender.email)
|
|
|
|
self.assertEqual(event_recipient_emails, expected_recipient_emails)
|
|
|
|
self.assertEqual(event['type'], 'typing')
|
|
|
|
self.assertEqual(event['op'], 'start')
|
|
|
|
|
2020-02-22 13:38:09 +01:00
|
|
|
def test_start_to_self(self) -> None:
|
2018-08-28 21:48:47 +02:00
|
|
|
"""
|
|
|
|
Sending typing notification to yourself (using user IDs)
|
|
|
|
is successful.
|
|
|
|
"""
|
|
|
|
user = self.example_user('hamlet')
|
|
|
|
email = user.email
|
|
|
|
expected_recipient_emails = set([email])
|
|
|
|
expected_recipient_ids = set([user.id])
|
|
|
|
events = [] # type: List[Mapping[str, Any]]
|
|
|
|
with tornado_redirected_to_list(events):
|
|
|
|
result = self.api_post(
|
|
|
|
email,
|
|
|
|
'/api/v1/typing',
|
|
|
|
{
|
|
|
|
'to': ujson.dumps([user.id]),
|
|
|
|
'op': 'start'
|
|
|
|
}
|
|
|
|
)
|
|
|
|
self.assert_json_success(result)
|
2016-10-28 18:50:21 +02:00
|
|
|
self.assertEqual(len(events), 1)
|
2016-10-12 20:57:59 +02:00
|
|
|
|
|
|
|
event = events[0]['event']
|
|
|
|
event_recipient_emails = set(user['email'] for user in event['recipients'])
|
2016-10-28 18:50:21 +02:00
|
|
|
event_user_ids = set(events[0]['users'])
|
|
|
|
event_recipient_user_ids = set(user['user_id'] for user in event['recipients'])
|
2016-10-12 20:57:59 +02:00
|
|
|
|
2016-10-28 18:50:21 +02:00
|
|
|
self.assertEqual(expected_recipient_ids, event_recipient_user_ids)
|
|
|
|
self.assertEqual(expected_recipient_ids, event_user_ids)
|
|
|
|
self.assertEqual(event_recipient_emails, expected_recipient_emails)
|
|
|
|
self.assertEqual(event['sender']['email'], email)
|
|
|
|
self.assertEqual(event['type'], 'typing')
|
|
|
|
self.assertEqual(event['op'], 'start')
|
2016-10-12 20:57:59 +02:00
|
|
|
|
2020-02-22 13:38:09 +01:00
|
|
|
def test_start_to_another_user(self) -> None:
|
2016-10-12 20:57:59 +02:00
|
|
|
"""
|
|
|
|
Sending typing notification to another user
|
|
|
|
is successful.
|
|
|
|
"""
|
2017-05-24 02:42:31 +02:00
|
|
|
sender = self.example_user('hamlet')
|
|
|
|
recipient = self.example_user('othello')
|
|
|
|
expected_recipients = set([sender, recipient])
|
|
|
|
expected_recipient_emails = set([user.email for user in expected_recipients])
|
|
|
|
expected_recipient_ids = set([user.id for user in expected_recipients])
|
2016-10-28 18:50:21 +02:00
|
|
|
|
2020-02-22 13:38:09 +01:00
|
|
|
params = dict(
|
|
|
|
to=ujson.dumps([recipient.id]),
|
|
|
|
op='start'
|
|
|
|
)
|
|
|
|
|
2017-08-04 02:25:38 +02:00
|
|
|
events = [] # type: List[Mapping[str, Any]]
|
2016-10-12 20:57:59 +02:00
|
|
|
with tornado_redirected_to_list(events):
|
2020-02-22 13:38:09 +01:00
|
|
|
result = self.api_post(sender.email, '/api/v1/typing', params)
|
|
|
|
|
2016-10-12 20:57:59 +02:00
|
|
|
self.assert_json_success(result)
|
2016-10-28 18:50:21 +02:00
|
|
|
self.assertEqual(len(events), 1)
|
2016-10-12 20:57:59 +02:00
|
|
|
|
|
|
|
event = events[0]['event']
|
|
|
|
event_recipient_emails = set(user['email'] for user in event['recipients'])
|
2016-10-28 18:50:21 +02:00
|
|
|
event_user_ids = set(events[0]['users'])
|
|
|
|
event_recipient_user_ids = set(user['user_id'] for user in event['recipients'])
|
|
|
|
|
|
|
|
self.assertEqual(expected_recipient_ids, event_recipient_user_ids)
|
|
|
|
self.assertEqual(expected_recipient_ids, event_user_ids)
|
|
|
|
self.assertEqual(event_recipient_emails, expected_recipient_emails)
|
2017-05-24 02:42:31 +02:00
|
|
|
self.assertEqual(event['sender']['email'], sender.email)
|
2016-10-28 18:50:21 +02:00
|
|
|
self.assertEqual(event['type'], 'typing')
|
|
|
|
self.assertEqual(event['op'], 'start')
|
2016-10-12 20:57:59 +02:00
|
|
|
|
2020-02-22 13:38:09 +01:00
|
|
|
def test_stop_to_self(self) -> None:
|
2016-10-12 20:57:59 +02:00
|
|
|
"""
|
|
|
|
Sending stopped typing notification to yourself
|
|
|
|
is successful.
|
|
|
|
"""
|
2017-05-08 16:23:43 +02:00
|
|
|
user = self.example_user('hamlet')
|
|
|
|
email = user.email
|
2016-10-28 18:50:21 +02:00
|
|
|
expected_recipient_emails = set([email])
|
2017-05-08 16:23:43 +02:00
|
|
|
expected_recipient_ids = set([user.id])
|
2016-10-12 20:57:59 +02:00
|
|
|
|
2017-08-04 02:25:38 +02:00
|
|
|
events = [] # type: List[Mapping[str, Any]]
|
2016-10-12 20:57:59 +02:00
|
|
|
with tornado_redirected_to_list(events):
|
2020-02-22 13:38:09 +01:00
|
|
|
params = dict(
|
|
|
|
to=ujson.dumps([user.id]),
|
|
|
|
op='stop'
|
|
|
|
)
|
|
|
|
result = self.api_post(email, '/api/v1/typing', params)
|
|
|
|
|
2016-10-12 20:57:59 +02:00
|
|
|
self.assert_json_success(result)
|
2016-10-28 18:50:21 +02:00
|
|
|
self.assertEqual(len(events), 1)
|
2016-10-12 20:57:59 +02:00
|
|
|
|
|
|
|
event = events[0]['event']
|
|
|
|
event_recipient_emails = set(user['email'] for user in event['recipients'])
|
2016-10-28 18:50:21 +02:00
|
|
|
event_user_ids = set(events[0]['users'])
|
|
|
|
event_recipient_user_ids = set(user['user_id'] for user in event['recipients'])
|
|
|
|
|
|
|
|
self.assertEqual(expected_recipient_ids, event_recipient_user_ids)
|
|
|
|
self.assertEqual(expected_recipient_ids, event_user_ids)
|
|
|
|
self.assertEqual(event_recipient_emails, expected_recipient_emails)
|
|
|
|
self.assertEqual(event['sender']['email'], email)
|
|
|
|
self.assertEqual(event['type'], 'typing')
|
|
|
|
self.assertEqual(event['op'], 'stop')
|
2016-10-12 20:57:59 +02:00
|
|
|
|
2020-02-22 13:38:09 +01:00
|
|
|
def test_stop_to_another_user(self) -> None:
|
2016-10-12 20:57:59 +02:00
|
|
|
"""
|
|
|
|
Sending stopped typing notification to another user
|
|
|
|
is successful.
|
|
|
|
"""
|
2017-05-24 02:42:31 +02:00
|
|
|
sender = self.example_user('hamlet')
|
|
|
|
recipient = self.example_user('othello')
|
|
|
|
expected_recipients = set([sender, recipient])
|
|
|
|
expected_recipient_emails = set([user.email for user in expected_recipients])
|
|
|
|
expected_recipient_ids = set([user.id for user in expected_recipients])
|
2016-10-28 18:50:21 +02:00
|
|
|
|
2017-08-04 02:25:38 +02:00
|
|
|
events = [] # type: List[Mapping[str, Any]]
|
2016-10-12 20:57:59 +02:00
|
|
|
with tornado_redirected_to_list(events):
|
2020-02-22 13:38:09 +01:00
|
|
|
params = dict(
|
|
|
|
to=ujson.dumps([recipient.id]),
|
|
|
|
op='stop'
|
|
|
|
)
|
|
|
|
result = self.api_post(sender.email, '/api/v1/typing', params)
|
|
|
|
|
2016-10-12 20:57:59 +02:00
|
|
|
self.assert_json_success(result)
|
2016-10-28 18:50:21 +02:00
|
|
|
self.assertEqual(len(events), 1)
|
2016-10-12 20:57:59 +02:00
|
|
|
|
|
|
|
event = events[0]['event']
|
|
|
|
event_recipient_emails = set(user['email'] for user in event['recipients'])
|
2016-10-28 18:50:21 +02:00
|
|
|
event_user_ids = set(events[0]['users'])
|
|
|
|
event_recipient_user_ids = set(user['user_id'] for user in event['recipients'])
|
|
|
|
|
|
|
|
self.assertEqual(expected_recipient_ids, event_recipient_user_ids)
|
|
|
|
self.assertEqual(expected_recipient_ids, event_user_ids)
|
|
|
|
self.assertEqual(event_recipient_emails, expected_recipient_emails)
|
2017-05-24 02:42:31 +02:00
|
|
|
self.assertEqual(event['sender']['email'], sender.email)
|
2016-10-28 18:50:21 +02:00
|
|
|
self.assertEqual(event['type'], 'typing')
|
|
|
|
self.assertEqual(event['op'], 'stop')
|
2018-08-21 02:41:48 +02:00
|
|
|
|
2020-02-22 13:38:09 +01:00
|
|
|
class TypingLegacyMobileSupportTest(ZulipTestCase):
|
|
|
|
def test_legacy_email_interface(self) -> None:
|
|
|
|
'''
|
|
|
|
We are keeping the email interface on life support
|
|
|
|
for a couple months until we get some of our
|
|
|
|
mobile users upgraded.
|
|
|
|
'''
|
|
|
|
sender = self.example_user('hamlet')
|
|
|
|
othello = self.example_user('othello')
|
|
|
|
cordelia = self.example_user('cordelia')
|
|
|
|
|
|
|
|
emails = [othello.email, cordelia.email]
|
|
|
|
|
|
|
|
params = dict(
|
|
|
|
to=ujson.dumps(emails),
|
|
|
|
op='start',
|
|
|
|
)
|
|
|
|
|
|
|
|
events = [] # type: List[Mapping[str, Any]]
|
|
|
|
with tornado_redirected_to_list(events):
|
|
|
|
result = self.api_post(sender.email, '/api/v1/typing', params)
|
|
|
|
|
|
|
|
self.assert_json_success(result)
|
|
|
|
event = events[0]['event']
|
|
|
|
|
|
|
|
event_recipient_user_ids = {
|
|
|
|
user['user_id']
|
|
|
|
for user in event['recipients']
|
|
|
|
}
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
event_recipient_user_ids,
|
|
|
|
{sender.id, othello.id, cordelia.id}
|
|
|
|
)
|