2005-11-27 06:46:31 +08:00
from django . conf import settings
2005-11-17 23:55:04 +08:00
2006-05-02 09:31:56 +08:00
from django import template
from django . template import loader
2005-11-17 23:55:04 +08:00
from django . utils . translation import activate , deactivate , install
2006-05-02 09:31:56 +08:00
from datetime import datetime
2005-11-27 06:46:31 +08:00
import traceback
2005-08-02 03:09:07 +08:00
2005-12-09 12:29:20 +08:00
#################################
# Custom template tag for tests #
#################################
register = template . Library ( )
class EchoNode ( template . Node ) :
def __init__ ( self , contents ) :
self . contents = contents
def render ( self , context ) :
return " " . join ( self . contents )
def do_echo ( parser , token ) :
return EchoNode ( token . contents . split ( ) [ 1 : ] )
register . tag ( " echo " , do_echo )
template . libraries [ ' django.templatetags.testtags ' ] = register
#####################################
# Helper objects for template tests #
#####################################
2006-05-02 09:31:56 +08:00
class SomeException ( Exception ) :
silent_variable_failure = True
class SomeOtherException ( Exception ) :
pass
2005-08-02 03:09:07 +08:00
class SomeClass :
def __init__ ( self ) :
self . otherclass = OtherClass ( )
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
def method ( self ) :
return " SomeClass.method "
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
def method2 ( self , o ) :
return o
2006-05-02 09:31:56 +08:00
def method3 ( self ) :
raise SomeException
def method4 ( self ) :
raise SomeOtherException
2005-08-02 03:09:07 +08:00
class OtherClass :
def method ( self ) :
return " OtherClass.method "
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# SYNTAX --
# 'template_name': ('template contents', 'context dict', 'expected string output' or Exception class)
TEMPLATE_TESTS = {
### BASIC SYNTAX ##########################################################
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Plain text should go through the template parser untouched
' basic-syntax01 ' : ( " something cool " , { } , " something cool " ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Variables should be replaced with their value in the current context
' basic-syntax02 ' : ( " {{ headline }} " , { ' headline ' : ' Success ' } , " Success " ) ,
# More than one replacement variable is allowed in a template
' basic-syntax03 ' : ( " {{ first }} --- {{ second }} " , { " first " : 1 , " second " : 2 } , " 1 --- 2 " ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Fail silently when a variable is not found in the current context
' basic-syntax04 ' : ( " as {{ missing }}df " , { } , " asdf " ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# A variable may not contain more than one word
' basic-syntax06 ' : ( " {{ multi word variable }} " , { } , template . TemplateSyntaxError ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Raise TemplateSyntaxError for empty variable tags
' basic-syntax07 ' : ( " {{ }} " , { } , template . TemplateSyntaxError ) ,
' basic-syntax08 ' : ( " {{ }} " , { } , template . TemplateSyntaxError ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Attribute syntax allows a template to call an object's attribute
' basic-syntax09 ' : ( " {{ var.method }} " , { " var " : SomeClass ( ) } , " SomeClass.method " ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Multiple levels of attribute access are allowed
' basic-syntax10 ' : ( " {{ var.otherclass.method }} " , { " var " : SomeClass ( ) } , " OtherClass.method " ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Fail silently when a variable's attribute isn't found
' basic-syntax11 ' : ( " {{ var.blech }} " , { " var " : SomeClass ( ) } , " " ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Raise TemplateSyntaxError when trying to access a variable beginning with an underscore
' basic-syntax12 ' : ( " {{ var.__dict__ }} " , { " var " : SomeClass ( ) } , template . TemplateSyntaxError ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Raise TemplateSyntaxError when trying to access a variable containing an illegal character
' basic-syntax13 ' : ( " {{ va>r }} " , { } , template . TemplateSyntaxError ) ,
' basic-syntax14 ' : ( " {{ (var.r) }} " , { } , template . TemplateSyntaxError ) ,
' basic-syntax15 ' : ( " {{ sp %a m }} " , { } , template . TemplateSyntaxError ) ,
' basic-syntax16 ' : ( " {{ eggs! }} " , { } , template . TemplateSyntaxError ) ,
' basic-syntax17 ' : ( " {{ moo? }} " , { } , template . TemplateSyntaxError ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Attribute syntax allows a template to call a dictionary key's value
' basic-syntax18 ' : ( " {{ foo.bar }} " , { " foo " : { " bar " : " baz " } } , " baz " ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Fail silently when a variable's dictionary key isn't found
' basic-syntax19 ' : ( " {{ foo.spam }} " , { " foo " : { " bar " : " baz " } } , " " ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Fail silently when accessing a non-simple method
' basic-syntax20 ' : ( " {{ var.method2 }} " , { " var " : SomeClass ( ) } , " " ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Basic filter usage
' basic-syntax21 ' : ( " {{ var|upper }} " , { " var " : " Django is the greatest! " } , " DJANGO IS THE GREATEST! " ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Chained filters
' basic-syntax22 ' : ( " {{ var|upper|lower }} " , { " var " : " Django is the greatest! " } , " django is the greatest! " ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Raise TemplateSyntaxError for space between a variable and filter pipe
' basic-syntax23 ' : ( " {{ var |upper }} " , { } , template . TemplateSyntaxError ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Raise TemplateSyntaxError for space after a filter pipe
' basic-syntax24 ' : ( " {{ var| upper }} " , { } , template . TemplateSyntaxError ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Raise TemplateSyntaxError for a nonexistent filter
' basic-syntax25 ' : ( " {{ var|does_not_exist }} " , { } , template . TemplateSyntaxError ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Raise TemplateSyntaxError when trying to access a filter containing an illegal character
' basic-syntax26 ' : ( " {{ var|fil(ter) }} " , { } , template . TemplateSyntaxError ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Raise TemplateSyntaxError for invalid block tags
' basic-syntax27 ' : ( " { % nothing_to_see_here % } " , { } , template . TemplateSyntaxError ) ,
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
# Raise TemplateSyntaxError for empty block tags
' basic-syntax28 ' : ( " { % % } " , { } , template . TemplateSyntaxError ) ,
2005-08-30 05:11:41 +08:00
2005-09-11 23:18:04 +08:00
# Chained filters, with an argument to the first one
' basic-syntax29 ' : ( ' {{ var|removetags: " b i " |upper|lower }} ' , { " var " : " <b><i>Yes</i></b> " } , " yes " ) ,
2005-11-27 06:46:31 +08:00
# Escaped string as argument
' basic-syntax30 ' : ( r ' {{ var|default_if_none: " endquote \ " hah " }} ' , { " var " : None } , ' endquote " hah ' ) ,
# Variable as argument
' basic-syntax31 ' : ( r ' {{ var|default_if_none:var2 }} ' , { " var " : None , " var2 " : " happy " } , ' happy ' ) ,
# Default argument testing
2006-05-02 09:31:56 +08:00
' basic-syntax32 ' : ( r ' {{ var|yesno: " yup,nup,mup " }} {{ var|yesno }} ' , { " var " : True } , ' yup yes ' ) ,
2005-11-24 07:10:17 +08:00
2006-05-02 09:31:56 +08:00
# Fail silently for methods that raise an exception with a "silent_variable_failure" attribute
' basic-syntax33 ' : ( r ' 1 {{ var.method3 }}2 ' , { " var " : SomeClass ( ) } , " 12 " ) ,
# In methods that raise an exception without a "silent_variable_attribute" set to True,
# the exception propogates
' basic-syntax34 ' : ( r ' 1 {{ var.method4 }}2 ' , { " var " : SomeClass ( ) } , SomeOtherException ) ,
# Escaped backslash in argument
' basic-syntax35 ' : ( r ' {{ var|default_if_none: " foo \ bar " }} ' , { " var " : None } , r ' foo \ bar ' ) ,
# Escaped backslash using known escape char
' basic-syntax35 ' : ( r ' {{ var|default_if_none: " foo \ now " }} ' , { " var " : None } , r ' foo \ now ' ) ,
2005-08-30 05:11:41 +08:00
### COMMENT TAG ###########################################################
' comment-tag01 ' : ( " { % c omment % }this is hidden { % e ndcomment % }hello " , { } , " hello " ) ,
' comment-tag02 ' : ( " { % c omment % }this is hidden { % e ndcomment % }hello { % c omment % }foo { % e ndcomment % } " , { } , " hello " ) ,
2006-01-15 08:48:23 +08:00
# Comment tag can contain invalid stuff.
' comment-tag03 ' : ( " foo { % c omment % } { % i f % } { % e ndcomment % } " , { } , " foo " ) ,
' comment-tag04 ' : ( " foo { % c omment % } { % e ndblock % } { % e ndcomment % } " , { } , " foo " ) ,
' comment-tag05 ' : ( " foo { % c omment % } { % s omerandomtag % } { % e ndcomment % } " , { } , " foo " ) ,
2006-05-02 09:31:56 +08:00
### CYCLE TAG #############################################################
#'cycleXX': ('', {}, ''),
' cycle01 ' : ( ' { % c ycle a, % } ' , { } , ' a ' ) ,
' cycle02 ' : ( ' { % c ycle a,b,c as abc % } { % c ycle abc % } ' , { } , ' ab ' ) ,
' cycle03 ' : ( ' { % c ycle a,b,c as abc % } { % c ycle abc % } { % c ycle abc % } ' , { } , ' abc ' ) ,
' cycle04 ' : ( ' { % c ycle a,b,c as abc % } { % c ycle abc % } { % c ycle abc % } { % c ycle abc % } ' , { } , ' abca ' ) ,
' cycle05 ' : ( ' { % c ycle % } ' , { } , template . TemplateSyntaxError ) ,
' cycle06 ' : ( ' { % c ycle a % } ' , { } , template . TemplateSyntaxError ) ,
' cycle07 ' : ( ' { % c ycle a,b,c as foo % } { % c ycle bar % } ' , { } , template . TemplateSyntaxError ) ,
### EXCEPTIONS ############################################################
# Raise exception for invalid template name
' exception01 ' : ( " { % e xtends ' nonexistent ' % } " , { } , template . TemplateSyntaxError ) ,
# Raise exception for invalid template name (in variable)
' exception02 ' : ( " { % e xtends nonexistent % } " , { } , template . TemplateSyntaxError ) ,
# Raise exception for extra {% extends %} tags
' exception03 ' : ( " { % e xtends ' inheritance01 ' % } { % block first % }2 { % e ndblock % } { % e xtends ' inheritance16 ' % } " , { } , template . TemplateSyntaxError ) ,
# Raise exception for custom tags used in child with {% load %} tag in parent, not in child
' exception04 ' : ( " { % e xtends ' inheritance17 ' % } { % block first % } { % e cho 400 % }5678 { % e ndblock % } " , { } , template . TemplateSyntaxError ) ,
### FILTER TAG ############################################################
' filter01 ' : ( ' { % f ilter upper % } { % e ndfilter % } ' , { } , ' ' ) ,
' filter02 ' : ( ' { % f ilter upper % }django { % e ndfilter % } ' , { } , ' DJANGO ' ) ,
' filter03 ' : ( ' { % f ilter upper|lower % }django { % e ndfilter % } ' , { } , ' django ' ) ,
### FIRSTOF TAG ###########################################################
' firstof01 ' : ( ' { % f irstof a b c % } ' , { ' a ' : 0 , ' b ' : 0 , ' c ' : 0 } , ' ' ) ,
' firstof02 ' : ( ' { % f irstof a b c % } ' , { ' a ' : 1 , ' b ' : 0 , ' c ' : 0 } , ' 1 ' ) ,
' firstof03 ' : ( ' { % f irstof a b c % } ' , { ' a ' : 0 , ' b ' : 2 , ' c ' : 0 } , ' 2 ' ) ,
' firstof04 ' : ( ' { % f irstof a b c % } ' , { ' a ' : 0 , ' b ' : 0 , ' c ' : 3 } , ' 3 ' ) ,
' firstof05 ' : ( ' { % f irstof a b c % } ' , { ' a ' : 1 , ' b ' : 2 , ' c ' : 3 } , ' 1 ' ) ,
' firstof06 ' : ( ' { % f irstof % } ' , { } , template . TemplateSyntaxError ) ,
2005-08-30 05:11:41 +08:00
### FOR TAG ###############################################################
' for-tag01 ' : ( " { % f or val in values % } {{ val }} { % e ndfor % } " , { " values " : [ 1 , 2 , 3 ] } , " 123 " ) ,
' for-tag02 ' : ( " { % f or val in values reversed % } {{ val }} { % e ndfor % } " , { " values " : [ 1 , 2 , 3 ] } , " 321 " ) ,
2005-09-30 07:34:29 +08:00
' for-tag-vars01 ' : ( " { % f or val in values % } {{ forloop.counter }} { % e ndfor % } " , { " values " : [ 6 , 6 , 6 ] } , " 123 " ) ,
' for-tag-vars02 ' : ( " { % f or val in values % } {{ forloop.counter0 }} { % e ndfor % } " , { " values " : [ 6 , 6 , 6 ] } , " 012 " ) ,
' for-tag-vars03 ' : ( " { % f or val in values % } {{ forloop.revcounter }} { % e ndfor % } " , { " values " : [ 6 , 6 , 6 ] } , " 321 " ) ,
' for-tag-vars04 ' : ( " { % f or val in values % } {{ forloop.revcounter0 }} { % e ndfor % } " , { " values " : [ 6 , 6 , 6 ] } , " 210 " ) ,
2005-08-30 05:11:41 +08:00
2006-05-02 09:31:56 +08:00
### IF TAG ################################################################
' if-tag01 ' : ( " { % i f foo % }yes { % e lse % }no { % e ndif % } " , { " foo " : True } , " yes " ) ,
' if-tag02 ' : ( " { % i f foo % }yes { % e lse % }no { % e ndif % } " , { " foo " : False } , " no " ) ,
' if-tag03 ' : ( " { % i f foo % }yes { % e lse % }no { % e ndif % } " , { } , " no " ) ,
2006-06-08 11:33:21 +08:00
# AND
' if-tag-and01 ' : ( " { % i f foo and bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : True } , ' yes ' ) ,
' if-tag-and02 ' : ( " { % i f foo and bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : False } , ' no ' ) ,
' if-tag-and03 ' : ( " { % i f foo and bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : True } , ' no ' ) ,
' if-tag-and04 ' : ( " { % i f foo and bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : False } , ' no ' ) ,
' if-tag-and05 ' : ( " { % i f foo and bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False } , ' no ' ) ,
' if-tag-and06 ' : ( " { % i f foo and bar % }yes { % e lse % }no { % e ndif % } " , { ' bar ' : False } , ' no ' ) ,
' if-tag-and07 ' : ( " { % i f foo and bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True } , ' no ' ) ,
' if-tag-and08 ' : ( " { % i f foo and bar % }yes { % e lse % }no { % e ndif % } " , { ' bar ' : True } , ' no ' ) ,
# OR
' if-tag-or01 ' : ( " { % i f foo or bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : True } , ' yes ' ) ,
' if-tag-or02 ' : ( " { % i f foo or bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : False } , ' yes ' ) ,
' if-tag-or03 ' : ( " { % i f foo or bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : True } , ' yes ' ) ,
' if-tag-or04 ' : ( " { % i f foo or bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : False } , ' no ' ) ,
' if-tag-or05 ' : ( " { % i f foo or bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False } , ' no ' ) ,
' if-tag-or06 ' : ( " { % i f foo or bar % }yes { % e lse % }no { % e ndif % } " , { ' bar ' : False } , ' no ' ) ,
' if-tag-or07 ' : ( " { % i f foo or bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True } , ' yes ' ) ,
' if-tag-or08 ' : ( " { % i f foo or bar % }yes { % e lse % }no { % e ndif % } " , { ' bar ' : True } , ' yes ' ) ,
# TODO: multiple ORs
# NOT
' if-tag-not01 ' : ( " { % i f not foo % }no { % e lse % }yes { % e ndif % } " , { ' foo ' : True } , ' yes ' ) ,
' if-tag-not02 ' : ( " { % i f not % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True } , ' no ' ) ,
' if-tag-not03 ' : ( " { % i f not % }yes { % e lse % }no { % e ndif % } " , { ' not ' : True } , ' yes ' ) ,
' if-tag-not04 ' : ( " { % i f not not % }no { % e lse % }yes { % e ndif % } " , { ' not ' : True } , ' yes ' ) ,
' if-tag-not05 ' : ( " { % i f not not % }no { % e lse % }yes { % e ndif % } " , { } , ' no ' ) ,
' if-tag-not06 ' : ( " { % i f foo and not bar % }yes { % e lse % }no { % e ndif % } " , { } , ' no ' ) ,
' if-tag-not07 ' : ( " { % i f foo and not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : True } , ' no ' ) ,
' if-tag-not08 ' : ( " { % i f foo and not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : False } , ' yes ' ) ,
' if-tag-not09 ' : ( " { % i f foo and not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : True } , ' no ' ) ,
' if-tag-not10 ' : ( " { % i f foo and not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : False } , ' no ' ) ,
' if-tag-not11 ' : ( " { % i f not foo and bar % }yes { % e lse % }no { % e ndif % } " , { } , ' no ' ) ,
' if-tag-not12 ' : ( " { % i f not foo and bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : True } , ' no ' ) ,
' if-tag-not13 ' : ( " { % i f not foo and bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : False } , ' no ' ) ,
' if-tag-not14 ' : ( " { % i f not foo and bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : True } , ' yes ' ) ,
' if-tag-not15 ' : ( " { % i f not foo and bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : False } , ' no ' ) ,
' if-tag-not16 ' : ( " { % i f foo or not bar % }yes { % e lse % }no { % e ndif % } " , { } , ' yes ' ) ,
' if-tag-not17 ' : ( " { % i f foo or not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : True } , ' yes ' ) ,
' if-tag-not18 ' : ( " { % i f foo or not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : False } , ' yes ' ) ,
' if-tag-not19 ' : ( " { % i f foo or not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : True } , ' no ' ) ,
' if-tag-not20 ' : ( " { % i f foo or not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : False } , ' yes ' ) ,
' if-tag-not21 ' : ( " { % i f not foo or bar % }yes { % e lse % }no { % e ndif % } " , { } , ' yes ' ) ,
' if-tag-not22 ' : ( " { % i f not foo or bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : True } , ' yes ' ) ,
' if-tag-not23 ' : ( " { % i f not foo or bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : False } , ' no ' ) ,
' if-tag-not24 ' : ( " { % i f not foo or bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : True } , ' yes ' ) ,
' if-tag-not25 ' : ( " { % i f not foo or bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : False } , ' yes ' ) ,
' if-tag-not26 ' : ( " { % i f not foo and not bar % }yes { % e lse % }no { % e ndif % } " , { } , ' yes ' ) ,
' if-tag-not27 ' : ( " { % i f not foo and not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : True } , ' no ' ) ,
' if-tag-not28 ' : ( " { % i f not foo and not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : False } , ' no ' ) ,
' if-tag-not29 ' : ( " { % i f not foo and not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : True } , ' no ' ) ,
' if-tag-not30 ' : ( " { % i f not foo and not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : False } , ' yes ' ) ,
' if-tag-not31 ' : ( " { % i f not foo or not bar % }yes { % e lse % }no { % e ndif % } " , { } , ' yes ' ) ,
' if-tag-not32 ' : ( " { % i f not foo or not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : True } , ' no ' ) ,
' if-tag-not33 ' : ( " { % i f not foo or not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True , ' bar ' : False } , ' yes ' ) ,
' if-tag-not34 ' : ( " { % i f not foo or not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : True } , ' yes ' ) ,
' if-tag-not35 ' : ( " { % i f not foo or not bar % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : False } , ' yes ' ) ,
# AND and OR raises a TemplateSyntaxError
' if-tag-error01 ' : ( " { % i f foo or bar and baz % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : False , ' bar ' : False } , template . TemplateSyntaxError ) ,
' if-tag-error02 ' : ( " { % i f foo and % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True } , template . TemplateSyntaxError ) ,
' if-tag-error03 ' : ( " { % i f foo or % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True } , template . TemplateSyntaxError ) ,
' if-tag-error04 ' : ( " { % i f not foo and % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True } , template . TemplateSyntaxError ) ,
' if-tag-error05 ' : ( " { % i f not foo or % }yes { % e lse % }no { % e ndif % } " , { ' foo ' : True } , template . TemplateSyntaxError ) ,
2006-05-02 09:31:56 +08:00
### IFCHANGED TAG #########################################################
' ifchanged01 ' : ( ' { % f or n in num % } { % i fchanged % } {{ n }} { % e ndifchanged % } { % e ndfor % } ' , { ' num ' : ( 1 , 2 , 3 ) } , ' 123 ' ) ,
' ifchanged02 ' : ( ' { % f or n in num % } { % i fchanged % } {{ n }} { % e ndifchanged % } { % e ndfor % } ' , { ' num ' : ( 1 , 1 , 3 ) } , ' 13 ' ) ,
' ifchanged03 ' : ( ' { % f or n in num % } { % i fchanged % } {{ n }} { % e ndifchanged % } { % e ndfor % } ' , { ' num ' : ( 1 , 1 , 1 ) } , ' 1 ' ) ,
2005-08-30 05:11:41 +08:00
### IFEQUAL TAG ###########################################################
' ifequal01 ' : ( " { % i fequal a b % }yes { % e ndifequal % } " , { " a " : 1 , " b " : 2 } , " " ) ,
' ifequal02 ' : ( " { % i fequal a b % }yes { % e ndifequal % } " , { " a " : 1 , " b " : 1 } , " yes " ) ,
' ifequal03 ' : ( " { % i fequal a b % }yes { % e lse % }no { % e ndifequal % } " , { " a " : 1 , " b " : 2 } , " no " ) ,
' ifequal04 ' : ( " { % i fequal a b % }yes { % e lse % }no { % e ndifequal % } " , { " a " : 1 , " b " : 1 } , " yes " ) ,
2005-09-01 10:18:04 +08:00
' ifequal05 ' : ( " { % i fequal a ' test ' % }yes { % e lse % }no { % e ndifequal % } " , { " a " : " test " } , " yes " ) ,
' ifequal06 ' : ( " { % i fequal a ' test ' % }yes { % e lse % }no { % e ndifequal % } " , { " a " : " no " } , " no " ) ,
' ifequal07 ' : ( ' { % i fequal a " test " % }yes { % e lse % }no { % e ndifequal % } ' , { " a " : " test " } , " yes " ) ,
' ifequal08 ' : ( ' { % i fequal a " test " % }yes { % e lse % }no { % e ndifequal % } ' , { " a " : " no " } , " no " ) ,
' ifequal09 ' : ( ' { % i fequal a " test " % }yes { % e lse % }no { % e ndifequal % } ' , { } , " no " ) ,
' ifequal10 ' : ( ' { % i fequal a b % }yes { % e lse % }no { % e ndifequal % } ' , { } , " yes " ) ,
2005-08-30 05:11:41 +08:00
2006-06-08 12:29:10 +08:00
# SMART SPLITTING
' ifequal-split01 ' : ( ' { % i fequal a " test man " % }yes { % e lse % }no { % e ndifequal % } ' , { } , " no " ) ,
' ifequal-split02 ' : ( ' { % i fequal a " test man " % }yes { % e lse % }no { % e ndifequal % } ' , { ' a ' : ' foo ' } , " no " ) ,
' ifequal-split03 ' : ( ' { % i fequal a " test man " % }yes { % e lse % }no { % e ndifequal % } ' , { ' a ' : ' test man ' } , " yes " ) ,
' ifequal-split04 ' : ( " { % i fequal a ' test man ' % }yes { % e lse % }no { % e ndifequal % } " , { ' a ' : ' test man ' } , " yes " ) ,
' ifequal-split05 ' : ( " { % i fequal a ' i \" love \" you ' % }yes { % e lse % }no { % e ndifequal % } " , { ' a ' : ' ' } , " no " ) ,
' ifequal-split06 ' : ( " { % i fequal a ' i \" love \" you ' % }yes { % e lse % }no { % e ndifequal % } " , { ' a ' : ' i " love " you ' } , " yes " ) ,
' ifequal-split07 ' : ( " { % i fequal a ' i \" love \" you ' % }yes { % e lse % }no { % e ndifequal % } " , { ' a ' : ' i love you ' } , " no " ) ,
' ifequal-split08 ' : ( r " { % i fequal a ' I \ ' m happy ' % }yes { % e lse % }no { % e ndifequal % } " , { ' a ' : " I ' m happy " } , " yes " ) ,
' ifequal-split09 ' : ( r " { % i fequal a ' slash \ man ' % }yes { % e lse % }no { % e ndifequal % } " , { ' a ' : r " slash \ man " } , " yes " ) ,
' ifequal-split10 ' : ( r " { % i fequal a ' slash \ man ' % }yes { % e lse % }no { % e ndifequal % } " , { ' a ' : r " slashman " } , " no " ) ,
2005-08-30 05:11:41 +08:00
### IFNOTEQUAL TAG ########################################################
' ifnotequal01 ' : ( " { % i fnotequal a b % }yes { % e ndifnotequal % } " , { " a " : 1 , " b " : 2 } , " yes " ) ,
' ifnotequal02 ' : ( " { % i fnotequal a b % }yes { % e ndifnotequal % } " , { " a " : 1 , " b " : 1 } , " " ) ,
' ifnotequal03 ' : ( " { % i fnotequal a b % }yes { % e lse % }no { % e ndifnotequal % } " , { " a " : 1 , " b " : 2 } , " yes " ) ,
' ifnotequal04 ' : ( " { % i fnotequal a b % }yes { % e lse % }no { % e ndifnotequal % } " , { " a " : 1 , " b " : 1 } , " no " ) ,
2005-11-22 13:44:04 +08:00
### INCLUDE TAG ###########################################################
' include01 ' : ( ' { % i nclude " basic-syntax01 " % } ' , { } , " something cool " ) ,
' include02 ' : ( ' { % i nclude " basic-syntax02 " % } ' , { ' headline ' : ' Included ' } , " Included " ) ,
' include03 ' : ( ' { % i nclude template_name % } ' , { ' template_name ' : ' basic-syntax02 ' , ' headline ' : ' Included ' } , " Included " ) ,
' include04 ' : ( ' a { % i nclude " nonexistent " % }b ' , { } , " ab " ) ,
2005-08-30 05:11:41 +08:00
### INHERITANCE ###########################################################
2005-08-02 03:09:07 +08:00
# Standard template with no inheritance
' inheritance01 ' : ( " 1 { % block first % }_ { % e ndblock % }3 { % block second % }_ { % e ndblock % } " , { } , ' 1_3_ ' ) ,
# Standard two-level inheritance
' inheritance02 ' : ( " { % e xtends ' inheritance01 ' % } { % block first % }2 { % e ndblock % } { % block second % }4 { % e ndblock % } " , { } , ' 1234 ' ) ,
# Three-level with no redefinitions on third level
' inheritance03 ' : ( " { % e xtends ' inheritance02 ' % } " , { } , ' 1234 ' ) ,
# Two-level with no redefinitions on second level
' inheritance04 ' : ( " { % e xtends ' inheritance01 ' % } " , { } , ' 1_3_ ' ) ,
# Two-level with double quotes instead of single quotes
' inheritance05 ' : ( ' { % e xtends " inheritance02 " % } ' , { } , ' 1234 ' ) ,
# Three-level with variable parent-template name
' inheritance06 ' : ( " { % e xtends foo % } " , { ' foo ' : ' inheritance02 ' } , ' 1234 ' ) ,
# Two-level with one block defined, one block not defined
' inheritance07 ' : ( " { % e xtends ' inheritance01 ' % } { % block second % }5 { % e ndblock % } " , { } , ' 1_35 ' ) ,
# Three-level with one block defined on this level, two blocks defined next level
' inheritance08 ' : ( " { % e xtends ' inheritance02 ' % } { % block second % }5 { % e ndblock % } " , { } , ' 1235 ' ) ,
# Three-level with second and third levels blank
' inheritance09 ' : ( " { % e xtends ' inheritance04 ' % } " , { } , ' 1_3_ ' ) ,
# Three-level with space NOT in a block -- should be ignored
' inheritance10 ' : ( " { % e xtends ' inheritance04 ' % } " , { } , ' 1_3_ ' ) ,
# Three-level with both blocks defined on this level, but none on second level
' inheritance11 ' : ( " { % e xtends ' inheritance04 ' % } { % block first % }2 { % e ndblock % } { % block second % }4 { % e ndblock % } " , { } , ' 1234 ' ) ,
# Three-level with this level providing one and second level providing the other
' inheritance12 ' : ( " { % e xtends ' inheritance07 ' % } { % block first % }2 { % e ndblock % } " , { } , ' 1235 ' ) ,
# Three-level with this level overriding second level
' inheritance13 ' : ( " { % e xtends ' inheritance02 ' % } { % block first % }a { % e ndblock % } { % block second % }b { % e ndblock % } " , { } , ' 1a3b ' ) ,
# A block defined only in a child template shouldn't be displayed
' inheritance14 ' : ( " { % e xtends ' inheritance01 ' % } { % block newblock % }NO DISPLAY { % e ndblock % } " , { } , ' 1_3_ ' ) ,
# A block within another block
' inheritance15 ' : ( " { % e xtends ' inheritance01 ' % } { % block first % }2 { % block inner % }inner { % e ndblock % } { % e ndblock % } " , { } , ' 12inner3_ ' ) ,
# A block within another block (level 2)
' inheritance16 ' : ( " { % e xtends ' inheritance15 ' % } { % block inner % }out { % e ndblock % } " , { } , ' 12out3_ ' ) ,
# {% load %} tag (parent -- setup for exception04)
' inheritance17 ' : ( " { % lo ad testtags % } { % block first % }1234 { % e ndblock % } " , { } , ' 1234 ' ) ,
# {% load %} tag (standard usage, without inheritance)
' inheritance18 ' : ( " { % lo ad testtags % } { % e cho this that theother % }5678 " , { } , ' this that theother5678 ' ) ,
# {% load %} tag (within a child template)
' inheritance19 ' : ( " { % e xtends ' inheritance01 ' % } { % block first % } { % lo ad testtags % } { % e cho 400 % }5678 { % e ndblock % } " , { } , ' 140056783_ ' ) ,
2005-09-29 12:22:09 +08:00
# Two-level inheritance with {{ block.super }}
' inheritance20 ' : ( " { % e xtends ' inheritance01 ' % } { % block first % } {{ block.super }}a { % e ndblock % } " , { } , ' 1_a3_ ' ) ,
# Three-level inheritance with {{ block.super }} from parent
' inheritance21 ' : ( " { % e xtends ' inheritance02 ' % } { % block first % } {{ block.super }}a { % e ndblock % } " , { } , ' 12a34 ' ) ,
# Three-level inheritance with {{ block.super }} from grandparent
' inheritance22 ' : ( " { % e xtends ' inheritance04 ' % } { % block first % } {{ block.super }}a { % e ndblock % } " , { } , ' 1_a3_ ' ) ,
# Three-level inheritance with {{ block.super }} from parent and grandparent
' inheritance23 ' : ( " { % e xtends ' inheritance20 ' % } { % block first % } {{ block.super }}b { % e ndblock % } " , { } , ' 1_ab3_ ' ) ,
2006-05-02 09:31:56 +08:00
### I18N ##################################################################
2005-11-25 09:54:17 +08:00
2006-01-15 09:51:30 +08:00
# {% spaceless %} tag
2006-01-18 01:59:31 +08:00
' spaceless01 ' : ( " { % s paceless % } <b> <i> text </i> </b> { % e ndspaceless % } " , { } , " <b> <i> text </i> </b> " ) ,
' spaceless02 ' : ( " { % s paceless % } <b> \n <i> text </i> \n </b> { % e ndspaceless % } " , { } , " <b> <i> text </i> </b> " ) ,
2006-01-15 09:51:30 +08:00
' spaceless03 ' : ( " { % s paceless % }<b><i>text</i></b> { % e ndspaceless % } " , { } , " <b><i>text</i></b> " ) ,
2005-11-04 12:59:46 +08:00
# simple translation of a string delimited by '
' i18n01 ' : ( " { % lo ad i18n % } { % trans ' xxxyyyxxx ' % } " , { } , " xxxyyyxxx " ) ,
# simple translation of a string delimited by "
' i18n02 ' : ( ' { % lo ad i18n % } { % trans " xxxyyyxxx " % } ' , { } , " xxxyyyxxx " ) ,
# simple translation of a variable
' i18n03 ' : ( ' { % lo ad i18n % } { % blocktrans % } {{ anton }} { % e ndblocktrans % } ' , { ' anton ' : ' xxxyyyxxx ' } , " xxxyyyxxx " ) ,
# simple translation of a variable and filter
' i18n04 ' : ( ' { % lo ad i18n % } { % blocktrans with anton|lower as berta % } {{ berta }} { % e ndblocktrans % } ' , { ' anton ' : ' XXXYYYXXX ' } , " xxxyyyxxx " ) ,
# simple translation of a string with interpolation
' i18n05 ' : ( ' { % lo ad i18n % } { % blocktrans % }xxx {{ anton }}xxx { % e ndblocktrans % } ' , { ' anton ' : ' yyy ' } , " xxxyyyxxx " ) ,
# simple translation of a string to german
' i18n06 ' : ( ' { % lo ad i18n % } { % trans " Page not found " % } ' , { ' LANGUAGE_CODE ' : ' de ' } , " Seite nicht gefunden " ) ,
# translation of singular form
' i18n07 ' : ( ' { % lo ad i18n % } { % blocktrans count number as counter % }singular { % plural % }plural { % e ndblocktrans % } ' , { ' number ' : 1 } , " singular " ) ,
# translation of plural form
' i18n08 ' : ( ' { % lo ad i18n % } { % blocktrans count number as counter % }singular { % plural % }plural { % e ndblocktrans % } ' , { ' number ' : 2 } , " plural " ) ,
# simple non-translation (only marking) of a string to german
' i18n09 ' : ( ' { % lo ad i18n % } { % trans " Page not found " noop % } ' , { ' LANGUAGE_CODE ' : ' de ' } , " Page not found " ) ,
# translation of a variable with a translated filter
' i18n10 ' : ( ' {{ bool|yesno:_( " ja,nein " ) }} ' , { ' bool ' : True } , ' ja ' ) ,
# translation of a variable with a non-translated filter
' i18n11 ' : ( ' {{ bool|yesno: " ja,nein " }} ' , { ' bool ' : True } , ' ja ' ) ,
# usage of the get_available_languages tag
' i18n12 ' : ( ' { % lo ad i18n % } { % g et_available_languages as langs % } { % f or lang in langs % } { % i fequal lang.0 " de " % } {{ lang.0 }} { % e ndifequal % } { % e ndfor % } ' , { } , ' de ' ) ,
# translation of a constant string
' i18n13 ' : ( ' {{ _( " Page not found " ) }} ' , { ' LANGUAGE_CODE ' : ' de ' } , ' Seite nicht gefunden ' ) ,
2006-05-02 09:31:56 +08:00
### MULTILINE #############################################################
' multiline01 ' : ( """
Hello ,
boys .
How
are
you
gentlemen .
""" ,
{ } ,
"""
Hello ,
boys .
How
are
you
gentlemen .
""" ),
### REGROUP TAG ###########################################################
' regroup01 ' : ( ' { % r egroup data by bar as grouped % } ' + \
' { % f or group in grouped % } ' + \
' {{ group.grouper }}: ' + \
' { % f or item in group.list % } ' + \
' {{ item.foo }} ' + \
' { % e ndfor % }, ' + \
' { % e ndfor % } ' ,
{ ' data ' : [ { ' foo ' : ' c ' , ' bar ' : 1 } ,
{ ' foo ' : ' d ' , ' bar ' : 1 } ,
{ ' foo ' : ' a ' , ' bar ' : 2 } ,
{ ' foo ' : ' b ' , ' bar ' : 2 } ,
{ ' foo ' : ' x ' , ' bar ' : 3 } ] } ,
' 1:cd,2:ab,3:x, ' ) ,
# Test for silent failure when target variable isn't found
' regroup02 ' : ( ' { % r egroup data by bar as grouped % } ' + \
' { % f or group in grouped % } ' + \
' {{ group.grouper }}: ' + \
' { % f or item in group.list % } ' + \
' {{ item.foo }} ' + \
' { % e ndfor % }, ' + \
' { % e ndfor % } ' ,
{ } , ' ' ) ,
### TEMPLATETAG TAG #######################################################
' templatetag01 ' : ( ' { % templatetag openblock % } ' , { } , ' { % ' ) ,
' templatetag02 ' : ( ' { % templatetag closeblock % } ' , { } , ' % } ' ) ,
' templatetag03 ' : ( ' { % templatetag openvariable % } ' , { } , ' {{ ' ) ,
' templatetag04 ' : ( ' { % templatetag closevariable % } ' , { } , ' }} ' ) ,
' templatetag05 ' : ( ' { % templatetag % } ' , { } , template . TemplateSyntaxError ) ,
' templatetag06 ' : ( ' { % templatetag foo % } ' , { } , template . TemplateSyntaxError ) ,
### WIDTHRATIO TAG ########################################################
' widthratio01 ' : ( ' { % widthratio a b 0 % } ' , { ' a ' : 50 , ' b ' : 100 } , ' 0 ' ) ,
' widthratio02 ' : ( ' { % widthratio a b 100 % } ' , { ' a ' : 0 , ' b ' : 0 } , ' ' ) ,
' widthratio03 ' : ( ' { % widthratio a b 100 % } ' , { ' a ' : 0 , ' b ' : 100 } , ' 0 ' ) ,
' widthratio04 ' : ( ' { % widthratio a b 100 % } ' , { ' a ' : 50 , ' b ' : 100 } , ' 50 ' ) ,
' widthratio05 ' : ( ' { % widthratio a b 100 % } ' , { ' a ' : 100 , ' b ' : 100 } , ' 100 ' ) ,
# 62.5 should round to 63
' widthratio06 ' : ( ' { % widthratio a b 100 % } ' , { ' a ' : 50 , ' b ' : 80 } , ' 63 ' ) ,
# 71.4 should round to 71
' widthratio07 ' : ( ' { % widthratio a b 100 % } ' , { ' a ' : 50 , ' b ' : 70 } , ' 71 ' ) ,
# Raise exception if we don't have 3 args, last one an integer
' widthratio08 ' : ( ' { % widthratio % } ' , { } , template . TemplateSyntaxError ) ,
' widthratio09 ' : ( ' { % widthratio a b % } ' , { ' a ' : 50 , ' b ' : 100 } , template . TemplateSyntaxError ) ,
' widthratio10 ' : ( ' { % widthratio a b 100.0 % } ' , { ' a ' : 50 , ' b ' : 100 } , template . TemplateSyntaxError ) ,
2006-06-08 11:33:21 +08:00
2006-05-02 09:31:56 +08:00
### NOW TAG ########################################################
# Simple case
' now01 ' : ( ' { % now " j n Y " % } ' , { } , str ( datetime . now ( ) . day ) + ' ' + str ( datetime . now ( ) . month ) + ' ' + str ( datetime . now ( ) . year ) ) ,
2006-06-08 11:33:21 +08:00
2006-05-02 09:31:56 +08:00
# Check parsing of escaped and special characters
' now02 ' : ( ' { % now " j " n " Y " % } ' , { } , template . TemplateSyntaxError ) ,
# 'now03' : ('{% now "j \"n\" Y"%}', {}, str(datetime.now().day) + '"' + str(datetime.now().month) + '"' + str(datetime.now().year)),
# 'now04' : ('{% now "j \nn\n Y"%}', {}, str(datetime.now().day) + '\n' + str(datetime.now().month) + '\n' + str(datetime.now().year))
2005-08-02 03:09:07 +08:00
}
def test_template_loader ( template_name , template_dirs = None ) :
2005-10-15 06:28:38 +08:00
" A custom template loader that loads the unit-test templates. "
2005-08-02 03:09:07 +08:00
try :
2005-11-27 06:46:31 +08:00
return ( TEMPLATE_TESTS [ template_name ] [ 0 ] , " test: %s " % template_name )
2005-08-02 03:09:07 +08:00
except KeyError :
raise template . TemplateDoesNotExist , template_name
def run_tests ( verbosity = 0 , standalone = False ) :
2005-10-15 06:28:38 +08:00
# Register our custom template loader.
old_template_loaders = loader . template_source_loaders
loader . template_source_loaders = [ test_template_loader ]
2005-08-02 03:09:07 +08:00
failed_tests = [ ]
tests = TEMPLATE_TESTS . items ( )
tests . sort ( )
2006-05-02 09:31:56 +08:00
# Turn TEMPLATE_DEBUG off, because tests assume that.
old_td , settings . TEMPLATE_DEBUG = settings . TEMPLATE_DEBUG , False
2005-08-02 03:09:07 +08:00
for name , vals in tests :
2005-11-17 23:55:04 +08:00
install ( )
2005-11-04 12:59:46 +08:00
if ' LANGUAGE_CODE ' in vals [ 1 ] :
activate ( vals [ 1 ] [ ' LANGUAGE_CODE ' ] )
2005-11-17 23:55:04 +08:00
else :
activate ( ' en-us ' )
2005-08-02 03:09:07 +08:00
try :
2005-10-15 04:10:13 +08:00
output = loader . get_template ( name ) . render ( template . Context ( vals [ 1 ] ) )
2005-08-02 03:09:07 +08:00
except Exception , e :
if e . __class__ == vals [ 2 ] :
if verbosity :
print " Template test: %s -- Passed " % name
else :
if verbosity :
2005-11-17 23:55:04 +08:00
traceback . print_exc ( )
2005-08-02 03:09:07 +08:00
print " Template test: %s -- FAILED. Got %s , exception: %s " % ( name , e . __class__ , e )
failed_tests . append ( name )
continue
2005-11-04 12:59:46 +08:00
if ' LANGUAGE_CODE ' in vals [ 1 ] :
deactivate ( )
2005-08-02 03:09:07 +08:00
if output == vals [ 2 ] :
if verbosity :
print " Template test: %s -- Passed " % name
else :
if verbosity :
print " Template test: %s -- FAILED. Expected %r , got %r " % ( name , vals [ 2 ] , output )
failed_tests . append ( name )
2005-10-15 06:28:38 +08:00
loader . template_source_loaders = old_template_loaders
2005-11-24 07:10:17 +08:00
deactivate ( )
2006-05-02 09:31:56 +08:00
settings . TEMPLATE_DEBUG = old_td
2005-08-02 03:09:07 +08:00
if failed_tests and not standalone :
msg = " Template tests %s failed. " % failed_tests
if not verbosity :
msg + = " Re-run tests with -v1 to see actual failures "
raise Exception , msg
2005-08-30 05:11:41 +08:00
2005-08-02 03:09:07 +08:00
if __name__ == " __main__ " :
2006-05-17 05:28:06 +08:00
settings . configure ( )
2005-08-02 03:09:07 +08:00
run_tests ( 1 , True )