1import pytest 2 3 4def test_paginated_children(pad): 5 page1 = pad.get("/projects", page_num=1) 6 7 assert page1 is not None 8 assert page1["_model"] == "projects" 9 assert page1["_template"] == "projects.html" 10 11 assert page1.datamodel.pagination_config.per_page == 4 12 13 assert page1.children.count() == 8 14 assert page1.page_num == 1 15 assert page1.pagination.items.count() == 4 16 17 children = page1.pagination.items.all() 18 assert len(children) == 4 19 assert [x["name"] for x in children] == [ 20 u"Coffee", 21 u"Bagpipe", 22 u"Master", 23 u"Oven", 24 ] 25 26 assert ("projects", "_primary", "1") in pad.cache.persistent 27 assert ("projects", "_primary", "2") not in pad.cache.persistent 28 29 page2 = pad.get("/projects", page_num=2) 30 31 assert page2.children.count() == 8 32 assert page2.page_num == 2 33 assert page2.pagination.items.count() == 3 34 35 children = page2.pagination.items.all() 36 assert len(children) == 3 37 assert [x["name"] for x in children] == [ 38 u"Postage", 39 u"Slave", 40 u"Wolf", 41 ] 42 43 assert ("projects", "_primary", "2") in pad.cache.persistent 44 45 46def test_unpaginated_children(pad): 47 page_all = pad.get("/projects") 48 49 assert page_all 50 51 assert page_all.pagination.items.count() == 7 52 assert page_all.page_num is None 53 54 children = page_all.pagination.items.all() 55 assert len(children) == 7 56 assert [x["name"] for x in children] == [ 57 u"Coffee", 58 u"Bagpipe", 59 u"Master", 60 u"Oven", 61 u"Postage", 62 u"Slave", 63 u"Wolf", 64 ] 65 66 67def test_pagination_access(pad): 68 page = pad.get("/projects", page_num=1) 69 70 assert page.pagination.page == 1 71 assert page.pagination.next.pagination.page == 2 72 assert page.pagination.for_page(2).pagination.page == 2 73 74 assert page.pagination.for_page(0) is None 75 assert page.pagination.for_page(3) is None 76 77 assert pad.get("/projects@1").page_num == 1 78 assert pad.get("/projects@2").page_num == 2 79 assert pad.get("/projects@3").page_num == 3 80 81 82def test_pagination_attributes(pad): 83 page = pad.get("/projects", page_num=1) 84 assert page.pagination.current is page 85 assert page.pagination.next is not None 86 assert page.pagination.next.page_num == 2 87 assert page.pagination.prev is None 88 assert page.pagination.pages == 2 89 assert page.pagination.prev_num is None 90 assert page.pagination.next_num == 2 91 assert page.pagination.has_next 92 assert not page.pagination.has_prev 93 94 page = page.pagination.next 95 assert page.pagination.current is page 96 assert page.pagination.next is None 97 assert page.pagination.prev.page_num == 1 98 assert not page.pagination.has_next 99 assert page.pagination.next is None 100 assert page.pagination.next_num is None 101 102 103def test_url_matching_for_pagination(pad): 104 page1 = pad.resolve_url_path("/projects/") 105 assert page1.page_num == 1 106 107 page2 = pad.resolve_url_path("/projects/page/2/") 108 assert page2.page_num == 2 109 110 page1_explicit = pad.resolve_url_path("/projects/page/1/") 111 assert page1_explicit is None 112 113 114def test_parent_access(pad): 115 page2 = pad.resolve_url_path("/projects/page/2/") 116 assert page2["_path"] == "/projects" 117 assert page2.path == "/projects@2" 118 assert page2.page_num == 2 119 120 child = page2.pagination.items.first() 121 assert child.parent.path == page2["_path"] 122 assert child.parent.page_num is None 123 124 125def test_pagination_url_paths(pad): 126 # Even though this is paginated, getting to the non paginated version 127 # just looks like going to the first page. We do this because it 128 # is more convenient for usage. 129 project = pad.get("/projects") 130 assert project.url_path == "/projects/" 131 132 # However first page looks the same 133 project = pad.get("/projects", page_num=1) 134 assert project.url_path == "/projects/" 135 136 # second page is different 137 project = pad.get("/projects", page_num=2) 138 assert project.url_path == "/projects/page/2/" 139 140 141def test_unpaginated_children_other_alt(pad): 142 page_all = pad.get("/projects", alt="de") 143 144 assert page_all.pagination.items.count() == 8 145 assert page_all.page_num is None 146 147 children = page_all.pagination.items.all() 148 assert len(children) == 8 149 assert [x["name"] for x in children] == [ 150 u"Kaffee", 151 u"Dudelsack", 152 u"Meister", 153 u"Ofen", 154 u"Porto", 155 u"Sklave", 156 u"Wolf", 157 u"Zaun", 158 ] 159 160 161def test_prev_next(pad): 162 # coffee, bagpipe, filtered, master have seq numbers 9, 8, 7, 6. 163 # They disagree with alphabetization, to ensure we use the pagination 164 # query order, "-seq". 165 bagpipe = pad.get("/projects/bagpipe") 166 assert bagpipe.get_siblings().prev_page["_id"] == "coffee" 167 168 # Next child "filtered" is skipped by pagination query, skip to "master". 169 assert bagpipe.get_siblings().next_page["_id"] == "master" 170 171 # Postage is on the previous page before oven, but prev / next ignore pages. 172 oven = pad.get("/projects/oven") 173 assert oven.get_siblings().prev_page["_id"] == "master" 174 assert oven.get_siblings().next_page["_id"] == "postage" 175 176 177def test_url_matching_for_alt_pagination(pad): 178 page1 = pad.resolve_url_path("/de/projects/") 179 assert page1.alt == "de" 180 assert page1.page_num == 1 181 182 page2 = pad.resolve_url_path("/de//projects/page/2/") 183 assert page2.alt == "de" 184 assert page2.page_num == 2 185 186 page1_explicit = pad.resolve_url_path("/de/projects/page/1/") 187 assert page1_explicit is None 188 189 190def test_pagination_items_filter(pad): 191 # This tests that items are excluded from the pagination based on a 192 # query if needed. 193 blog = pad.get("/blog", page_num=1) 194 assert ( 195 blog.datamodel.pagination_config.items 196 == "this.children.filter(F._model == 'blog-post')" 197 ) 198 199 assert blog.children.count() == 3 200 assert sorted(x["_id"] for x in blog.children) == ["dummy.xml", "post1", "post2"] 201 202 assert blog.pagination.items.count() == 2 203 # Sort order is pub_date descending, so post 2 is first. 204 assert blog.pagination.items.first()["_id"] == "post2" 205 206 dummy = blog.children.get("dummy.xml") 207 assert dummy is not None 208 assert dummy["_model"] == "none" 209 210 211def test_virtual_path_behavior(pad): 212 # Base record 213 blog = pad.get("/blog") 214 assert blog.path == "/blog" 215 assert blog["_path"] == "/blog" 216 assert blog.page_num is None 217 assert blog.url_path == "/blog/" 218 assert blog.record is blog 219 220 # Record for page 1 which is a bit special 221 blog_page1 = pad.get("/blog@1") 222 assert blog_page1.path == "/blog@1" 223 assert blog_page1["_path"] == "/blog" 224 assert blog_page1.url_path == "/blog/" 225 assert blog_page1.page_num == 1 226 assert blog_page1.parent is pad.root 227 assert blog_page1.record is blog 228 229 # Record for page 2 which is slightly less special 230 blog_page2 = pad.get("/blog@2") 231 assert blog_page2.path == "/blog@2" 232 assert blog_page2["_path"] == "/blog" 233 assert blog_page2.url_path == "/blog/page/2/" 234 assert blog_page2.page_num == 2 235 assert blog_page2.parent is pad.root 236 assert blog_page2.record is blog 237 238 # Make sure URL generation works as you would expect: 239 assert blog.url_to("@1", absolute=True) == "/blog/" 240 assert blog.url_to("@2", absolute=True) == "/blog/page/2/" 241 assert blog.url_to("..", absolute=True) == "/" 242 assert blog_page2.url_to("..", absolute=True) == "/" 243 assert blog_page2.url_to("@1", absolute=True) == "/blog/" 244 assert blog_page2.url_to("@3", absolute=True) == "/blog/page/3/" 245 246 247class Test_Pagination_iter_pages(object): 248 @pytest.fixture 249 def pagination(self, pad, page, pages, monkeypatch): 250 projects = pad.get("/projects", page_num=1) 251 pagination = projects.pagination 252 # hack in the desired page and total 253 monkeypatch.setattr(pagination, "page", page) 254 monkeypatch.setattr(pagination, "total", pages) 255 monkeypatch.setattr(pagination, "per_page", 1) 256 assert pagination.pages == pages 257 return pagination 258 259 @pytest.mark.parametrize( 260 ( 261 "page", 262 "pages", 263 "left_edge", 264 "left_current", 265 "right_current", 266 "right_edge", 267 "expected", 268 ), 269 [ 270 (1, 9, 0, 0, 0, 0, [1, None]), 271 (2, 9, 0, 0, 0, 0, [None, 2, None]), 272 (8, 9, 0, 0, 0, 0, [None, 8, None]), 273 (9, 9, 0, 0, 0, 0, [None, 9]), 274 (1, 9, 1, 0, 0, 1, [1, None, 9]), 275 (2, 9, 1, 0, 0, 1, [1, 2, None, 9]), 276 (3, 9, 1, 0, 0, 1, [1, None, 3, None, 9]), 277 (7, 9, 1, 0, 0, 1, [1, None, 7, None, 9]), 278 (8, 9, 1, 0, 0, 1, [1, None, 8, 9]), 279 (9, 9, 1, 0, 0, 1, [1, None, 9]), 280 (1, 9, 0, 1, 1, 0, [1, 2, None]), 281 (2, 9, 0, 1, 1, 0, [1, 2, 3, None]), 282 (3, 9, 0, 1, 1, 0, [None, 2, 3, 4, None]), 283 (7, 9, 0, 1, 1, 0, [None, 6, 7, 8, None]), 284 (8, 9, 0, 1, 1, 0, [None, 7, 8, 9]), 285 (9, 9, 0, 1, 1, 0, [None, 8, 9]), 286 (1, 9, 1, 1, 1, 1, [1, 2, None, 9]), 287 (2, 9, 1, 1, 1, 1, [1, 2, 3, None, 9]), 288 (3, 9, 1, 1, 1, 1, [1, 2, 3, 4, None, 9]), 289 (4, 9, 1, 1, 1, 1, [1, None, 3, 4, 5, None, 9]), 290 (6, 9, 1, 1, 1, 1, [1, None, 5, 6, 7, None, 9]), 291 (7, 9, 1, 1, 1, 1, [1, None, 6, 7, 8, 9]), 292 (8, 9, 1, 1, 1, 1, [1, None, 7, 8, 9]), 293 (9, 9, 1, 1, 1, 1, [1, None, 8, 9]), 294 ], 295 ) 296 def test( 297 self, 298 pagination, 299 page, 300 left_edge, 301 left_current, 302 right_current, 303 right_edge, 304 expected, 305 ): 306 assert ( 307 list( 308 pagination.iter_pages( 309 left_edge, left_current, right_current, right_edge 310 ) 311 ) 312 == expected 313 ) 314