mirror of https://github.com/mitsuhiko/flask.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
443 lines
12 KiB
443 lines
12 KiB
# -*- coding: utf-8 -*- |
|
""" |
|
tests.templating |
|
~~~~~~~~~~~~~~~~ |
|
|
|
Template functionality |
|
|
|
:copyright: (c) 2015 by Armin Ronacher. |
|
:license: BSD, see LICENSE for more details. |
|
""" |
|
|
|
import pytest |
|
|
|
import flask |
|
import logging |
|
from jinja2 import TemplateNotFound |
|
import werkzeug.serving |
|
|
|
|
|
def test_context_processing(app, client): |
|
@app.context_processor |
|
def context_processor(): |
|
return {'injected_value': 42} |
|
|
|
@app.route('/') |
|
def index(): |
|
return flask.render_template('context_template.html', value=23) |
|
|
|
rv = client.get('/') |
|
assert rv.data == b'<p>23|42' |
|
|
|
|
|
def test_original_win(app, client): |
|
@app.route('/') |
|
def index(): |
|
return flask.render_template_string('{{ config }}', config=42) |
|
|
|
rv = client.get('/') |
|
assert rv.data == b'42' |
|
|
|
|
|
def test_request_less_rendering(app, app_ctx): |
|
app.config['WORLD_NAME'] = 'Special World' |
|
|
|
@app.context_processor |
|
def context_processor(): |
|
return dict(foo=42) |
|
|
|
rv = flask.render_template_string('Hello {{ config.WORLD_NAME }} ' |
|
'{{ foo }}') |
|
assert rv == 'Hello Special World 42' |
|
|
|
|
|
def test_standard_context(app, client): |
|
@app.route('/') |
|
def index(): |
|
flask.g.foo = 23 |
|
flask.session['test'] = 'aha' |
|
return flask.render_template_string(''' |
|
{{ request.args.foo }} |
|
{{ g.foo }} |
|
{{ config.DEBUG }} |
|
{{ session.test }} |
|
''') |
|
|
|
rv = client.get('/?foo=42') |
|
assert rv.data.split() == [b'42', b'23', b'False', b'aha'] |
|
|
|
|
|
def test_escaping(app, client): |
|
text = '<p>Hello World!' |
|
|
|
@app.route('/') |
|
def index(): |
|
return flask.render_template('escaping_template.html', text=text, |
|
html=flask.Markup(text)) |
|
|
|
lines = client.get('/').data.splitlines() |
|
assert lines == [ |
|
b'<p>Hello World!', |
|
b'<p>Hello World!', |
|
b'<p>Hello World!', |
|
b'<p>Hello World!', |
|
b'<p>Hello World!', |
|
b'<p>Hello World!' |
|
] |
|
|
|
|
|
def test_no_escaping(app, client): |
|
text = '<p>Hello World!' |
|
|
|
@app.route('/') |
|
def index(): |
|
return flask.render_template('non_escaping_template.txt', text=text, |
|
html=flask.Markup(text)) |
|
|
|
lines = client.get('/').data.splitlines() |
|
assert lines == [ |
|
b'<p>Hello World!', |
|
b'<p>Hello World!', |
|
b'<p>Hello World!', |
|
b'<p>Hello World!', |
|
b'<p>Hello World!', |
|
b'<p>Hello World!', |
|
b'<p>Hello World!', |
|
b'<p>Hello World!' |
|
] |
|
|
|
|
|
def test_escaping_without_template_filename(app, client, req_ctx): |
|
assert flask.render_template_string( |
|
'{{ foo }}', foo='<test>') == '<test>' |
|
assert flask.render_template('mail.txt', foo='<test>') == '<test> Mail' |
|
|
|
|
|
def test_macros(app, req_ctx): |
|
macro = flask.get_template_attribute('_macro.html', 'hello') |
|
assert macro('World') == 'Hello World!' |
|
|
|
|
|
def test_template_filter(app): |
|
@app.template_filter() |
|
def my_reverse(s): |
|
return s[::-1] |
|
|
|
assert 'my_reverse' in app.jinja_env.filters.keys() |
|
assert app.jinja_env.filters['my_reverse'] == my_reverse |
|
assert app.jinja_env.filters['my_reverse']('abcd') == 'dcba' |
|
|
|
|
|
def test_add_template_filter(app): |
|
def my_reverse(s): |
|
return s[::-1] |
|
|
|
app.add_template_filter(my_reverse) |
|
assert 'my_reverse' in app.jinja_env.filters.keys() |
|
assert app.jinja_env.filters['my_reverse'] == my_reverse |
|
assert app.jinja_env.filters['my_reverse']('abcd') == 'dcba' |
|
|
|
|
|
def test_template_filter_with_name(app): |
|
@app.template_filter('strrev') |
|
def my_reverse(s): |
|
return s[::-1] |
|
|
|
assert 'strrev' in app.jinja_env.filters.keys() |
|
assert app.jinja_env.filters['strrev'] == my_reverse |
|
assert app.jinja_env.filters['strrev']('abcd') == 'dcba' |
|
|
|
|
|
def test_add_template_filter_with_name(app): |
|
def my_reverse(s): |
|
return s[::-1] |
|
|
|
app.add_template_filter(my_reverse, 'strrev') |
|
assert 'strrev' in app.jinja_env.filters.keys() |
|
assert app.jinja_env.filters['strrev'] == my_reverse |
|
assert app.jinja_env.filters['strrev']('abcd') == 'dcba' |
|
|
|
|
|
def test_template_filter_with_template(app, client): |
|
@app.template_filter() |
|
def super_reverse(s): |
|
return s[::-1] |
|
|
|
@app.route('/') |
|
def index(): |
|
return flask.render_template('template_filter.html', value='abcd') |
|
|
|
rv = client.get('/') |
|
assert rv.data == b'dcba' |
|
|
|
|
|
def test_add_template_filter_with_template(app, client): |
|
def super_reverse(s): |
|
return s[::-1] |
|
|
|
app.add_template_filter(super_reverse) |
|
|
|
@app.route('/') |
|
def index(): |
|
return flask.render_template('template_filter.html', value='abcd') |
|
|
|
rv = client.get('/') |
|
assert rv.data == b'dcba' |
|
|
|
|
|
def test_template_filter_with_name_and_template(app, client): |
|
@app.template_filter('super_reverse') |
|
def my_reverse(s): |
|
return s[::-1] |
|
|
|
@app.route('/') |
|
def index(): |
|
return flask.render_template('template_filter.html', value='abcd') |
|
|
|
rv = client.get('/') |
|
assert rv.data == b'dcba' |
|
|
|
|
|
def test_add_template_filter_with_name_and_template(app, client): |
|
def my_reverse(s): |
|
return s[::-1] |
|
|
|
app.add_template_filter(my_reverse, 'super_reverse') |
|
|
|
@app.route('/') |
|
def index(): |
|
return flask.render_template('template_filter.html', value='abcd') |
|
|
|
rv = client.get('/') |
|
assert rv.data == b'dcba' |
|
|
|
|
|
def test_template_test(app): |
|
@app.template_test() |
|
def boolean(value): |
|
return isinstance(value, bool) |
|
|
|
assert 'boolean' in app.jinja_env.tests.keys() |
|
assert app.jinja_env.tests['boolean'] == boolean |
|
assert app.jinja_env.tests['boolean'](False) |
|
|
|
|
|
def test_add_template_test(app): |
|
def boolean(value): |
|
return isinstance(value, bool) |
|
|
|
app.add_template_test(boolean) |
|
assert 'boolean' in app.jinja_env.tests.keys() |
|
assert app.jinja_env.tests['boolean'] == boolean |
|
assert app.jinja_env.tests['boolean'](False) |
|
|
|
|
|
def test_template_test_with_name(app): |
|
@app.template_test('boolean') |
|
def is_boolean(value): |
|
return isinstance(value, bool) |
|
|
|
assert 'boolean' in app.jinja_env.tests.keys() |
|
assert app.jinja_env.tests['boolean'] == is_boolean |
|
assert app.jinja_env.tests['boolean'](False) |
|
|
|
|
|
def test_add_template_test_with_name(app): |
|
def is_boolean(value): |
|
return isinstance(value, bool) |
|
|
|
app.add_template_test(is_boolean, 'boolean') |
|
assert 'boolean' in app.jinja_env.tests.keys() |
|
assert app.jinja_env.tests['boolean'] == is_boolean |
|
assert app.jinja_env.tests['boolean'](False) |
|
|
|
|
|
def test_template_test_with_template(app, client): |
|
@app.template_test() |
|
def boolean(value): |
|
return isinstance(value, bool) |
|
|
|
@app.route('/') |
|
def index(): |
|
return flask.render_template('template_test.html', value=False) |
|
|
|
rv = client.get('/') |
|
assert b'Success!' in rv.data |
|
|
|
|
|
def test_add_template_test_with_template(app, client): |
|
def boolean(value): |
|
return isinstance(value, bool) |
|
|
|
app.add_template_test(boolean) |
|
|
|
@app.route('/') |
|
def index(): |
|
return flask.render_template('template_test.html', value=False) |
|
|
|
rv = client.get('/') |
|
assert b'Success!' in rv.data |
|
|
|
|
|
def test_template_test_with_name_and_template(app, client): |
|
@app.template_test('boolean') |
|
def is_boolean(value): |
|
return isinstance(value, bool) |
|
|
|
@app.route('/') |
|
def index(): |
|
return flask.render_template('template_test.html', value=False) |
|
|
|
rv = client.get('/') |
|
assert b'Success!' in rv.data |
|
|
|
|
|
def test_add_template_test_with_name_and_template(app, client): |
|
def is_boolean(value): |
|
return isinstance(value, bool) |
|
|
|
app.add_template_test(is_boolean, 'boolean') |
|
|
|
@app.route('/') |
|
def index(): |
|
return flask.render_template('template_test.html', value=False) |
|
|
|
rv = client.get('/') |
|
assert b'Success!' in rv.data |
|
|
|
|
|
def test_add_template_global(app, app_ctx): |
|
@app.template_global() |
|
def get_stuff(): |
|
return 42 |
|
|
|
assert 'get_stuff' in app.jinja_env.globals.keys() |
|
assert app.jinja_env.globals['get_stuff'] == get_stuff |
|
assert app.jinja_env.globals['get_stuff'](), 42 |
|
|
|
rv = flask.render_template_string('{{ get_stuff() }}') |
|
assert rv == '42' |
|
|
|
|
|
def test_custom_template_loader(client): |
|
class MyFlask(flask.Flask): |
|
def create_global_jinja_loader(self): |
|
from jinja2 import DictLoader |
|
return DictLoader({'index.html': 'Hello Custom World!'}) |
|
|
|
app = MyFlask(__name__) |
|
|
|
@app.route('/') |
|
def index(): |
|
return flask.render_template('index.html') |
|
|
|
c = app.test_client() |
|
rv = c.get('/') |
|
assert rv.data == b'Hello Custom World!' |
|
|
|
|
|
def test_iterable_loader(app, client): |
|
@app.context_processor |
|
def context_processor(): |
|
return {'whiskey': 'Jameson'} |
|
|
|
@app.route('/') |
|
def index(): |
|
return flask.render_template( |
|
['no_template.xml', # should skip this one |
|
'simple_template.html', # should render this |
|
'context_template.html'], |
|
value=23) |
|
|
|
rv = client.get('/') |
|
assert rv.data == b'<h1>Jameson</h1>' |
|
|
|
|
|
def test_templates_auto_reload(app): |
|
# debug is False, config option is None |
|
assert app.debug is False |
|
assert app.config['TEMPLATES_AUTO_RELOAD'] is None |
|
assert app.jinja_env.auto_reload is False |
|
# debug is False, config option is False |
|
app = flask.Flask(__name__) |
|
app.config['TEMPLATES_AUTO_RELOAD'] = False |
|
assert app.debug is False |
|
assert app.jinja_env.auto_reload is False |
|
# debug is False, config option is True |
|
app = flask.Flask(__name__) |
|
app.config['TEMPLATES_AUTO_RELOAD'] = True |
|
assert app.debug is False |
|
assert app.jinja_env.auto_reload is True |
|
# debug is True, config option is None |
|
app = flask.Flask(__name__) |
|
app.config['DEBUG'] = True |
|
assert app.config['TEMPLATES_AUTO_RELOAD'] is None |
|
assert app.jinja_env.auto_reload is True |
|
# debug is True, config option is False |
|
app = flask.Flask(__name__) |
|
app.config['DEBUG'] = True |
|
app.config['TEMPLATES_AUTO_RELOAD'] = False |
|
assert app.jinja_env.auto_reload is False |
|
# debug is True, config option is True |
|
app = flask.Flask(__name__) |
|
app.config['DEBUG'] = True |
|
app.config['TEMPLATES_AUTO_RELOAD'] = True |
|
assert app.jinja_env.auto_reload is True |
|
|
|
def test_templates_auto_reload_debug_run(app, monkeypatch): |
|
def run_simple_mock(*args, **kwargs): |
|
pass |
|
|
|
monkeypatch.setattr(werkzeug.serving, 'run_simple', run_simple_mock) |
|
|
|
app.run() |
|
assert app.templates_auto_reload == False |
|
assert app.jinja_env.auto_reload == False |
|
|
|
app.run(debug=True) |
|
assert app.templates_auto_reload == True |
|
assert app.jinja_env.auto_reload == True |
|
|
|
|
|
def test_template_loader_debugging(test_apps, monkeypatch): |
|
from blueprintapp import app |
|
|
|
called = [] |
|
|
|
class _TestHandler(logging.Handler): |
|
def handle(x, record): |
|
called.append(True) |
|
text = str(record.msg) |
|
assert '1: trying loader of application "blueprintapp"' in text |
|
assert ('2: trying loader of blueprint "admin" ' |
|
'(blueprintapp.apps.admin)') in text |
|
assert ('trying loader of blueprint "frontend" ' |
|
'(blueprintapp.apps.frontend)') in text |
|
assert 'Error: the template could not be found' in text |
|
assert ('looked up from an endpoint that belongs to ' |
|
'the blueprint "frontend"') in text |
|
assert 'See http://flask.pocoo.org/docs/blueprints/#templates' in text |
|
|
|
with app.test_client() as c: |
|
monkeypatch.setitem(app.config, 'EXPLAIN_TEMPLATE_LOADING', True) |
|
monkeypatch.setattr( |
|
logging.getLogger('flask'), 'handlers', [_TestHandler()] |
|
) |
|
|
|
with pytest.raises(TemplateNotFound) as excinfo: |
|
c.get('/missing') |
|
|
|
assert 'missing_template.html' in str(excinfo.value) |
|
|
|
assert len(called) == 1 |
|
|
|
|
|
def test_custom_jinja_env(): |
|
class CustomEnvironment(flask.templating.Environment): |
|
pass |
|
|
|
class CustomFlask(flask.Flask): |
|
jinja_environment = CustomEnvironment |
|
|
|
app = CustomFlask(__name__) |
|
assert isinstance(app.jinja_env, CustomEnvironment)
|
|
|