This commit is contained in:
Markus Unterwaditzer 2014-09-03 20:50:54 +02:00
parent e77bc2d86c
commit d0cf5ef394
6 changed files with 497 additions and 520 deletions

View file

@ -90,25 +90,6 @@ class TestFlask(object):
consistency. consistency.
""" """
@pytest.fixture(autouse=True)
def setup_path(self, monkeypatch):
monkeypatch.syspath_prepend(
os.path.abspath(os.path.join(
os.path.dirname(__file__), 'test_apps'))
)
@pytest.fixture(autouse=True)
def leak_detector(self, request):
request.addfinalizer(self.ensure_clean_request_context)
def ensure_clean_request_context(self):
# make sure we're not leaking a request context since we are
# testing flask internally in debug mode in a few cases
leaks = []
while flask._request_ctx_stack.top is not None:
leaks.append(flask._request_ctx_stack.pop())
assert leaks == []
def setup_method(self, method): def setup_method(self, method):
self.setup() self.setup()

View file

@ -6,12 +6,34 @@
:copyright: (c) 2014 by the Flask Team, see AUTHORS for more details. :copyright: (c) 2014 by the Flask Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details. :license: BSD, see LICENSE for more details.
""" """
import flask
import os
import sys
import pkgutil import pkgutil
import pytest import pytest
import sys
import textwrap import textwrap
@pytest.fixture(autouse=True)
def setup_path(monkeypatch):
monkeypatch.syspath_prepend(
os.path.abspath(os.path.join(
os.path.dirname(__file__), 'test_apps'))
)
@pytest.fixture(autouse=True)
def leak_detector(request):
def ensure_clean_request_context():
# make sure we're not leaking a request context since we are
# testing flask internally in debug mode in a few cases
leaks = []
while flask._request_ctx_stack.top is not None:
leaks.append(flask._request_ctx_stack.pop())
assert leaks == []
request.addfinalizer(ensure_clean_request_context)
@pytest.fixture(params=(True, False)) @pytest.fixture(params=(True, False))
def limit_loader(request, monkeypatch): def limit_loader(request, monkeypatch):
"""Patch pkgutil.get_loader to give loader without get_filename or archive. """Patch pkgutil.get_loader to give loader without get_filename or archive.

View file

