blueprints.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. # -*- coding: utf-8 -*-
  2. """
  3. flask.testsuite.blueprints
  4. ~~~~~~~~~~~~~~~~~~~~~~~~~~
  5. Blueprints (and currently modules)
  6. :copyright: (c) 2011 by Armin Ronacher.
  7. :license: BSD, see LICENSE for more details.
  8. """
  9. import flask
  10. import unittest
  11. import warnings
  12. from flask.testsuite import FlaskTestCase, emits_module_deprecation_warning
  13. from flask._compat import text_type
  14. from werkzeug.exceptions import NotFound
  15. from werkzeug.http import parse_cache_control_header
  16. from jinja2 import TemplateNotFound
  17. # import moduleapp here because it uses deprecated features and we don't
  18. # want to see the warnings
  19. warnings.simplefilter('ignore', DeprecationWarning)
  20. from moduleapp import app as moduleapp
  21. warnings.simplefilter('default', DeprecationWarning)
  22. class ModuleTestCase(FlaskTestCase):
  23. @emits_module_deprecation_warning
  24. def test_basic_module(self):
  25. app = flask.Flask(__name__)
  26. admin = flask.Module(__name__, 'admin', url_prefix='/admin')
  27. @admin.route('/')
  28. def admin_index():
  29. return 'admin index'
  30. @admin.route('/login')
  31. def admin_login():
  32. return 'admin login'
  33. @admin.route('/logout')
  34. def admin_logout():
  35. return 'admin logout'
  36. @app.route('/')
  37. def index():
  38. return 'the index'
  39. app.register_module(admin)
  40. c = app.test_client()
  41. self.assert_equal(c.get('/').data, b'the index')
  42. self.assert_equal(c.get('/admin/').data, b'admin index')
  43. self.assert_equal(c.get('/admin/login').data, b'admin login')
  44. self.assert_equal(c.get('/admin/logout').data, b'admin logout')
  45. @emits_module_deprecation_warning
  46. def test_default_endpoint_name(self):
  47. app = flask.Flask(__name__)
  48. mod = flask.Module(__name__, 'frontend')
  49. def index():
  50. return 'Awesome'
  51. mod.add_url_rule('/', view_func=index)
  52. app.register_module(mod)
  53. rv = app.test_client().get('/')
  54. self.assert_equal(rv.data, b'Awesome')
  55. with app.test_request_context():
  56. self.assert_equal(flask.url_for('frontend.index'), '/')
  57. @emits_module_deprecation_warning
  58. def test_request_processing(self):
  59. catched = []
  60. app = flask.Flask(__name__)
  61. admin = flask.Module(__name__, 'admin', url_prefix='/admin')
  62. @admin.before_request
  63. def before_admin_request():
  64. catched.append('before-admin')
  65. @admin.after_request
  66. def after_admin_request(response):
  67. catched.append('after-admin')
  68. return response
  69. @admin.route('/')
  70. def admin_index():
  71. return 'the admin'
  72. @app.before_request
  73. def before_request():
  74. catched.append('before-app')
  75. @app.after_request
  76. def after_request(response):
  77. catched.append('after-app')
  78. return response
  79. @app.route('/')
  80. def index():
  81. return 'the index'
  82. app.register_module(admin)
  83. c = app.test_client()
  84. self.assert_equal(c.get('/').data, b'the index')
  85. self.assert_equal(catched, ['before-app', 'after-app'])
  86. del catched[:]
  87. self.assert_equal(c.get('/admin/').data, b'the admin')
  88. self.assert_equal(catched, ['before-app', 'before-admin',
  89. 'after-admin', 'after-app'])
  90. @emits_module_deprecation_warning
  91. def test_context_processors(self):
  92. app = flask.Flask(__name__)
  93. admin = flask.Module(__name__, 'admin', url_prefix='/admin')
  94. @app.context_processor
  95. def inject_all_regular():
  96. return {'a': 1}
  97. @admin.context_processor
  98. def inject_admin():
  99. return {'b': 2}
  100. @admin.app_context_processor
  101. def inject_all_module():
  102. return {'c': 3}
  103. @app.route('/')
  104. def index():
  105. return flask.render_template_string('{{ a }}{{ b }}{{ c }}')
  106. @admin.route('/')
  107. def admin_index():
  108. return flask.render_template_string('{{ a }}{{ b }}{{ c }}')
  109. app.register_module(admin)
  110. c = app.test_client()
  111. self.assert_equal(c.get('/').data, b'13')
  112. self.assert_equal(c.get('/admin/').data, b'123')
  113. @emits_module_deprecation_warning
  114. def test_late_binding(self):
  115. app = flask.Flask(__name__)
  116. admin = flask.Module(__name__, 'admin')
  117. @admin.route('/')
  118. def index():
  119. return '42'
  120. app.register_module(admin, url_prefix='/admin')
  121. self.assert_equal(app.test_client().get('/admin/').data, b'42')
  122. @emits_module_deprecation_warning
  123. def test_error_handling(self):
  124. app = flask.Flask(__name__)
  125. admin = flask.Module(__name__, 'admin')
  126. @admin.app_errorhandler(404)
  127. def not_found(e):
  128. return 'not found', 404
  129. @admin.app_errorhandler(500)
  130. def internal_server_error(e):
  131. return 'internal server error', 500
  132. @admin.route('/')
  133. def index():
  134. flask.abort(404)
  135. @admin.route('/error')
  136. def error():
  137. 1 // 0
  138. app.register_module(admin)
  139. c = app.test_client()
  140. rv = c.get('/')
  141. self.assert_equal(rv.status_code, 404)
  142. self.assert_equal(rv.data, b'not found')
  143. rv = c.get('/error')
  144. self.assert_equal(rv.status_code, 500)
  145. self.assert_equal(b'internal server error', rv.data)
  146. def test_templates_and_static(self):
  147. app = moduleapp
  148. app.testing = True
  149. c = app.test_client()
  150. rv = c.get('/')
  151. self.assert_equal(rv.data, b'Hello from the Frontend')
  152. rv = c.get('/admin/')
  153. self.assert_equal(rv.data, b'Hello from the Admin')
  154. rv = c.get('/admin/index2')
  155. self.assert_equal(rv.data, b'Hello from the Admin')
  156. rv = c.get('/admin/static/test.txt')
  157. self.assert_equal(rv.data.strip(), b'Admin File')
  158. rv.close()
  159. rv = c.get('/admin/static/css/test.css')
  160. self.assert_equal(rv.data.strip(), b'/* nested file */')
  161. rv.close()
  162. with app.test_request_context():
  163. self.assert_equal(flask.url_for('admin.static', filename='test.txt'),
  164. '/admin/static/test.txt')
  165. with app.test_request_context():
  166. try:
  167. flask.render_template('missing.html')
  168. except TemplateNotFound as e:
  169. self.assert_equal(e.name, 'missing.html')
  170. else:
  171. self.assert_true(0, 'expected exception')
  172. with flask.Flask(__name__).test_request_context():
  173. self.assert_equal(flask.render_template('nested/nested.txt'), 'I\'m nested')
  174. def test_safe_access(self):
  175. app = moduleapp
  176. with app.test_request_context():
  177. f = app.view_functions['admin.static']
  178. try:
  179. f('/etc/passwd')
  180. except NotFound:
  181. pass
  182. else:
  183. self.assert_true(0, 'expected exception')
  184. try:
  185. f('../__init__.py')
  186. except NotFound:
  187. pass
  188. else:
  189. self.assert_true(0, 'expected exception')
  190. # testcase for a security issue that may exist on windows systems
  191. import os
  192. import ntpath
  193. old_path = os.path
  194. os.path = ntpath
  195. try:
  196. try:
  197. f('..\\__init__.py')
  198. except NotFound:
  199. pass
  200. else:
  201. self.assert_true(0, 'expected exception')
  202. finally:
  203. os.path = old_path
  204. @emits_module_deprecation_warning
  205. def test_endpoint_decorator(self):
  206. from werkzeug.routing import Submount, Rule
  207. from flask import Module
  208. app = flask.Flask(__name__)
  209. app.testing = True
  210. app.url_map.add(Submount('/foo', [
  211. Rule('/bar', endpoint='bar'),
  212. Rule('/', endpoint='index')
  213. ]))
  214. module = Module(__name__, __name__)
  215. @module.endpoint('bar')
  216. def bar():
  217. return 'bar'
  218. @module.endpoint('index')
  219. def index():
  220. return 'index'
  221. app.register_module(module)
  222. c = app.test_client()
  223. self.assert_equal(c.get('/foo/').data, b'index')
  224. self.assert_equal(c.get('/foo/bar').data, b'bar')
  225. class BlueprintTestCase(FlaskTestCase):
  226. def test_blueprint_specific_error_handling(self):
  227. frontend = flask.Blueprint('frontend', __name__)
  228. backend = flask.Blueprint('backend', __name__)
  229. sideend = flask.Blueprint('sideend', __name__)
  230. @frontend.errorhandler(403)
  231. def frontend_forbidden(e):
  232. return 'frontend says no', 403
  233. @frontend.route('/frontend-no')
  234. def frontend_no():
  235. flask.abort(403)
  236. @backend.errorhandler(403)
  237. def backend_forbidden(e):
  238. return 'backend says no', 403
  239. @backend.route('/backend-no')
  240. def backend_no():
  241. flask.abort(403)
  242. @sideend.route('/what-is-a-sideend')
  243. def sideend_no():
  244. flask.abort(403)
  245. app = flask.Flask(__name__)
  246. app.register_blueprint(frontend)
  247. app.register_blueprint(backend)
  248. app.register_blueprint(sideend)
  249. @app.errorhandler(403)
  250. def app_forbidden(e):
  251. return 'application itself says no', 403
  252. c = app.test_client()
  253. self.assert_equal(c.get('/frontend-no').data, b'frontend says no')
  254. self.assert_equal(c.get('/backend-no').data, b'backend says no')
  255. self.assert_equal(c.get('/what-is-a-sideend').data, b'application itself says no')
  256. def test_blueprint_url_definitions(self):
  257. bp = flask.Blueprint('test', __name__)
  258. @bp.route('/foo', defaults={'baz': 42})
  259. def foo(bar, baz):
  260. return '%s/%d' % (bar, baz)
  261. @bp.route('/bar')
  262. def bar(bar):
  263. return text_type(bar)
  264. app = flask.Flask(__name__)
  265. app.register_blueprint(bp, url_prefix='/1', url_defaults={'bar': 23})
  266. app.register_blueprint(bp, url_prefix='/2', url_defaults={'bar': 19})
  267. c = app.test_client()
  268. self.assert_equal(c.get('/1/foo').data, b'23/42')
  269. self.assert_equal(c.get('/2/foo').data, b'19/42')
  270. self.assert_equal(c.get('/1/bar').data, b'23')
  271. self.assert_equal(c.get('/2/bar').data, b'19')
  272. def test_blueprint_url_processors(self):
  273. bp = flask.Blueprint('frontend', __name__, url_prefix='/<lang_code>')
  274. @bp.url_defaults
  275. def add_language_code(endpoint, values):
  276. values.setdefault('lang_code', flask.g.lang_code)
  277. @bp.url_value_preprocessor
  278. def pull_lang_code(endpoint, values):
  279. flask.g.lang_code = values.pop('lang_code')
  280. @bp.route('/')
  281. def index():
  282. return flask.url_for('.about')
  283. @bp.route('/about')
  284. def about():
  285. return flask.url_for('.index')
  286. app = flask.Flask(__name__)
  287. app.register_blueprint(bp)
  288. c = app.test_client()
  289. self.assert_equal(c.get('/de/').data, b'/de/about')
  290. self.assert_equal(c.get('/de/about').data, b'/de/')
  291. def test_templates_and_static(self):
  292. from blueprintapp import app
  293. c = app.test_client()
  294. rv = c.get('/')
  295. self.assert_equal(rv.data, b'Hello from the Frontend')
  296. rv = c.get('/admin/')
  297. self.assert_equal(rv.data, b'Hello from the Admin')
  298. rv = c.get('/admin/index2')
  299. self.assert_equal(rv.data, b'Hello from the Admin')
  300. rv = c.get('/admin/static/test.txt')
  301. self.assert_equal(rv.data.strip(), b'Admin File')
  302. rv.close()
  303. rv = c.get('/admin/static/css/test.css')
  304. self.assert_equal(rv.data.strip(), b'/* nested file */')
  305. rv.close()
  306. # try/finally, in case other tests use this app for Blueprint tests.
  307. max_age_default = app.config['SEND_FILE_MAX_AGE_DEFAULT']
  308. try:
  309. expected_max_age = 3600
  310. if app.config['SEND_FILE_MAX_AGE_DEFAULT'] == expected_max_age:
  311. expected_max_age = 7200
  312. app.config['SEND_FILE_MAX_AGE_DEFAULT'] = expected_max_age
  313. rv = c.get('/admin/static/css/test.css')
  314. cc = parse_cache_control_header(rv.headers['Cache-Control'])
  315. self.assert_equal(cc.max_age, expected_max_age)
  316. rv.close()
  317. finally:
  318. app.config['SEND_FILE_MAX_AGE_DEFAULT'] = max_age_default
  319. with app.test_request_context():
  320. self.assert_equal(flask.url_for('admin.static', filename='test.txt'),
  321. '/admin/static/test.txt')
  322. with app.test_request_context():
  323. try:
  324. flask.render_template('missing.html')
  325. except TemplateNotFound as e:
  326. self.assert_equal(e.name, 'missing.html')
  327. else:
  328. self.assert_true(0, 'expected exception')
  329. with flask.Flask(__name__).test_request_context():
  330. self.assert_equal(flask.render_template('nested/nested.txt'), 'I\'m nested')
  331. def test_default_static_cache_timeout(self):
  332. app = flask.Flask(__name__)
  333. class MyBlueprint(flask.Blueprint):
  334. def get_send_file_max_age(self, filename):
  335. return 100
  336. blueprint = MyBlueprint('blueprint', __name__, static_folder='static')
  337. app.register_blueprint(blueprint)
  338. # try/finally, in case other tests use this app for Blueprint tests.
  339. max_age_default = app.config['SEND_FILE_MAX_AGE_DEFAULT']
  340. try:
  341. with app.test_request_context():
  342. unexpected_max_age = 3600
  343. if app.config['SEND_FILE_MAX_AGE_DEFAULT'] == unexpected_max_age:
  344. unexpected_max_age = 7200
  345. app.config['SEND_FILE_MAX_AGE_DEFAULT'] = unexpected_max_age
  346. rv = blueprint.send_static_file('index.html')
  347. cc = parse_cache_control_header(rv.headers['Cache-Control'])
  348. self.assert_equal(cc.max_age, 100)
  349. rv.close()
  350. finally:
  351. app.config['SEND_FILE_MAX_AGE_DEFAULT'] = max_age_default
  352. def test_templates_list(self):
  353. from blueprintapp import app
  354. templates = sorted(app.jinja_env.list_templates())
  355. self.assert_equal(templates, ['admin/index.html',
  356. 'frontend/index.html'])
  357. def test_dotted_names(self):
  358. frontend = flask.Blueprint('myapp.frontend', __name__)
  359. backend = flask.Blueprint('myapp.backend', __name__)
  360. @frontend.route('/fe')
  361. def frontend_index():
  362. return flask.url_for('myapp.backend.backend_index')
  363. @frontend.route('/fe2')
  364. def frontend_page2():
  365. return flask.url_for('.frontend_index')
  366. @backend.route('/be')
  367. def backend_index():
  368. return flask.url_for('myapp.frontend.frontend_index')
  369. app = flask.Flask(__name__)
  370. app.register_blueprint(frontend)
  371. app.register_blueprint(backend)
  372. c = app.test_client()
  373. self.assert_equal(c.get('/fe').data.strip(), b'/be')
  374. self.assert_equal(c.get('/fe2').data.strip(), b'/fe')
  375. self.assert_equal(c.get('/be').data.strip(), b'/fe')
  376. def test_dotted_names_from_app(self):
  377. app = flask.Flask(__name__)
  378. app.testing = True
  379. test = flask.Blueprint('test', __name__)
  380. @app.route('/')
  381. def app_index():
  382. return flask.url_for('test.index')
  383. @test.route('/test/')
  384. def index():
  385. return flask.url_for('app_index')
  386. app.register_blueprint(test)
  387. with app.test_client() as c:
  388. rv = c.get('/')
  389. self.assert_equal(rv.data, b'/test/')
  390. def test_empty_url_defaults(self):
  391. bp = flask.Blueprint('bp', __name__)
  392. @bp.route('/', defaults={'page': 1})
  393. @bp.route('/page/<int:page>')
  394. def something(page):
  395. return str(page)
  396. app = flask.Flask(__name__)
  397. app.register_blueprint(bp)
  398. c = app.test_client()
  399. self.assert_equal(c.get('/').data, b'1')
  400. self.assert_equal(c.get('/page/2').data, b'2')
  401. def test_route_decorator_custom_endpoint(self):
  402. bp = flask.Blueprint('bp', __name__)
  403. @bp.route('/foo')
  404. def foo():
  405. return flask.request.endpoint
  406. @bp.route('/bar', endpoint='bar')
  407. def foo_bar():
  408. return flask.request.endpoint
  409. @bp.route('/bar/123', endpoint='123')
  410. def foo_bar_foo():
  411. return flask.request.endpoint
  412. @bp.route('/bar/foo')
  413. def bar_foo():
  414. return flask.request.endpoint
  415. app = flask.Flask(__name__)
  416. app.register_blueprint(bp, url_prefix='/py')
  417. @app.route('/')
  418. def index():
  419. return flask.request.endpoint
  420. c = app.test_client()
  421. self.assertEqual(c.get('/').data, b'index')
  422. self.assertEqual(c.get('/py/foo').data, b'bp.foo')
  423. self.assertEqual(c.get('/py/bar').data, b'bp.bar')
  424. self.assertEqual(c.get('/py/bar/123').data, b'bp.123')
  425. self.assertEqual(c.get('/py/bar/foo').data, b'bp.bar_foo')
  426. def test_route_decorator_custom_endpoint_with_dots(self):
  427. bp = flask.Blueprint('bp', __name__)
  428. @bp.route('/foo')
  429. def foo():
  430. return flask.request.endpoint
  431. try:
  432. @bp.route('/bar', endpoint='bar.bar')
  433. def foo_bar():
  434. return flask.request.endpoint
  435. except AssertionError:
  436. pass
  437. else:
  438. raise AssertionError('expected AssertionError not raised')
  439. try:
  440. @bp.route('/bar/123', endpoint='bar.123')
  441. def foo_bar_foo():
  442. return flask.request.endpoint
  443. except AssertionError:
  444. pass
  445. else:
  446. raise AssertionError('expected AssertionError not raised')
  447. def foo_foo_foo():
  448. pass
  449. self.assertRaises(
  450. AssertionError,
  451. lambda: bp.add_url_rule(
  452. '/bar/123', endpoint='bar.123', view_func=foo_foo_foo
  453. )
  454. )
  455. self.assertRaises(
  456. AssertionError,
  457. bp.route('/bar/123', endpoint='bar.123'),
  458. lambda: None
  459. )
  460. app = flask.Flask(__name__)
  461. app.register_blueprint(bp, url_prefix='/py')
  462. c = app.test_client()
  463. self.assertEqual(c.get('/py/foo').data, b'bp.foo')
  464. # The rule's didn't actually made it through
  465. rv = c.get('/py/bar')
  466. assert rv.status_code == 404
  467. rv = c.get('/py/bar/123')
  468. assert rv.status_code == 404
  469. def test_template_filter(self):
  470. bp = flask.Blueprint('bp', __name__)
  471. @bp.app_template_filter()
  472. def my_reverse(s):
  473. return s[::-1]
  474. app = flask.Flask(__name__)
  475. app.register_blueprint(bp, url_prefix='/py')
  476. self.assert_in('my_reverse', app.jinja_env.filters.keys())
  477. self.assert_equal(app.jinja_env.filters['my_reverse'], my_reverse)
  478. self.assert_equal(app.jinja_env.filters['my_reverse']('abcd'), 'dcba')
  479. def test_add_template_filter(self):
  480. bp = flask.Blueprint('bp', __name__)
  481. def my_reverse(s):
  482. return s[::-1]
  483. bp.add_app_template_filter(my_reverse)
  484. app = flask.Flask(__name__)
  485. app.register_blueprint(bp, url_prefix='/py')
  486. self.assert_in('my_reverse', app.jinja_env.filters.keys())
  487. self.assert_equal(app.jinja_env.filters['my_reverse'], my_reverse)
  488. self.assert_equal(app.jinja_env.filters['my_reverse']('abcd'), 'dcba')
  489. def test_template_filter_with_name(self):
  490. bp = flask.Blueprint('bp', __name__)
  491. @bp.app_template_filter('strrev')
  492. def my_reverse(s):
  493. return s[::-1]
  494. app = flask.Flask(__name__)
  495. app.register_blueprint(bp, url_prefix='/py')
  496. self.assert_in('strrev', app.jinja_env.filters.keys())
  497. self.assert_equal(app.jinja_env.filters['strrev'], my_reverse)
  498. self.assert_equal(app.jinja_env.filters['strrev']('abcd'), 'dcba')
  499. def test_add_template_filter_with_name(self):
  500. bp = flask.Blueprint('bp', __name__)
  501. def my_reverse(s):
  502. return s[::-1]
  503. bp.add_app_template_filter(my_reverse, 'strrev')
  504. app = flask.Flask(__name__)
  505. app.register_blueprint(bp, url_prefix='/py')
  506. self.assert_in('strrev', app.jinja_env.filters.keys())
  507. self.assert_equal(app.jinja_env.filters['strrev'], my_reverse)
  508. self.assert_equal(app.jinja_env.filters['strrev']('abcd'), 'dcba')
  509. def test_template_filter_with_template(self):
  510. bp = flask.Blueprint('bp', __name__)
  511. @bp.app_template_filter()
  512. def super_reverse(s):
  513. return s[::-1]
  514. app = flask.Flask(__name__)
  515. app.register_blueprint(bp, url_prefix='/py')
  516. @app.route('/')
  517. def index():
  518. return flask.render_template('template_filter.html', value='abcd')
  519. rv = app.test_client().get('/')
  520. self.assert_equal(rv.data, b'dcba')
  521. def test_template_filter_after_route_with_template(self):
  522. app = flask.Flask(__name__)
  523. @app.route('/')
  524. def index():
  525. return flask.render_template('template_filter.html', value='abcd')
  526. bp = flask.Blueprint('bp', __name__)
  527. @bp.app_template_filter()
  528. def super_reverse(s):
  529. return s[::-1]
  530. app.register_blueprint(bp, url_prefix='/py')
  531. rv = app.test_client().get('/')
  532. self.assert_equal(rv.data, b'dcba')
  533. def test_add_template_filter_with_template(self):
  534. bp = flask.Blueprint('bp', __name__)
  535. def super_reverse(s):
  536. return s[::-1]
  537. bp.add_app_template_filter(super_reverse)
  538. app = flask.Flask(__name__)
  539. app.register_blueprint(bp, url_prefix='/py')
  540. @app.route('/')
  541. def index():
  542. return flask.render_template('template_filter.html', value='abcd')
  543. rv = app.test_client().get('/')
  544. self.assert_equal(rv.data, b'dcba')
  545. def test_template_filter_with_name_and_template(self):
  546. bp = flask.Blueprint('bp', __name__)
  547. @bp.app_template_filter('super_reverse')
  548. def my_reverse(s):
  549. return s[::-1]
  550. app = flask.Flask(__name__)
  551. app.register_blueprint(bp, url_prefix='/py')
  552. @app.route('/')
  553. def index():
  554. return flask.render_template('template_filter.html', value='abcd')
  555. rv = app.test_client().get('/')
  556. self.assert_equal(rv.data, b'dcba')
  557. def test_add_template_filter_with_name_and_template(self):
  558. bp = flask.Blueprint('bp', __name__)
  559. def my_reverse(s):
  560. return s[::-1]
  561. bp.add_app_template_filter(my_reverse, 'super_reverse')
  562. app = flask.Flask(__name__)
  563. app.register_blueprint(bp, url_prefix='/py')
  564. @app.route('/')
  565. def index():
  566. return flask.render_template('template_filter.html', value='abcd')
  567. rv = app.test_client().get('/')
  568. self.assert_equal(rv.data, b'dcba')
  569. def test_template_test(self):
  570. bp = flask.Blueprint('bp', __name__)
  571. @bp.app_template_test()
  572. def is_boolean(value):
  573. return isinstance(value, bool)
  574. app = flask.Flask(__name__)
  575. app.register_blueprint(bp, url_prefix='/py')
  576. self.assert_in('is_boolean', app.jinja_env.tests.keys())
  577. self.assert_equal(app.jinja_env.tests['is_boolean'], is_boolean)
  578. self.assert_true(app.jinja_env.tests['is_boolean'](False))
  579. def test_add_template_test(self):
  580. bp = flask.Blueprint('bp', __name__)
  581. def is_boolean(value):
  582. return isinstance(value, bool)
  583. bp.add_app_template_test(is_boolean)
  584. app = flask.Flask(__name__)
  585. app.register_blueprint(bp, url_prefix='/py')
  586. self.assert_in('is_boolean', app.jinja_env.tests.keys())
  587. self.assert_equal(app.jinja_env.tests['is_boolean'], is_boolean)
  588. self.assert_true(app.jinja_env.tests['is_boolean'](False))
  589. def test_template_test_with_name(self):
  590. bp = flask.Blueprint('bp', __name__)
  591. @bp.app_template_test('boolean')
  592. def is_boolean(value):
  593. return isinstance(value, bool)
  594. app = flask.Flask(__name__)
  595. app.register_blueprint(bp, url_prefix='/py')
  596. self.assert_in('boolean', app.jinja_env.tests.keys())
  597. self.assert_equal(app.jinja_env.tests['boolean'], is_boolean)
  598. self.assert_true(app.jinja_env.tests['boolean'](False))
  599. def test_add_template_test_with_name(self):
  600. bp = flask.Blueprint('bp', __name__)
  601. def is_boolean(value):
  602. return isinstance(value, bool)
  603. bp.add_app_template_test(is_boolean, 'boolean')
  604. app = flask.Flask(__name__)
  605. app.register_blueprint(bp, url_prefix='/py')
  606. self.assert_in('boolean', app.jinja_env.tests.keys())
  607. self.assert_equal(app.jinja_env.tests['boolean'], is_boolean)
  608. self.assert_true(app.jinja_env.tests['boolean'](False))
  609. def test_template_test_with_template(self):
  610. bp = flask.Blueprint('bp', __name__)
  611. @bp.app_template_test()
  612. def boolean(value):
  613. return isinstance(value, bool)
  614. app = flask.Flask(__name__)
  615. app.register_blueprint(bp, url_prefix='/py')
  616. @app.route('/')
  617. def index():
  618. return flask.render_template('template_test.html', value=False)
  619. rv = app.test_client().get('/')
  620. self.assert_in(b'Success!', rv.data)
  621. def test_template_test_after_route_with_template(self):
  622. app = flask.Flask(__name__)
  623. @app.route('/')
  624. def index():
  625. return flask.render_template('template_test.html', value=False)
  626. bp = flask.Blueprint('bp', __name__)
  627. @bp.app_template_test()
  628. def boolean(value):
  629. return isinstance(value, bool)
  630. app.register_blueprint(bp, url_prefix='/py')
  631. rv = app.test_client().get('/')
  632. self.assert_in(b'Success!', rv.data)
  633. def test_add_template_test_with_template(self):
  634. bp = flask.Blueprint('bp', __name__)
  635. def boolean(value):
  636. return isinstance(value, bool)
  637. bp.add_app_template_test(boolean)
  638. app = flask.Flask(__name__)
  639. app.register_blueprint(bp, url_prefix='/py')
  640. @app.route('/')
  641. def index():
  642. return flask.render_template('template_test.html', value=False)
  643. rv = app.test_client().get('/')
  644. self.assert_in(b'Success!', rv.data)
  645. def test_template_test_with_name_and_template(self):
  646. bp = flask.Blueprint('bp', __name__)
  647. @bp.app_template_test('boolean')
  648. def is_boolean(value):
  649. return isinstance(value, bool)
  650. app = flask.Flask(__name__)
  651. app.register_blueprint(bp, url_prefix='/py')
  652. @app.route('/')
  653. def index():
  654. return flask.render_template('template_test.html', value=False)
  655. rv = app.test_client().get('/')
  656. self.assert_in(b'Success!', rv.data)
  657. def test_add_template_test_with_name_and_template(self):
  658. bp = flask.Blueprint('bp', __name__)
  659. def is_boolean(value):
  660. return isinstance(value, bool)
  661. bp.add_app_template_test(is_boolean, 'boolean')
  662. app = flask.Flask(__name__)
  663. app.register_blueprint(bp, url_prefix='/py')
  664. @app.route('/')
  665. def index():
  666. return flask.render_template('template_test.html', value=False)
  667. rv = app.test_client().get('/')
  668. self.assert_in(b'Success!', rv.data)
  669. def suite():
  670. suite = unittest.TestSuite()
  671. suite.addTest(unittest.makeSuite(BlueprintTestCase))
  672. suite.addTest(unittest.makeSuite(ModuleTestCase))
  673. return suite