diff --git a/tests/template_tests/syntax_tests/test_include.py b/tests/template_tests/syntax_tests/test_include.py index 17ad9c1e4c..ecd3d59c29 100644 --- a/tests/template_tests/syntax_tests/test_include.py +++ b/tests/template_tests/syntax_tests/test_include.py @@ -1,5 +1,7 @@ -from django.template import Context, TemplateDoesNotExist, TemplateSyntaxError -from django.test import SimpleTestCase +from django.template import ( + Context, Template, TemplateDoesNotExist, TemplateSyntaxError, engines, +) +from django.test import SimpleTestCase, override_settings from ..utils import setup from .test_basic import basic_templates @@ -199,3 +201,130 @@ class IncludeTagTests(SimpleTestCase): template.render(context) else: self.assertEqual(template.render(context), '') + + +class IncludeTests(SimpleTestCase): + + # Test the base loader class via the app loader. load_template + # from base is used by all shipped loaders excepting cached, + # which has its own test. + @override_settings(TEMPLATES=[{ + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'APP_DIRS': True, + 'OPTIONS': { + # Enable debug, otherwise the exception raised during + # {% include %} processing will be suppressed. + 'debug': True, + } + }]) + def test_include_missing_template(self): + """ + Tests that the correct template is identified as not existing + when {% include %} specifies a template that does not exist. + """ + template = engines['django'].get_template('test_include_error.html') + with self.assertRaises(TemplateDoesNotExist) as e: + template.render() + self.assertEqual(e.exception.args[0], 'missing.html') + + # Test the base loader class via the app loader. load_template + # from base is used by all shipped loaders excepting cached, + # which has its own test. + @override_settings(TEMPLATES=[{ + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'APP_DIRS': True, + 'OPTIONS': { + # Enable debug, otherwise the exception raised during + # {% include %} processing will be suppressed. + 'debug': True, + } + }]) + def test_extends_include_missing_baseloader(self): + """ + #12787 -- Tests that the correct template is identified as not existing + when {% extends %} specifies a template that does exist, but that + template has an {% include %} of something that does not exist. + """ + template = engines['django'].get_template('test_extends_error.html') + with self.assertRaises(TemplateDoesNotExist) as e: + template.render() + self.assertEqual(e.exception.args[0], 'missing.html') + + @override_settings(TEMPLATES=[{ + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'OPTIONS': { + 'debug': True, + 'loaders': [ + ('django.template.loaders.cached.Loader', [ + 'django.template.loaders.app_directories.Loader', + ]), + ], + }, + }]) + def test_extends_include_missing_cachedloader(self): + """ + Test the cache loader separately since it overrides load_template. + """ + + template = engines['django'].get_template('test_extends_error.html') + with self.assertRaises(TemplateDoesNotExist) as e: + template.render() + self.assertEqual(e.exception.args[0], 'missing.html') + + # Repeat to ensure it still works when loading from the cache + template = engines['django'].get_template('test_extends_error.html') + with self.assertRaises(TemplateDoesNotExist) as e: + template.render() + self.assertEqual(e.exception.args[0], 'missing.html') + + def test_include_template_argument(self): + """ + Support any render() supporting object + """ + ctx = Context({ + 'tmpl': Template('This worked!'), + }) + outer_tmpl = Template('{% include tmpl %}') + output = outer_tmpl.render(ctx) + self.assertEqual(output, 'This worked!') + + @override_settings(TEMPLATES=[{ + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'OPTIONS': { + 'debug': True, + }, + }]) + def test_include_immediate_missing(self): + """ + #16417 -- Include tags pointing to missing templates should not raise + an error at parsing time. + """ + template = Template('{% include "this_does_not_exist.html" %}') + self.assertIsInstance(template, Template) + + @override_settings(TEMPLATES=[{ + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'APP_DIRS': True, + 'OPTIONS': { + 'debug': True, + }, + }]) + def test_include_recursive(self): + comments = [ + { + 'comment': 'A1', + 'children': [ + {'comment': 'B1', 'children': []}, + {'comment': 'B2', 'children': []}, + {'comment': 'B3', 'children': [ + {'comment': 'C1', 'children': []} + ]}, + ] + } + ] + + t = engines['django'].get_template('recursive_include.html') + self.assertEqual( + "Recursion! A1 Recursion! B1 B2 B3 Recursion! C1", + t.render({'comments': comments}).replace(' ', '').replace('\n', ' ').strip(), + ) diff --git a/tests/template_tests/tests.py b/tests/template_tests/tests.py index 13806f8b07..a49efcad4f 100644 --- a/tests/template_tests/tests.py +++ b/tests/template_tests/tests.py @@ -27,150 +27,6 @@ class TemplateTests(SimpleTestCase): self.assertEqual(template.origin.source, 'string template') -class IncludeTests(SimpleTestCase): - - # Test the base loader class via the app loader. load_template - # from base is used by all shipped loaders excepting cached, - # which has its own test. - @override_settings(TEMPLATES=[{ - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'APP_DIRS': True, - 'OPTIONS': { - # Enable debug, otherwise the exception raised during - # {% include %} processing will be suppressed. - 'debug': True, - } - }]) - def test_include_missing_template(self): - """ - Tests that the correct template is identified as not existing - when {% include %} specifies a template that does not exist. - """ - load_name = 'test_include_error.html' - r = None - try: - tmpl = loader.select_template([load_name]) - r = tmpl.render() - except template.TemplateDoesNotExist as e: - self.assertEqual(e.args[0], 'missing.html') - self.assertEqual(r, None, 'Template rendering unexpectedly succeeded, produced: ->%r<-' % r) - - # Test the base loader class via the app loader. load_template - # from base is used by all shipped loaders excepting cached, - # which has its own test. - @override_settings(TEMPLATES=[{ - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'APP_DIRS': True, - 'OPTIONS': { - # Enable debug, otherwise the exception raised during - # {% include %} processing will be suppressed. - 'debug': True, - } - }]) - def test_extends_include_missing_baseloader(self): - """ - Tests that the correct template is identified as not existing - when {% extends %} specifies a template that does exist, but - that template has an {% include %} of something that does not - exist. See #12787. - """ - load_name = 'test_extends_error.html' - tmpl = loader.get_template(load_name) - r = None - try: - r = tmpl.render() - except template.TemplateDoesNotExist as e: - self.assertEqual(e.args[0], 'missing.html') - self.assertEqual(r, None, 'Template rendering unexpectedly succeeded, produced: ->%r<-' % r) - - @override_settings(TEMPLATES=[{ - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'OPTIONS': { - 'debug': True, - 'loaders': [ - ('django.template.loaders.cached.Loader', [ - 'django.template.loaders.app_directories.Loader', - ]), - ], - }, - }]) - def test_extends_include_missing_cachedloader(self): - """ - Same as test_extends_include_missing_baseloader, only tests - behavior of the cached loader instead of base loader. - """ - load_name = 'test_extends_error.html' - tmpl = loader.get_template(load_name) - r = None - try: - r = tmpl.render() - except template.TemplateDoesNotExist as e: - self.assertEqual(e.args[0], 'missing.html') - self.assertEqual(r, None, 'Template rendering unexpectedly succeeded, produced: ->%r<-' % r) - - # For the cached loader, repeat the test, to ensure the first attempt did not cache a - # result that behaves incorrectly on subsequent attempts. - tmpl = loader.get_template(load_name) - try: - tmpl.render() - except template.TemplateDoesNotExist as e: - self.assertEqual(e.args[0], 'missing.html') - self.assertEqual(r, None, 'Template rendering unexpectedly succeeded, produced: ->%r<-' % r) - - def test_include_template_argument(self): - """ - Support any render() supporting object - """ - ctx = Context({ - 'tmpl': Template('This worked!'), - }) - outer_tmpl = Template('{% include tmpl %}') - output = outer_tmpl.render(ctx) - self.assertEqual(output, 'This worked!') - - @override_settings(TEMPLATES=[{ - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'OPTIONS': { - 'debug': True, - }, - }]) - def test_include_immediate_missing(self): - """ - Test that an {% include %} tag with a literal string referencing a - template that does not exist does not raise an exception at parse - time. Regression test for #16417. - """ - tmpl = Template('{% include "this_does_not_exist.html" %}') - self.assertIsInstance(tmpl, Template) - - @override_settings(TEMPLATES=[{ - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'APP_DIRS': True, - 'OPTIONS': { - 'debug': True, - }, - }]) - def test_include_recursive(self): - comments = [ - { - 'comment': 'A1', - 'children': [ - {'comment': 'B1', 'children': []}, - {'comment': 'B2', 'children': []}, - {'comment': 'B3', 'children': [ - {'comment': 'C1', 'children': []} - ]}, - ] - } - ] - - t = loader.get_template('recursive_include.html') - self.assertEqual( - "Recursion! A1 Recursion! B1 B2 B3 Recursion! C1", - t.render({'comments': comments}).replace(' ', '').replace('\n', ' ').strip(), - ) - - class TemplateRegressionTests(SimpleTestCase): def test_token_smart_split(self):