2017-03-08 11:57:55 +01:00
|
|
|
from __future__ import absolute_import
|
|
|
|
from __future__ import print_function
|
|
|
|
|
2017-03-25 21:23:54 +01:00
|
|
|
import datetime
|
|
|
|
import os
|
2017-03-08 11:57:55 +01:00
|
|
|
import ujson
|
|
|
|
|
|
|
|
from django.http import HttpResponse
|
2017-03-25 21:23:54 +01:00
|
|
|
from mock import MagicMock, patch
|
2017-03-08 11:57:55 +01:00
|
|
|
from six.moves import urllib
|
|
|
|
from typing import Any, Dict
|
|
|
|
|
|
|
|
from zerver.lib.test_classes import ZulipTestCase
|
2017-04-18 07:15:13 +02:00
|
|
|
from zerver.lib.test_helpers import HostRequestMock
|
2017-03-08 11:57:55 +01:00
|
|
|
from zerver.lib.test_runner import slow
|
|
|
|
from zerver.models import get_realm, get_stream, get_user_profile_by_email
|
2017-03-25 21:23:54 +01:00
|
|
|
from zerver.views.home import home, sent_time_in_epoch_seconds
|
2017-03-08 11:57:55 +01:00
|
|
|
|
|
|
|
class HomeTest(ZulipTestCase):
|
|
|
|
@slow('big method')
|
|
|
|
def test_home(self):
|
|
|
|
# type: () -> None
|
|
|
|
|
|
|
|
# Keep this list sorted!!!
|
|
|
|
html_bits = [
|
|
|
|
'Compose your message here...',
|
|
|
|
'Exclude messages with topic',
|
|
|
|
'Get started',
|
|
|
|
'Keyboard shortcuts',
|
|
|
|
'Loading...',
|
|
|
|
'Manage streams',
|
|
|
|
'Narrow by topic',
|
|
|
|
'Next message',
|
|
|
|
'SHARE THE LOVE',
|
|
|
|
'Search streams',
|
|
|
|
'Welcome to Zulip',
|
|
|
|
'pygments.css',
|
|
|
|
'var page_params',
|
|
|
|
]
|
|
|
|
|
|
|
|
# Keep this list sorted!!!
|
|
|
|
expected_keys = [
|
|
|
|
"alert_words",
|
|
|
|
"attachments",
|
|
|
|
"autoscroll_forever",
|
|
|
|
"avatar_source",
|
|
|
|
"avatar_url",
|
|
|
|
"avatar_url_medium",
|
|
|
|
"can_create_streams",
|
|
|
|
"cross_realm_bots",
|
|
|
|
"debug_mode",
|
|
|
|
"default_desktop_notifications",
|
|
|
|
"default_language",
|
|
|
|
"default_language_name",
|
|
|
|
"desktop_notifications_enabled",
|
|
|
|
"development_environment",
|
|
|
|
"email",
|
|
|
|
"emoji_alt_code",
|
2017-04-02 21:05:33 +02:00
|
|
|
"emojiset",
|
|
|
|
"emojiset_choices",
|
2017-03-08 11:57:55 +01:00
|
|
|
"enable_digest_emails",
|
|
|
|
"enable_offline_email_notifications",
|
|
|
|
"enable_offline_push_notifications",
|
|
|
|
"enable_online_push_notifications",
|
|
|
|
"enter_sends",
|
|
|
|
"event_queue_id",
|
|
|
|
"first_in_realm",
|
|
|
|
"fullname",
|
|
|
|
"furthest_read_time",
|
|
|
|
"has_mobile_devices",
|
|
|
|
"have_initial_messages",
|
2017-01-24 01:48:35 +01:00
|
|
|
"hotspots",
|
2017-03-08 11:57:55 +01:00
|
|
|
"initial_pointer",
|
|
|
|
"initial_servertime",
|
|
|
|
"is_admin",
|
|
|
|
"language_list",
|
|
|
|
"language_list_dbl_col",
|
|
|
|
"last_event_id",
|
|
|
|
"left_side_userlist",
|
|
|
|
"login_page",
|
|
|
|
"max_avatar_file_size",
|
|
|
|
"max_icon_file_size",
|
|
|
|
"max_message_id",
|
|
|
|
"maxfilesize",
|
|
|
|
"muted_topics",
|
|
|
|
"narrow",
|
|
|
|
"narrow_stream",
|
|
|
|
"needs_tutorial",
|
2017-04-21 07:53:21 +02:00
|
|
|
"never_subscribed",
|
2017-03-08 11:57:55 +01:00
|
|
|
"notifications_stream",
|
|
|
|
"people_list",
|
|
|
|
"pm_content_in_desktop_notifications",
|
|
|
|
"poll_timeout",
|
2017-04-24 21:23:50 +02:00
|
|
|
"presences",
|
2017-03-08 11:57:55 +01:00
|
|
|
"prompt_for_invites",
|
|
|
|
"realm_add_emoji_by_admins_only",
|
|
|
|
"realm_allow_message_editing",
|
|
|
|
"realm_authentication_methods",
|
2017-03-05 04:17:12 +01:00
|
|
|
"realm_bot_domain",
|
2017-04-21 08:24:30 +02:00
|
|
|
"realm_bots",
|
2017-03-08 11:57:55 +01:00
|
|
|
"realm_create_stream_by_admins_only",
|
|
|
|
"realm_default_language",
|
|
|
|
"realm_default_streams",
|
2017-03-18 20:19:44 +01:00
|
|
|
"realm_description",
|
2017-04-20 07:30:51 +02:00
|
|
|
"realm_domains",
|
2017-03-13 18:41:27 +01:00
|
|
|
"realm_email_changes_disabled",
|
2017-03-08 11:57:55 +01:00
|
|
|
"realm_emoji",
|
|
|
|
"realm_filters",
|
|
|
|
"realm_icon_source",
|
|
|
|
"realm_icon_url",
|
2017-03-13 14:42:03 +01:00
|
|
|
"realm_inline_image_preview",
|
|
|
|
"realm_inline_url_embed_preview",
|
2017-03-08 11:57:55 +01:00
|
|
|
"realm_invite_by_admins_only",
|
|
|
|
"realm_invite_required",
|
2017-04-20 08:03:44 +02:00
|
|
|
"realm_is_zephyr_mirror_realm",
|
2017-04-20 07:50:34 +02:00
|
|
|
"realm_mandatory_topics",
|
2017-03-08 11:57:55 +01:00
|
|
|
"realm_message_content_edit_limit_seconds",
|
2016-11-30 10:42:58 +01:00
|
|
|
"realm_message_retention_days",
|
2017-03-08 11:57:55 +01:00
|
|
|
"realm_name",
|
2017-03-13 18:33:49 +01:00
|
|
|
"realm_name_changes_disabled",
|
2017-04-20 08:21:31 +02:00
|
|
|
"realm_password_auth_enabled",
|
2017-03-08 11:57:55 +01:00
|
|
|
"realm_presence_disabled",
|
|
|
|
"realm_restricted_to_domain",
|
2017-04-20 07:59:03 +02:00
|
|
|
"realm_show_digest_email",
|
2017-03-08 11:57:55 +01:00
|
|
|
"realm_uri",
|
|
|
|
"realm_waiting_period_threshold",
|
|
|
|
"referrals",
|
|
|
|
"save_stacktraces",
|
|
|
|
"server_generation",
|
2017-03-13 14:42:03 +01:00
|
|
|
"server_inline_image_preview",
|
|
|
|
"server_inline_url_embed_preview",
|
2017-03-08 11:57:55 +01:00
|
|
|
"server_uri",
|
|
|
|
"share_the_love",
|
|
|
|
"sounds_enabled",
|
|
|
|
"stream_desktop_notifications_enabled",
|
|
|
|
"stream_sounds_enabled",
|
2017-04-21 07:43:51 +02:00
|
|
|
"subscriptions",
|
2017-03-08 11:57:55 +01:00
|
|
|
"test_suite",
|
2017-03-14 10:53:09 +01:00
|
|
|
"timezone",
|
2017-03-08 11:57:55 +01:00
|
|
|
"twenty_four_hour_time",
|
|
|
|
"unread_count",
|
2017-04-21 07:49:41 +02:00
|
|
|
"unsubscribed",
|
2017-03-08 11:57:55 +01:00
|
|
|
"use_websockets",
|
|
|
|
"user_id",
|
|
|
|
"zulip_version",
|
|
|
|
]
|
|
|
|
|
|
|
|
email = "hamlet@zulip.com"
|
|
|
|
|
|
|
|
# Verify fails if logged-out
|
|
|
|
result = self.client_get('/')
|
|
|
|
self.assertEqual(result.status_code, 302)
|
|
|
|
|
|
|
|
self.login(email)
|
|
|
|
|
2017-04-21 08:24:30 +02:00
|
|
|
# Create bot for realm_bots testing. Must be done before fetching home_page.
|
2017-03-08 11:57:55 +01:00
|
|
|
bot_info = {
|
|
|
|
'full_name': 'The Bot of Hamlet',
|
|
|
|
'short_name': 'hambot',
|
|
|
|
}
|
|
|
|
self.client_post("/json/bots", bot_info)
|
|
|
|
|
|
|
|
# Verify succeeds once logged-in
|
|
|
|
result = self._get_home_page(stream='Denmark')
|
|
|
|
html = result.content.decode('utf-8')
|
|
|
|
|
|
|
|
for html_bit in html_bits:
|
|
|
|
if html_bit not in html:
|
|
|
|
raise AssertionError('%s not in result' % (html_bit,))
|
|
|
|
|
|
|
|
page_params = self._get_page_params(result)
|
|
|
|
|
|
|
|
actual_keys = sorted([str(k) for k in page_params.keys()])
|
|
|
|
|
|
|
|
self.assertEqual(actual_keys, expected_keys)
|
|
|
|
|
|
|
|
# TODO: Inspect the page_params data further.
|
|
|
|
# print(ujson.dumps(page_params, indent=2))
|
2017-04-21 08:24:30 +02:00
|
|
|
realm_bots_expected_keys = [
|
2017-03-08 11:57:55 +01:00
|
|
|
'api_key',
|
|
|
|
'avatar_url',
|
|
|
|
'default_all_public_streams',
|
|
|
|
'default_events_register_stream',
|
|
|
|
'default_sending_stream',
|
|
|
|
'email',
|
|
|
|
'full_name',
|
|
|
|
'is_active',
|
|
|
|
'owner',
|
|
|
|
'user_id',
|
|
|
|
]
|
|
|
|
|
2017-04-21 08:24:30 +02:00
|
|
|
realm_bots_actual_keys = sorted([str(key) for key in page_params['realm_bots'][0].keys()])
|
|
|
|
self.assertEqual(realm_bots_actual_keys, realm_bots_expected_keys)
|
2017-03-08 11:57:55 +01:00
|
|
|
|
|
|
|
def _get_home_page(self, **kwargs):
|
|
|
|
# type: (**Any) -> HttpResponse
|
|
|
|
with \
|
|
|
|
patch('zerver.lib.events.request_event_queue', return_value=42), \
|
|
|
|
patch('zerver.lib.events.get_user_events', return_value=[]):
|
|
|
|
result = self.client_get('/', dict(**kwargs))
|
|
|
|
return result
|
|
|
|
|
|
|
|
def _get_page_params(self, result):
|
|
|
|
# type: (HttpResponse) -> Dict[str, Any]
|
|
|
|
html = result.content.decode('utf-8')
|
|
|
|
lines = html.split('\n')
|
|
|
|
page_params_line = [l for l in lines if l.startswith('var page_params')][0]
|
|
|
|
page_params_json = page_params_line.split(' = ')[1].rstrip(';')
|
|
|
|
page_params = ujson.loads(page_params_json)
|
|
|
|
return page_params
|
|
|
|
|
|
|
|
def _sanity_check(self, result):
|
|
|
|
# type: (HttpResponse) -> None
|
|
|
|
'''
|
|
|
|
Use this for tests that are geared toward specific edge cases, but
|
|
|
|
which still want the home page to load properly.
|
|
|
|
'''
|
|
|
|
html = result.content.decode('utf-8')
|
|
|
|
if 'Compose your message' not in html:
|
|
|
|
raise AssertionError('Home page probably did not load.')
|
|
|
|
|
|
|
|
def test_terms_of_service(self):
|
|
|
|
# type: () -> None
|
|
|
|
email = 'hamlet@zulip.com'
|
|
|
|
self.login(email)
|
|
|
|
|
|
|
|
for user_tos_version in [None, '1.1', '2.0.3.4']:
|
|
|
|
user = get_user_profile_by_email(email)
|
|
|
|
user.tos_version = user_tos_version
|
|
|
|
user.save()
|
|
|
|
|
|
|
|
with \
|
|
|
|
self.settings(TERMS_OF_SERVICE='whatever'), \
|
|
|
|
self.settings(TOS_VERSION='99.99'):
|
|
|
|
|
|
|
|
result = self.client_get('/', dict(stream='Denmark'))
|
|
|
|
|
|
|
|
html = result.content.decode('utf-8')
|
|
|
|
self.assertIn('There are new Terms of Service', html)
|
|
|
|
|
2017-03-25 21:23:54 +01:00
|
|
|
def test_terms_of_service_first_time_template(self):
|
|
|
|
# type: () -> None
|
|
|
|
email = "hamlet@zulip.com"
|
|
|
|
self.login(email)
|
|
|
|
|
|
|
|
user = get_user_profile_by_email(email)
|
|
|
|
user.tos_version = None
|
|
|
|
user.save()
|
|
|
|
|
|
|
|
with \
|
|
|
|
self.settings(FIRST_TIME_TOS_TEMPLATE='hello.html'), \
|
|
|
|
self.settings(TOS_VERSION='99.99'):
|
|
|
|
result = self.client_post('/accounts/accept_terms/')
|
|
|
|
self.assertEqual(result.status_code, 200)
|
|
|
|
self.assert_in_response("I agree to the", result)
|
|
|
|
self.assert_in_response("Finally, workplace chat", result)
|
|
|
|
|
|
|
|
def test_accept_terms_of_service(self):
|
|
|
|
# type: () -> None
|
|
|
|
email = "hamlet@zulip.com"
|
|
|
|
self.login(email)
|
|
|
|
|
|
|
|
result = self.client_post('/accounts/accept_terms/')
|
|
|
|
self.assertEqual(result.status_code, 200)
|
|
|
|
self.assert_in_response("I agree to the", result)
|
|
|
|
|
|
|
|
result = self.client_post('/accounts/accept_terms/', {'terms': True})
|
|
|
|
self.assertEqual(result.status_code, 302)
|
|
|
|
self.assertEqual(result['Location'], '/')
|
|
|
|
|
2017-03-08 11:57:55 +01:00
|
|
|
def test_bad_narrow(self):
|
|
|
|
# type: () -> None
|
|
|
|
email = 'hamlet@zulip.com'
|
|
|
|
self.login(email)
|
|
|
|
with patch('logging.exception') as mock:
|
|
|
|
result = self._get_home_page(stream='Invalid Stream')
|
|
|
|
mock.assert_called_once_with('Narrow parsing')
|
|
|
|
self._sanity_check(result)
|
|
|
|
|
|
|
|
def test_bad_pointer(self):
|
|
|
|
# type: () -> None
|
|
|
|
email = 'hamlet@zulip.com'
|
|
|
|
user_profile = get_user_profile_by_email(email)
|
|
|
|
user_profile.pointer = 999999
|
|
|
|
user_profile.save()
|
|
|
|
|
|
|
|
self.login(email)
|
|
|
|
with patch('logging.warning') as mock:
|
|
|
|
result = self._get_home_page()
|
|
|
|
mock.assert_called_once_with('hamlet@zulip.com has invalid pointer 999999')
|
|
|
|
self._sanity_check(result)
|
|
|
|
|
|
|
|
def test_topic_narrow(self):
|
|
|
|
# type: () -> None
|
|
|
|
email = 'hamlet@zulip.com'
|
|
|
|
self.login(email)
|
|
|
|
result = self._get_home_page(stream='Denmark', topic='lunch')
|
|
|
|
self._sanity_check(result)
|
|
|
|
html = result.content.decode('utf-8')
|
|
|
|
self.assertIn('lunch', html)
|
|
|
|
|
|
|
|
def test_notifications_stream(self):
|
|
|
|
# type: () -> None
|
|
|
|
email = 'hamlet@zulip.com'
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
realm.notifications_stream = get_stream('Denmark', realm)
|
|
|
|
realm.save()
|
|
|
|
self.login(email)
|
|
|
|
result = self._get_home_page()
|
|
|
|
page_params = self._get_page_params(result)
|
|
|
|
self.assertEqual(page_params['notifications_stream'], 'Denmark')
|
|
|
|
|
|
|
|
def test_people(self):
|
|
|
|
# type: () -> None
|
|
|
|
email = 'hamlet@zulip.com'
|
|
|
|
self.login(email)
|
|
|
|
result = self._get_home_page()
|
|
|
|
page_params = self._get_page_params(result)
|
2017-04-21 08:24:30 +02:00
|
|
|
for params in ['people_list', 'realm_bots']:
|
2017-03-08 11:57:55 +01:00
|
|
|
users = page_params['people_list']
|
|
|
|
self.assertTrue(len(users) >= 3)
|
|
|
|
for user in users:
|
|
|
|
self.assertEqual(user['user_id'],
|
|
|
|
get_user_profile_by_email(user['email']).id)
|
|
|
|
|
|
|
|
cross_bots = page_params['cross_realm_bots']
|
|
|
|
self.assertEqual(len(cross_bots), 2)
|
|
|
|
cross_bots.sort(key=lambda d: d['email'])
|
|
|
|
self.assertEqual(cross_bots, [
|
|
|
|
dict(
|
|
|
|
user_id=get_user_profile_by_email('feedback@zulip.com').id,
|
|
|
|
is_admin=False,
|
|
|
|
email='feedback@zulip.com',
|
|
|
|
full_name='Zulip Feedback Bot',
|
|
|
|
is_bot=True
|
|
|
|
),
|
|
|
|
dict(
|
|
|
|
user_id=get_user_profile_by_email('notification-bot@zulip.com').id,
|
|
|
|
is_admin=False,
|
|
|
|
email='notification-bot@zulip.com',
|
|
|
|
full_name='Notification Bot',
|
|
|
|
is_bot=True
|
|
|
|
),
|
|
|
|
])
|
|
|
|
|
|
|
|
def test_new_stream(self):
|
|
|
|
# type: () -> None
|
|
|
|
email = 'hamlet@zulip.com'
|
|
|
|
stream_name = 'New stream'
|
|
|
|
self.subscribe_to_stream(email, stream_name)
|
|
|
|
self.login(email)
|
|
|
|
result = self._get_home_page(stream=stream_name)
|
|
|
|
page_params = self._get_page_params(result)
|
|
|
|
self.assertEqual(page_params['narrow_stream'], stream_name)
|
|
|
|
self.assertEqual(page_params['narrow'], [dict(operator='stream', operand=stream_name)])
|
|
|
|
self.assertEqual(page_params['initial_pointer'], -1)
|
|
|
|
self.assertEqual(page_params['max_message_id'], -1)
|
|
|
|
self.assertEqual(page_params['have_initial_messages'], False)
|
|
|
|
|
|
|
|
def test_invites_by_admins_only(self):
|
|
|
|
# type: () -> None
|
|
|
|
email = 'hamlet@zulip.com'
|
|
|
|
user_profile = get_user_profile_by_email(email)
|
|
|
|
|
|
|
|
realm = user_profile.realm
|
|
|
|
realm.invite_by_admins_only = True
|
|
|
|
realm.save()
|
|
|
|
|
|
|
|
self.login(email)
|
|
|
|
self.assertFalse(user_profile.is_realm_admin)
|
|
|
|
result = self._get_home_page()
|
|
|
|
html = result.content.decode('utf-8')
|
|
|
|
self.assertNotIn('Invite more users', html)
|
|
|
|
|
|
|
|
user_profile.is_realm_admin = True
|
|
|
|
user_profile.save()
|
|
|
|
result = self._get_home_page()
|
|
|
|
html = result.content.decode('utf-8')
|
|
|
|
self.assertIn('Invite more users', html)
|
|
|
|
|
|
|
|
def test_desktop_home(self):
|
|
|
|
# type: () -> None
|
|
|
|
email = 'hamlet@zulip.com'
|
|
|
|
self.login(email)
|
|
|
|
result = self.client_get("/desktop_home")
|
|
|
|
self.assertEqual(result.status_code, 301)
|
|
|
|
self.assertTrue(result["Location"].endswith("/desktop_home/"))
|
|
|
|
result = self.client_get("/desktop_home/")
|
|
|
|
self.assertEqual(result.status_code, 302)
|
|
|
|
path = urllib.parse.urlparse(result['Location']).path
|
|
|
|
self.assertEqual(path, "/")
|
|
|
|
|
|
|
|
def test_generate_204(self):
|
|
|
|
# type: () -> None
|
|
|
|
email = 'hamlet@zulip.com'
|
|
|
|
self.login(email)
|
|
|
|
result = self.client_get("/api/v1/generate_204")
|
|
|
|
self.assertEqual(result.status_code, 204)
|
2017-03-25 21:23:54 +01:00
|
|
|
|
|
|
|
def test_message_sent_time(self):
|
|
|
|
# type: () -> None
|
|
|
|
epoch_seconds = 1490472096
|
|
|
|
pub_date = datetime.datetime.fromtimestamp(epoch_seconds)
|
|
|
|
user_message = MagicMock()
|
|
|
|
user_message.message.pub_date = pub_date
|
|
|
|
self.assertEqual(sent_time_in_epoch_seconds(user_message), epoch_seconds)
|
|
|
|
|
|
|
|
def test_handlebars_compile_error(self):
|
|
|
|
# type: () -> None
|
2017-04-18 07:15:13 +02:00
|
|
|
request = HostRequestMock()
|
2017-03-25 21:23:54 +01:00
|
|
|
with self.settings(DEVELOPMENT=True):
|
|
|
|
with patch('os.path.exists', return_value=True):
|
|
|
|
result = home(request)
|
|
|
|
self.assertEqual(result.status_code, 500)
|
|
|
|
self.assert_in_response('Error compiling handlebars templates.', result)
|
|
|
|
|
|
|
|
def test_subdomain_homepage(self):
|
|
|
|
# type: () -> None
|
|
|
|
email = 'hamlet@zulip.com'
|
|
|
|
self.login(email)
|
|
|
|
with self.settings(SUBDOMAINS_HOMEPAGE=True):
|
|
|
|
with patch('zerver.views.home.get_subdomain', return_value=""):
|
|
|
|
result = self._get_home_page()
|
|
|
|
self.assertEqual(result.status_code, 200)
|
|
|
|
self.assert_in_response('Finally, workplace chat', result)
|
|
|
|
|
|
|
|
with patch('zerver.views.home.get_subdomain', return_value="subdomain"):
|
|
|
|
result = self._get_home_page()
|
|
|
|
self._sanity_check(result)
|