@ -16,106 +16,98 @@ import unittest
from tests import TestFlask from tests import TestFlask
class TestAppContext(TestFlask): def test_basic_url_generation():
app = flask.Flask(__name__)
app.config['SERVER_NAME'] = 'localhost'
app.config['PREFERRED_URL_SCHEME'] = 'https'
def test_basic_url_generation(self): @app.route('/')
app = flask.Flask(__name__) def index():
app.config['SERVER_NAME'] = 'localhost' pass
app.config['PREFERRED_URL_SCHEME'] = 'https'
@app.route('/') with app.app_context():
def index(): rv = flask.url_for('index')
pass assert rv == 'https://localhost/'
with app.app_context(): def test_url_generation_requires_server_name():
rv = flask.url_for('index') app = flask.Flask(__name__)
assert rv == 'https://localhost/' with app.app_context():
def test_url_generation_requires_server_name(self):
app = flask.Flask(__name__)
with app.app_context():
with pytest.raises(RuntimeError):
flask.url_for('index')
def test_url_generation_without_context_fails(self):
with pytest.raises(RuntimeError): with pytest.raises(RuntimeError):
flask.url_for('index') flask.url_for('index')
def test_request_context_means_app_context(self): def test_url_generation_without_context_fails():
app = flask.Flask(__name__) with pytest.raises(RuntimeError):
with app.test_request_context(): flask.url_for('index')
assert flask.current_app._get_current_object() == app
assert flask._app_ctx_stack.top == None
def test_app_context_provides_current_app(self): def test_request_context_means_app_context():
app = flask.Flask(__name__) app = flask.Flask(__name__)
with app.app_context(): with app.test_request_context():
assert flask.current_app._get_current_object() == app assert flask.current_app._get_current_object() == app
assert flask._app_ctx_stack.top == None assert flask._app_ctx_stack.top == None
def test_app_tearing_down(self): def test_app_context_provides_current_app():
cleanup_stuff = [] app = flask.Flask(__name__)
app = flask.Flask(__name__) with app.app_context():
@app.teardown_appcontext assert flask.current_app._get_current_object() == app
def cleanup(exception): assert flask._app_ctx_stack.top == None
cleanup_stuff.append(exception)
with app.app_context(): def test_app_tearing_down():
pass cleanup_stuff = []
app = flask.Flask(__name__)
@app.teardown_appcontext
def cleanup(exception):
cleanup_stuff.append(exception)
assert cleanup_stuff == [None] with app.app_context():
pass
def test_app_tearing_down_with_previous_exception(self): assert cleanup_stuff == [None]
cleanup_stuff = []
app = flask.Flask(__name__)
@app.teardown_appcontext
def cleanup(exception):
cleanup_stuff.append(exception)
try: def test_app_tearing_down_with_previous_exception():
raise Exception('dummy') cleanup_stuff = []
except Exception: app = flask.Flask(__name__)
pass @app.teardown_appcontext
def cleanup(exception):
cleanup_stuff.append(exception)
with app.app_context(): try:
pass raise Exception('dummy')
except Exception:
pass
assert cleanup_stuff == [None] with app.app_context():
pass
def test_custom_app_ctx_globals_class(self): assert cleanup_stuff == [None]
class CustomRequestGlobals(object):
def __init__(self):
self.spam = 'eggs'
app = flask.Flask(__name__)
app.app_ctx_globals_class = CustomRequestGlobals
with app.app_context():
assert flask.render_template_string('{{ g.spam }}') == 'eggs'
def test_context_refcounts(self): def test_custom_app_ctx_globals_class():
called = [] class CustomRequestGlobals(object):
app = flask.Flask(__name__) def __init__(self):
@app.teardown_request self.spam = 'eggs'
def teardown_req(error=None): app = flask.Flask(__name__)
called.append('request') app.app_ctx_globals_class = CustomRequestGlobals
@app.teardown_appcontext with app.app_context():
def teardown_app(error=None): assert flask.render_template_string('{{ g.spam }}') == 'eggs'
called.append('app')
@app.route('/')
def index():
with flask._app_ctx_stack.top:
with flask._request_ctx_stack.top:
pass
env = flask._request_ctx_stack.top.request.environ
assert env['werkzeug.request'] is not None
return u''
c = app.test_client()
res = c.get('/')
assert res.status_code == 200
assert res.data == b''
assert called == ['request', 'app']
def test_context_refcounts():
def suite(): called = []
suite = unittest.TestSuite() app = flask.Flask(__name__)
suite.addTest(unittest.makeSuite(TestAppContext)) @app.teardown_request
return suite def teardown_req(error=None):
called.append('request')
@app.teardown_appcontext
def teardown_app(error=None):
called.append('app')
@app.route('/')
def index():
with flask._app_ctx_stack.top:
with flask._request_ctx_stack.top:
pass
env = flask._request_ctx_stack.top.request.environ
assert env['werkzeug.request'] is not None
return u''
c = app.test_client()
res = c.get('/')
assert res.status_code == 200
assert res.data == b''
assert called == ['request', 'app']

View file

