1import json 2from nose import SkipTest 3from tests.test_stack import TestConfig, app_from_config 4from tg.support.paginate import Page 5from tg.controllers.util import _urlencode 6from tg import json_encode 7from tg.util.webtest import test_context 8 9 10def setup_noDB(): 11 base_config = TestConfig(folder='rendering', 12 values={ 13 'use_sqlalchemy': False, 14 'use_toscawidgets': False, 15 'use_toscawidgets2': False 16 }) 17 return app_from_config(base_config) 18 19 20_pager = ('<div id="pager"><span class="pager_curpage">1</span>' 21 ' <a href="%(url)s?page=2">2</a>' 22 ' <a href="%(url)s?page=3">3</a>' 23 ' <span class="pager_dotdot">..</span>' 24 ' <a href="%(url)s?page=5">5</a></div>') 25 26_data = '<ul id="data">%s</ul>' % ''.join( 27 '<li>%d</li>' % i for i in range(10)) 28 29 30class TestPagination: 31 def setup(self): 32 self.app = setup_noDB() 33 34 def test_basic_pagination(self): 35 url = '/paginated/42' 36 page = self.app.get(url) 37 assert _pager % locals() in page, page 38 assert _data in page, page 39 url = '/paginated/42?page=2' 40 page = self.app.get(url) 41 assert '<li>0</li>' not in page 42 assert '<li>10</li>' in page 43 44 def test_pagination_negative(self): 45 url = '/paginated/42?page=-1' 46 page = self.app.get(url) 47 assert '<li>0</li>' in page 48 49 def test_pagination_items_per_page(self): 50 url = '/paginated/42?items_per_page=20' 51 page = self.app.get(url) 52 assert '<li>0</li>' in page 53 assert '<li>19</li>' in page 54 55 def test_pagination_items_per_page_negative(self): 56 url = '/paginated/42?items_per_page=-1' 57 page = self.app.get(url) 58 assert '<li>0</li>' in page 59 assert '<li>10</li>' not in page 60 61 def test_pagination_non_paginable(self): 62 url = '/paginated_text' 63 page = self.app.get(url) 64 assert 'Some Text' in page 65 66 def test_pagination_with_validation(self): 67 url = '/paginated_validated/42' 68 page = self.app.get(url) 69 assert _pager % locals() in page, page 70 assert _data in page, page 71 url = '/paginated_validated/42?page=2' 72 page = self.app.get(url) 73 assert '<li>0</li>' not in page 74 assert '<li>10</li>' in page 75 76 def test_validation_with_pagination(self): 77 url = '/validated_paginated/42' 78 page = self.app.get(url) 79 assert _pager % locals() in page, page 80 assert _data in page, page 81 url = '/validated_paginated/42?page=2' 82 page = self.app.get(url) 83 assert '<li>0</li>' not in page 84 assert '<li>10</li>' in page 85 86 def test_pagination_with_link_args(self): 87 url = '/paginate_with_params/42' 88 page = self.app.get(url) 89 assert 'param1=hi' in page 90 assert 'param2=man' in page 91 assert 'partial' not in page 92 assert '/fake_url' in page 93 url = '/paginate_with_params/42?page=2' 94 page = self.app.get(url) 95 assert '<li>0</li>' not in page 96 assert '<li>10</li>' in page 97 98 def test_multiple_paginators(self): 99 url = '/multiple_paginators/42' 100 101 try: 102 from collections import OrderedDict 103 params = (('testdata_page', 2), ('testdata2_page', 2)) 104 reverse_params = OrderedDict(reversed(params)) 105 params = OrderedDict(params) 106 except ImportError: 107 reverse_params = params = {'testdata2_page': 2, 'testdata_page': 2} 108 109 goto_page2_link = url + '?' + _urlencode(params) 110 goto_page2_reverse_link = url + '?' + _urlencode(reverse_params) 111 112 page = self.app.get(url) 113 assert '/multiple_paginators/42?testdata2_page=2' in page, str(page) 114 assert '/multiple_paginators/42?testdata_page=2' in page, str(page) 115 116 url = '/multiple_paginators/42?testdata_page=2' 117 page = self.app.get(url) 118 119 assert ( 120 goto_page2_link in page or goto_page2_reverse_link in page 121 ), str(page) 122 assert '/multiple_paginators/42?testdata_page=4' in page, str(page) 123 124 assert '<li>0</li>' not in page 125 assert '<li>10</li>' in page 126 assert '<li>142</li>' in page 127 assert '<li>151</li>' in page 128 129 url = '/multiple_paginators/42?testdata2_page=2' 130 page = self.app.get(url) 131 132 assert ( 133 goto_page2_link in page or goto_page2_reverse_link in page 134 ), str(page) 135 assert '/multiple_paginators/42?testdata2_page=4' in page, str(page) 136 137 assert '<li>0</li>' in page 138 assert '<li>9</li>' in page 139 assert '<li>151</li>' not in page 140 assert '<li>161</li>' in page 141 142 def test_json_pagination(self): 143 url = '/paginated/42.json' 144 page = self.app.get(url) 145 assert '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]' in page 146 147 url = '/paginated/42.json?page=2' 148 page = self.app.get(url) 149 assert '[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]' in page 150 151 152class TestPage(object): 153 def test_not_a_number_page(self): 154 p = Page(range(100), items_per_page=10, page='A') 155 sec = list(p) 156 assert sec[-1] == 9, sec 157 158 def test_empty_list(self): 159 p = Page([], items_per_page=10, page=1) 160 assert list(p) == [] 161 162 def test_page_out_of_bound(self): 163 p = Page(range(100), items_per_page=10, page=10000) 164 sec = list(p) 165 assert sec[-1] == 99, sec 166 167 def test_page_out_of_lower_bound(self): 168 p = Page(range(100), items_per_page=10, page=-5) 169 sec = list(p) 170 assert sec[-1] == 9, sec 171 172 def test_navigator_one_page(self): 173 with test_context(None, '/'): 174 p = Page(range(10), items_per_page=10, page=10) 175 assert p.pager() == '' 176 177 def test_navigator_middle_page(self): 178 with test_context(None, '/'): 179 p = Page(range(100), items_per_page=10, page=5) 180 pager = p.pager() 181 182 assert '?page=1' in pager 183 assert '?page=4' in pager 184 assert '?page=6' in pager 185 assert '?page=10' in pager 186 187 def test_navigator_ajax(self): 188 with test_context(None, '/'): 189 p = Page(range(100), items_per_page=10, page=5) 190 pager = p.pager(onclick='goto($page)') 191 192 assert 'goto(1)' in pager 193 assert 'goto(4)' in pager 194 assert 'goto(6)' in pager 195 assert 'goto(10)' in pager 196 197 198try: 199 import sqlite3 200except: 201 import pysqlite2 202from sqlalchemy import (MetaData, Table, Column, ForeignKey, Integer, String) 203from sqlalchemy.orm import create_session, mapper, relation 204 205metadata = MetaData('sqlite:///:memory:') 206 207test1 = Table('test1', metadata, 208 Column('id', Integer, primary_key=True), 209 Column('val', String(8))) 210 211test2 = Table('test2', metadata, 212 Column('id', Integer, primary_key=True), 213 Column('test1id', Integer, ForeignKey('test1.id')), 214 Column('val', String(8))) 215 216test3 = Table('test3', metadata, 217 Column('id', Integer, primary_key=True), 218 Column('val', String(8))) 219 220test4 = Table('test4', metadata, 221 Column('id', Integer, primary_key=True), 222 Column('val', String(8))) 223 224metadata.create_all() 225 226class Test2(object): 227 pass 228mapper(Test2, test2) 229 230class Test1(object): 231 pass 232mapper(Test1, test1, properties={'test2s': relation(Test2)}) 233 234class Test3(object): 235 pass 236mapper(Test3, test3) 237 238class Test4(object): 239 pass 240mapper(Test4, test4) 241 242test1.insert().execute({'id': 1, 'val': 'bob'}) 243test2.insert().execute({'id': 1, 'test1id': 1, 'val': 'fred'}) 244test2.insert().execute({'id': 2, 'test1id': 1, 'val': 'alice'}) 245test3.insert().execute({'id': 1, 'val': 'bob'}) 246test4.insert().execute({'id': 1, 'val': 'alberto'}) 247 248class TestPageSQLA(object): 249 def setup(self): 250 self.s = create_session() 251 252 def test_relationship(self): 253 t = self.s.query(Test1).get(1) 254 p = Page(t.test2s, items_per_page=1, page=1) 255 assert len(list(p)) == 1 256 assert list(p)[0].val == 'fred', list(p) 257 258 def test_query(self): 259 q = self.s.query(Test2) 260 p = Page(q, items_per_page=1, page=1) 261 assert len(list(p)) == 1 262 assert list(p)[0].val == 'fred', list(p) 263 264 def test_json_query(self): 265 q = self.s.query(Test2) 266 p = Page(q, items_per_page=1, page=1) 267 res = json.loads(json_encode(p)) 268 assert len(res['entries']) == 1 269 assert res['total'] == 2 270 assert res['entries'][0]['val'] == 'fred' 271 272 273try: 274 import ming 275 from ming import create_datastore, Session, schema, ASCENDING 276 from ming.odm import ODMSession, FieldProperty, ForeignIdProperty, RelationProperty, Mapper 277 from ming.odm.declarative import MappedClass 278except ImportError: 279 ming = None 280 281 282class TestPageMing(object): 283 @classmethod 284 def setupClass(cls): 285 if ming is None: 286 raise SkipTest('Ming not available...') 287 288 cls.basic_session = Session(create_datastore('mim:///testdb')) 289 cls.s = ODMSession(cls.basic_session) 290 291 class Author(MappedClass): 292 class __mongometa__: 293 session = cls.s 294 name = 'wiki_author' 295 296 _id = FieldProperty(schema.ObjectId) 297 name = FieldProperty(str) 298 pages = RelationProperty('WikiPage') 299 300 class WikiPage(MappedClass): 301 class __mongometa__: 302 session = cls.s 303 name = 'wiki_page' 304 305 _id = FieldProperty(schema.ObjectId) 306 title = FieldProperty(str) 307 text = FieldProperty(str) 308 order = FieldProperty(int) 309 author_id = ForeignIdProperty(Author) 310 author = RelationProperty(Author) 311 312 cls.Author = Author 313 cls.WikiPage = WikiPage 314 Mapper.compile_all() 315 316 cls.author = Author(name='author1') 317 author2 = Author(name='author2') 318 319 WikiPage(title='Hello', text='Text', order=1, author=cls.author) 320 WikiPage(title='Another', text='Text', order=2, author=cls.author) 321 WikiPage(title='ThirdOne', text='Text', order=3, author=author2) 322 cls.s.flush() 323 cls.s.clear() 324 325 def teardown(self): 326 self.s.clear() 327 328 def test_query(self): 329 q = self.WikiPage.query.find().sort([('order', ASCENDING)]) 330 p = Page(q, items_per_page=1, page=1) 331 assert len(list(p)) == 1 332 assert list(p)[0].title == 'Hello', list(p) 333 334 def test_json_query(self): 335 q = self.WikiPage.query.find().sort([('order', ASCENDING)]) 336 p = Page(q, items_per_page=1, page=1) 337 res = json.loads(json_encode(p)) 338 assert len(res['entries']) == 1 339 assert res['total'] == 3 340 assert res['entries'][0]['title'] == 'Hello', res['entries'] 341 assert res['entries'][0]['author_id'] == str(self.author._id), res['entries'] 342 343 def test_relation(self): 344 a = self.Author.query.find({'name': 'author1'}).first() 345 p = Page(a.pages, items_per_page=1, page=1) 346 assert len(list(p)) == 1 347 assert list(p)[0].title in ('Hello', 'Another'), list(p) 348