from axiom.store import Store from axiom.item import Item from axiom.attributes import integer, text, AND from twisted.trial import unittest from xmantissa import tdb class X(Item): typeName = 'test_tdb_model_dummy' schemaVersion = 1 number = integer() textNumber = text() phoneticDigits = text() digits = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'] def breakdown(x): for c in x: yield digits[int(c)] class ModelTest(unittest.TestCase): def setUp(self): self.store = Store() def _(): for x in range(107): X(store=self.store, number=x, textNumber=unicode(x), phoneticDigits=u' '.join(breakdown(str(x)))) self.store.transact(_) def assertNumbersAre(self, tdm, seq): self.assertEquals(list(x.get('number') for x in tdm.currentPage()), seq) def testUniformValues(self): for x in self.store.query(X): x.number = 1 tdm = tdb.TabularDataModel(self.store, X, [X.number], itemsPerPage=15) self.failUnless(tdm.hasNextPage(), 'expected there to be a next page') def testDeleteEverything(self): tdm = tdb.TabularDataModel(self.store, X, [X.number, X.textNumber, X.phoneticDigits], itemsPerPage=15) self.assertNumbersAre(tdm, range(15)) for item in self.store.query(X): item.deleteFromStore() self.assertNumbersAre(tdm, []) def testOnePage(self): tdm = tdb.TabularDataModel(self.store, X, [X.number, X.textNumber, X.phoneticDigits], AND(X.number >= 17, X.number < 94), itemsPerPage=15) _assertNumbersAre = lambda seq: self.assertNumbersAre(tdm, seq) _assertNumbersAre(range(17, 17+15)) tdm.nextPage() _assertNumbersAre(range(17+15, 17+30)) tdm.firstPage() _assertNumbersAre(range(17, 17+15)) def testLeafing(self): tdm = tdb.TabularDataModel(self.store, X, [X.number, X.textNumber, X.phoneticDigits], itemsPerPage=15) _assertNumbersAre = lambda seq: self.assertNumbersAre(tdm, seq) _assertNumbersAre(range(15)) tdm.nextPage() _assertNumbersAre(range(15, 30)) tdm.prevPage() _assertNumbersAre(range(15)) tdm.lastPage() # This next assert is kind of weak, because it is valid to have only a # few results on the last page, but right now the strategy is to # always keep the page full of results. No matter what though, the # last page should contain the last value. self.assertEquals(list(tdm.currentPage())[-1]['number'], 106) tdm.firstPage() _assertNumbersAre(range(15)) def testLeafingAndSorting(self): tdm = tdb.TabularDataModel(self.store, X, [X.number, X.textNumber, X.phoneticDigits], itemsPerPage=15) _assertNumbersAre = lambda seq: self.assertNumbersAre(tdm, seq) _assertNumbersAre(range(15)) tdm.lastPage() _assertNumbersAre(range(107-15, 107)) tdm.prevPage() _assertNumbersAre(range(107-30, 107-15)) tdm.firstPage() _assertNumbersAre(range(15)) tdm.resort('number', False) tdm.firstPage() _assertNumbersAre(list(reversed(range(107-15, 107)))) tdm.lastPage() _assertNumbersAre(list(reversed(range(15)))) def testPageUnderrun(self): tdm = tdb.TabularDataModel(self.store, X, [X.number, X.textNumber, X.phoneticDigits], itemsPerPage=15) _assertNumbersAre = lambda seq: self.assertNumbersAre(tdm, seq) _assertNumbersAre(range(15)) # go to the pre-penultimate page for i in xrange(5): tdm.nextPage() _assertNumbersAre(range(15*5, (15*5)+15)) tdm.nextPage() lastFullSet = range(15*6, (15*6)+15) _assertNumbersAre(lastFullSet) tdm.nextPage() lastSet = [105, 106] _assertNumbersAre(lastSet) def testItemUnderrun(self): tdm = tdb.TabularDataModel(self.store, X, [X.number, X.textNumber, X.phoneticDigits], itemsPerPage=110) assertFirstPage = lambda: self.assertNumbersAre(tdm, range(107)) assertFirstPage() tdm.nextPage() assertFirstPage() tdm.prevPage() assertFirstPage() tdm.lastPage() assertFirstPage() tdm.firstPage() assertFirstPage() def testTwoPageNextLastEquality(self): tdm = tdb.TabularDataModel(self.store, X, [X.number], itemsPerPage=100) assertFirstPage = lambda: self.assertNumbersAre(tdm, range(100)) assertSecondPage = lambda: self.assertNumbersAre(tdm, range(100, 107)) assertFirstPage() tdm.nextPage() assertSecondPage() tdm.firstPage() assertFirstPage() tdm.lastPage() assertSecondPage() testTwoPageNextLastEquality.todo = 'is this a bug? it seems like one to me' def testPagination(self): tdm = tdb.TabularDataModel(self.store, X, [X.number, X.textNumber, X.phoneticDigits], itemsPerPage=15) self.assertEquals(tdm.pageNumber, 1) self.assertEquals(tdm.totalItems, 107) self.assertEquals(tdm.totalPages, 8) tdm.nextPage() self.assertEquals(tdm.pageNumber, 2) self.assertEquals(tdm.totalItems, 107) self.assertEquals(tdm.totalPages, 8) tdm.nextPage() self.assertEquals(tdm.pageNumber, 3) self.assertEquals(tdm.totalItems, 107) self.assertEquals(tdm.totalPages, 8) tdm.nextPage() self.assertEquals(tdm.pageNumber, 4) self.assertEquals(tdm.totalItems, 107) self.assertEquals(tdm.totalPages, 8) tdm.nextPage() self.assertEquals(tdm.pageNumber, 5) self.assertEquals(tdm.totalItems, 107) self.assertEquals(tdm.totalPages, 8) tdm.nextPage() self.assertEquals(tdm.pageNumber, 6) self.assertEquals(tdm.totalItems, 107) self.assertEquals(tdm.totalPages, 8) tdm.nextPage() self.assertEquals(tdm.pageNumber, 7) self.assertEquals(tdm.totalItems, 107) self.assertEquals(tdm.totalPages, 8) tdm.nextPage() self.assertEquals(tdm.pageNumber, 8) self.assertEquals(tdm.totalItems, 107) self.assertEquals(tdm.totalPages, 8) tdm.lastPage() self.assertEquals(tdm.pageNumber, 8) self.assertEquals(tdm.totalPages, 8) self.assertEquals(tdm.totalItems, 107) tdm.firstPage() self.assertEquals(tdm.pageNumber, 1) self.assertEquals(tdm.totalPages, 8) self.assertEquals(tdm.totalItems, 107) def testSortItemUnderrun(self): tdm = tdb.TabularDataModel(self.store, X, [X.number, X.textNumber, X.phoneticDigits], itemsPerPage=110) assertFirstPage = lambda: self.assertNumbersAre(tdm, range(107)) assertFirstPage() tdm.resort(tdm.currentSortColumn.attributeID) assertFirstPage() tdm.resort(tdm.currentSortColumn.attributeID, False) self.assertNumbersAre(tdm, list(reversed(range(107)))) tdm.resort(tdm.currentSortColumn.attributeID) assertFirstPage() tdm.resort(tdm.currentSortColumn.attributeID, True) assertFirstPage() def testChangeSortColumnItemUnderrun(self): tdm = tdb.TabularDataModel(self.store, X, [X.number, X.textNumber, X.phoneticDigits], itemsPerPage=110) assertFirstPage = lambda: self.assertNumbersAre(tdm, range(107)) assertFirstPage() tdm.resort(tdm.currentSortColumn.attributeID, True) assertFirstPage() # change sort direction, keep column tdm.resort(tdm.currentSortColumn.attributeID, False) self.assertNumbersAre(tdm, list(reversed(range(107)))) # change sort column and direction tdm.resort('phoneticDigits', True) # switch back to previous sort column & direction tdm.resort('number', False) self.assertNumbersAre(tdm, list(reversed(range(107)))) msg = 'itemsPerPage > totalItems, should only have one page' self.failIf(tdm.hasPrevPage(), msg) self.failIf(tdm.hasNextPage(), msg) def testOnePageHasNextPrev(self): bigtdm = tdb.TabularDataModel(self.store, X, [X.number, X.textNumber, X.phoneticDigits], itemsPerPage=200) bigtdm.nextPage() bigtdm.nextPage() self.failIf(bigtdm.hasNextPage()) self.failIf(bigtdm.hasPrevPage()) def testMultiPageHasNextPrev(self): tdm = tdb.TabularDataModel(self.store, X, [X.number, X.textNumber, X.phoneticDigits], itemsPerPage=15) self.failIf(tdm.hasPrevPage()) self.failUnless(tdm.hasNextPage()) tdm.nextPage() self.failUnless(tdm.hasNextPage()) self.failUnless(tdm.hasPrevPage()) tdm.prevPage() self.failIf(tdm.hasPrevPage()) self.failUnless(tdm.hasNextPage()) tdm.lastPage() self.failIf(tdm.hasNextPage()) self.failUnless(tdm.hasPrevPage()) tdm.prevPage() self.failUnless(tdm.hasNextPage()) self.failUnless(tdm.hasPrevPage()) tdm.firstPage() for x in range(6): tdm.nextPage() self.failUnless(tdm.hasPrevPage()) self.failUnless(tdm.hasNextPage()) tdm.nextPage() self.failUnless(tdm.hasPrevPage()) self.failIf(tdm.hasNextPage()) def testCurrentPageDoesntChange(self): tdm = tdb.TabularDataModel(self.store, X, [X.number, X.textNumber, X.phoneticDigits], itemsPerPage=15) for y in range(3): tdm.nextPage() example = tdm.currentPage() for x in range(3): self.assertEquals(example, tdm.currentPage()) def testDeleteItems(self): tdm = tdb.TabularDataModel(self.store, X, [X.number, X.textNumber, X.phoneticDigits], itemsPerPage=15) r = tdm.currentPage() r0 = r[0]['__item__'] r0.deleteFromStore() rx = tdm.currentPage() r1 = rx[0]['__item__'] self.failIf(r1._Item__deleting, "First item in current page was deleted!") r1.deleteFromStore() tdm.nextPage() self.assertNumbersAre(tdm, range(16, 16+15)) tdm.prevPage() self.assertNumbersAre(tdm, range(2, 2+15)) # The distinction between this test and the nextPage test above is # important: we never "skip" items when paging. The current results of # the TDM represent *what the user has seen*. In the previous case, we # have never called currentPage and received a result with #16 in it # before calling nextPage. In this case, assertNumbersAre(2,...) has # "seen" the page with #16 on it, so we are (correctly) taken to the # next item after that to begin the next page. tdm.nextPage() self.assertNumbersAre(tdm, range(17, 17+15)) def testSorting(self): tdm = tdb.TabularDataModel(self.store, X, [X.number, X.textNumber, X.phoneticDigits], itemsPerPage=15) _assertNumbersAre = lambda seq: self.assertNumbersAre(tdm, seq) tdm.resort('number', True) _assertNumbersAre(range(15)) tdm.resort('number', False) _assertNumbersAre(list(reversed(range(15)))) _assertNumbersAre(list(reversed(range(15)))) tdm.nextPage() _assertNumbersAre(list(reversed(range(15)))) def testUnsortableColumns(self): class UnsortableColumn(tdb.AttributeColumn): def sortAttribute(self): return None tdm = tdb.TabularDataModel(self.store, X, [X.number, UnsortableColumn(X.textNumber), UnsortableColumn(X.phoneticDigits)], itemsPerPage=15) self.assertNumbersAre(tdm, range(15)) self.assertRaises(tdb.Unsortable, lambda: tdm.resort('textNumber')) self.assertRaises(tdb.Unsortable, lambda: tdm.resort('phoneticDigits')) # check to see if the last valid state remains self.assertNumbersAre(tdm, range(15))