@ -20,120 +20,118 @@ except ImportError:
from tests import TestFlask from tests import TestFlask
from flask._compat import PY2 from flask._compat import PY2
class TestExtImportHook(TestFlask):
def setup(self): @pytest.fixture(autouse=True)
# we clear this out for various reasons. The most important one is def importhook_setup(monkeypatch, request):
# that a real flaskext could be in there which would disable our # we clear this out for various reasons. The most important one is
# fake package. Secondly we want to make sure that the flaskext # that a real flaskext could be in there which would disable our
# import hook does not break on reloading. # fake package. Secondly we want to make sure that the flaskext
for entry, value in list(sys.modules.items()): # import hook does not break on reloading.
if (entry.startswith('flask.ext.') or for entry, value in list(sys.modules.items()):
entry.startswith('flask_') or if (entry.startswith('flask.ext.') or
entry.startswith('flaskext.') or entry.startswith('flask_') or
entry == 'flaskext') and value is not None: entry.startswith('flaskext.') or
sys.modules.pop(entry, None) entry == 'flaskext') and value is not None:
from flask import ext monkeypatch.delitem(sys.modules, entry)
reload_module(ext) from flask import ext
reload_module(ext)
# reloading must not add more hooks # reloading must not add more hooks
import_hooks = 0 import_hooks = 0
for item in sys.meta_path: for item in sys.meta_path:
cls = type(item) cls = type(item)
if cls.__module__ == 'flask.exthook' and \ if cls.__module__ == 'flask.exthook' and \
cls.__name__ == 'ExtensionImporter': cls.__name__ == 'ExtensionImporter':
import_hooks += 1 import_hooks += 1
assert import_hooks == 1 assert import_hooks == 1
def teardown(self): def teardown():
from flask import ext from flask import ext
for key in ext.__dict__: for key in ext.__dict__:
assert '.' not in key assert '.' not in key
def test_flaskext_new_simple_import_normal(self): request.addfinalizer(teardown)
from flask.ext.newext_simple import ext_id
assert ext_id == 'newext_simple'
def test_flaskext_new_simple_import_module(self): def test_flaskext_new_simple_import_normal():
from flask.ext import newext_simple from flask.ext.newext_simple import ext_id
assert newext_simple.ext_id == 'newext_simple' assert ext_id == 'newext_simple'
assert newext_simple.__name__ == 'flask_newext_simple'
def test_flaskext_new_package_import_normal(self): def test_flaskext_new_simple_import_module():
from flask.ext.newext_package import ext_id from flask.ext import newext_simple
assert ext_id == 'newext_package' assert newext_simple.ext_id == 'newext_simple'
assert newext_simple.__name__ == 'flask_newext_simple'
def test_flaskext_new_package_import_module(self): def test_flaskext_new_package_import_normal():
from flask.ext import newext_package from flask.ext.newext_package import ext_id
assert newext_package.ext_id == 'newext_package' assert ext_id == 'newext_package'
assert newext_package.__name__ == 'flask_newext_package'
def test_flaskext_new_package_import_submodule_function(self): def test_flaskext_new_package_import_module():
from flask.ext.newext_package.submodule import test_function from flask.ext import newext_package
assert test_function() == 42 assert newext_package.ext_id == 'newext_package'
assert newext_package.__name__ == 'flask_newext_package'
def test_flaskext_new_package_import_submodule(self): def test_flaskext_new_package_import_submodule_function():
from flask.ext.newext_package import submodule from flask.ext.newext_package.submodule import test_function
assert submodule.__name__ == 'flask_newext_package.submodule' assert test_function() == 42
assert submodule.test_function() == 42
def test_flaskext_old_simple_import_normal(self): def test_flaskext_new_package_import_submodule():
from flask.ext.oldext_simple import ext_id from flask.ext.newext_package import submodule
assert ext_id == 'oldext_simple' assert submodule.__name__ == 'flask_newext_package.submodule'
assert submodule.test_function() == 42
def test_flaskext_old_simple_import_module(self): def test_flaskext_old_simple_import_normal():
from flask.ext import oldext_simple from flask.ext.oldext_simple import ext_id
assert oldext_simple.ext_id == 'oldext_simple' assert ext_id == 'oldext_simple'
assert oldext_simple.__name__ == 'flaskext.oldext_simple'
def test_flaskext_old_package_import_normal(self): def test_flaskext_old_simple_import_module():
from flask.ext.oldext_package import ext_id from flask.ext import oldext_simple
assert ext_id == 'oldext_package' assert oldext_simple.ext_id == 'oldext_simple'
assert oldext_simple.__name__ == 'flaskext.oldext_simple'
def test_flaskext_old_package_import_module(self): def test_flaskext_old_package_import_normal():
from flask.ext import oldext_package from flask.ext.oldext_package import ext_id
assert oldext_package.ext_id == 'oldext_package' assert ext_id == 'oldext_package'
assert oldext_package.__name__ == 'flaskext.oldext_package'
def test_flaskext_old_package_import_submodule(self): def test_flaskext_old_package_import_module():
from flask.ext.oldext_package import submodule from flask.ext import oldext_package
assert submodule.__name__ == 'flaskext.oldext_package.submodule' assert oldext_package.ext_id == 'oldext_package'
assert submodule.test_function() == 42 assert oldext_package.__name__ == 'flaskext.oldext_package'
def test_flaskext_old_package_import_submodule_function(self): def test_flaskext_old_package_import_submodule():
from flask.ext.oldext_package.submodule import test_function from flask.ext.oldext_package import submodule
assert test_function() == 42 assert submodule.__name__ == 'flaskext.oldext_package.submodule'
assert submodule.test_function() == 42
def test_flaskext_broken_package_no_module_caching(self): def test_flaskext_old_package_import_submodule_function():
for x in range(2): from flask.ext.oldext_package.submodule import test_function
with pytest.raises(ImportError): assert test_function() == 42
import flask.ext.broken
def test_no_error_swallowing(self): def test_flaskext_broken_package_no_module_caching():
try: for x in range(2):
with pytest.raises(ImportError):
import flask.ext.broken import flask.ext.broken
except ImportError:
exc_type, exc_value, tb = sys.exc_info()
assert exc_type is ImportError
if PY2:
message = 'No module named missing_module'
else:
message = 'No module named \'missing_module\''
assert str(exc_value) == message
assert tb.tb_frame.f_globals is globals()
# reraise() adds a second frame so we need to skip that one too. def test_no_error_swallowing():
# On PY3 we even have another one :( try:
next = tb.tb_next.tb_next import flask.ext.broken
if not PY2: except ImportError:
next = next.tb_next exc_type, exc_value, tb = sys.exc_info()
assert exc_type is ImportError
import os.path if PY2:
assert os.path.join('flask_broken', '__init__.py') in \ message = 'No module named missing_module'
next.tb_frame.f_code.co_filename else:
message = 'No module named \'missing_module\''
assert str(exc_value) == message
assert tb.tb_frame.f_globals is globals()
# reraise() adds a second frame so we need to skip that one too.
# On PY3 we even have another one :(
next = tb.tb_next.tb_next
if not PY2:
next = next.tb_next
def suite(): import os.path
suite = unittest.TestSuite() assert os.path.join('flask_broken', '__init__.py') in \
suite.addTest(unittest.makeSuite(TestExtImportHook)) next.tb_frame.f_code.co_filename
return suite else:
1/0 # XXX

