Rendered tables now include empty_text
[django-tables2.git] / tests / templates.py
1 # -*- coding: utf8 -*-
2 """Test template specific functionality.
3
4 Make sure tables expose their functionality to templates right. This
5 generally about testing "out"-functionality of the tables, whether
6 via templates or otherwise. Whether a test belongs here or, say, in
7 ``test_basic``, is not always a clear-cut decision.
8 """
9
10 from django.template import Template, Context
11 from django.http import HttpRequest
12 import django_tables as tables
13 from attest import Tests, Assert
14 from xml.etree import ElementTree as ET
15
16 templates = Tests()
17
18
19 @templates.context
20 def context():
21     class Context(object):
22         class CountryTable(tables.Table):
23             name = tables.Column()
24             capital = tables.Column(sortable=False)
25             population = tables.Column(verbose_name='Population Size')
26             currency = tables.Column(visible=False)
27             tld = tables.Column(visible=False, verbose_name='Domain')
28             calling_code = tables.Column(accessor='cc',
29                                          verbose_name='Phone Ext.')
30
31         data = [
32             {'name': 'Germany', 'capital': 'Berlin', 'population': 83,
33              'currency': 'Euro (€)', 'tld': 'de', 'cc': 49},
34             {'name': 'France', 'population': 64, 'currency': 'Euro (€)',
35              'tld': 'fr', 'cc': 33},
36             {'name': 'Netherlands', 'capital': 'Amsterdam', 'cc': '31'},
37             {'name': 'Austria', 'cc': 43, 'currency': 'Euro (€)',
38              'population': 8}
39         ]
40     yield Context
41
42
43 @templates.test
44 def as_html(context):
45     table = context.CountryTable(context.data)
46     root = ET.fromstring(table.as_html())    
47     Assert(len(root.findall('.//thead/tr'))) == 1
48     Assert(len(root.findall('.//thead/tr/th'))) == 4
49     Assert(len(root.findall('.//tbody/tr'))) == 4
50     Assert(len(root.findall('.//tbody/tr/td'))) == 16
51     
52     # no data with no empty_text
53     table = context.CountryTable([])
54     root = ET.fromstring(table.as_html())
55     Assert(1) == len(root.findall('.//thead/tr'))
56     Assert(4) == len(root.findall('.//thead/tr/th'))
57     Assert(0) == len(root.findall('.//tbody/tr'))
58     
59     # no data WITH empty_text
60     table = context.CountryTable([], empty_text='this table is empty')
61     root = ET.fromstring(table.as_html())
62     Assert(1) == len(root.findall('.//thead/tr'))
63     Assert(4) == len(root.findall('.//thead/tr/th'))
64     Assert(1) == len(root.findall('.//tbody/tr'))
65     Assert(1) == len(root.findall('.//tbody/tr/td'))
66     Assert(int(root.find('.//tbody/tr/td').attrib['colspan'])) == len(root.findall('.//thead/tr/th'))
67     Assert(root.find('.//tbody/tr/td').text) == 'this table is empty'
68
69
70 @templates.test
71 def custom_rendering(context):
72     """For good measure, render some actual templates."""
73     countries = context.CountryTable(context.data)
74     context = Context({'countries': countries})
75
76     # automatic and manual column verbose names
77     template = Template('{% for column in countries.columns %}{{ column }}/'
78                         '{{ column.name }} {% endfor %}')
79     result = ('Name/name Capital/capital Population Size/population '
80               'Phone Ext./calling_code ')
81     Assert(result) == template.render(context)
82
83     # row values
84     template = Template('{% for row in countries.rows %}{% for value in row %}'
85                         '{{ value }} {% endfor %}{% endfor %}')
86     result = ('Germany Berlin 83 49 France None 64 33 Netherlands Amsterdam '
87               'None 31 Austria None 8 43 ')
88     Assert(result) == template.render(context)
89
90
91 @templates.test
92 def templatetag(context):
93     # ensure it works with a multi-order-by
94     table = context.CountryTable(context.data, order_by=('name', 'population'))
95     t = Template('{% load django_tables %}{% render_table table %}')
96     html = t.render(Context({'request': HttpRequest(), 'table': table}))
97     
98     root = ET.fromstring(html)    
99     Assert(len(root.findall('.//thead/tr'))) == 1
100     Assert(len(root.findall('.//thead/tr/th'))) == 4
101     Assert(len(root.findall('.//tbody/tr'))) == 4
102     Assert(len(root.findall('.//tbody/tr/td'))) == 16
103     
104     # no data with no empty_text
105     table = context.CountryTable([])
106     t = Template('{% load django_tables %}{% render_table table %}')
107     html = t.render(Context({'request': HttpRequest(), 'table': table}))
108     root = ET.fromstring(html)    
109     Assert(len(root.findall('.//thead/tr'))) == 1
110     Assert(len(root.findall('.//thead/tr/th'))) == 4
111     Assert(len(root.findall('.//tbody/tr'))) == 0
112     
113     # no data WITH empty_text
114     table = context.CountryTable([], empty_text='this table is empty')
115     t = Template('{% load django_tables %}{% render_table table %}')
116     html = t.render(Context({'request': HttpRequest(), 'table': table}))
117     root = ET.fromstring(html)    
118     Assert(len(root.findall('.//thead/tr'))) == 1
119     Assert(len(root.findall('.//thead/tr/th'))) == 4
120     Assert(len(root.findall('.//tbody/tr'))) == 1
121     Assert(len(root.findall('.//tbody/tr/td'))) == 1
122     Assert(int(root.find('.//tbody/tr/td').attrib['colspan'])) == len(root.findall('.//thead/tr/th'))
123     Assert(root.find('.//tbody/tr/td').text) == 'this table is empty'
124     
125     
126