3
0
Fork 0

feat: add backend pagination support for grids

This commit is contained in:
Lance Edgar 2024-08-16 22:52:24 -05:00
parent dd3d640b1c
commit d151758c48
7 changed files with 501 additions and 29 deletions

View file

@ -3,6 +3,7 @@
from unittest import TestCase
from unittest.mock import patch
from paginate import Page
from pyramid import testing
from wuttjamaican.conf import WuttaConfig
@ -168,6 +169,105 @@ class TestGrid(WebTestCase):
size = grid.get_pagesize()
self.assertEqual(size, 15)
##############################
# configuration methods
##############################
def test_load_settings(self):
grid = self.make_grid(key='foo', paginated=True, paginate_on_backend=True,
pagesize=20, page=1)
# settings are loaded, applied, saved
self.assertEqual(grid.page, 1)
self.assertNotIn('grid.foo.page', self.request.session)
self.request.GET = {'pagesize': '10', 'page': '2'}
grid.load_settings()
self.assertEqual(grid.page, 2)
self.assertEqual(self.request.session['grid.foo.page'], 2)
# can skip the saving step
self.request.GET = {'pagesize': '10', 'page': '3'}
grid.load_settings(store=False)
self.assertEqual(grid.page, 3)
self.assertEqual(self.request.session['grid.foo.page'], 2)
# no error for non-paginated grid
grid = self.make_grid(key='foo', paginated=False)
grid.load_settings()
self.assertFalse(grid.paginated)
def test_request_has_settings(self):
grid = self.make_grid(key='foo')
self.assertFalse(grid.request_has_settings())
with patch.object(self.request, 'GET', new={'pagesize': '20'}):
self.assertTrue(grid.request_has_settings())
with patch.object(self.request, 'GET', new={'page': '1'}):
self.assertTrue(grid.request_has_settings())
def test_update_page_settings(self):
grid = self.make_grid(key='foo')
# settings are updated from session
settings = {'pagesize': 20, 'page': 1}
self.request.session['grid.foo.pagesize'] = 10
self.request.session['grid.foo.page'] = 2
grid.update_page_settings(settings)
self.assertEqual(settings['pagesize'], 10)
self.assertEqual(settings['page'], 2)
# settings are updated from request
self.request.GET = {'pagesize': '15', 'page': '4'}
grid.update_page_settings(settings)
self.assertEqual(settings['pagesize'], 15)
self.assertEqual(settings['page'], 4)
def test_persist_settings(self):
grid = self.make_grid(key='foo', paginated=True, paginate_on_backend=True)
# nb. no error if empty settings, but it saves null values
grid.persist_settings({})
self.assertIsNone(self.request.session['grid.foo.page'])
# provided values are saved
grid.persist_settings({'pagesize': 15, 'page': 3})
self.assertEqual(self.request.session['grid.foo.page'], 3)
##############################
# data methods
##############################
def test_get_visible_data(self):
data = [
{'foo': 1, 'bar': 1},
{'foo': 2, 'bar': 2},
{'foo': 3, 'bar': 3},
{'foo': 4, 'bar': 4},
{'foo': 5, 'bar': 5},
{'foo': 6, 'bar': 6},
{'foo': 7, 'bar': 7},
{'foo': 8, 'bar': 8},
{'foo': 9, 'bar': 9},
]
grid = self.make_grid(data=data,
columns=['foo', 'bar'],
paginated=True, paginate_on_backend=True,
pagesize=4, page=2)
visible = grid.get_visible_data()
self.assertEqual(len(visible), 4)
self.assertEqual(visible[0], {'foo': 5, 'bar': 5})
def test_paginate_data(self):
grid = self.make_grid()
pager = grid.paginate_data([])
self.assertIsInstance(pager, Page)
##############################
# rendering methods
##############################
def test_render_vue_tag(self):
grid = self.make_grid(columns=['foo', 'bar'])
html = grid.render_vue_tag()
@ -221,6 +321,28 @@ class TestGrid(WebTestCase):
data = grid.get_vue_data()
self.assertEqual(data, [{'foo': 'blah blah', '_action_url_view': '/blarg'}])
def test_get_vue_pager_stats(self):
data = [
{'foo': 1, 'bar': 1},
{'foo': 2, 'bar': 2},
{'foo': 3, 'bar': 3},
{'foo': 4, 'bar': 4},
{'foo': 5, 'bar': 5},
{'foo': 6, 'bar': 6},
{'foo': 7, 'bar': 7},
{'foo': 8, 'bar': 8},
{'foo': 9, 'bar': 9},
]
grid = self.make_grid(columns=['foo', 'bar'], pagesize=4, page=2)
grid.pager = grid.paginate_data(data)
stats = grid.get_vue_pager_stats()
self.assertEqual(stats['item_count'], 9)
self.assertEqual(stats['items_per_page'], 4)
self.assertEqual(stats['page'], 2)
self.assertEqual(stats['first_item'], 5)
self.assertEqual(stats['last_item'], 8)
class TestGridAction(TestCase):

View file

@ -1,46 +1,56 @@
# -*- coding: utf-8; -*-
from unittest import TestCase
from pyramid import testing
from pyramid.httpexceptions import HTTPFound, HTTPForbidden, HTTPNotFound
from wuttjamaican.conf import WuttaConfig
from wuttaweb.views import base
from wuttaweb.views import base as mod
from wuttaweb.forms import Form
from wuttaweb.grids import Grid
from wuttaweb.grids import Grid, GridAction
from tests.util import WebTestCase
class TestView(TestCase):
class TestView(WebTestCase):
def setUp(self):
self.config = WuttaConfig()
self.app = self.config.get_app()
self.request = testing.DummyRequest(wutta_config=self.config)
self.view = base.View(self.request)
def make_view(self):
return mod.View(self.request)
def test_basic(self):
self.assertIs(self.view.request, self.request)
self.assertIs(self.view.config, self.config)
self.assertIs(self.view.app, self.app)
view = self.make_view()
self.assertIs(view.request, self.request)
self.assertIs(view.config, self.config)
self.assertIs(view.app, self.app)
def test_forbidden(self):
error = self.view.forbidden()
view = self.make_view()
error = view.forbidden()
self.assertIsInstance(error, HTTPForbidden)
def test_make_form(self):
form = self.view.make_form()
view = self.make_view()
form = view.make_form()
self.assertIsInstance(form, Form)
def test_make_grid(self):
grid = self.view.make_grid()
view = self.make_view()
grid = view.make_grid()
self.assertIsInstance(grid, Grid)
def test_make_grid_action(self):
view = self.make_view()
action = view.make_grid_action('view')
self.assertIsInstance(action, GridAction)
def test_notfound(self):
error = self.view.notfound()
view = self.make_view()
error = view.notfound()
self.assertIsInstance(error, HTTPNotFound)
def test_redirect(self):
error = self.view.redirect('/')
view = self.make_view()
error = view.redirect('/')
self.assertIsInstance(error, HTTPFound)
self.assertEqual(error.location, '/')
def test_json_response(self):
view = self.make_view()
response = view.json_response({'foo': 'bar'})
self.assertEqual(response.status_code, 200)

View file

@ -747,6 +747,14 @@ class TestMasterView(WebTestCase):
data = [{'name': 'foo', 'value': 'bar'}]
with patch.object(view, 'get_grid_data', return_value=data):
response = view.index()
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content_type, 'text/html')
# then once more as 'partial' - aka. data only
self.request.GET = {'partial': '1'}
response = view.index()
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content_type, 'application/json')
def test_create(self):
self.pyramid_config.include('wuttaweb.views.common')