8885c1683a0af180092577ed1ba83fe88480b2d8
[django-pagination.git] / fnp_django_pagination / tests / test_main.py
1 # Copyright (c) 2008, Eric Florenzano
2 # Copyright (c) 2010, 2011 Linaro Limited
3 # All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met:
8 #
9 #     * Redistributions of source code must retain the above copyright
10 #       notice, this list of conditions and the following disclaimer.
11 #     * Redistributions in binary form must reproduce the above
12 #       copyright notice, this list of conditions and the following
13 #       disclaimer in the documentation and/or other materials provided
14 #       with the distribution.
15 #     * Neither the name of the author nor the names of other
16 #       contributors may be used to endorse or promote products derived
17 #       from this software without specific prior written permission.
18 #
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 from django.core.paginator import Paginator
32 from django.http import HttpRequest as DjangoHttpRequest
33 from django.template import Template, Context
34
35 try:
36     from django.test import SimpleTestCase
37 except ImportError:  # Django 1.2 compatible
38     from django.test import TestCase as SimpleTestCase
39
40 from fnp_django_pagination.paginator import InfinitePaginator, FinitePaginator
41 from fnp_django_pagination.templatetags.pagination_tags import paginate
42 from fnp_django_pagination.middleware import PaginationMiddleware
43
44
45 class HttpRequest(DjangoHttpRequest):
46      page = lambda self, suffix: 1
47
48
49 class CommonTestCase(SimpleTestCase):
50     def test_records_for_the_first_page(self):
51         p = Paginator(range(15), 2)
52         pg = paginate({'paginator': p, 'page_obj': p.page(1)})
53         self.assertListEqual(pg['pages'], [1, 2, 3, 4, 5, 6, 7, 8])
54         self.assertEqual(pg['records']['first'], 1)
55         self.assertEqual(pg['records']['last'], 2)
56
57     def test_records_for_the_last_page(self):
58         p = Paginator(range(15), 2)
59         pg = paginate({'paginator': p, 'page_obj': p.page(8)})
60         self.assertListEqual(pg['pages'], [1, 2, 3, 4, 5, 6, 7, 8])
61         self.assertEqual(pg['records']['first'], 15)
62         self.assertEqual(pg['records']['last'], 15)
63
64     def test_pages_list(self):
65         p = Paginator(range(17), 2)
66         self.assertEqual(paginate({'paginator': p, 'page_obj': p.page(1)})['pages'], [1, 2, 3, 4, 5, 6, 7, 8, 9])
67
68     def test_page_with_empty_objects_list(self):
69         p = Paginator(range(0), 2)
70         self.assertListEqual(paginate({'paginator': p, 'page_obj': p.page(1)})['pages'], [1])
71
72
73 class DefaultWindowTestCase(SimpleTestCase):
74     """
75     Test paginate using default window setting
76     moving the window from 1 ... to end
77     window size = 2, margin = 2
78     window = 2 -> show 5 pages
79     """
80     def setUp(self):
81         self.p = Paginator(range(31), 2)
82
83     def test_on_start_page_1(self):
84         # [1] 2 3 4 5 ... 15, 16
85         self.assertListEqual(
86             paginate({'paginator': self.p, 'page_obj': self.p.page(1)}, 2, 2)['pages'],
87             [1, 2, 3, 4, 5, None, 15, 16]
88         )
89
90     def test_on_start_page_2(self):
91         # 1 [2] 3 4 5 ... 15, 16
92         self.assertListEqual(
93             paginate({'paginator': self.p, 'page_obj': self.p.page(2)}, 2, 2)['pages'],
94             [1, 2, 3, 4, 5, None, 15, 16]
95         )
96
97     def test_on_start_page_3(self):
98         # 1 2 [3] 4 5 ... 15, 16
99         self.assertListEqual(
100             paginate({'paginator': self.p, 'page_obj': self.p.page(3)}, 2, 2)['pages'],
101             [1, 2, 3, 4, 5, None, 15, 16]
102         )
103
104     def test_on_start_page_4(self):
105         # 1 2 3 [4] 5 6 ... 15, 16
106         self.assertListEqual(
107             paginate({'paginator': self.p, 'page_obj': self.p.page(4)}, 2, 2)['pages'],
108             [1, 2, 3, 4, 5, 6, None, 15, 16])
109
110     def test_on_start_page_5(self):
111         # 1 2 3 4 [5] 6 7 ... 15, 16
112         self.assertListEqual(
113             paginate({'paginator': self.p, 'page_obj': self.p.page(5)}, 2, 2)['pages'],
114             [1, 2, 3, 4, 5, 6, 7, None, 15, 16]
115         )
116
117     def test_in_middle(self):
118         # 1 2 ... 5 6 [7] 8 9 ... 15, 16
119         self.assertListEqual(
120             paginate({'paginator': self.p, 'page_obj': self.p.page(7)}, 2, 2)['pages'],
121             [1, 2, None, 5, 6, 7, 8, 9, None, 15, 16]
122         )
123
124     def test_on_end_page_13(self):
125         # 1 2 ... 12 [13] 14 15 16
126         self.assertListEqual(
127             paginate({'paginator': self.p, 'page_obj': self.p.page(13)}, 2, 2)['pages'],
128             [1, 2, None, 11, 12, 13, 14, 15, 16],
129         )
130
131     def test_on_end(self):
132         # 1 2 ... 12 13 14 15 [16
133         self.assertListEqual(
134             paginate({'paginator': self.p, 'page_obj': self.p.page(16)}, 2, 2)['pages'],
135             [1, 2, None, 12, 13, 14, 15, 16]
136         )
137
138
139 class NoMarginTestCase(SimpleTestCase):
140     def setUp(self):
141         self.p = Paginator(range(31), 2)
142
143     def test_on_start(self):
144         self.assertListEqual(
145             paginate({'paginator': self.p, 'page_obj': self.p.page(3)}, 2, 0)['pages'],
146             [1, 2, 3, 4, 5, None],
147         )
148
149     def test_in_middle(self):
150         self.assertListEqual(
151             paginate({'paginator': self.p, 'page_obj': self.p.page(5)}, 2, 0)['pages'],
152             [None, 3, 4, 5, 6, 7, None],
153         )
154
155     def test_on_end(self):
156         self.assertListEqual(
157             paginate({'paginator': self.p, 'page_obj': self.p.page(16)}, 2, 0)['pages'],
158             [None, 12, 13, 14, 15, 16],
159         )
160
161
162 class ZeroWindowZeroMarginTestCase(SimpleTestCase):
163     """
164     Test paginate using window=0 and margin=0
165     """
166     def setUp(self):
167         self.p = Paginator(range(31), 2)
168
169     def test_on_start_page_1(self):
170         self.assertListEqual(
171             paginate({'paginator': self.p, 'page_obj': self.p.page(1)}, 0, 0)['pages'],
172             [1, None],
173         )
174
175     def test_in_middle_page_2(self):
176         self.assertListEqual(
177             paginate({'paginator': self.p, 'page_obj': self.p.page(2)}, 0, 0)['pages'],
178             [None, 2, None],
179         )
180
181     def test_in_middle_page_3(self):
182         self.assertListEqual(
183             paginate({'paginator': self.p, 'page_obj': self.p.page(3)}, 0, 0)['pages'],
184             [None, 3, None],
185         )
186
187     def test_in_middle_page_10(self):
188         self.assertListEqual(
189             paginate({'paginator': self.p, 'page_obj': self.p.page(10)}, 0, 0)['pages'],
190             [None, 10, None],
191         )
192
193     def test_in_middle_page_14(self):
194         self.assertListEqual(
195             paginate({'paginator': self.p, 'page_obj': self.p.page(14)}, 0, 0)['pages'],
196             [None, 14, None],
197         )
198
199     def test_in_middle_page_15(self):
200         self.assertListEqual(
201             paginate({'paginator': self.p, 'page_obj': self.p.page(15)}, 0, 0)['pages'],
202             [None, 15, None],
203         )
204
205     def test_on_end_page_16(self):
206         self.assertListEqual(
207             paginate({'paginator': self.p, 'page_obj': self.p.page(16)}, 0, 0)['pages'],
208             [None, 16],
209         )
210
211
212 class NoEllipsisTestCase(SimpleTestCase):
213     """
214     Tests a case where should be no any ellipsis pages.
215     """
216     def setUp(self):
217         self.p = Paginator(range(100), 25)
218
219     def test_on_start(self):
220         self.assertListEqual(
221             paginate({'paginator': self.p, 'page_obj': self.p.page(1)}, 2, 0)['pages'],
222             [1, 2, 3, 4],
223         )
224
225     def test_in_middle_page_2(self):
226         self.assertListEqual(
227             paginate({'paginator': self.p, 'page_obj': self.p.page(2)}, 2, 0)['pages'],
228             [1, 2, 3, 4],
229         )
230
231     def test_in_middle_page_3(self):
232         self.assertListEqual(
233             paginate({'paginator': self.p, 'page_obj': self.p.page(3)}, 2, 0)['pages'],
234             [1, 2, 3, 4],
235         )
236
237     def test_on_end(self):
238         self.assertListEqual(
239             paginate({'paginator': self.p, 'page_obj': self.p.page(4)}, 2, 0)['pages'],
240             [1, 2, 3, 4],
241         )
242
243
244 class SpecialTestCase(SimpleTestCase):
245     def test_middle_with_no_window_and_margin_1(self):
246         p = Paginator(range(31), 2)
247         self.assertListEqual(
248             paginate({'paginator': p, 'page_obj': p.page(5)}, 0, 1)['pages'],
249             [1, None, 5, None, 16],
250         )
251
252     def test_middle_with_no_window_and_margin_4(self):
253         p = Paginator(range(21), 2, 1)
254         self.assertListEqual(
255             paginate({'paginator': p, 'page_obj': p.page(1)}, 0, 4)['pages'],
256             [1, 2, 3, 4, None, 7, 8, 9, 10],
257         )
258
259
260 class TemplateRenderingTestCase(SimpleTestCase):
261     def test_default_tag_options(self):
262         t = Template("{% load pagination_tags %}{% autopaginate var %}{% paginate %}")
263         self.assertIn(
264             '<div class="pagination">',
265             t.render(Context({'var': range(21), 'request': HttpRequest()})),
266         )
267
268     def test_paginate_by_option(self):
269         t = Template("{% load pagination_tags %}{% autopaginate var 20 %}{% paginate %}")
270         self.assertIn(
271             '<div class="pagination">',
272             t.render(Context({'var': range(21), 'request': HttpRequest()})),
273         )
274
275     def test_orphans_option(self):
276         t = Template("{% load pagination_tags %}{% autopaginate var by %}{% paginate %}")
277         content = t.render(Context({'var': range(21), 'by': 20, 'request': HttpRequest()}))
278         self.assertIn('<div class="pagination">', content)
279         self.assertIn('<a href="?page=2"', content)
280
281     def test_as_option(self):
282         t = Template("{% load pagination_tags %}{% autopaginate var by as foo %}{{ foo }}")
283         self.assertEqual(
284             t.render(Context({'var': range(21), 'by': 20, 'request': HttpRequest()})),
285             str(range(20)),
286         )
287
288     def test_multiple_pagination(self):
289         t = Template("{% load pagination_tags %}{% autopaginate var2 by as foo2 %}{% paginate %}"
290                      "{% autopaginate var by as foo %}{% paginate %}")
291         content = t.render(Context({'var': range(21), 'var2': range(50, 121), 'by': 20, 'request': HttpRequest()}))
292         self.assertIn('<div class="pagination">', content)
293         self.assertIn('<a href="?page_var2=2"', content)
294         self.assertIn('<a href="?page_var=2"', content)
295
296
297 class InfinitePaginatorTestCase(SimpleTestCase):
298     def setUp(self):
299         self.p = InfinitePaginator(range(20), 2, link_template='/bacon/page/%d')
300
301     def test_paginator_repr(self):
302         self.assertEqual(
303             repr(InfinitePaginator),
304             "<class 'fnp_django_pagination.paginator.InfinitePaginator'>",
305         )
306
307     def test_validate_number(self):
308         self.assertEqual(self.p.validate_number(2), 2)
309
310     def test_orphans(self):
311         self.assertEqual(self.p.orphans, 0)
312
313     def test_page_repr(self):
314         self.assertEqual(repr(self.p.page(3)), '<Page 3>')
315
316     def test_page_end_index(self):
317         self.assertEqual(self.p.page(3).end_index(), 6)
318
319     def test_page_has_next(self):
320         self.assertTrue(self.p.page(3).has_next(), True)
321
322     def test_page_has_previous(self):
323         self.assertTrue(self.p.page(3).has_previous(), True)
324
325     def test_page_next_link(self):
326         self.assertEqual(self.p.page(3).next_link(), '/bacon/page/4')
327
328     def test_page_previous_link(self):
329         self.assertEqual(self.p.page(3).previous_link(), '/bacon/page/2')
330
331     def test_last_page_which_has_no_next_page(self):
332         self.assertFalse(self.p.page(10).has_next())
333
334     def test_first_page_which_has_no_previous_page(self):
335         self.assertFalse(self.p.page(1).has_previous())
336
337
338 class FinitePaginatorTestCase(SimpleTestCase):
339     def setUp(self):
340         self.p = FinitePaginator(range(20), 2, offset=10, link_template='/bacon/page/%d')
341
342     def test_repr(self):
343         self.assertEqual(
344             repr(FinitePaginator),
345             "<class 'fnp_django_pagination.paginator.FinitePaginator'>"
346         )
347
348     def test_validate_number(self):
349         self.assertEqual(self.p.validate_number(2), 2)
350
351     def test_orphans(self):
352         self.assertEqual(self.p.orphans, 0)
353
354     def test_page_repr(self):
355         self.assertEqual(repr(self.p.page(3)), '<Page 3>')
356
357     def test_page_start_index(self):
358         self.assertEqual(self.p.page(3).start_index(), 10)
359
360     def test_page_end(self):
361         self.assertEqual(self.p.page(3).end_index(), 6)
362
363     def test_page_has_next(self):
364         self.assertTrue(self.p.page(3).has_next(), True)
365
366     def test_page_has_previous(self):
367         self.assertTrue(self.p.page(3).has_previous(), True)
368
369     def test_page_next_link(self):
370         self.assertEqual(self.p.page(3).next_link(), '/bacon/page/4')
371
372     def test_page_previous_link(self):
373         self.assertEqual(self.p.page(3).previous_link(), '/bacon/page/2')
374
375     def test_on_start_page_repr(self):
376         self.assertEqual(repr(self.p.page(2)), '<Page 2>')
377
378     def test_on_start_has_no_next(self):
379         self.assertTrue(self.p.page(2).has_next(), False)
380
381     def test_on_start_has_previous(self):
382         self.assertTrue(self.p.page(2).has_previous(), True)
383
384     def test_on_start_has_next_link(self):
385         self.assertEqual(self.p.page(2).next_link(), '/bacon/page/3')
386
387     def test_on_start_has_previous_link(self):
388         self.assertEqual(self.p.page(2).previous_link(), '/bacon/page/1')
389
390
391 class MiddlewareTestCase(SimpleTestCase):
392     """
393     Test middleware
394     """
395     def test_get_page_in_request(self):
396         middleware = PaginationMiddleware()
397         request = DjangoHttpRequest()
398         middleware.process_request(request)
399         self.assertEqual(request.page(''), 1)