2014-11-12 09:32:44 +08:00
|
|
|
import functools
|
2015-01-28 20:35:27 +08:00
|
|
|
import os
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
from django.template.engine import Engine
|
|
|
|
from django.test.utils import override_settings
|
|
|
|
from django.utils.safestring import mark_safe
|
|
|
|
|
2017-01-20 21:01:02 +08:00
|
|
|
ROOT = os.path.dirname(os.path.abspath(__file__))
|
2015-02-19 05:51:05 +08:00
|
|
|
TEMPLATE_DIR = os.path.join(ROOT, "templates")
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
|
2020-05-03 22:13:38 +08:00
|
|
|
def setup(templates, *args, test_once=False):
|
2014-11-12 09:32:44 +08:00
|
|
|
"""
|
|
|
|
Runs test method multiple times in the following order:
|
|
|
|
|
2014-12-15 06:13:03 +08:00
|
|
|
debug cached string_if_invalid
|
|
|
|
----- ------ -----------------
|
|
|
|
False False
|
|
|
|
False True
|
|
|
|
False False INVALID
|
|
|
|
False True INVALID
|
|
|
|
True False
|
|
|
|
True True
|
2020-05-03 22:13:38 +08:00
|
|
|
|
|
|
|
Use test_once=True to test deprecation warnings since the message won't be
|
|
|
|
displayed multiple times.
|
2014-11-12 09:32:44 +08:00
|
|
|
"""
|
|
|
|
|
|
|
|
for arg in args:
|
|
|
|
templates.update(arg)
|
|
|
|
|
|
|
|
# numerous tests make use of an inclusion tag
|
|
|
|
# add this in here for simplicity
|
|
|
|
templates["inclusion.html"] = "{{ result }}"
|
|
|
|
|
2014-12-07 16:43:10 +08:00
|
|
|
loaders = [
|
|
|
|
(
|
|
|
|
"django.template.loaders.cached.Loader",
|
|
|
|
[
|
|
|
|
("django.template.loaders.locmem.Loader", templates),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
]
|
|
|
|
|
2014-11-12 09:32:44 +08:00
|
|
|
def decorator(func):
|
2014-12-07 16:43:10 +08:00
|
|
|
# Make Engine.get_default() raise an exception to ensure that tests
|
|
|
|
# are properly isolated from Django's global settings.
|
|
|
|
@override_settings(TEMPLATES=None)
|
2014-12-03 19:22:15 +08:00
|
|
|
@functools.wraps(func)
|
2014-11-12 09:32:44 +08:00
|
|
|
def inner(self):
|
2015-05-09 04:10:36 +08:00
|
|
|
# Set up custom template tag libraries if specified
|
|
|
|
libraries = getattr(self, "libraries", {})
|
|
|
|
|
2014-12-07 16:43:10 +08:00
|
|
|
self.engine = Engine(
|
2015-05-09 04:10:36 +08:00
|
|
|
libraries=libraries,
|
2014-12-07 16:43:10 +08:00
|
|
|
loaders=loaders,
|
|
|
|
)
|
|
|
|
func(self)
|
2014-12-02 05:20:37 +08:00
|
|
|
if test_once:
|
|
|
|
return
|
2014-12-07 16:43:10 +08:00
|
|
|
func(self)
|
2014-11-12 09:32:44 +08:00
|
|
|
|
2014-12-07 16:43:10 +08:00
|
|
|
self.engine = Engine(
|
2015-05-09 04:10:36 +08:00
|
|
|
libraries=libraries,
|
2014-12-07 16:43:10 +08:00
|
|
|
loaders=loaders,
|
|
|
|
string_if_invalid="INVALID",
|
|
|
|
)
|
2014-11-12 09:32:44 +08:00
|
|
|
func(self)
|
|
|
|
func(self)
|
|
|
|
|
2014-12-07 16:43:10 +08:00
|
|
|
self.engine = Engine(
|
|
|
|
debug=True,
|
2015-05-09 04:10:36 +08:00
|
|
|
libraries=libraries,
|
2014-12-07 16:43:10 +08:00
|
|
|
loaders=loaders,
|
|
|
|
)
|
|
|
|
func(self)
|
|
|
|
func(self)
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
return inner
|
2014-12-07 16:43:10 +08:00
|
|
|
|
2014-11-12 09:32:44 +08:00
|
|
|
return decorator
|
|
|
|
|
|
|
|
|
|
|
|
# Helper objects
|
|
|
|
|
2015-05-09 04:10:36 +08:00
|
|
|
|
2014-11-12 09:32:44 +08:00
|
|
|
class SomeException(Exception):
|
|
|
|
silent_variable_failure = True
|
|
|
|
|
|
|
|
|
|
|
|
class SomeOtherException(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class ShouldNotExecuteException(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class SomeClass:
|
|
|
|
def __init__(self):
|
|
|
|
self.otherclass = OtherClass()
|
|
|
|
|
|
|
|
def method(self):
|
|
|
|
return "SomeClass.method"
|
|
|
|
|
|
|
|
def method2(self, o):
|
|
|
|
return o
|
|
|
|
|
|
|
|
def method3(self):
|
|
|
|
raise SomeException
|
|
|
|
|
|
|
|
def method4(self):
|
|
|
|
raise SomeOtherException
|
|
|
|
|
|
|
|
def method5(self):
|
|
|
|
raise TypeError
|
|
|
|
|
|
|
|
def __getitem__(self, key):
|
|
|
|
if key == "silent_fail_key":
|
|
|
|
raise SomeException
|
|
|
|
elif key == "noisy_fail_key":
|
|
|
|
raise SomeOtherException
|
|
|
|
raise KeyError
|
|
|
|
|
|
|
|
@property
|
|
|
|
def silent_fail_attribute(self):
|
|
|
|
raise SomeException
|
|
|
|
|
|
|
|
@property
|
|
|
|
def noisy_fail_attribute(self):
|
|
|
|
raise SomeOtherException
|
|
|
|
|
|
|
|
@property
|
|
|
|
def attribute_error_attribute(self):
|
|
|
|
raise AttributeError
|
|
|
|
|
2016-09-01 01:44:38 +08:00
|
|
|
@property
|
|
|
|
def type_error_attribute(self):
|
|
|
|
raise TypeError
|
|
|
|
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
class OtherClass:
|
|
|
|
def method(self):
|
|
|
|
return "OtherClass.method"
|
|
|
|
|
|
|
|
|
2017-01-19 15:39:46 +08:00
|
|
|
class TestObj:
|
2014-11-12 09:32:44 +08:00
|
|
|
def is_true(self):
|
|
|
|
return True
|
|
|
|
|
|
|
|
def is_false(self):
|
|
|
|
return False
|
|
|
|
|
|
|
|
def is_bad(self):
|
|
|
|
raise ShouldNotExecuteException()
|
|
|
|
|
|
|
|
|
2017-01-19 15:39:46 +08:00
|
|
|
class SilentGetItemClass:
|
2014-11-12 09:32:44 +08:00
|
|
|
def __getitem__(self, key):
|
|
|
|
raise SomeException
|
|
|
|
|
|
|
|
|
2017-01-19 15:39:46 +08:00
|
|
|
class SilentAttrClass:
|
2014-11-12 09:32:44 +08:00
|
|
|
def b(self):
|
|
|
|
raise SomeException
|
2022-02-04 03:24:19 +08:00
|
|
|
|
2014-11-12 09:32:44 +08:00
|
|
|
b = property(b)
|
|
|
|
|
|
|
|
|
|
|
|
class UTF8Class:
|
2017-01-22 09:02:00 +08:00
|
|
|
"Class whose __str__ returns non-ASCII data"
|
2022-02-04 03:24:19 +08:00
|
|
|
|
2014-11-12 09:32:44 +08:00
|
|
|
def __str__(self):
|
|
|
|
return "ŠĐĆŽćžšđ"
|
|
|
|
|
|
|
|
|
2017-01-21 05:04:05 +08:00
|
|
|
# These two classes are used to test auto-escaping of string output.
|
2014-11-12 09:32:44 +08:00
|
|
|
class UnsafeClass:
|
|
|
|
def __str__(self):
|
|
|
|
return "you & me"
|
|
|
|
|
|
|
|
|
|
|
|
class SafeClass:
|
|
|
|
def __str__(self):
|
|
|
|
return mark_safe("you > me")
|