summaryrefslogtreecommitdiff
path: root/tests/template_tests/test_logging.py
blob: 89db04fafd3c6fe32c34e0b31fff2bee0c21b4c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import logging

from django.template import Context, Engine, Variable, VariableDoesNotExist
from django.test import SimpleTestCase, ignore_warnings
from django.utils.deprecation import RemovedInDjango21Warning


class TestHandler(logging.Handler):
    def __init__(self):
        super().__init__()
        self.log_record = None

    def emit(self, record):
        self.log_record = record


class BaseTemplateLoggingTestCase(SimpleTestCase):
    def setUp(self):
        self.test_handler = TestHandler()
        self.logger = logging.getLogger('django.template')
        self.original_level = self.logger.level
        self.logger.addHandler(self.test_handler)
        self.logger.setLevel(self.loglevel)

    def tearDown(self):
        self.logger.removeHandler(self.test_handler)
        self.logger.level = self.original_level


class VariableResolveLoggingTests(BaseTemplateLoggingTestCase):
    loglevel = logging.DEBUG

    def test_log_on_variable_does_not_exist_silent(self):
        class TestObject:
            class SilentDoesNotExist(Exception):
                silent_variable_failure = True

            @property
            def template_name(self):
                return "template_name"

            @property
            def template(self):
                return Engine().from_string('')

            @property
            def article(self):
                raise TestObject.SilentDoesNotExist("Attribute does not exist.")

            def __iter__(self):
                return iter(attr for attr in dir(TestObject) if attr[:2] != "__")

            def __getitem__(self, item):
                return self.__dict__[item]

        Variable('article').resolve(TestObject())

        self.assertEqual(
            self.test_handler.log_record.getMessage(),
            "Exception while resolving variable 'article' in template 'template_name'."
        )
        self.assertIsNotNone(self.test_handler.log_record.exc_info)
        raised_exception = self.test_handler.log_record.exc_info[1]
        self.assertEqual(str(raised_exception), 'Attribute does not exist.')

    def test_log_on_variable_does_not_exist_not_silent(self):
        with self.assertRaises(VariableDoesNotExist):
            Variable('article.author').resolve({'article': {'section': 'News'}})

        self.assertEqual(
            self.test_handler.log_record.getMessage(),
            "Exception while resolving variable 'author' in template 'unknown'."
        )
        self.assertIsNotNone(self.test_handler.log_record.exc_info)
        raised_exception = self.test_handler.log_record.exc_info[1]
        self.assertEqual(
            str(raised_exception),
            "Failed lookup for key [author] in {'section': 'News'}"
        )

    def test_no_log_when_variable_exists(self):
        Variable('article.section').resolve({'article': {'section': 'News'}})
        self.assertIsNone(self.test_handler.log_record)


class IncludeNodeLoggingTests(BaseTemplateLoggingTestCase):
    loglevel = logging.WARN

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.engine = Engine(loaders=[
            ('django.template.loaders.locmem.Loader', {
                'child': '{{ raises_exception }}',
            }),
        ], debug=False)

        def error_method():
            raise IndexError("some generic exception")

        cls.ctx = Context({'raises_exception': error_method})

    def test_logs_exceptions_during_rendering_with_debug_disabled(self):
        template = self.engine.from_string('{% include "child" %}')
        template.name = 'template_name'
        with ignore_warnings(category=RemovedInDjango21Warning):
            self.assertEqual(template.render(self.ctx), '')
        self.assertEqual(
            self.test_handler.log_record.getMessage(),
            "Exception raised while rendering {% include %} for template "
            "'template_name'. Empty string rendered instead."
        )
        self.assertIsNotNone(self.test_handler.log_record.exc_info)
        self.assertEqual(self.test_handler.log_record.levelno, logging.WARN)

    def test_logs_exceptions_during_rendering_with_no_template_name(self):
        template = self.engine.from_string('{% include "child" %}')
        with ignore_warnings(category=RemovedInDjango21Warning):
            self.assertEqual(template.render(self.ctx), '')
        self.assertEqual(
            self.test_handler.log_record.getMessage(),
            "Exception raised while rendering {% include %} for template "
            "'unknown'. Empty string rendered instead."
        )
        self.assertIsNotNone(self.test_handler.log_record.exc_info)
        self.assertEqual(self.test_handler.log_record.levelno, logging.WARN)