# -*- coding: utf-8; -*- from unittest import TestCase from unittest.mock import patch from sqlalchemy import orm from paginate import Page from paginate_sqlalchemy import SqlalchemyOrmPage from pyramid import testing from wuttjamaican.conf import WuttaConfig from wuttaweb.grids import base as mod from wuttaweb.forms import FieldList from tests.util import WebTestCase class TestGrid(WebTestCase): def make_grid(self, request=None, **kwargs): return mod.Grid(request or self.request, **kwargs) def test_constructor(self): # empty grid = self.make_grid() self.assertIsNone(grid.key) self.assertEqual(grid.columns, []) self.assertIsNone(grid.data) # now with columns grid = self.make_grid(columns=['foo', 'bar']) self.assertIsInstance(grid.columns, FieldList) self.assertEqual(grid.columns, ['foo', 'bar']) def test_constructor_sorting(self): model = self.app.model # defaults, not sortable grid = self.make_grid() self.assertFalse(grid.sortable) self.assertTrue(grid.sort_on_backend) self.assertEqual(grid.sorters, {}) self.assertEqual(grid.sort_defaults, []) # defaults, sortable grid = self.make_grid(sortable=True) self.assertTrue(grid.sortable) self.assertTrue(grid.sort_on_backend) self.assertEqual(grid.sorters, {}) self.assertEqual(grid.sort_defaults, []) # sorters may be pre-populated grid = self.make_grid(model_class=model.Setting, sortable=True) self.assertEqual(len(grid.sorters), 2) self.assertIn('name', grid.sorters) self.assertIn('value', grid.sorters) self.assertEqual(grid.sort_defaults, []) # sort defaults as str grid = self.make_grid(model_class=model.Setting, sortable=True, sort_defaults='name') self.assertEqual(grid.sort_defaults, [mod.SortInfo('name', 'asc')]) # sort defaults as tuple grid = self.make_grid(model_class=model.Setting, sortable=True, sort_defaults=('name', 'desc')) self.assertEqual(grid.sort_defaults, [mod.SortInfo('name', 'desc')]) # sort defaults as list w/ single tuple grid = self.make_grid(model_class=model.Setting, sortable=True, sort_defaults=[('name', 'desc')]) self.assertEqual(grid.sort_defaults, [mod.SortInfo('name', 'desc')]) # sort defaults as list w/ multiple grid = self.make_grid(model_class=model.Setting, sortable=True, sort_defaults=[('name', 'desc'), ('value', 'asc')]) self.assertEqual(grid.sort_defaults, [mod.SortInfo('name', 'desc')]) def test_vue_tagname(self): grid = self.make_grid() self.assertEqual(grid.vue_tagname, 'wutta-grid') def test_vue_component(self): grid = self.make_grid() self.assertEqual(grid.vue_component, 'WuttaGrid') def test_get_columns(self): model = self.app.model # empty grid = self.make_grid() self.assertEqual(grid.columns, []) self.assertEqual(grid.get_columns(), []) # explicit grid = self.make_grid(columns=['foo', 'bar']) self.assertEqual(grid.columns, ['foo', 'bar']) self.assertEqual(grid.get_columns(), ['foo', 'bar']) # derived from model grid = self.make_grid(model_class=model.Setting) self.assertEqual(grid.columns, ['name', 'value']) self.assertEqual(grid.get_columns(), ['name', 'value']) def test_append(self): grid = self.make_grid(columns=['one', 'two']) self.assertEqual(grid.columns, ['one', 'two']) grid.append('one', 'two', 'three') self.assertEqual(grid.columns, ['one', 'two', 'three']) def test_remove(self): grid = self.make_grid(columns=['one', 'two', 'three', 'four']) self.assertEqual(grid.columns, ['one', 'two', 'three', 'four']) grid.remove('two', 'three') self.assertEqual(grid.columns, ['one', 'four']) def test_set_label(self): grid = self.make_grid(columns=['foo', 'bar']) self.assertEqual(grid.labels, {}) # basic grid.set_label('foo', "Foo Fighters") self.assertEqual(grid.labels['foo'], "Foo Fighters") # can replace label grid.set_label('foo', "Different") self.assertEqual(grid.labels['foo'], "Different") self.assertEqual(grid.get_label('foo'), "Different") def test_get_label(self): grid = self.make_grid(columns=['foo', 'bar']) self.assertEqual(grid.labels, {}) # default derived from key self.assertEqual(grid.get_label('foo'), "Foo") # can override grid.set_label('foo', "Different") self.assertEqual(grid.get_label('foo'), "Different") def test_set_renderer(self): grid = self.make_grid(columns=['foo', 'bar']) self.assertEqual(grid.renderers, {}) def render1(record, key, value): pass # basic grid.set_renderer('foo', render1) self.assertIs(grid.renderers['foo'], render1) def render2(record, key, value, extra=None): return extra # can pass kwargs to get a partial grid.set_renderer('foo', render2, extra=42) self.assertIsNot(grid.renderers['foo'], render2) self.assertEqual(grid.renderers['foo'](None, None, None), 42) def test_linked_columns(self): grid = self.make_grid(columns=['foo', 'bar']) self.assertEqual(grid.linked_columns, []) self.assertFalse(grid.is_linked('foo')) grid.set_link('foo') self.assertEqual(grid.linked_columns, ['foo']) self.assertTrue(grid.is_linked('foo')) self.assertFalse(grid.is_linked('bar')) grid.set_link('bar') self.assertEqual(grid.linked_columns, ['foo', 'bar']) self.assertTrue(grid.is_linked('foo')) self.assertTrue(grid.is_linked('bar')) grid.set_link('foo', False) self.assertEqual(grid.linked_columns, ['bar']) self.assertFalse(grid.is_linked('foo')) self.assertTrue(grid.is_linked('bar')) def test_get_pagesize_options(self): grid = self.make_grid() # default options = grid.get_pagesize_options() self.assertEqual(options, [5, 10, 20, 50, 100, 200]) # override default options = grid.get_pagesize_options(default=[42]) self.assertEqual(options, [42]) # from config self.config.setdefault('wuttaweb.grids.default_pagesize_options', '1 2 3') options = grid.get_pagesize_options() self.assertEqual(options, [1, 2, 3]) def test_get_pagesize(self): grid = self.make_grid() # default size = grid.get_pagesize() self.assertEqual(size, 20) # override default size = grid.get_pagesize(default=42) self.assertEqual(size, 42) # override default options self.config.setdefault('wuttaweb.grids.default_pagesize_options', '10 15 30') grid = self.make_grid() size = grid.get_pagesize() self.assertEqual(size, 10) # from config self.config.setdefault('wuttaweb.grids.default_pagesize', '15') size = grid.get_pagesize() self.assertEqual(size, 15) ############################## # configuration methods ############################## def test_load_settings(self): model = self.app.model # nb. first use a paging grid 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) # nb. next use a sorting grid grid = self.make_grid(key='settings', model_class=model.Setting, sortable=True, sort_on_backend=True) # settings are loaded, applied, saved self.assertEqual(grid.sort_defaults, []) self.assertFalse(hasattr(grid, 'active_sorters')) self.request.GET = {'sort1key': 'name', 'sort1dir': 'desc'} grid.load_settings() self.assertEqual(grid.active_sorters, [{'key': 'name', 'dir': 'desc'}]) self.assertEqual(self.request.session['grid.settings.sorters.length'], 1) self.assertEqual(self.request.session['grid.settings.sorters.1.key'], 'name') self.assertEqual(self.request.session['grid.settings.sorters.1.dir'], 'desc') # can skip the saving step self.request.GET = {'sort1key': 'name', 'sort1dir': 'asc'} grid.load_settings(store=False) self.assertEqual(grid.active_sorters, [{'key': 'name', 'dir': 'asc'}]) self.assertEqual(self.request.session['grid.settings.sorters.length'], 1) self.assertEqual(self.request.session['grid.settings.sorters.1.key'], 'name') self.assertEqual(self.request.session['grid.settings.sorters.1.dir'], 'desc') # no error for non-sortable grid grid = self.make_grid(key='foo', sortable=False) grid.load_settings() self.assertFalse(grid.sortable) # with sort defaults grid = self.make_grid(model_class=model.Setting, sortable=True, sort_on_backend=True, sort_defaults='name') self.assertFalse(hasattr(grid, 'active_sorters')) grid.load_settings() self.assertEqual(grid.active_sorters, [{'key': 'name', 'dir': 'asc'}]) # with multi-column sort defaults grid = self.make_grid(model_class=model.Setting, sortable=True, sort_on_backend=True) grid.sort_defaults = [ mod.SortInfo('name', 'asc'), mod.SortInfo('value', 'desc'), ] self.assertFalse(hasattr(grid, 'active_sorters')) grid.load_settings() self.assertEqual(grid.active_sorters, [{'key': 'name', 'dir': 'asc'}]) # load settings from session when nothing is in request self.request.GET = {} self.request.session.invalidate() self.assertNotIn('grid.settings.sorters.length', self.request.session) self.request.session['grid.settings.sorters.length'] = 1 self.request.session['grid.settings.sorters.1.key'] = 'name' self.request.session['grid.settings.sorters.1.dir'] = 'desc' grid = self.make_grid(key='settings', model_class=model.Setting, sortable=True, sort_on_backend=True, paginated=True, paginate_on_backend=True) self.assertFalse(hasattr(grid, 'active_sorters')) grid.load_settings() self.assertEqual(grid.active_sorters, [{'key': 'name', 'dir': 'desc'}]) def test_request_has_settings(self): grid = self.make_grid(key='foo') # paging self.assertFalse(grid.request_has_settings('page')) with patch.object(self.request, 'GET', new={'pagesize': '20'}): self.assertTrue(grid.request_has_settings('page')) with patch.object(self.request, 'GET', new={'page': '1'}): self.assertTrue(grid.request_has_settings('page')) # sorting self.assertFalse(grid.request_has_settings('sort')) with patch.object(self.request, 'GET', new={'sort1key': 'name'}): self.assertTrue(grid.request_has_settings('sort')) def test_get_setting(self): grid = self.make_grid(key='foo') settings = {} # default is null value = grid.get_setting(settings, 'pagesize') self.assertIsNone(value) # can read value from user session self.request.session['grid.foo.pagesize'] = 15 value = grid.get_setting(settings, 'pagesize', src='session') self.assertEqual(value, 15) # string value not normalized self.request.session['grid.foo.pagesize'] = '15' value = grid.get_setting(settings, 'pagesize', src='session') self.assertEqual(value, '15') self.assertNotEqual(value, 15) # but can be normalized self.request.session['grid.foo.pagesize'] = '15' value = grid.get_setting(settings, 'pagesize', src='session', normalize=int) self.assertEqual(value, 15) # can read value from request self.request.GET = {'pagesize': '25'} value = grid.get_setting(settings, 'pagesize', src='request', normalize=int) self.assertEqual(value, 25) # null when normalization fails self.request.GET = {'pagesize': 'invalid'} value = grid.get_setting(settings, 'pagesize', src='request', normalize=int) self.assertIsNone(value) # reset del self.request.session['grid.foo.pagesize'] self.request.GET = {} # value can come from provided settings settings['pagesize'] = '35' value = grid.get_setting(settings, 'pagesize', src='session', normalize=int) self.assertEqual(value, 35) def test_update_sort_settings(self): model = self.app.model # nothing happens if not sortable grid = self.make_grid(key='settings', model_class=model.Setting) settings = {'sorters.length': 0} self.request.session['grid.settings.sorters.length'] = 1 self.request.session['grid.settings.sorters.1.key'] = 'name' self.request.session['grid.settings.sorters.1.dir'] = 'asc' grid.update_sort_settings(settings, src='session') self.assertEqual(settings['sorters.length'], 0) # nb. now use a sortable grid grid = self.make_grid(key='settings', model_class=model.Setting, sortable=True, sort_on_backend=True) # settings are updated from session settings = {'sorters.length': 1, 'sorters.1.key': 'name', 'sorters.1.dir': 'asc'} self.request.session['grid.settings.sorters.length'] = 1 self.request.session['grid.settings.sorters.1.key'] = 'name' self.request.session['grid.settings.sorters.1.dir'] = 'asc' grid.update_sort_settings(settings, src='session') self.assertEqual(settings['sorters.length'], 1) self.assertEqual(settings['sorters.1.key'], 'name') self.assertEqual(settings['sorters.1.dir'], 'asc') # settings are updated from request self.request.GET = {'sort1key': 'value', 'sort1dir': 'desc'} grid.update_sort_settings(settings, src='request') self.assertEqual(settings['sorters.length'], 1) self.assertEqual(settings['sorters.1.key'], 'value') self.assertEqual(settings['sorters.1.dir'], 'desc') def test_update_page_settings(self): # nothing happens if not paginated grid = self.make_grid(key='foo') 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'], 20) self.assertEqual(settings['page'], 1) # nb. now use a paginated grid grid = self.make_grid(key='foo', paginated=True, paginate_on_backend=True) # 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): model = self.app.model # nb. start out with paginated-only grid grid = self.make_grid(key='foo', paginated=True, paginate_on_backend=True) # invalid dest self.assertRaises(ValueError, grid.persist_settings, {}, dest='doesnotexist') # nb. no error if empty settings, but it saves null values grid.persist_settings({}, dest='session') self.assertIsNone(self.request.session['grid.foo.page']) # provided values are saved grid.persist_settings({'pagesize': 15, 'page': 3}, dest='session') self.assertEqual(self.request.session['grid.foo.page'], 3) # nb. now switch to sortable-only grid grid = self.make_grid(key='settings', model_class=model.Setting, sortable=True, sort_on_backend=True) # no error if empty settings; does not save values grid.persist_settings({}, dest='session') self.assertNotIn('grid.settings.sorters.length', self.request.session) # provided values are saved grid.persist_settings({'sorters.length': 2, 'sorters.1.key': 'name', 'sorters.1.dir': 'desc', 'sorters.2.key': 'value', 'sorters.2.dir': 'asc'}, dest='session') self.assertEqual(self.request.session['grid.settings.sorters.length'], 2) self.assertEqual(self.request.session['grid.settings.sorters.1.key'], 'name') self.assertEqual(self.request.session['grid.settings.sorters.1.dir'], 'desc') self.assertEqual(self.request.session['grid.settings.sorters.2.key'], 'value') self.assertEqual(self.request.session['grid.settings.sorters.2.dir'], 'asc') # old values removed when new are saved grid.persist_settings({'sorters.length': 1, 'sorters.1.key': 'name', 'sorters.1.dir': 'desc'}, dest='session') self.assertEqual(self.request.session['grid.settings.sorters.length'], 1) self.assertEqual(self.request.session['grid.settings.sorters.1.key'], 'name') self.assertEqual(self.request.session['grid.settings.sorters.1.dir'], 'desc') self.assertNotIn('grid.settings.sorters.2.key', self.request.session) self.assertNotIn('grid.settings.sorters.2.dir', self.request.session) ############################## # sorting methods ############################## def test_make_backend_sorters(self): model = self.app.model # default is empty grid = self.make_grid() sorters = grid.make_backend_sorters() self.assertEqual(sorters, {}) # makes sorters if model class grid = self.make_grid(model_class=model.Setting) sorters = grid.make_backend_sorters() self.assertEqual(len(sorters), 2) self.assertIn('name', sorters) self.assertIn('value', sorters) # does not replace supplied sorters grid = self.make_grid(model_class=model.Setting) mysorters = {'value': 42} sorters = grid.make_backend_sorters(mysorters) self.assertEqual(len(sorters), 2) self.assertIn('name', sorters) self.assertIn('value', sorters) self.assertEqual(sorters['value'], 42) self.assertEqual(mysorters['value'], 42) def test_make_sorter(self): model = self.app.model sample_data = [ {'name': 'foo1', 'value': 'ONE'}, {'name': 'foo2', 'value': 'two'}, {'name': 'foo3', 'value': 'three'}, {'name': 'foo4', 'value': 'four'}, {'name': 'foo5', 'value': 'five'}, {'name': 'foo6', 'value': 'six'}, {'name': 'foo7', 'value': 'seven'}, {'name': 'foo8', 'value': 'eight'}, {'name': 'foo9', 'value': 'nine'}, ] for setting in sample_data: self.app.save_setting(self.session, setting['name'], setting['value']) self.session.commit() sample_query = self.session.query(model.Setting) # plain data grid = self.make_grid(columns=['name', 'value']) sorter = grid.make_sorter('name') sorted_data = sorter(sample_data, 'desc') self.assertEqual(sorted_data[0], {'name': 'foo9', 'value': 'nine'}) sorted_data = sorter(sample_data, 'asc') self.assertEqual(sorted_data[0], {'name': 'foo1', 'value': 'ONE'}) # model class, but still plain data grid = self.make_grid(model_class=model.Setting) sorter = grid.make_sorter('name') sorted_data = sorter(sample_data, 'desc') self.assertEqual(sorted_data[0], {'name': 'foo9', 'value': 'nine'}) sorted_data = sorter(sample_data, 'asc') self.assertEqual(sorted_data[0], {'name': 'foo1', 'value': 'ONE'}) # repeat previous test, w/ model property grid = self.make_grid(model_class=model.Setting) sorter = grid.make_sorter(model.Setting.name) sorted_data = sorter(sample_data, 'desc') self.assertEqual(sorted_data[0], {'name': 'foo9', 'value': 'nine'}) sorted_data = sorter(sample_data, 'asc') self.assertEqual(sorted_data[0], {'name': 'foo1', 'value': 'ONE'}) # sqlalchemy query grid = self.make_grid(model_class=model.Setting) sorter = grid.make_sorter('name') sorted_query = sorter(sample_query, 'desc') sorted_data = sorted_query.all() self.assertEqual(dict(sorted_data[0]), {'name': 'foo9', 'value': 'nine'}) sorted_query = sorter(sample_query, 'asc') sorted_data = sorted_query.all() self.assertEqual(dict(sorted_data[0]), {'name': 'foo1', 'value': 'ONE'}) # repeat previous test, w/ model property grid = self.make_grid(model_class=model.Setting) sorter = grid.make_sorter(model.Setting.name) sorted_query = sorter(sample_query, 'desc') sorted_data = sorted_query.all() self.assertEqual(dict(sorted_data[0]), {'name': 'foo9', 'value': 'nine'}) sorted_query = sorter(sample_query, 'asc') sorted_data = sorted_query.all() self.assertEqual(dict(sorted_data[0]), {'name': 'foo1', 'value': 'ONE'}) # sortfunc for "invalid" column will fail when called; however # it can work for manual sort w/ custom keyfunc grid = self.make_grid(model_class=model.Setting) sorter = grid.make_sorter('doesnotexist') self.assertRaises(TypeError, sorter, sample_query, 'desc') self.assertRaises(KeyError, sorter, sample_data, 'desc') sorter = grid.make_sorter('doesnotexist', keyfunc=lambda obj: obj['name']) sorted_data = sorter(sample_data, 'desc') self.assertEqual(len(sorted_data), 9) sorted_data = sorter(sample_data, 'asc') self.assertEqual(len(sorted_data), 9) # case folding is off by default grid = self.make_grid(model_class=model.Setting) sorter = grid.make_sorter('value') sorted_data = sorter(sample_data, 'desc') self.assertEqual(dict(sorted_data[0]), {'name': 'foo2', 'value': 'two'}) sorted_data = sorter(sample_data, 'asc') self.assertEqual(dict(sorted_data[0]), {'name': 'foo1', 'value': 'ONE'}) # results are different with case folding grid = self.make_grid(model_class=model.Setting) sorter = grid.make_sorter('value', foldcase=True) sorted_data = sorter(sample_data, 'desc') self.assertEqual(dict(sorted_data[0]), {'name': 'foo2', 'value': 'two'}) sorted_data = sorter(sample_data, 'asc') self.assertEqual(dict(sorted_data[0]), {'name': 'foo8', 'value': 'eight'}) def test_set_sorter(self): model = self.app.model # explicit sortfunc grid = self.make_grid() self.assertEqual(grid.sorters, {}) sortfunc = lambda data, direction: data grid.set_sorter('foo', sortfunc) self.assertIs(grid.sorters['foo'], sortfunc) # auto from model property grid = self.make_grid(model_class=model.Setting, sortable=True, sorters={}) self.assertEqual(grid.sorters, {}) grid.set_sorter('name', model.Setting.name) self.assertTrue(callable(grid.sorters['name'])) # auto from column name grid = self.make_grid(model_class=model.Setting, sortable=True, sorters={}) self.assertEqual(grid.sorters, {}) grid.set_sorter('name', 'name') self.assertTrue(callable(grid.sorters['name'])) # auto from key grid = self.make_grid(model_class=model.Setting, sortable=True, sorters={}) self.assertEqual(grid.sorters, {}) grid.set_sorter('name') self.assertTrue(callable(grid.sorters['name'])) def test_remove_sorter(self): model = self.app.model # basics grid = self.make_grid(model_class=model.Setting, sortable=True) self.assertEqual(len(grid.sorters), 2) self.assertIn('name', grid.sorters) self.assertIn('value', grid.sorters) grid.remove_sorter('value') self.assertNotIn('value', grid.sorters) def test_set_sort_defaults(self): model = self.app.model # basics grid = self.make_grid(model_class=model.Setting, sortable=True) self.assertEqual(grid.sort_defaults, []) grid.set_sort_defaults('name', 'asc') self.assertEqual(grid.sort_defaults, [mod.SortInfo('name', 'asc')]) def test_is_sortable(self): model = self.app.model # basics, frontend sorting grid = self.make_grid(model_class=model.Setting, sortable=True, sort_on_backend=False) self.assertTrue(grid.is_sortable('name')) self.assertTrue(grid.is_sortable('value')) grid.remove_sorter('value') # nb. columns are always sortable for frontend, despite remove_sorter() self.assertTrue(grid.is_sortable('value')) # nb. when grid is not sortable, no column is either grid.sortable = False self.assertFalse(grid.is_sortable('name')) # same test but with backend sorting grid = self.make_grid(model_class=model.Setting, sortable=True, sort_on_backend=True) self.assertTrue(grid.is_sortable('name')) self.assertTrue(grid.is_sortable('value')) grid.remove_sorter('value') self.assertFalse(grid.is_sortable('value')) # nb. when grid is not sortable, no column is either grid.sortable = False self.assertFalse(grid.is_sortable('name')) ############################## # data methods ############################## def test_get_visible_data(self): model = self.app.model sample_data = [ {'name': 'foo1', 'value': 'ONE'}, {'name': 'foo2', 'value': 'two'}, {'name': 'foo3', 'value': 'three'}, {'name': 'foo4', 'value': 'four'}, {'name': 'foo5', 'value': 'five'}, {'name': 'foo6', 'value': 'six'}, {'name': 'foo7', 'value': 'seven'}, {'name': 'foo8', 'value': 'eight'}, {'name': 'foo9', 'value': 'nine'}, ] for setting in sample_data: self.app.save_setting(self.session, setting['name'], setting['value']) self.session.commit() sample_query = self.session.query(model.Setting) # data is sorted and paginated grid = self.make_grid(model_class=model.Setting, data=sample_query, sortable=True, sort_on_backend=True, sort_defaults=('name', 'desc'), paginated=True, paginate_on_backend=True, pagesize=4, page=2) grid.load_settings() visible = grid.get_visible_data() self.assertEqual([s.name for s in visible], ['foo5', 'foo4', 'foo3', 'foo2']) def test_sort_data(self): model = self.app.model sample_data = [ {'name': 'foo1', 'value': 'ONE'}, {'name': 'foo2', 'value': 'two'}, {'name': 'foo3', 'value': 'three'}, {'name': 'foo4', 'value': 'four'}, {'name': 'foo5', 'value': 'five'}, {'name': 'foo6', 'value': 'six'}, {'name': 'foo7', 'value': 'seven'}, {'name': 'foo8', 'value': 'eight'}, {'name': 'foo9', 'value': 'nine'}, ] for setting in sample_data: self.app.save_setting(self.session, setting['name'], setting['value']) self.session.commit() sample_query = self.session.query(model.Setting) grid = self.make_grid(model_class=model.Setting, sortable=True, sort_on_backend=True, sort_defaults=('name', 'desc')) grid.load_settings() # can sort a simple list of data sorted_data = grid.sort_data(sample_data) self.assertIsInstance(sorted_data, list) self.assertEqual(len(sorted_data), 9) self.assertEqual(sorted_data[0]['name'], 'foo9') self.assertEqual(sorted_data[-1]['name'], 'foo1') # can also sort a data query sorted_query = grid.sort_data(sample_query) self.assertIsInstance(sorted_query, orm.Query) sorted_data = sorted_query.all() self.assertEqual(len(sorted_data), 9) self.assertEqual(sorted_data[0]['name'], 'foo9') self.assertEqual(sorted_data[-1]['name'], 'foo1') # cannot sort data if sorter missing in overrides sorted_data = grid.sort_data(sample_data, sorters=[]) # nb. sorted data is in same order as original sample (not sorted) self.assertEqual(sorted_data[0]['name'], 'foo1') self.assertEqual(sorted_data[-1]['name'], 'foo9') # error if mult-column sort attempted self.assertRaises(NotImplementedError, grid.sort_data, sample_data, sorters=[ {'key': 'name', 'dir': 'desc'}, {'key': 'value', 'dir': 'asc'}, ]) # cannot sort data if sortfunc is missing for column grid.remove_sorter('name') sorted_data = grid.sort_data(sample_data) # nb. sorted data is in same order as original sample (not sorted) self.assertEqual(sorted_data[0]['name'], 'foo1') self.assertEqual(sorted_data[-1]['name'], 'foo9') def test_paginate_data(self): model = self.app.model sample_data = [ {'name': 'foo1', 'value': 'ONE'}, {'name': 'foo2', 'value': 'two'}, {'name': 'foo3', 'value': 'three'}, {'name': 'foo4', 'value': 'four'}, {'name': 'foo5', 'value': 'five'}, {'name': 'foo6', 'value': 'six'}, {'name': 'foo7', 'value': 'seven'}, {'name': 'foo8', 'value': 'eight'}, {'name': 'foo9', 'value': 'nine'}, ] for setting in sample_data: self.app.save_setting(self.session, setting['name'], setting['value']) self.session.commit() sample_query = self.session.query(model.Setting) # basic list pager grid = self.make_grid(paginated=True, paginate_on_backend=True) pager = grid.paginate_data(sample_data) self.assertIsInstance(pager, Page) # basic query pager grid = self.make_grid(paginated=True, paginate_on_backend=True) pager = grid.paginate_data(sample_query) self.assertIsInstance(pager, SqlalchemyOrmPage) # page is reset to 1 for empty data self.request.session['grid.foo.page'] = 2 grid = self.make_grid(key='foo', paginated=True, paginate_on_backend=True) grid.load_settings() self.assertEqual(grid.page, 2) self.assertEqual(self.request.session['grid.foo.page'], 2) pager = grid.paginate_data(sample_data) self.assertEqual(pager.page, 1) self.assertEqual(grid.page, 1) self.assertEqual(self.request.session['grid.foo.page'], 1) ############################## # rendering methods ############################## def test_render_vue_tag(self): grid = self.make_grid(columns=['foo', 'bar']) html = grid.render_vue_tag() self.assertEqual(html, '') def test_render_vue_template(self): self.pyramid_config.include('pyramid_mako') self.pyramid_config.add_subscriber('wuttaweb.subscribers.before_render', 'pyramid.events.BeforeRender') grid = self.make_grid(columns=['foo', 'bar']) html = grid.render_vue_template() self.assertIn('