View file

@ -16,31 +16,23 @@ from tests import TestFlask
from flask._compat import StringIO from flask._compat import StringIO
class TestFlaskSubclassing(TestFlask): def test_suppressed_exception_logging():
class SuppressedFlask(flask.Flask):
def log_exception(self, exc_info):
pass
def test_suppressed_exception_logging(self): out = StringIO()
class SuppressedFlask(flask.Flask): app = SuppressedFlask(__name__)
def log_exception(self, exc_info): app.logger_name = 'flask_tests/test_suppressed_exception_logging'
pass app.logger.addHandler(StreamHandler(out))
out = StringIO() @app.route('/')
app = SuppressedFlask(__name__) def index():
app.logger_name = 'flask_tests/test_suppressed_exception_logging' 1 // 0
app.logger.addHandler(StreamHandler(out))
@app.route('/') rv = app.test_client().get('/')
def index(): assert rv.status_code == 500
1 // 0 assert b'Internal Server Error' in rv.data
rv = app.test_client().get('/') err = out.getvalue()
assert rv.status_code == 500 assert err == ''
assert b'Internal Server Error' in rv.data
err = out.getvalue()
assert err == ''
def suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestFlaskSubclassing))
return suite

View file

@ -9,6 +9,8 @@
:license: BSD, see LICENSE for more details. :license: BSD, see LICENSE for more details.
""" """
import pytest
import flask import flask
import unittest import unittest
import logging import logging
@ -17,334 +19,324 @@ from jinja2 import TemplateNotFound
from tests import TestFlask from tests import TestFlask
class TestTemplating(TestFlask): def test_context_processing():
app = flask.Flask(__name__)
@app.context_processor
def context_processor():
return {'injected_value': 42}
@app.route('/')
def index():
return flask.render_template('context_template.html', value=23)
rv = app.test_client().get('/')
assert rv.data == b'<p>23|42'
def test_context_processing(self): def test_original_win():
app = flask.Flask(__name__) app = flask.Flask(__name__)
@app.context_processor @app.route('/')
def context_processor(): def index():
return {'injected_value': 42} return flask.render_template_string('{{ config }}', config=42)
@app.route('/') rv = app.test_client().get('/')
def index(): assert rv.data == b'42'
return flask.render_template('context_template.html', value=23)
rv = app.test_client().get('/')
assert rv.data == b'<p>23|42'
def test_original_win(self): def test_request_less_rendering():
app = flask.Flask(__name__) app = flask.Flask(__name__)
@app.route('/') app.config['WORLD_NAME'] = 'Special World'
def index(): @app.context_processor
return flask.render_template_string('{{ config }}', config=42) def context_processor():
rv = app.test_client().get('/') return dict(foo=42)
assert rv.data == b'42'
def test_request_less_rendering(self): with app.app_context():
app = flask.Flask(__name__) rv = flask.render_template_string('Hello {{ config.WORLD_NAME }} '
app.config['WORLD_NAME'] = 'Special World' '{{ foo }}')
@app.context_processor assert rv == 'Hello Special World 42'
def context_processor():
return dict(foo=42)
with app.app_context(): def test_standard_context():
rv = flask.render_template_string('Hello {{ config.WORLD_NAME }} ' app = flask.Flask(__name__)
'{{ foo }}') app.secret_key = 'development key'
assert rv == 'Hello Special World 42' @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 = app.test_client().get('/?foo=42')
assert rv.data.split() == [b'42', b'23', b'False', b'aha']
def test_standard_context(self): def test_escaping():
app = flask.Flask(__name__) text = '<p>Hello World!'
app.secret_key = 'development key' app = flask.Flask(__name__)
@app.route('/') @app.route('/')
def index(): def index():
flask.g.foo = 23 return flask.render_template('escaping_template.html', text=text,
flask.session['test'] = 'aha' html=flask.Markup(text))
return flask.render_template_string(''' lines = app.test_client().get('/').data.splitlines()
{{ request.args.foo }} assert lines == [
{{ g.foo }} b'&lt;p&gt;Hello World!',
{{ config.DEBUG }} b'<p>Hello World!',
{{ session.test }} b'<p>Hello World!',
''') b'<p>Hello World!',
rv = app.test_client().get('/?foo=42') b'&lt;p&gt;Hello World!',
assert rv.data.split() == [b'42', b'23', b'False', b'aha'] b'<p>Hello World!'
]
def test_escaping(self): def test_no_escaping():
text = '<p>Hello World!' app = flask.Flask(__name__)
app = flask.Flask(__name__) with app.test_request_context():
@app.route('/') assert flask.render_template_string(
def index(): '{{ foo }}', foo='<test>') == '<test>'
return flask.render_template('escaping_template.html', text=text, assert flask.render_template('mail.txt', foo='<test>') == \
html=flask.Markup(text)) '<test> Mail'
lines = app.test_client().get('/').data.splitlines()
assert lines == [
b'&lt;p&gt;Hello World!',
b'<p>Hello World!',
b'<p>Hello World!',
b'<p>Hello World!',
b'&lt;p&gt;Hello World!',
b'<p>Hello World!'
]
def test_no_escaping(self): def test_macros():
app = flask.Flask(__name__) app = flask.Flask(__name__)
with app.test_request_context(): with app.test_request_context():
assert flask.render_template_string( macro = flask.get_template_attribute('_macro.html', 'hello')
'{{ foo }}', foo='<test>') == '<test>' assert macro('World') == 'Hello World!'
assert flask.render_template('mail.txt', foo='<test>') == \
'<test> Mail'
def test_macros(self): def test_template_filter():
app = flask.Flask(__name__) app = flask.Flask(__name__)
with app.test_request_context(): @app.template_filter()
macro = flask.get_template_attribute('_macro.html', 'hello') def my_reverse(s):
assert macro('World') == 'Hello World!' 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_template_filter(self): def test_add_template_filter():
app = flask.Flask(__name__) app = flask.Flask(__name__)
@app.template_filter() def my_reverse(s):
def my_reverse(s): return s[::-1]
return s[::-1] app.add_template_filter(my_reverse)
assert 'my_reverse' in app.jinja_env.filters.keys() 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'] == my_reverse
assert app.jinja_env.filters['my_reverse']('abcd') == 'dcba' assert app.jinja_env.filters['my_reverse']('abcd') == 'dcba'
def test_add_template_filter(self): def test_template_filter_with_name():
app = flask.Flask(__name__) app = flask.Flask(__name__)
def my_reverse(s): @app.template_filter('strrev')
return s[::-1] def my_reverse(s):
app.add_template_filter(my_reverse) return s[::-1]
assert 'my_reverse' in app.jinja_env.filters.keys() assert 'strrev' in app.jinja_env.filters.keys()
assert app.jinja_env.filters['my_reverse'] == my_reverse assert app.jinja_env.filters['strrev'] == my_reverse
assert app.jinja_env.filters['my_reverse']('abcd') == 'dcba' assert app.jinja_env.filters['strrev']('abcd') == 'dcba'
def test_template_filter_with_name(self): def test_add_template_filter_with_name():
app = flask.Flask(__name__) app = flask.Flask(__name__)
@app.template_filter('strrev') def my_reverse(s):
def my_reverse(s): return s[::-1]
return s[::-1] app.add_template_filter(my_reverse, 'strrev')
assert 'strrev' in app.jinja_env.filters.keys() assert 'strrev' in app.jinja_env.filters.keys()
assert app.jinja_env.filters['strrev'] == my_reverse assert app.jinja_env.filters['strrev'] == my_reverse
assert app.jinja_env.filters['strrev']('abcd') == 'dcba' assert app.jinja_env.filters['strrev']('abcd') == 'dcba'
def test_add_template_filter_with_name(self): def test_template_filter_with_template():
app = flask.Flask(__name__) app = flask.Flask(__name__)
def my_reverse(s): @app.template_filter()
return s[::-1] def super_reverse(s):
app.add_template_filter(my_reverse, 'strrev') return s[::-1]
assert 'strrev' in app.jinja_env.filters.keys() @app.route('/')
assert app.jinja_env.filters['strrev'] == my_reverse def index():
assert app.jinja_env.filters['strrev']('abcd') == 'dcba' return flask.render_template('template_filter.html', value='abcd')
rv = app.test_client().get('/')
assert rv.data == b'dcba'
def test_template_filter_with_template(self): def test_add_template_filter_with_template():
app = flask.Flask(__name__) app = flask.Flask(__name__)
@app.template_filter() def super_reverse(s):
def super_reverse(s): return s[::-1]
return s[::-1] app.add_template_filter(super_reverse)
@app.route('/') @app.route('/')
def index(): def index():
return flask.render_template('template_filter.html', value='abcd') return flask.render_template('template_filter.html', value='abcd')
rv = app.test_client().get('/') rv = app.test_client().get('/')
assert rv.data == b'dcba' assert rv.data == b'dcba'
def test_add_template_filter_with_template(self): def test_template_filter_with_name_and_template():
app = flask.Flask(__name__) app = flask.Flask(__name__)
def super_reverse(s): @app.template_filter('super_reverse')
return s[::-1] def my_reverse(s):
app.add_template_filter(super_reverse) return s[::-1]
@app.route('/') @app.route('/')
def index(): def index():
return flask.render_template('template_filter.html', value='abcd') return flask.render_template('template_filter.html', value='abcd')
rv = app.test_client().get('/') rv = app.test_client().get('/')
assert rv.data == b'dcba' assert rv.data == b'dcba'
def test_template_filter_with_name_and_template(self): def test_add_template_filter_with_name_and_template():
app = flask.Flask(__name__) app = flask.Flask(__name__)
@app.template_filter('super_reverse') def my_reverse(s):
def my_reverse(s): return s[::-1]
return s[::-1] app.add_template_filter(my_reverse, 'super_reverse')
@app.route('/') @app.route('/')
def index(): def index():
return flask.render_template('template_filter.html', value='abcd') return flask.render_template('template_filter.html', value='abcd')
rv = app.test_client().get('/') rv = app.test_client().get('/')
assert rv.data == b'dcba' assert rv.data == b'dcba'
def test_add_template_filter_with_name_and_template(self): def test_template_test():
app = flask.Flask(__name__) app = flask.Flask(__name__)
def my_reverse(s): @app.template_test()
return s[::-1] def boolean(value):
app.add_template_filter(my_reverse, 'super_reverse') return isinstance(value, bool)
@app.route('/') assert 'boolean' in app.jinja_env.tests.keys()
def index(): assert app.jinja_env.tests['boolean'] == boolean
return flask.render_template('template_filter.html', value='abcd') assert app.jinja_env.tests['boolean'](False)
rv = app.test_client().get('/')
assert rv.data == b'dcba'
def test_template_test(self): def test_add_template_test():
app = flask.Flask(__name__) app = flask.Flask(__name__)
@app.template_test() def boolean(value):
def boolean(value): return isinstance(value, bool)
return isinstance(value, bool) app.add_template_test(boolean)
assert 'boolean' in app.jinja_env.tests.keys() assert 'boolean' in app.jinja_env.tests.keys()
assert app.jinja_env.tests['boolean'] == boolean assert app.jinja_env.tests['boolean'] == boolean
assert app.jinja_env.tests['boolean'](False) assert app.jinja_env.tests['boolean'](False)
def test_add_template_test(self): def test_template_test_with_name():
app = flask.Flask(__name__) app = flask.Flask(__name__)
def boolean(value): @app.template_test('boolean')
return isinstance(value, bool) def is_boolean(value):
app.add_template_test(boolean) return isinstance(value, bool)
assert 'boolean' in app.jinja_env.tests.keys() assert 'boolean' in app.jinja_env.tests.keys()
assert app.jinja_env.tests['boolean'] == boolean assert app.jinja_env.tests['boolean'] == is_boolean
assert app.jinja_env.tests['boolean'](False) assert app.jinja_env.tests['boolean'](False)
def test_template_test_with_name(self): def test_add_template_test_with_name():
app = flask.Flask(__name__) app = flask.Flask(__name__)
@app.template_test('boolean') def is_boolean(value):
def is_boolean(value): return isinstance(value, bool)
return isinstance(value, bool) app.add_template_test(is_boolean, 'boolean')
assert 'boolean' in app.jinja_env.tests.keys() assert 'boolean' in app.jinja_env.tests.keys()
assert app.jinja_env.tests['boolean'] == is_boolean assert app.jinja_env.tests['boolean'] == is_boolean
assert app.jinja_env.tests['boolean'](False) assert app.jinja_env.tests['boolean'](False)
def test_add_template_test_with_name(self): def test_template_test_with_template():
app = flask.Flask(__name__) app = flask.Flask(__name__)
def is_boolean(value): @app.template_test()
return isinstance(value, bool) def boolean(value):
app.add_template_test(is_boolean, 'boolean') return isinstance(value, bool)
assert 'boolean' in app.jinja_env.tests.keys() @app.route('/')
assert app.jinja_env.tests['boolean'] == is_boolean def index():
assert app.jinja_env.tests['boolean'](False) return flask.render_template('template_test.html', value=False)
rv = app.test_client().get('/')
assert b'Success!' in rv.data
def test_template_test_with_template(self): def test_add_template_test_with_template():
app = flask.Flask(__name__) app = flask.Flask(__name__)
@app.template_test() def boolean(value):
def boolean(value): return isinstance(value, bool)
return isinstance(value, bool) app.add_template_test(boolean)
@app.route('/') @app.route('/')
def index(): def index():
return flask.render_template('template_test.html', value=False) return flask.render_template('template_test.html', value=False)
rv = app.test_client().get('/') rv = app.test_client().get('/')
assert b'Success!' in rv.data assert b'Success!' in rv.data
def test_add_template_test_with_template(self): def test_template_test_with_name_and_template():
app = flask.Flask(__name__) app = flask.Flask(__name__)
def boolean(value): @app.template_test('boolean')
return isinstance(value, bool) def is_boolean(value):
app.add_template_test(boolean) return isinstance(value, bool)
@app.route('/') @app.route('/')
def index(): def index():
return flask.render_template('template_test.html', value=False) return flask.render_template('template_test.html', value=False)
rv = app.test_client().get('/') rv = app.test_client().get('/')
assert b'Success!' in rv.data assert b'Success!' in rv.data
def test_template_test_with_name_and_template(self): def test_add_template_test_with_name_and_template():
app = flask.Flask(__name__) app = flask.Flask(__name__)
@app.template_test('boolean') def is_boolean(value):
def is_boolean(value): return isinstance(value, bool)
return isinstance(value, bool) app.add_template_test(is_boolean, 'boolean')
@app.route('/') @app.route('/')
def index(): def index():
return flask.render_template('template_test.html', value=False) return flask.render_template('template_test.html', value=False)
rv = app.test_client().get('/') rv = app.test_client().get('/')
assert b'Success!' in rv.data assert b'Success!' in rv.data
def test_add_template_test_with_name_and_template(self): def test_add_template_global():
app = flask.Flask(__name__) app = flask.Flask(__name__)
def is_boolean(value): @app.template_global()
return isinstance(value, bool) def get_stuff():
app.add_template_test(is_boolean, 'boolean') return 42
@app.route('/') assert 'get_stuff' in app.jinja_env.globals.keys()
def index(): assert app.jinja_env.globals['get_stuff'] == get_stuff
return flask.render_template('template_test.html', value=False) assert app.jinja_env.globals['get_stuff'](), 42
rv = app.test_client().get('/') with app.app_context():
assert b'Success!' in rv.data rv = flask.render_template_string('{{ get_stuff() }}')
assert rv == '42'
def test_add_template_global(self): def test_custom_template_loader():
app = flask.Flask(__name__) class MyFlask(flask.Flask):
@app.template_global() def create_global_jinja_loader(self):
def get_stuff(): from jinja2 import DictLoader
return 42 return DictLoader({'index.html': 'Hello Custom World!'})
assert 'get_stuff' in app.jinja_env.globals.keys() app = MyFlask(__name__)
assert app.jinja_env.globals['get_stuff'] == get_stuff @app.route('/')
assert app.jinja_env.globals['get_stuff'](), 42 def index():
with app.app_context(): return flask.render_template('index.html')
rv = flask.render_template_string('{{ get_stuff() }}') c = app.test_client()
assert rv == '42' rv = c.get('/')
assert rv.data == b'Hello Custom World!'
def test_custom_template_loader(self): def test_iterable_loader():
class MyFlask(flask.Flask): app = flask.Flask(__name__)
def create_global_jinja_loader(self): @app.context_processor
from jinja2 import DictLoader def context_processor():
return DictLoader({'index.html': 'Hello Custom World!'}) return {'whiskey': 'Jameson'}
app = MyFlask(__name__) @app.route('/')
@app.route('/') def index():
def index(): return flask.render_template(
return flask.render_template('index.html') ['no_template.xml', # should skip this one
c = app.test_client() 'simple_template.html', # should render this
rv = c.get('/') 'context_template.html'],
assert rv.data == b'Hello Custom World!' value=23)
def test_iterable_loader(self): rv = app.test_client().get('/')
app = flask.Flask(__name__) assert rv.data == b'<h1>Jameson</h1>'
@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 = app.test_client().get('/') def test_templates_auto_reload():
assert rv.data == b'<h1>Jameson</h1>' app = flask.Flask(__name__)
assert app.config['TEMPLATES_AUTO_RELOAD']
assert app.jinja_env.auto_reload
app = flask.Flask(__name__)
app.config['TEMPLATES_AUTO_RELOAD'] = False
assert not app.jinja_env.auto_reload
def test_templates_auto_reload(self): def test_template_loader_debugging():
app = flask.Flask(__name__) from blueprintapp import app
assert app.config['TEMPLATES_AUTO_RELOAD']
assert app.jinja_env.auto_reload
app = flask.Flask(__name__)
app.config['TEMPLATES_AUTO_RELOAD'] = False
assert not app.jinja_env.auto_reload
def test_template_loader_debugging(self): called = []
from blueprintapp import app 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
called = [] with app.test_client() as c:
class _TestHandler(logging.Handler): try:
def handle(x, record): old_load_setting = app.config['EXPLAIN_TEMPLATE_LOADING']
called.append(True) old_handlers = app.logger.handlers[:]
text = str(record.msg) app.logger.handlers = [_TestHandler()]
assert '1: trying loader of application "blueprintapp"' in text app.config['EXPLAIN_TEMPLATE_LOADING'] = True
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: with pytest.raises(TemplateNotFound) as excinfo:
try: c.get('/missing')
old_load_setting = app.config['EXPLAIN_TEMPLATE_LOADING']
old_handlers = app.logger.handlers[:]
app.logger.handlers = [_TestHandler()]
app.config['EXPLAIN_TEMPLATE_LOADING'] = True
try: assert 'missing_template.html' in str(excinfo.value)
c.get('/missing') finally:
except TemplateNotFound as e: app.logger.handlers[:] = old_handlers
assert 'missing_template.html' in str(e) app.config['EXPLAIN_TEMPLATE_LOADING'] = old_load_setting
else:
self.fail('Expected template not found exception.')
finally:
app.logger.handlers[:] = old_handlers
app.config['EXPLAIN_TEMPLATE_LOADING'] = old_load_setting
assert len(called) == 1 assert len(called) == 1
def suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestTemplating))
return suite