mostly done, just need to add empty_text functionality, and sortable
[django-tables2.git] / tests / core.py
1 """Test the core table functionality."""
2 import copy
3 from attest import Tests, Assert
4 from django.http import Http404
5 from django.core.paginator import Paginator
6 import django_tables as tables
7 from django_tables import utils
8
9 core = Tests()
10
11
12 @core.context
13 def context():
14     class Context(object):
15         memory_data = [
16             {'i': 2, 'alpha': 'b', 'beta': 'b'},
17             {'i': 1, 'alpha': 'a', 'beta': 'c'},
18             {'i': 3, 'alpha': 'c', 'beta': 'a'},
19         ]
20
21         class UnsortedTable(tables.Table):
22             i = tables.Column()
23             alpha = tables.Column()
24             beta = tables.Column()
25
26         class SortedTable(UnsortedTable):
27             class Meta:
28                 order_by = 'alpha'
29
30         table = UnsortedTable(memory_data)
31
32     yield Context
33
34
35 @core.test
36 def declarations(context):
37     """Test defining tables by declaration."""
38     class GeoAreaTable(tables.Table):
39         name = tables.Column()
40         population = tables.Column()
41
42     assert len(GeoAreaTable.base_columns) == 2
43     assert 'name' in GeoAreaTable.base_columns
44     assert not hasattr(GeoAreaTable, 'name')
45
46     class CountryTable(GeoAreaTable):
47         capital = tables.Column()
48
49     assert len(CountryTable.base_columns) == 3
50     assert 'capital' in CountryTable.base_columns
51
52     # multiple inheritance
53     class AddedMixin(tables.Table):
54         added = tables.Column()
55
56     class CityTable(GeoAreaTable, AddedMixin):
57         mayor = tables.Column()
58
59     assert len(CityTable.base_columns) == 4
60     assert 'added' in CityTable.base_columns
61
62
63 @core.test
64 def datasource_untouched(context):
65     """Ensure that data that is provided to the table (the datasource) is not
66     modified by table operations.
67     """
68     original_data = copy.deepcopy(context.memory_data)
69
70     table = context.UnsortedTable(context.memory_data)
71     table.order_by = 'i'
72     list(table.rows)
73     assert context.memory_data == Assert(original_data)
74
75     table = context.UnsortedTable(context.memory_data)
76     table.order_by = 'beta'
77     list(table.rows)
78     assert context.memory_data == Assert(original_data)
79
80
81 @core.test
82 def sorting(ctx):
83     # fallback to Table.Meta
84     Assert(('alpha', )) == ctx.SortedTable([], order_by=None).order_by == ctx.SortedTable([]).order_by
85
86     # values of order_by are wrapped in tuples before being returned
87     Assert(ctx.SortedTable([], order_by='alpha').order_by)   == ('alpha', )
88     Assert(ctx.SortedTable([], order_by=('beta',)).order_by) == ('beta', )
89
90     # "no sorting"
91     table = ctx.SortedTable([])
92     table.order_by = []
93     Assert(()) == table.order_by == ctx.SortedTable([], order_by=[]).order_by
94
95     table = ctx.SortedTable([])
96     table.order_by = ()
97     Assert(()) == table.order_by == ctx.SortedTable([], order_by=()).order_by
98
99     table = ctx.SortedTable([])
100     table.order_by = ''
101     Assert(()) == table.order_by == ctx.SortedTable([], order_by='').order_by
102
103     # apply a sorting
104     table = ctx.UnsortedTable([])
105     table.order_by = 'alpha'
106     Assert(('alpha', )) == ctx.UnsortedTable([], order_by='alpha').order_by == table.order_by
107
108     table = ctx.SortedTable([])
109     table.order_by = 'alpha'
110     Assert(('alpha', )) == ctx.SortedTable([], order_by='alpha').order_by  == table.order_by
111
112     # let's check the data
113     table = ctx.SortedTable(ctx.memory_data, order_by='beta')
114     Assert(3) == table.rows[0]['i']
115
116     # allow fallback to Table.Meta.order_by
117     table = ctx.SortedTable(ctx.memory_data)
118     Assert(1) == table.rows[0]['i']
119
120
121 @core.test
122 def column_count(context):
123     class SimpleTable(tables.Table):
124         visible = tables.Column(visible=True)
125         hidden = tables.Column(visible=False)
126
127     # The columns container supports the len() builtin
128     assert len(SimpleTable([]).columns) == 1
129
130
131 @core.test
132 def column_accessor(context):
133     class SimpleTable(context.UnsortedTable):
134         col1 = tables.Column(accessor='alpha.upper.isupper')
135         col2 = tables.Column(accessor='alpha.upper')
136     table = SimpleTable(context.memory_data)
137     row = table.rows[0]
138     Assert(row['col1']) is True
139     Assert(row['col2']) == 'B'
140
141
142 @core.test
143 def pagination():
144     class BookTable(tables.Table):
145         name = tables.Column()
146
147     # create some sample data
148     data = []
149     for i in range(100):
150         data.append({'name': 'Book No. %d' % i})
151     books = BookTable(data)
152
153     # external paginator
154     paginator = Paginator(books.rows, 10)
155     assert paginator.num_pages == 10
156     page = paginator.page(1)
157     assert page.has_previous() is False
158     assert page.has_next() is True
159
160     # integrated paginator
161     books.paginate(page=1)
162     Assert(hasattr(books, 'page')) is True
163
164     books.paginate(page=1, per_page=10)
165     Assert(len(list(books.page.object_list))) == 10
166
167     # new attributes
168     Assert(books.paginator.num_pages) == 10
169     Assert(books.page.has_previous()) is False
170     Assert(books.page.has_next()) is True
171
172     # exceptions are converted into 404s
173     with Assert.raises(Http404) as error:
174         books.paginate(Paginator, page=9999, per_page=10)
175         books.paginate(Paginator, page='abc', per_page=10)