1# -*- coding: utf-8 -*- 2from nose import SkipTest 3import shutil, os 4import json 5import tg 6from tg.configuration import milestones 7#tg.configuration.reqlocal_config.push_process_config({}) 8 9from tests.test_stack import TestConfig, app_from_config 10from tg.configuration.hooks import _TGGlobalHooksNamespace 11from tg.util import Bunch 12from tg._compat import PY3, im_func 13from tg.renderers.genshi import GenshiRenderer 14from tg import expose 15from tg import TGController, AppConfig 16from webtest import TestApp 17from datetime import datetime 18 19try: 20 from tgext.chameleon_genshi import ChameleonGenshiRenderer 21except ImportError: 22 ChameleonGenshiRenderer = None 23 24def setup_noDB(genshi_doctype=None, genshi_method=None, genshi_encoding=None, extra=None, 25 extra_init=None): 26 base_config = TestConfig(folder='rendering', values={ 27 'use_sqlalchemy': False, 28 'use_legacy_renderer': False, 29 # this is specific to mako to make sure inheritance works 30 'use_dotted_templatenames': False, 31 'use_toscawidgets': False, 32 'use_toscawidgets2': False 33 }) 34 35 deployment_config = {} 36 # remove previous option value to avoid using the old one 37 tg.config.pop('templating.genshi.doctype', None) 38 if genshi_doctype: 39 deployment_config['templating.genshi.doctype'] = genshi_doctype 40 tg.config.pop('templating.genshi.method', None) 41 if genshi_method: 42 deployment_config['templating.genshi.method'] = genshi_method 43 tg.config.pop('templating.genshi.encoding', None) 44 if genshi_encoding: 45 deployment_config['templating.genshi.encoding'] = genshi_encoding 46 47 deployment_config.update(extra or {}) 48 49 if extra_init is not None: 50 extra_init(base_config) 51 52 return app_from_config(base_config, deployment_config) 53 54def test_default_genshi_renderer(): 55 app = setup_noDB() 56 resp = app.get('/') 57 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' 58 ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">') in resp 59 assert "Welcome" in resp 60 assert "TurboGears" in resp 61 62def test_genshi_nameconstant(): 63 from genshi.template.astutil import ASTCodeGenerator, parse 64 from tg.renderers.genshi import GenshiRenderer 65 66 # This checks genshi gets monkeypatched to fix it on Py34 if option is provided 67 GenshiRenderer.create(Bunch({ 68 'templating.genshi.name_constant_patch': True, 69 'use_dotted_templatenames': False, 70 'auto_reload_templates': False, 71 'paths': Bunch({'templates': '/tmp'}) 72 }), None) 73 assert hasattr(ASTCodeGenerator, 'visit_NameConstant') 74 75 astgen = ASTCodeGenerator(parse('range(10)', mode='eval')) 76 for n in (False, True, None): 77 astgen._new_line() 78 astgen.visit_NameConstant(Bunch(value=n)) 79 line = str(astgen.line) 80 assert line == str(n), line 81 82 astgen._new_line() 83 try: 84 astgen.visit_NameConstant(Bunch(value='HELLO_WORLD')) 85 except Exception as e: 86 assert 'Unknown NameConstant' in str(e) 87 else: 88 assert False 89 90def test_genshi_doctype_html5(): 91 app = setup_noDB(genshi_doctype='html5') 92 resp = app.get('/') 93 assert '<!DOCTYPE html>' in resp 94 assert "Welcome" in resp 95 assert "TurboGears" in resp 96 97def test_genshi_auto_doctype(): 98 app = setup_noDB() 99 resp = app.get('/auto_doctype') 100 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' 101 ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">') in resp 102 assert 'content="text/html; charset=utf-8"' in resp 103 assert "doctype generation" in resp 104 assert "<hr />" in resp 105 assert "<p>Rendered with Genshi.</p>" in resp 106 107def test_genshi_method_html(): 108 app = setup_noDB(genshi_method='html') 109 resp = app.get('/auto_doctype') 110 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"' 111 ' "http://www.w3.org/TR/html4/loose.dtd">') in resp 112 assert 'content="text/html; charset=utf-8"' in resp 113 assert "doctype generation" in resp 114 assert "<hr>" in resp 115 assert "<p>Rendered with Genshi.</p>" in resp 116 117def test_genshi_method_xhtml(): 118 app = setup_noDB(genshi_method='xhtml') 119 resp = app.get('/auto_doctype') 120 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' 121 ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">') in resp 122 assert 'content="text/html; charset=utf-8"' in resp 123 assert "doctype generation" in resp 124 assert "<hr />" in resp 125 assert "<p>Rendered with Genshi.</p>" in resp 126 127def test_genshi_doctype_html(): 128 app = setup_noDB(genshi_doctype='html') 129 resp = app.get('/auto_doctype') 130 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"' 131 ' "http://www.w3.org/TR/html4/strict.dtd">') in resp 132 assert 'content="text/html; charset=utf-8"' in resp 133 assert "doctype generation" in resp 134 assert "<hr>" in resp 135 assert "<p>Rendered with Genshi.</p>" in resp 136 137def test_genshi_doctype_html5(): 138 app = setup_noDB(genshi_doctype='html5') 139 resp = app.get('/auto_doctype') 140 assert '<!DOCTYPE html>' in resp 141 assert 'content="text/html; charset=utf-8"' in resp 142 assert "doctype generation" in resp 143 assert "<hr>" in resp 144 assert "<p>Rendered with Genshi.</p>" in resp 145 146def test_genshi_doctype_xhtml_strict(): 147 app = setup_noDB(genshi_doctype='xhtml-strict') 148 resp = app.get('/auto_doctype') 149 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"' 150 ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">') in resp 151 assert 'content="text/html; charset=utf-8"' in resp 152 assert "doctype generation" in resp 153 assert "<hr />" in resp 154 assert "<p>Rendered with Genshi.</p>" in resp 155 156def test_genshi_doctype_html_maps_to_xhtml(): 157 app = setup_noDB(genshi_doctype={'text/html': ('xhtml', 'html')}) 158 resp = app.get('/auto_doctype_html') 159 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"' 160 ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">') in resp 161 assert 'content="text/html; charset=utf-8"' in resp 162 assert "doctype generation" in resp 163 assert "<hr />" in resp 164 assert "<p>Rendered with Genshi.</p>" in resp 165 166def test_genshi_method_html_maps_to_xhtml(): 167 app = setup_noDB(genshi_method={'text/html': ('xhtml', 'html')}) 168 resp = app.get('/auto_doctype_html') 169 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' 170 ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">') in resp 171 assert 'content="text/html; charset=utf-8"' in resp 172 assert "doctype generation" in resp 173 assert "<hr />" in resp 174 assert "<p>Rendered with Genshi.</p>" in resp 175 176def test_genshi_method_xml_overridden_by_content_type_html(): 177 app = setup_noDB(genshi_method='xml') 178 resp = app.get('/auto_doctype_html') 179 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"' 180 ' "http://www.w3.org/TR/html4/strict.dtd">') in resp 181 assert 'content="text/html; charset=utf-8"' in resp 182 assert "doctype generation" in resp 183 assert "<hr>" in resp 184 assert "<p>Rendered with Genshi.</p>" in resp 185 186def test_genshi_method_xhtml_is_ok_with_content_type_html(): 187 app = setup_noDB(genshi_method='xhtml') 188 resp = app.get('/auto_doctype_html') 189 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' 190 ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">') in resp 191 assert 'content="text/html; charset=utf-8"' in resp 192 assert "doctype generation" in resp 193 assert "<hr />" in resp 194 assert "<p>Rendered with Genshi.</p>" in resp 195 196def test_genshi_doctype_xhtml_maps_to_html(): 197 app = setup_noDB( 198 genshi_doctype={'application/xhtml+xml': ('html', 'xhtml')}) 199 resp = app.get('/auto_doctype_xhtml') 200 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"' 201 ' "http://www.w3.org/TR/html4/strict.dtd">') in resp 202 assert 'content="application/xhtml+xml; charset=utf-8"' in resp 203 assert "doctype generation" in resp 204 assert "<hr />" in resp 205 assert "<p>Rendered with Genshi.</p>" in resp 206 207def test_genshi_method_xhtml_maps_to_html(): 208 app = setup_noDB( 209 genshi_doctype={'application/xhtml+xml': ('html', 'xhtml')}, 210 genshi_method={'application/xhtml+xml': ('html', 'xhtml')}) 211 resp = app.get('/auto_doctype_xhtml') 212 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"' 213 ' "http://www.w3.org/TR/html4/strict.dtd">') in resp 214 assert 'content="application/xhtml+xml; charset=utf-8"' in resp 215 assert "doctype generation" in resp 216 assert "<hr>" in resp 217 assert "<p>Rendered with Genshi.</p>" in resp 218 219def test_genshi_method_xml_overridden_by_content_type_xhtml(): 220 app = setup_noDB(genshi_method='xml') 221 resp = app.get('/auto_doctype_xhtml') 222 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"' 223 ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">') in resp 224 assert 'content="application/xhtml+xml; charset=utf-8"' in resp 225 assert "doctype generation" in resp 226 assert "<hr />" in resp 227 assert "<p>Rendered with Genshi.</p>" in resp 228 229def test_genshi_method_html_overridden_by_content_type_xhtml(): 230 app = setup_noDB(genshi_method='html') 231 resp = app.get('/auto_doctype_xhtml') 232 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"' 233 ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">') in resp 234 assert 'content="application/xhtml+xml; charset=utf-8"' in resp 235 assert "doctype generation" in resp 236 assert "<hr />" in resp 237 assert "<p>Rendered with Genshi.</p>" in resp 238 239def test_genshi_explicit_no_doctype(): 240 app = setup_noDB() 241 resp = app.get('/explicit_no_doctype') 242 assert 'DOCTYPE' not in resp 243 assert 'content="text/html; charset=utf-8"' in resp 244 assert "doctype generation" in resp 245 assert "<hr />" in resp 246 assert "<p>Rendered with Genshi.</p>" in resp 247 248def test_genshi_explicit_doctype_html(): 249 app = setup_noDB(genshi_doctype='xhtml') 250 resp = app.get('/explicit_doctype_html') 251 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"' 252 ' "http://www.w3.org/TR/html4/strict.dtd">') in resp 253 assert 'content="text/html; charset=utf-8"' in resp 254 assert "doctype generation" in resp 255 assert "<hr>" in resp 256 assert "<p>Rendered with Genshi.</p>" in resp 257 258def test_genshi_explicit_doctype_xhtml(): 259 app = setup_noDB(genshi_doctype='html') 260 resp = app.get('/explicit_doctype_xhtml') 261 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"' 262 ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">') in resp 263 assert 'content="text/html; charset=utf-8"' in resp 264 assert "doctype generation" in resp 265 assert "<hr />" in resp 266 assert "<p>Rendered with Genshi.</p>" in resp 267 268def test_html_priority_for_ie(): 269 app = setup_noDB() 270 resp = app.get('/html_and_json', headers={'Accept': 271 'application/x-ms-application, image/jpeg, application/xaml+xml,' 272 ' image/gif, image/pjpeg, application/x-ms-xbap, */*'}) 273 assert 'text/html' in str(resp), resp 274 275def test_genshi_foreign_characters(): 276 app = setup_noDB() 277 resp = app.get('/foreign') 278 assert "Foreign Cuisine" in resp 279 assert "Crème brûlée with Käsebrötchen" in resp 280 281def test_genshi_inheritance(): 282 app = setup_noDB() 283 resp = app.get('/genshi_inherits') 284 assert "Inheritance template" in resp 285 assert "Master template" in resp 286 287def test_genshi_sub_inheritance(): 288 app = setup_noDB() 289 resp = app.get('/genshi_inherits_sub') 290 assert "Inheritance template" in resp 291 assert "Master template" in resp 292 assert "from sub-template: sub.tobeincluded" in resp 293 294def test_genshi_sub_inheritance_from_bottom(): 295 app = setup_noDB() 296 resp = app.get('/genshi_inherits_sub_from_bottom') 297 assert "from sub-template: sub.frombottom" in resp 298 assert "Master template" in resp 299 300def test_chameleon_genshi_base(): 301 if ChameleonGenshiRenderer is None: 302 raise SkipTest() 303 304 def add_chameleon_renderer(app_config): 305 app_config.register_rendering_engine(ChameleonGenshiRenderer) 306 app_config.renderers.append('chameleon_genshi') 307 308 app = setup_noDB(extra_init=add_chameleon_renderer) 309 310 # Manually add the exposition again as it was already discarded 311 # due to chameleon_genshi not being in the available renderes. 312 milestones.renderers_ready._reset() 313 from .controllers.root import RootController 314 controller = im_func(RootController.chameleon_genshi_index) 315 expose('chameleon_genshi:index.html')(controller) 316 milestones.renderers_ready.reach() 317 318 resp = app.get('/chameleon_genshi_index') 319 assert ("<p>TurboGears 2 is rapid web application development toolkit" 320 " designed to make your life easier.</p>") in resp 321 322def test_chameleon_genshi_inheritance(): 323 if ChameleonGenshiRenderer is None: 324 raise SkipTest() 325 326 def add_chameleon_renderer(app_config): 327 app_config.register_rendering_engine(ChameleonGenshiRenderer) 328 app_config.renderers.append('chameleon_genshi') 329 330 try: 331 import lxml 332 except ImportError: 333 # match templates need lxml, but since they don're really work anyway 334 # (at least not fully compatible with Genshi), we just skip this test 335 return 336 337 app = setup_noDB(extra_init=add_chameleon_renderer) 338 339 milestones.renderers_ready._reset() 340 from .controllers.root import RootController 341 controller = im_func(RootController.chameleon_genshi_inherits) 342 expose('chameleon_genshi:genshi_inherits.html')(controller) 343 milestones.renderers_ready.reach() 344 345 try: 346 resp = app.get('/chameleon_genshi_inherits') 347 except NameError as e: 348 # known issue with chameleon.genshi 1.0 349 if 'match_templates' not in str(e): 350 raise 351 except AttributeError as e: 352 # known issue with chameleon.genshi 1.3 353 if 'XPathResult' not in str(e): 354 raise 355 else: 356 assert "Inheritance template" in resp 357 assert "Master template" in resp 358 359def test_jinja_autoload(): 360 app = setup_noDB() 361 362 try: 363 resp = app.get('/jinja_autoload') 364 assert False 365 except Exception as e: 366 assert "no filter named 'polluting_function'" in str(e) 367 368def _test_jinja_inherits(): 369 app = setup_noDB() 370 resp = app.get('/jinja_inherits') 371 assert "Welcome on my awsome homepage" in resp, resp 372 373def test_jinja_extensions(): 374 base_config = TestConfig(folder = 'rendering', 375 values = {'use_sqlalchemy': False, 376 'use_legacy_renderer': False, 377 # this is specific to mako 378 # to make sure inheritance works 379 'use_dotted_templatenames': False, 380 'renderers':['jinja'], 381 'jinja_extensions': ['jinja2.ext.do', 'jinja2.ext.i18n', 382 'jinja2.ext.with_', 'jinja2.ext.autoescape'], 383 'use_toscawidgets': False, 384 'use_toscawidgets2': False 385 } 386 ) 387 app = app_from_config(base_config) 388 resp = app.get('/jinja_extensions') 389 assert "<b>Autoescape Off</b>" in resp, resp 390 assert "<b>Test Autoescape On</b>" in resp, resp 391 392def test_jinja_buildin_filters(): 393 app = setup_noDB() 394 resp = app.get('/jinja_buildins') 395 assert 'HELLO JINJA!' in resp, resp 396 397def test_jinja_custom_filters(): 398 # Simple test filter to get a md5 hash of a string 399 def codify(value): 400 try: 401 from hashlib import md5 402 except ImportError: 403 from md5 import md5 404 string_hash = md5(value.encode('ascii')) 405 return string_hash.hexdigest() 406 407 base_config = TestConfig(folder = 'rendering', 408 values = {'use_sqlalchemy': False, 409 'use_legacy_renderer': False, 410 # this is specific to mako 411 # to make sure inheritance works 412 'use_dotted_templatenames': False, 413 'renderers':['jinja'], 414 'jinja_filters': {'codify': codify}, 415 'use_toscawidgets': False, 416 'use_toscawidgets2': False 417 } 418 ) 419 app = app_from_config(base_config) 420 421 try: 422 resp = app.get('/jinja_filters') 423 finally: 424 # Remove filters so we don't mess with other test units 425 tg.config.pop('jinja_filters') 426 427 assert '8bb23e0b574ecb147536efacc864891b' in resp, resp 428 429def test_jinja_autoload_filters(): 430 app = setup_noDB() 431 resp = app.get('/jinja_filters') 432 assert '29464d5ffe8f8dba1782fffcd6ed9fca6ceb4742' in resp, resp 433 434def test_mako_renderer(): 435 app = setup_noDB() 436 resp = app.get('/mako_index') 437 assert "<p>This is the mako index page</p>" in resp, resp 438 439def test_mako_renderer_compiled(): 440 app = setup_noDB(extra={ 441 'templating.mako.compiled_templates_dir': '_tg_tests_mako_compiled/dest' 442 }) 443 444 resp = app.get('/mako_index') 445 assert "<p>This is the mako index page</p>" in resp, resp 446 447 assert os.path.exists('_tg_tests_mako_compiled') 448 shutil.rmtree('_tg_tests_mako_compiled', True) 449 450def test_mako_renderer_compiled_existing(): 451 os.makedirs('_tg_tests_mako_compiled/dest') 452 test_mako_renderer_compiled() 453 454def test_mako_renderer_compiled_no_access(): 455 os.makedirs('_tg_tests_mako_compiled') 456 os.makedirs('_tg_tests_mako_compiled/dest', mode=0o400) 457 test_mako_renderer_compiled() 458 459def test_mako_renderer_compiled_no_access_parent(): 460 os.makedirs('_tg_tests_mako_compiled', mode=0o400) 461 test_mako_renderer_compiled() 462 463def test_mako_inheritance(): 464 app = setup_noDB() 465 resp = app.get('/mako_inherits') 466 assert "inherited mako page" in resp, resp 467 assert "Inside parent template" in resp, resp 468 469def test_template_override(): 470# app = setup_noDB() 471 base_config = TestConfig(folder = 'rendering', 472 values = {'use_sqlalchemy': False, 473 'use_legacy_renderer': False, 474 # this is specific to mako 475 # to make sure inheritance works 476 'use_dotted_templatenames': True, 477 'renderers':['genshi'], 478 'use_toscawidgets': False, 479 'use_toscawidgets2': False 480 } 481 ) 482 app = app_from_config(base_config) 483 r =app.get('/template_override') 484 assert "Not overridden" in r, r 485 r = app.get('/template_override', params=dict(override=True)) 486 assert "This is overridden." in r, r 487 # now invoke the controller again without override, 488 # it should yield the old result 489 r = app.get('/template_override') 490 assert "Not overridden" in r, r 491 492def test_template_override_wts(): 493# app = setup_noDB() 494 base_config = TestConfig(folder = 'rendering', 495 values = {'use_sqlalchemy': False, 496 'use_legacy_renderer': False, 497 # this is specific to mako 498 # to make sure inheritance works 499 'use_dotted_templatenames': True, 500 'renderers':['genshi'], 501 'use_toscawidgets': False, 502 'use_toscawidgets2': False 503 } 504 ) 505 app = app_from_config(base_config) 506 r = app.get('/template_override_wts', status=301) # ensure with_trailing_slash 507 r =app.get('/template_override_wts/') 508 assert "Not overridden" in r, r 509 r = app.get('/template_override_wts/', params=dict(override=True)) 510 assert "This is overridden." in r, r 511 # now invoke the controller again without override, 512 # it should yield the old result 513 r = app.get('/template_override_wts/') 514 assert "Not overridden" in r, r 515 516def test_template_override_content_type(): 517 base_config = TestConfig(folder = 'rendering', 518 values = {'use_sqlalchemy': False, 519 'use_legacy_renderer': False, 520 # this is specific to mako 521 # to make sure inheritance works 522 'use_dotted_templatenames': True, 523 'renderers':['mako', 'genshi'], 524 'use_toscawidgets': False, 525 'use_toscawidgets2': False 526 } 527 ) 528 app = app_from_config(base_config) 529 r =app.get('/template_override_content_type') 530 assert r.content_type == 'text/javascript' 531 assert "Not overridden" in r, r 532 r = app.get('/template_override_content_type', params=dict(override=True)) 533 assert r.content_type == 'text/javascript' 534 assert "This is overridden." in r, r 535 # now invoke the controller again without override, 536 # it should yield the old result 537 r = app.get('/template_override_content_type') 538 assert "Not overridden" in r, r 539 540def test_template_custom_format_default(): 541 app = setup_noDB() 542 resp = app.get('/custom_format') 543 assert 'OK' in resp 544 assert resp.content_type == 'text/html' 545 546def test_template_custom_format_xml(): 547 app = setup_noDB() 548 resp = app.get('/custom_format?format=xml') 549 assert 'xml' in resp 550 assert resp.content_type == 'text/xml' 551 552def test_template_custom_format_json(): 553 app = setup_noDB() 554 resp = app.get('/custom_format?format=json') 555 assert 'json' in resp 556 assert resp.content_type == 'application/json' 557 558def test_template_custom_format_html(): 559 app = setup_noDB() 560 resp = app.get('/custom_format?format=html') 561 assert 'html' in resp 562 assert resp.content_type == 'text/html' 563 564def test_template_custom_format_nonexisting(): 565 app = setup_noDB() 566 567 try: 568 resp = app.get('/custom_format?format=csv') 569 assert False 570 except Exception as e: 571 assert 'not a valid custom_format' in str(e) 572 573def test_template_override_multiple_content_type(): 574 app = setup_noDB() 575 resp = app.get('/template_override_multiple_content_type') 576 assert 'something' in resp 577 578 resp = app.get( 579 '/template_override_multiple_content_type', 580 params=dict(override=True)) 581 assert 'This is the mako index page' in resp 582 583def test_override_template_on_noncontroller(): 584 tg.override_template(None, 'this.is.not.a.template') 585 586def test_jinja2_manual_rendering(): 587 app = setup_noDB() 588 tgresp = app.get('/jinja2_manual_rendering') 589 pyresp = app.get('/jinja2_manual_rendering?frompylons=1') 590 assert str(tgresp) == str(pyresp), str(tgresp) + '\n------\n' + str(pyresp) 591 592def test_no_template(): 593 app = setup_noDB() 594 resp = app.get('/no_template_generator') 595 assert '1234' in resp, resp 596 597def test_genshi_manual_render_no_doctype(): 598 app = setup_noDB() 599 resp = app.get('/genshi_manual_rendering_with_doctype') 600 assert 'DOCTYPE' not in resp, resp 601 assert "<hr />" in resp 602 assert 'content="text/html; charset=utf-8"' in resp 603 assert "<p>Rendered with Genshi.</p>" in resp 604 605def test_genshi_manual_render_auto_doctype(): 606 app = setup_noDB() 607 resp = app.get('/genshi_manual_rendering_with_doctype?doctype=auto') 608 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' 609 ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">') in resp 610 assert 'content="text/html; charset=utf-8"' in resp 611 assert "<hr />" in resp 612 assert "<p>Rendered with Genshi.</p>" in resp 613 614def test_genshi_manual_render_html_doctype(): 615 app = setup_noDB() 616 resp = app.get('/genshi_manual_rendering_with_doctype?doctype=html') 617 assert ('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"' 618 ' "http://www.w3.org/TR/html4/strict.dtd">') in resp 619 assert 'content="text/html; charset=utf-8"' in resp 620 assert "<hr>" in resp 621 assert "<p>Rendered with Genshi.</p>" in resp 622 623def test_genshi_manual_render_svg_doctype(): 624 app = setup_noDB() 625 resp = app.get('/genshi_manual_rendering_with_doctype?doctype=svg') 626 assert '<!DOCTYPE svg' in resp 627 628def test_genshi_methods_for_doctype(): 629 assert GenshiRenderer.method_for_doctype('application/xml') == 'xhtml' 630 631def test_variable_provider(): 632 app = setup_noDB(extra={'variable_provider': lambda: {'inject_this_var':5}}) 633 resp = app.get('/get_tg_vars') 634 assert 'inject_this_var' in resp 635 636def test_index_dotted_with_forced_extension(): 637 app = setup_noDB() 638 resp = app.get('/index_dotted_with_forced_extension') 639 assert 'Welcome to TurboGears' in resp 640 assert 'NOW: IT WORKS' in resp 641 642 # The purely kajiki version of this template doesn't have NOW, 643 # check it's actually like that otherwise we would pass the previous 644 # check even when it didn't resolve to the genshi template. 645 kresp = app.get('/kajiki_index_dotted') 646 assert 'Welcome to TurboGears' in kresp 647 assert 'NOW: IT WORKS' not in kresp 648 649def test_render_hooks(): 650 old_hooks, tg.hooks = tg.hooks, _TGGlobalHooksNamespace() 651 652 calls = [] 653 def render_call_hook(*args, **kw): 654 calls.append(1) 655 656 base_config = TestConfig(folder='rendering', values={ 657 'use_sqlalchemy': False, 658 'use_legacy_renderer': False, 659 # this is specific to mako to make sure inheritance works 660 'use_dotted_templatenames': False, 661 'use_toscawidgets': False, 662 'use_toscawidgets2': False 663 }) 664 665 milestones._reset_all() 666 base_config.register_hook('before_render_call', render_call_hook) 667 base_config.register_hook('after_render_call', render_call_hook) 668 app = app_from_config(base_config, reset_milestones=False) 669 app.get('/') 670 671 try: 672 assert len(calls) == 2 673 finally: 674 tg.hooks = old_hooks 675 676 677class TestEngineDetection(object): 678 def setUp(self): 679 self.app = setup_noDB(genshi_doctype='html', extra={ 680 'errorpage.enabled': True 681 }) 682 683 def test_no_engine_for_content_type(self): 684 resp = self.app.get('/aborted_json', status=403) 685 assert '{"error":"value"}' in resp 686 687 def test_content_type_provided(self): 688 resp = self.app.get('/according_to_content_type?ctype=text/html') 689 assert '<p>SomeValue' in resp 690 resp = self.app.get('/according_to_content_type?ctype=application/json') 691 assert 'value": "SomeValue' in resp, resp 692 693 694class TestTemplateCaching(object): 695 def setUp(self): 696 base_config = TestConfig(folder='rendering', values={ 697 'use_sqlalchemy': False, 698 'use_legacy_renderer': False, 699 # this is specific to mako to make sure inheritance works 700 'use_dotted_templatenames': False, 701 'use_toscawidgets': False, 702 'use_toscawidgets2': False, 703 'cache_dir': '.' 704 }) 705 self.app = app_from_config(base_config) 706 707 def test_basic(self): 708 resp = self.app.get('/template_caching') 709 current_date = resp.text.split('NOW:')[1].split('\n')[0].strip() 710 711 resp = self.app.get('/template_caching') 712 assert current_date in resp, (current_date, resp.body) 713 714 def test_default_type(self): 715 resp = self.app.get('/template_caching_default_type') 716 current_date = resp.text.split('NOW:')[1].split('\n')[0].strip() 717 718 resp = self.app.get('/template_caching_default_type') 719 assert current_date in resp, (current_date, resp.body) 720 721 def test_template_caching_options(self): 722 resp = self.app.get('/template_caching_options', params={'cache_type':'memory'}) 723 resp = json.loads(resp.text) 724 assert resp['cls'] == 'MemoryNamespaceManager', resp 725 726 resp = self.app.get('/template_caching_options', params={'cache_expire':1}) 727 resp = json.loads(resp.text) 728 assert resp['cls'] == 'NoImplementation', resp 729 730 resp = self.app.get('/template_caching_options', params={'cache_key':'TEST'}) 731 resp = json.loads(resp.text) 732 assert resp['cls'] == 'NoImplementation', resp 733 734 735class TestJSONRendering(object): 736 def setUp(self): 737 base_config = TestConfig(folder='rendering', values={ 738 'use_sqlalchemy': False, 739 'use_legacy_renderer': False, 740 # this is specific to mako to make sure inheritance works 741 'use_dotted_templatenames': False, 742 'use_toscawidgets': False, 743 'use_toscawidgets2': False, 744 'cache_dir': '.', 745 'json.isodates': True 746 }) 747 self.app = app_from_config(base_config) 748 749 def teardown(self): 750 milestones._reset_all() 751 752 def test_jsonp(self): 753 resp = self.app.get('/get_jsonp', params={'call': 'callme'}) 754 assert 'callme({"value": 5});' in resp.text, resp 755 756 def test_jsonp_with_key(self): 757 resp = self.app.get('/get_jsonp_with_key', params={'call': 'callme'}) 758 assert 'callme({"value": 5});' in resp.text, resp 759 760 def test_jsonp_missing_callback(self): 761 resp = self.app.get('/get_jsonp', status=400) 762 assert 'JSONP requires a "call" parameter with callback name' in resp.text, resp 763 764 def test_json_isodates_default(self): 765 resp = self.app.get('/get_json_isodates_default') 766 assert 'T' in resp.json_body['date'] 767 assert resp.json_body['date'].startswith(datetime.utcnow().strftime('%Y-%m-%d')) 768 769 def test_json_isodates(self): 770 resp = self.app.get('/get_json_isodates_on') 771 assert 'T' in resp.json_body['date'] 772 assert resp.json_body['date'].startswith(datetime.utcnow().strftime('%Y-%m-%d')) 773 774 def test_json_without_isodates(self): 775 resp = self.app.get('/get_json_isodates_off') 776 assert ' ' in resp.json_body['date'], resp 777 778 def test_json_lists_allowing(self): 779 resp = self.app.get('/get_json_list') 780 assert '[1, 2, 3]' == resp.text 781 782 def test_json_return_list(self): 783 try: 784 resp = self.app.get("/json_return_list") 785 assert False 786 except Exception as e: 787 assert 'Your Encoded object must be dict-like' in str(e), e 788