2016-05-24 14:06:34 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
2017-03-31 07:40:52 +02:00
|
|
|
import re
|
2016-06-04 20:28:02 +02:00
|
|
|
from typing import Any, Dict, Iterable
|
2016-05-24 14:06:34 +02:00
|
|
|
import logging
|
|
|
|
|
2016-05-11 19:29:29 +02:00
|
|
|
from django.conf import settings
|
|
|
|
from django.test import override_settings
|
2016-05-11 19:01:53 +02:00
|
|
|
from django.template import Template, Context
|
2016-05-24 14:06:34 +02:00
|
|
|
from django.template.loader import get_template
|
|
|
|
|
2016-11-10 19:30:09 +01:00
|
|
|
from zerver.lib.test_helpers import get_all_templates
|
|
|
|
from zerver.lib.test_classes import (
|
|
|
|
ZulipTestCase,
|
|
|
|
)
|
2017-10-07 00:29:18 +02:00
|
|
|
from zerver.lib.test_runner import slow
|
2016-11-15 13:41:12 +01:00
|
|
|
from zerver.context_processors import common_context
|
|
|
|
|
2016-05-24 14:06:34 +02:00
|
|
|
|
2017-11-05 11:49:43 +01:00
|
|
|
class get_form_value:
|
2017-11-05 10:51:25 +01:00
|
|
|
def __init__(self, value: Any) -> None:
|
2016-05-24 14:06:34 +02:00
|
|
|
self._value = value
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def value(self) -> Any:
|
2016-05-24 14:06:34 +02:00
|
|
|
return self._value
|
|
|
|
|
|
|
|
|
2017-11-02 18:36:25 +01:00
|
|
|
class DummyForm(Dict[str, Any]):
|
2016-05-24 14:06:34 +02:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
2016-08-23 02:08:42 +02:00
|
|
|
class TemplateTestCase(ZulipTestCase):
|
2016-05-24 14:06:34 +02:00
|
|
|
"""
|
|
|
|
Tests that backend template rendering doesn't crash.
|
|
|
|
|
|
|
|
This renders all the Zulip backend templates, passing dummy data
|
|
|
|
as the context, which allows us to verify whether any of the
|
|
|
|
templates are broken enough to not render at all (no verification
|
|
|
|
is done that the output looks right). Please see `get_context`
|
|
|
|
function documentation for more information.
|
|
|
|
"""
|
2017-10-07 00:29:18 +02:00
|
|
|
@slow("Tests a large number of different templates")
|
2016-05-11 19:29:29 +02:00
|
|
|
@override_settings(TERMS_OF_SERVICE=None)
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_templates(self) -> None:
|
2016-06-04 20:28:02 +02:00
|
|
|
|
2016-05-24 14:06:34 +02:00
|
|
|
# Just add the templates whose context has a conflict with other
|
2016-05-11 19:01:53 +02:00
|
|
|
# templates' context in `defer`.
|
|
|
|
defer = ['analytics/activity.html']
|
2016-12-01 08:54:21 +01:00
|
|
|
|
|
|
|
# Django doesn't send template_rendered signal for parent templates
|
|
|
|
# https://code.djangoproject.com/ticket/24622
|
|
|
|
covered = [
|
2016-11-15 13:41:12 +01:00
|
|
|
'zerver/portico.html',
|
|
|
|
'zerver/portico_signup.html',
|
|
|
|
]
|
2016-12-01 08:54:21 +01:00
|
|
|
|
|
|
|
logged_out = [
|
|
|
|
'confirmation/confirm.html', # seems unused
|
2017-05-13 23:57:06 +02:00
|
|
|
'zerver/compare.html',
|
2017-05-10 03:42:24 +02:00
|
|
|
'zerver/footer.html',
|
2016-12-01 08:54:21 +01:00
|
|
|
]
|
|
|
|
|
2016-11-15 13:41:12 +01:00
|
|
|
logged_in = [
|
2016-12-20 02:30:08 +01:00
|
|
|
'analytics/stats.html',
|
2017-02-22 02:34:05 +01:00
|
|
|
'zerver/drafts.html',
|
2016-11-15 13:41:12 +01:00
|
|
|
'zerver/home.html',
|
|
|
|
'zerver/invite_user.html',
|
|
|
|
'zerver/keyboard_shortcuts.html',
|
2017-03-01 18:00:51 +01:00
|
|
|
'zerver/left_sidebar.html',
|
2017-03-09 02:30:44 +01:00
|
|
|
'zerver/landing_nav.html',
|
2016-11-15 13:41:12 +01:00
|
|
|
'zerver/logout.html',
|
|
|
|
'zerver/markdown_help.html',
|
|
|
|
'zerver/navbar.html',
|
2017-03-01 18:02:15 +01:00
|
|
|
'zerver/right_sidebar.html',
|
2016-11-15 13:41:12 +01:00
|
|
|
'zerver/search_operators.html',
|
2016-12-03 01:12:52 +01:00
|
|
|
'zerver/settings_overlay.html',
|
2017-03-01 17:59:23 +01:00
|
|
|
'zerver/settings_sidebar.html',
|
2016-11-15 13:41:12 +01:00
|
|
|
'zerver/stream_creation_prompt.html',
|
|
|
|
'zerver/subscriptions.html',
|
2017-02-20 02:37:58 +01:00
|
|
|
'zerver/message_history.html',
|
2017-05-14 21:14:26 +02:00
|
|
|
'zerver/delete_message.html',
|
2016-11-15 13:41:12 +01:00
|
|
|
]
|
|
|
|
unusual = [
|
2017-05-01 20:28:42 +02:00
|
|
|
'zerver/emails/confirm_new_email.subject',
|
2017-09-26 01:41:15 +02:00
|
|
|
'zerver/emails/compiled/confirm_new_email.html',
|
2017-05-01 20:28:42 +02:00
|
|
|
'zerver/emails/confirm_new_email.txt',
|
2017-05-01 22:03:05 +02:00
|
|
|
'zerver/emails/notify_change_in_email.subject',
|
2017-09-26 01:41:15 +02:00
|
|
|
'zerver/emails/compiled/notify_change_in_email.html',
|
2017-05-04 06:42:23 +02:00
|
|
|
'zerver/emails/digest.subject',
|
|
|
|
'zerver/emails/digest.html',
|
|
|
|
'zerver/emails/digest.txt',
|
|
|
|
'zerver/emails/followup_day1.subject',
|
2017-09-26 01:41:15 +02:00
|
|
|
'zerver/emails/compiled/followup_day1.html',
|
2017-05-04 06:42:23 +02:00
|
|
|
'zerver/emails/followup_day1.txt',
|
|
|
|
'zerver/emails/followup_day2.subject',
|
|
|
|
'zerver/emails/followup_day2.txt',
|
2017-09-26 01:41:15 +02:00
|
|
|
'zerver/emails/compiled/followup_day2.html',
|
|
|
|
'zerver/emails/compiled/password_reset.html',
|
2016-11-15 13:41:12 +01:00
|
|
|
'corporate/mit.html',
|
|
|
|
'corporate/zephyr.html',
|
|
|
|
'corporate/zephyr-mirror.html',
|
|
|
|
'pipeline/css.jinja',
|
|
|
|
'pipeline/inline_js.jinja',
|
|
|
|
'pipeline/js.jinja',
|
|
|
|
'zilencer/enterprise_tos_accept_body.txt',
|
|
|
|
'zerver/zulipchat_migration_tos.html',
|
|
|
|
'zilencer/enterprise_tos_accept_body.txt',
|
2018-03-05 20:19:07 +01:00
|
|
|
'zerver/invalid_email.html',
|
2016-11-15 13:41:12 +01:00
|
|
|
'zerver/topic_is_muted.html',
|
|
|
|
'zerver/bankruptcy.html',
|
2017-03-01 18:03:35 +01:00
|
|
|
'zerver/lightbox_overlay.html',
|
2016-11-15 13:41:12 +01:00
|
|
|
'zerver/invalid_realm.html',
|
|
|
|
'zerver/compose.html',
|
|
|
|
'zerver/debug.html',
|
|
|
|
'zerver/base.html',
|
|
|
|
'zerver/api_content.json',
|
2017-02-28 05:42:19 +01:00
|
|
|
'zerver/handlebars_compilation_failed.html',
|
2017-08-04 02:48:07 +02:00
|
|
|
'zerver/portico-header.html',
|
2018-02-08 15:17:26 +01:00
|
|
|
'zerver/deprecation_notice.html',
|
2017-07-12 09:44:50 +02:00
|
|
|
'two_factor/_wizard_forms.html',
|
2016-11-15 13:41:12 +01:00
|
|
|
]
|
2017-03-31 07:40:52 +02:00
|
|
|
|
|
|
|
integrations_regexp = re.compile('zerver/integrations/.*.html')
|
|
|
|
|
2017-09-17 02:14:56 +02:00
|
|
|
# Since static/generated/bots/ is searched by Jinja2 for templates,
|
|
|
|
# it mistakes logo files under that directory for templates.
|
2018-07-02 00:05:24 +02:00
|
|
|
bot_logos_regexp = re.compile(r'\w+\/logo\.(svg|png)$')
|
2017-09-17 02:14:56 +02:00
|
|
|
|
2017-04-10 12:55:43 +02:00
|
|
|
skip = covered + defer + logged_out + logged_in + unusual + ['tests/test_markdown.html',
|
|
|
|
'zerver/terms.html',
|
|
|
|
'zerver/privacy.html']
|
2017-09-17 02:14:56 +02:00
|
|
|
|
|
|
|
templates = [t for t in get_all_templates() if not (
|
|
|
|
t in skip or integrations_regexp.match(t) or bot_logos_regexp.match(t))]
|
2016-05-24 14:06:34 +02:00
|
|
|
self.render_templates(templates, self.get_context())
|
|
|
|
|
2016-05-11 19:01:53 +02:00
|
|
|
# Test the deferred templates with updated context.
|
2016-05-24 14:06:34 +02:00
|
|
|
update = {'data': [('one', 'two')]}
|
2016-05-11 19:01:53 +02:00
|
|
|
self.render_templates(defer, self.get_context(**update))
|
2016-05-24 14:06:34 +02:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def render_templates(self, templates: Iterable[str], context: Dict[str, Any]) -> None:
|
2016-11-15 13:41:12 +01:00
|
|
|
for template_name in templates:
|
|
|
|
template = get_template(template_name)
|
2016-05-24 14:06:34 +02:00
|
|
|
try:
|
|
|
|
template.render(context)
|
2017-03-05 08:23:45 +01:00
|
|
|
except Exception: # nocoverage # nicer error handler
|
2016-08-09 18:53:41 +02:00
|
|
|
logging.error("Exception while rendering '{}'".format(template.template.name))
|
|
|
|
raise
|
2016-05-24 14:06:34 +02:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def get_context(self, **kwargs: Any) -> Dict[str, Any]:
|
2016-05-24 14:06:34 +02:00
|
|
|
"""Get the dummy context for shallow testing.
|
|
|
|
|
|
|
|
The context returned will always contain a parameter called
|
|
|
|
`shallow_tested`, which tells the signal receiver that the
|
|
|
|
test was not rendered in an actual logical test (so we can
|
|
|
|
still do coverage reporting on which templates have a logical
|
|
|
|
test).
|
|
|
|
|
|
|
|
Note: `context` just holds dummy values used to make the test
|
|
|
|
pass. This context only ensures that the templates do not
|
|
|
|
throw a 500 error when rendered using dummy data. If new
|
|
|
|
required parameters are added to a template, this test will
|
|
|
|
fail; the usual fix is to just update the context below to add
|
|
|
|
the new parameter to the dummy data.
|
|
|
|
|
|
|
|
:param kwargs: Keyword arguments can be used to update the base
|
|
|
|
context.
|
|
|
|
|
|
|
|
"""
|
2017-05-07 19:39:30 +02:00
|
|
|
user_profile = self.example_user('hamlet')
|
|
|
|
email = user_profile.email
|
2016-05-24 14:06:34 +02:00
|
|
|
|
|
|
|
context = dict(
|
2017-04-03 11:49:13 +02:00
|
|
|
article="zerver/help/index.md",
|
2016-05-24 14:06:34 +02:00
|
|
|
shallow_tested=True,
|
|
|
|
user_profile=user_profile,
|
2016-08-21 08:19:25 +02:00
|
|
|
user=user_profile,
|
2016-05-24 14:06:34 +02:00
|
|
|
form=DummyForm(
|
|
|
|
full_name=get_form_value('John Doe'),
|
|
|
|
terms=get_form_value(True),
|
|
|
|
email=get_form_value(email),
|
2016-12-20 10:41:46 +01:00
|
|
|
emails=get_form_value(email),
|
2016-05-24 14:06:34 +02:00
|
|
|
),
|
|
|
|
current_url=lambda: 'www.zulip.com',
|
2016-08-09 18:53:57 +02:00
|
|
|
integrations_dict={},
|
2016-05-24 14:06:34 +02:00
|
|
|
referrer=dict(
|
|
|
|
full_name='John Doe',
|
|
|
|
realm=dict(name='zulip.com'),
|
|
|
|
),
|
|
|
|
message_count=0,
|
|
|
|
messages=[dict(header='Header')],
|
|
|
|
new_streams=dict(html=''),
|
|
|
|
data=dict(title='Title'),
|
2017-01-30 23:19:38 +01:00
|
|
|
device_info={"device_browser": "Chrome",
|
|
|
|
"device_os": "Windows",
|
|
|
|
"device_ip": "127.0.0.1",
|
|
|
|
"login_time": "9:33am NewYork, NewYork",
|
|
|
|
},
|
2017-11-08 05:39:42 +01:00
|
|
|
api_uri_context={},
|
2016-05-24 14:06:34 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
context.update(kwargs)
|
|
|
|
return context
|
2016-05-11 19:01:53 +02:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_markdown_in_template(self) -> None:
|
2016-05-11 19:01:53 +02:00
|
|
|
template = get_template("tests/test_markdown.html")
|
|
|
|
context = {
|
|
|
|
'markdown_test_file': "zerver/tests/markdown/test_markdown.md"
|
|
|
|
}
|
|
|
|
content = template.render(context)
|
|
|
|
|
|
|
|
content_sans_whitespace = content.replace(" ", "").replace('\n', '')
|
|
|
|
self.assertEqual(content_sans_whitespace,
|
2016-11-09 21:52:42 +01:00
|
|
|
'header<h1id="hello">Hello!</h1><p>Thisissome<em>boldtext</em>.</p>footer')
|
2016-05-11 19:29:29 +02:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_custom_tos_template(self) -> None:
|
2016-05-11 19:29:29 +02:00
|
|
|
response = self.client_get("/terms/")
|
2016-11-19 21:54:00 +01:00
|
|
|
|
|
|
|
self.assert_in_success_response([u"Thanks for using our products and services (\"Services\"). ",
|
|
|
|
u"By using our Services, you are agreeing to these terms"],
|
|
|
|
response)
|
2017-04-10 12:55:43 +02:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_custom_terms_of_service_template(self) -> None:
|
2017-04-12 23:40:38 +02:00
|
|
|
not_configured_message = 'This installation of Zulip does not have a configured ' \
|
|
|
|
'terms of service'
|
2017-04-10 12:55:43 +02:00
|
|
|
with self.settings(TERMS_OF_SERVICE=None):
|
|
|
|
response = self.client_get('/terms/')
|
|
|
|
self.assert_in_success_response([not_configured_message], response)
|
|
|
|
with self.settings(TERMS_OF_SERVICE='zerver/tests/markdown/test_markdown.md'):
|
|
|
|
response = self.client_get('/terms/')
|
|
|
|
self.assert_in_success_response(['This is some <em>bold text</em>.'], response)
|
|
|
|
self.assert_not_in_success_response([not_configured_message], response)
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_custom_privacy_policy_template(self) -> None:
|
2017-04-12 23:40:38 +02:00
|
|
|
not_configured_message = 'This installation of Zulip does not have a configured ' \
|
|
|
|
'privacy policy'
|
2017-04-10 12:55:43 +02:00
|
|
|
with self.settings(PRIVACY_POLICY=None):
|
|
|
|
response = self.client_get('/privacy/')
|
|
|
|
self.assert_in_success_response([not_configured_message], response)
|
|
|
|
with self.settings(PRIVACY_POLICY='zerver/tests/markdown/test_markdown.md'):
|
|
|
|
response = self.client_get('/privacy/')
|
|
|
|
self.assert_in_success_response(['This is some <em>bold text</em>.'], response)
|
|
|
|
self.assert_not_in_success_response([not_configured_message], response)
|