1 # Copyright (c) 2008, Eric Florenzano
2 # Copyright (c) 2010, 2011 Linaro Limited
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
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.
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.
31 from django.core.paginator import Paginator
32 from django.http import HttpRequest as DjangoHttpRequest
33 from django.template import Template, Context
34 from django.test import SimpleTestCase
35 from fnp_django_pagination.paginator import InfinitePaginator, FinitePaginator
36 from fnp_django_pagination.templatetags.pagination_tags import paginate
37 from fnp_django_pagination.middleware import PaginationMiddleware
40 class HttpRequest(DjangoHttpRequest):
41 page = lambda self, suffix: 1
44 class CommonTestCase(SimpleTestCase):
45 def test_records_for_the_first_page(self):
46 p = Paginator(range(15), 2)
47 pg = paginate({'paginator': p, 'page_obj': p.page(1)})
48 self.assertListEqual(pg['pages'], [1, 2, 3, 4, 5, 6, 7, 8])
49 self.assertEqual(pg['records']['first'], 1)
50 self.assertEqual(pg['records']['last'], 2)
52 def test_records_for_the_last_page(self):
53 p = Paginator(range(15), 2)
54 pg = paginate({'paginator': p, 'page_obj': p.page(8)})
55 self.assertListEqual(pg['pages'], [1, 2, 3, 4, 5, 6, 7, 8])
56 self.assertEqual(pg['records']['first'], 15)
57 self.assertEqual(pg['records']['last'], 15)
59 def test_pages_list(self):
60 p = Paginator(range(17), 2)
61 self.assertEqual(paginate({'paginator': p, 'page_obj': p.page(1)})['pages'], [1, 2, 3, 4, 5, 6, 7, 8, 9])
63 def test_page_with_empty_objects_list(self):
64 p = Paginator(range(0), 2)
65 self.assertListEqual(paginate({'paginator': p, 'page_obj': p.page(1)})['pages'], [1])
68 class DefaultWindowTestCase(SimpleTestCase):
70 Test paginate using default window setting
71 moving the window from 1 ... to end
72 window size = 2, margin = 2
73 window = 2 -> show 5 pages
76 self.p = Paginator(range(31), 2)
78 def test_on_start_page_1(self):
79 # [1] 2 3 4 5 ... 15, 16
81 paginate({'paginator': self.p, 'page_obj': self.p.page(1)}, 2, 2)['pages'],
82 [1, 2, 3, 4, 5, None, 15, 16]
85 def test_on_start_page_2(self):
86 # 1 [2] 3 4 5 ... 15, 16
88 paginate({'paginator': self.p, 'page_obj': self.p.page(2)}, 2, 2)['pages'],
89 [1, 2, 3, 4, 5, None, 15, 16]
92 def test_on_start_page_3(self):
93 # 1 2 [3] 4 5 ... 15, 16
95 paginate({'paginator': self.p, 'page_obj': self.p.page(3)}, 2, 2)['pages'],
96 [1, 2, 3, 4, 5, None, 15, 16]
99 def test_on_start_page_4(self):
100 # 1 2 3 [4] 5 6 ... 15, 16
101 self.assertListEqual(
102 paginate({'paginator': self.p, 'page_obj': self.p.page(4)}, 2, 2)['pages'],
103 [1, 2, 3, 4, 5, 6, None, 15, 16])
105 def test_on_start_page_5(self):
106 # 1 2 3 4 [5] 6 7 ... 15, 16
107 self.assertListEqual(
108 paginate({'paginator': self.p, 'page_obj': self.p.page(5)}, 2, 2)['pages'],
109 [1, 2, 3, 4, 5, 6, 7, None, 15, 16]
112 def test_in_middle(self):
113 # 1 2 ... 5 6 [7] 8 9 ... 15, 16
114 self.assertListEqual(
115 paginate({'paginator': self.p, 'page_obj': self.p.page(7)}, 2, 2)['pages'],
116 [1, 2, None, 5, 6, 7, 8, 9, None, 15, 16]
119 def test_on_end_page_13(self):
120 # 1 2 ... 12 [13] 14 15 16
121 self.assertListEqual(
122 paginate({'paginator': self.p, 'page_obj': self.p.page(13)}, 2, 2)['pages'],
123 [1, 2, None, 11, 12, 13, 14, 15, 16],
126 def test_on_end(self):
127 # 1 2 ... 12 13 14 15 [16
128 self.assertListEqual(
129 paginate({'paginator': self.p, 'page_obj': self.p.page(16)}, 2, 2)['pages'],
130 [1, 2, None, 12, 13, 14, 15, 16]
134 class NoMarginTestCase(SimpleTestCase):
136 self.p = Paginator(range(31), 2)
138 def test_on_start(self):
139 self.assertListEqual(
140 paginate({'paginator': self.p, 'page_obj': self.p.page(3)}, 2, 0)['pages'],
141 [1, 2, 3, 4, 5, None],
144 def test_in_middle(self):
145 self.assertListEqual(
146 paginate({'paginator': self.p, 'page_obj': self.p.page(5)}, 2, 0)['pages'],
147 [None, 3, 4, 5, 6, 7, None],
150 def test_on_end(self):
151 self.assertListEqual(
152 paginate({'paginator': self.p, 'page_obj': self.p.page(16)}, 2, 0)['pages'],
153 [None, 12, 13, 14, 15, 16],
157 class ZeroWindowZeroMarginTestCase(SimpleTestCase):
159 Test paginate using window=0 and margin=0
162 self.p = Paginator(range(31), 2)
164 def test_on_start_page_1(self):
165 self.assertListEqual(
166 paginate({'paginator': self.p, 'page_obj': self.p.page(1)}, 0, 0)['pages'],
170 def test_in_middle_page_2(self):
171 self.assertListEqual(
172 paginate({'paginator': self.p, 'page_obj': self.p.page(2)}, 0, 0)['pages'],
176 def test_in_middle_page_3(self):
177 self.assertListEqual(
178 paginate({'paginator': self.p, 'page_obj': self.p.page(3)}, 0, 0)['pages'],
182 def test_in_middle_page_10(self):
183 self.assertListEqual(
184 paginate({'paginator': self.p, 'page_obj': self.p.page(10)}, 0, 0)['pages'],
188 def test_in_middle_page_14(self):
189 self.assertListEqual(
190 paginate({'paginator': self.p, 'page_obj': self.p.page(14)}, 0, 0)['pages'],
194 def test_in_middle_page_15(self):
195 self.assertListEqual(
196 paginate({'paginator': self.p, 'page_obj': self.p.page(15)}, 0, 0)['pages'],
200 def test_on_end_page_16(self):
201 self.assertListEqual(
202 paginate({'paginator': self.p, 'page_obj': self.p.page(16)}, 0, 0)['pages'],
207 class NoEllipsisTestCase(SimpleTestCase):
209 Tests a case where should be no any ellipsis pages.
212 self.p = Paginator(range(100), 25)
214 def test_on_start(self):
215 self.assertListEqual(
216 paginate({'paginator': self.p, 'page_obj': self.p.page(1)}, 2, 0)['pages'],
220 def test_in_middle_page_2(self):
221 self.assertListEqual(
222 paginate({'paginator': self.p, 'page_obj': self.p.page(2)}, 2, 0)['pages'],
226 def test_in_middle_page_3(self):
227 self.assertListEqual(
228 paginate({'paginator': self.p, 'page_obj': self.p.page(3)}, 2, 0)['pages'],
232 def test_on_end(self):
233 self.assertListEqual(
234 paginate({'paginator': self.p, 'page_obj': self.p.page(4)}, 2, 0)['pages'],
239 class SpecialTestCase(SimpleTestCase):
240 def test_middle_with_no_window_and_margin_1(self):
241 p = Paginator(range(31), 2)
242 self.assertListEqual(
243 paginate({'paginator': p, 'page_obj': p.page(5)}, 0, 1)['pages'],
244 [1, None, 5, None, 16],
247 def test_middle_with_no_window_and_margin_4(self):
248 p = Paginator(range(21), 2, 1)
249 self.assertListEqual(
250 paginate({'paginator': p, 'page_obj': p.page(1)}, 0, 4)['pages'],
251 [1, 2, 3, 4, None, 7, 8, 9, 10],
255 class TemplateRenderingTestCase(SimpleTestCase):
256 def test_default_tag_options(self):
257 t = Template("{% load pagination_tags %}{% autopaginate var %}{% paginate %}")
259 '<div class="pagination">',
260 t.render(Context({'var': range(21), 'request': HttpRequest()})),
263 def test_paginate_by_option(self):
264 t = Template("{% load pagination_tags %}{% autopaginate var 20 %}{% paginate %}")
266 '<div class="pagination">',
267 t.render(Context({'var': range(21), 'request': HttpRequest()})),
270 def test_orphans_option(self):
271 t = Template("{% load pagination_tags %}{% autopaginate var by %}{% paginate %}")
272 content = t.render(Context({'var': range(21), 'by': 20, 'request': HttpRequest()}))
273 self.assertIn('<div class="pagination">', content)
274 self.assertIn('<a href="?page=2"', content)
276 def test_as_option(self):
277 t = Template("{% load pagination_tags %}{% autopaginate var by as foo %}{{ foo }}")
279 t.render(Context({'var': range(21), 'by': 20, 'request': HttpRequest()})),
283 def test_multiple_pagination(self):
284 t = Template("{% load pagination_tags %}{% autopaginate var2 by as foo2 %}{% paginate %}"
285 "{% autopaginate var by as foo %}{% paginate %}")
286 content = t.render(Context({'var': range(21), 'var2': range(50, 121), 'by': 20, 'request': HttpRequest()}))
287 self.assertIn('<div class="pagination">', content)
288 self.assertIn('<a href="?page_var2=2"', content)
289 self.assertIn('<a href="?page_var=2"', content)
292 class InfinitePaginatorTestCase(SimpleTestCase):
294 self.p = InfinitePaginator(range(20), 2, link_template='/bacon/page/%d')
296 def test_paginator_repr(self):
298 repr(InfinitePaginator),
299 "<class 'fnp_django_pagination.paginator.InfinitePaginator'>",
302 def test_validate_number(self):
303 self.assertEqual(self.p.validate_number(2), 2)
305 def test_orphans(self):
306 self.assertEqual(self.p.orphans, 0)
308 def test_page_repr(self):
309 self.assertEqual(repr(self.p.page(3)), '<Page 3>')
311 def test_page_end_index(self):
312 self.assertEqual(self.p.page(3).end_index(), 6)
314 def test_page_has_next(self):
315 self.assertTrue(self.p.page(3).has_next(), True)
317 def test_page_has_previous(self):
318 self.assertTrue(self.p.page(3).has_previous(), True)
320 def test_page_next_link(self):
321 self.assertEqual(self.p.page(3).next_link(), '/bacon/page/4')
323 def test_page_previous_link(self):
324 self.assertEqual(self.p.page(3).previous_link(), '/bacon/page/2')
326 def test_last_page_which_has_no_next_page(self):
327 self.assertFalse(self.p.page(10).has_next())
329 def test_first_page_which_has_no_previous_page(self):
330 self.assertFalse(self.p.page(1).has_previous())
333 class FinitePaginatorTestCase(SimpleTestCase):
335 self.p = FinitePaginator(range(20), 2, offset=10, link_template='/bacon/page/%d')
339 repr(FinitePaginator),
340 "<class 'fnp_django_pagination.paginator.FinitePaginator'>"
343 def test_validate_number(self):
344 self.assertEqual(self.p.validate_number(2), 2)
346 def test_orphans(self):
347 self.assertEqual(self.p.orphans, 0)
349 def test_page_repr(self):
350 self.assertEqual(repr(self.p.page(3)), '<Page 3>')
352 def test_page_start_index(self):
353 self.assertEqual(self.p.page(3).start_index(), 10)
355 def test_page_end(self):
356 self.assertEqual(self.p.page(3).end_index(), 6)
358 def test_page_has_next(self):
359 self.assertTrue(self.p.page(3).has_next(), True)
361 def test_page_has_previous(self):
362 self.assertTrue(self.p.page(3).has_previous(), True)
364 def test_page_next_link(self):
365 self.assertEqual(self.p.page(3).next_link(), '/bacon/page/4')
367 def test_page_previous_link(self):
368 self.assertEqual(self.p.page(3).previous_link(), '/bacon/page/2')
370 def test_on_start_page_repr(self):
371 self.assertEqual(repr(self.p.page(2)), '<Page 2>')
373 def test_on_start_has_no_next(self):
374 self.assertTrue(self.p.page(2).has_next(), False)
376 def test_on_start_has_previous(self):
377 self.assertTrue(self.p.page(2).has_previous(), True)
379 def test_on_start_has_next_link(self):
380 self.assertEqual(self.p.page(2).next_link(), '/bacon/page/3')
382 def test_on_start_has_previous_link(self):
383 self.assertEqual(self.p.page(2).previous_link(), '/bacon/page/1')
386 class MiddlewareTestCase(SimpleTestCase):
390 def test_get_page_in_request(self):
391 middleware = PaginationMiddleware(lambda: None)
392 request = DjangoHttpRequest()
393 middleware.process_request(request)
394 self.assertEqual(request.page(''), 1)