Back to index

plone3  3.1.7
test_navigation_portlet.py
Go to the documentation of this file.
00001 from zope.component import getUtility, getMultiAdapter
00002 
00003 from Products.GenericSetup.utils import _getDottedName
00004 
00005 from plone.portlets.interfaces import IPortletType
00006 from plone.portlets.interfaces import IPortletManager
00007 from plone.portlets.interfaces import IPortletAssignment
00008 from plone.portlets.interfaces import IPortletDataProvider
00009 from plone.portlets.interfaces import IPortletRenderer
00010 
00011 from plone.app.portlets.portlets import navigation
00012 from plone.app.portlets.storage import PortletAssignmentMapping
00013 
00014 from plone.app.portlets.tests.base import PortletsTestCase
00015 
00016 from Products.CMFPlone.tests import dummy
00017 
00018 class TestPortlet(PortletsTestCase):
00019 
00020     def afterSetUp(self):
00021         self.setRoles(('Manager',))
00022 
00023     def testPortletTypeRegistered(self):
00024         portlet = getUtility(IPortletType, name='portlets.Navigation')
00025         self.assertEquals(portlet.addview, 'portlets.Navigation')
00026 
00027     def testRegisteredInterfaces(self):
00028         portlet = getUtility(IPortletType, name='portlets.Navigation')
00029         registered_interfaces = [_getDottedName(i) for i in portlet.for_] 
00030         registered_interfaces.sort() 
00031         self.assertEquals(['plone.app.portlets.interfaces.IColumn'],
00032           registered_interfaces)
00033 
00034     def testInterfaces(self):
00035         portlet = navigation.Assignment()
00036         self.failUnless(IPortletAssignment.providedBy(portlet))
00037         self.failUnless(IPortletDataProvider.providedBy(portlet.data))
00038 
00039     def testInvokeAddview(self):
00040         portlet = getUtility(IPortletType, name='portlets.Navigation')
00041         mapping = self.portal.restrictedTraverse('++contextportlets++plone.leftcolumn')
00042         for m in mapping.keys():
00043             del mapping[m]
00044         addview = mapping.restrictedTraverse('+/' + portlet.addview)
00045 
00046         addview.createAndAdd(data={})
00047 
00048         self.assertEquals(len(mapping), 1)
00049         self.failUnless(isinstance(mapping.values()[0], navigation.Assignment))
00050 
00051     def testInvokeEditView(self):
00052         mapping = PortletAssignmentMapping()
00053         request = self.folder.REQUEST
00054 
00055         mapping['foo'] = navigation.Assignment()
00056         editview = getMultiAdapter((mapping['foo'], request), name='edit')
00057         self.failUnless(isinstance(editview, navigation.EditForm))
00058 
00059     def testRenderer(self):
00060         context = self.folder
00061         request = self.folder.REQUEST
00062         view = self.folder.restrictedTraverse('@@plone')
00063         manager = getUtility(IPortletManager, name='plone.leftcolumn', context=self.portal)
00064         assignment = navigation.Assignment()
00065 
00066         renderer = getMultiAdapter((context, request, view, manager, assignment), IPortletRenderer)
00067         self.failUnless(isinstance(renderer, navigation.Renderer))
00068 
00069 class TestRenderer(PortletsTestCase):
00070 
00071     def afterSetUp(self):
00072         self.populateSite()
00073         
00074     def renderer(self, context=None, request=None, view=None, manager=None, assignment=None):
00075         context = context or self.folder
00076         request = request or self.folder.REQUEST
00077         view = view or self.folder.restrictedTraverse('@@plone')
00078         manager = manager or getUtility(IPortletManager, name='plone.leftcolumn', context=self.portal)
00079         assignment = assignment or navigation.Assignment(topLevel=0)
00080 
00081         return getMultiAdapter((context, request, view, manager, assignment), IPortletRenderer)
00082 
00083     def populateSite(self):
00084         self.setRoles(['Manager'])
00085         self.portal.invokeFactory('Document', 'doc1')
00086         self.portal.invokeFactory('Document', 'doc2')
00087         self.portal.invokeFactory('Document', 'doc3')
00088         self.portal.invokeFactory('Folder', 'folder1')
00089         self.portal.invokeFactory('Link', 'link1')
00090         self.portal.link1.setRemoteUrl('http://plone.org')
00091         self.portal.link1.reindexObject()
00092         folder1 = getattr(self.portal, 'folder1')
00093         folder1.invokeFactory('Document', 'doc11')
00094         folder1.invokeFactory('Document', 'doc12')
00095         folder1.invokeFactory('Document', 'doc13')
00096         self.portal.invokeFactory('Folder', 'folder2')
00097         folder2 = getattr(self.portal, 'folder2')
00098         folder2.invokeFactory('Document', 'doc21')
00099         folder2.invokeFactory('Document', 'doc22')
00100         folder2.invokeFactory('Document', 'doc23')
00101         folder2.invokeFactory('File', 'file21')
00102         self.setRoles(['Member'])
00103 
00104     def testCreateNavTree(self):
00105         view = self.renderer(self.portal)
00106         tree = view.getNavTree()
00107         self.failUnless(tree)
00108         self.failUnless(tree.has_key('children'))
00109     
00110     def testCreateNavTreeCurrentItem(self):
00111         # With the context set to folder2 it should return a dict with
00112         # currentItem set to True
00113         view = self.renderer(self.portal.folder2)
00114         tree = view.getNavTree()
00115         self.failUnless(tree)
00116         self.assertEqual(tree['children'][-1]['currentItem'], True)
00117 
00118     def testNavTreeExcludesItemsWithExcludeProperty(self):
00119         # Make sure that items witht he exclude_from_nav property set get
00120         # no_display set to True
00121         self.portal.folder2.setExcludeFromNav(True)
00122         self.portal.folder2.reindexObject()
00123         view = self.renderer(self.portal.folder1.doc11)
00124         tree = view.getNavTree()
00125         self.failUnless(tree)
00126         for c in tree['children']:
00127             if c['item'].getPath() == '/plone/folder2':
00128                 self.fail()
00129 
00130     def testShowAllParentsOverridesNavTreeExcludesItemsWithExcludeProperty(self):
00131         # Make sure that items whose ids are in the idsNotToList navTree
00132         # property are not included
00133         self.portal.folder2.setExcludeFromNav(True)
00134         self.portal.folder2.reindexObject()
00135         ntp=self.portal.portal_properties.navtree_properties
00136         ntp.manage_changeProperties(showAllParents=True)
00137         view = self.renderer(self.portal.folder2.doc21)
00138         tree = view.getNavTree()
00139         self.failUnless(tree)
00140         found = False
00141         for c in tree['children']:
00142             if c['item'].getPath() == '/plone/folder2':
00143                 found = True
00144                 break
00145         self.failUnless(found)
00146 
00147     def testNavTreeExcludesItemsInIdsNotToList(self):
00148         # Make sure that items whose ids are in the idsNotToList navTree
00149         # property are not included
00150         ntp=self.portal.portal_properties.navtree_properties
00151         ntp.manage_changeProperties(idsNotToList=['folder2'])
00152         view = self.renderer(self.portal.folder1.doc11)
00153         tree = view.getNavTree()
00154         self.failUnless(tree)
00155         for c in tree['children']:
00156             if c['item'].getPath() == '/plone/folder2':
00157                 self.fail()
00158 
00159     def testShowAllParentsOverridesNavTreeExcludesItemsInIdsNotToList(self):
00160         # Make sure that items whose ids are in the idsNotToList navTree
00161         # property are not included
00162         ntp=self.portal.portal_properties.navtree_properties
00163         ntp.manage_changeProperties(idsNotToList=['folder2'], showAllParents=True)
00164         view = self.renderer(self.portal.folder2.doc21)
00165         tree = view.getNavTree()
00166         self.failUnless(tree)
00167         found = False
00168         for c in tree['children']:
00169             if c['item'].getPath() == '/plone/folder2':
00170                 found = True
00171                 break
00172         self.failUnless(found)
00173 
00174     def testNavTreeExcludesDefaultPage(self):
00175         # Make sure that items which are the default page are excluded
00176         self.portal.folder2.setDefaultPage('doc21')
00177         view = self.renderer(self.portal.folder1.doc11)
00178         tree = view.getNavTree()
00179         self.failUnless(tree)
00180         # Ensure that our 'doc21' default page is not in the tree.
00181         self.assertEqual([c for c in tree['children'][-1]['children']
00182                                             if c['item'].getPath()[-5:]=='doc21'],[])
00183 
00184     def testNavTreeMarksParentMetaTypesNotToQuery(self):
00185         # Make sure that items whose ids are in the idsNotToList navTree
00186         # property get no_display set to True
00187         view = self.renderer(self.portal.folder2.file21)
00188         tree = view.getNavTree()
00189         self.assertEqual(tree['children'][-1]['show_children'],True)
00190         ntp=self.portal.portal_properties.navtree_properties
00191         ntp.manage_changeProperties(parentMetaTypesNotToQuery=['Folder'])
00192         view = self.renderer(self.portal.folder2.file21)
00193         tree = view.getNavTree()
00194         self.assertEqual(tree['children'][-1]['show_children'],False)
00195 
00196     def testCreateNavTreeWithLink(self):
00197         view = self.renderer(self.portal)
00198         tree = view.getNavTree()
00199         for child in tree['children']:
00200             if child['portal_type'] != 'Link':
00201                 self.failIf(child['item'].getRemoteUrl)
00202             if child['Title'] == 'link1':
00203                 self.failUnlessEqual(child['item'].getRemoteUrl, 'http://plone.org')
00204 
00205     def testNonStructuralFolderHidesChildren(self):
00206         # Make sure NonStructuralFolders act as if parentMetaTypesNotToQuery
00207         # is set.
00208         f = dummy.NonStructuralFolder('ns_folder')
00209         self.folder._setObject('ns_folder', f)
00210         self.portal.portal_catalog.reindexObject(self.folder.ns_folder)
00211         self.portal.portal_catalog.reindexObject(self.folder)
00212         view = self.renderer(self.folder.ns_folder)
00213         tree = view.getNavTree()
00214         self.assertEqual(tree['children'][0]['children'][0]['children'][0]['item'].getPath(),
00215                                 '/plone/Members/test_user_1_/ns_folder')
00216         self.assertEqual(len(tree['children'][0]['children'][0]['children'][0]['children']), 0)
00217 
00218     def testTopLevel(self):
00219         view = self.renderer(self.portal.folder2.file21, assignment=navigation.Assignment(topLevel=1))
00220         tree = view.getNavTree()
00221         self.failUnless(tree)
00222         self.assertEqual(tree['children'][-1]['item'].getPath(), '/plone/folder2/file21')
00223 
00224     def testTopLevelWithContextAboveLevel(self):
00225         view = self.renderer(self.portal, assignment=navigation.Assignment(topLevel=1))
00226         tree = view.getNavTree()
00227         self.failUnless(tree)
00228         self.assertEqual(len(tree['children']), 0)
00229 
00230     def testTopLevelTooDeep(self):
00231         view = self.renderer(self.portal, assignment=navigation.Assignment(topLevel=5))
00232         tree = view.getNavTree()
00233         self.failUnless(tree)
00234         self.assertEqual(len(tree['children']), 0)
00235 
00236     def testTopLevelWithNavigationRoot(self):
00237         self.portal.folder2.invokeFactory('Folder', 'folder21')
00238         self.portal.folder2.folder21.invokeFactory('Document', 'doc211')
00239         view = self.renderer(self.portal.folder2.folder21, assignment=navigation.Assignment(topLevel=1, root='/folder2'))
00240         tree = view.getNavTree()
00241         self.failUnless(tree)
00242         self.assertEqual(len(tree['children']), 1)
00243         self.assertEqual(tree['children'][0]['item'].getPath(), '/plone/folder2/folder21/doc211')
00244 
00245     def testTopLevelWithPortalFactory(self):
00246         id=self.portal.generateUniqueId('Document')
00247         typeName='Document'
00248         newObject=self.portal.folder1.restrictedTraverse('portal_factory/' + typeName + '/' + id)
00249         # Will raise a KeyError unless bug is fixed
00250         view = self.renderer(newObject, assignment=navigation.Assignment(topLevel=1))
00251         tree = view.getNavTree()
00252     
00253     def testShowAllParentsOverridesBottomLevel(self):
00254         view = self.renderer(self.portal.folder2.file21, assignment=navigation.Assignment(bottomLevel=1, topLevel=0))
00255         tree = view.getNavTree()
00256         self.failUnless(tree)
00257         # Note: showAllParents makes sure we actually return items on the,
00258         # path to the context, but the portlet will not display anything
00259         # below bottomLevel. 
00260         self.assertEqual(tree['children'][-1]['item'].getPath(), '/plone/folder2')
00261         self.assertEqual(len(tree['children'][-1]['children']), 1)
00262         self.assertEqual(tree['children'][-1]['children'][0]['item'].getPath(), '/plone/folder2/file21')
00263         
00264     def testBottomLevelStopsAtFolder(self):
00265         view = self.renderer(self.portal.folder2, assignment=navigation.Assignment(bottomLevel=1, topLevel=0))
00266         tree = view.getNavTree()
00267         self.failUnless(tree)
00268         self.assertEqual(tree['children'][-1]['item'].getPath(), '/plone/folder2')
00269         self.assertEqual(len(tree['children'][-1]['children']), 0)
00270         
00271     def testNoRootSet(self):
00272         view = self.renderer(self.portal.folder2.file21, assignment=navigation.Assignment(root='', topLevel=0))
00273         tree = view.getNavTree()
00274         self.failUnless(tree)
00275         self.assertEqual(tree['children'][-1]['item'].getPath(), '/plone/folder2')
00276         
00277     def testRootIsPortal(self):
00278         view = self.renderer(self.portal.folder2.file21, assignment=navigation.Assignment(root='/', topLevel=0))
00279         tree = view.getNavTree()
00280         self.failUnless(tree)
00281         self.assertEqual(tree['children'][-1]['item'].getPath(), '/plone/folder2')
00282         
00283     def testRootIsNotPortal(self):
00284         view = self.renderer(self.portal.folder2.file21, assignment=navigation.Assignment(root='/folder2', topLevel=0))
00285         tree = view.getNavTree()
00286         self.failUnless(tree)
00287         self.assertEqual(tree['children'][0]['item'].getPath(), '/plone/folder2/doc21')
00288 
00289     def testRootDoesNotExist(self):
00290         view = self.renderer(self.portal.folder2.file21, assignment=navigation.Assignment(root='/dodo', topLevel=0))
00291         tree = view.getNavTree()
00292         self.failUnless(tree)
00293         self.assertEqual(tree.get('item', None), None)
00294         self.assertEqual(len(tree['children']), 0)
00295 
00296     def testAboveRoot(self):
00297         ntp=self.portal.portal_properties.navtree_properties
00298         ntp.manage_changeProperties(root='/folder2')
00299         view = self.renderer(self.portal)
00300         tree = view.getNavTree()
00301         self.failUnless(tree)
00302         self.assertEqual(tree['children'][0]['item'].getPath(), '/plone/folder2/doc21')
00303 
00304     def testOutsideRoot(self):
00305         view = self.renderer(self.portal.folder1, assignment=navigation.Assignment(root='/folder2'))
00306         tree = view.getNavTree()
00307         self.failUnless(tree)
00308         self.assertEqual(tree['children'][0]['item'].getPath(), '/plone/folder2/doc21')
00309 
00310     def testRootIsCurrent(self):
00311         view = self.renderer(self.portal.folder2, assignment=navigation.Assignment(currentFolderOnly=True))
00312         tree = view.getNavTree()
00313         self.failUnless(tree)
00314         self.assertEqual(tree['children'][0]['item'].getPath(), '/plone/folder2/doc21')
00315         
00316     def testRootIsCurrentWithFolderishDefaultPage(self):
00317         self.portal.folder2.invokeFactory('Folder', 'folder21')
00318         self.portal.folder2.setDefaultPage('folder21')
00319         
00320         view = self.renderer(self.portal.folder2.folder21, assignment=navigation.Assignment(currentFolderOnly=True))
00321         tree = view.getNavTree()
00322         self.failUnless(tree)
00323         self.assertEqual(tree['children'][0]['item'].getPath(), '/plone/folder2/doc21')
00324 
00325     def testCustomQuery(self):
00326         # Try a custom query script for the navtree that returns only published
00327         # objects
00328         self.setRoles(['Manager'])
00329         workflow = self.portal.portal_workflow
00330         factory = self.portal.manage_addProduct['PythonScripts']
00331         factory.manage_addPythonScript('getCustomNavQuery')
00332         script = self.portal.getCustomNavQuery
00333         script.ZPythonScript_edit('','return {"review_state":"published"}')
00334         self.assertEqual(self.portal.getCustomNavQuery(),{"review_state":"published"})
00335         view = self.renderer(self.portal.folder2)
00336         tree = view.getNavTree()
00337         self.failUnless(tree)
00338         self.failUnless(tree.has_key('children'))
00339         #Should only contain current object
00340         self.assertEqual(len(tree['children']), 4)
00341         #change workflow for folder1
00342         workflow.doActionFor(self.portal.folder1, 'publish')
00343         self.portal.folder1.reindexObject()
00344         view = self.renderer(self.portal.folder2)
00345         tree = view.getNavTree()
00346         #Should only contain current object and published folder
00347         self.assertEqual(len(tree['children']), 5)
00348 
00349     def testStateFiltering(self):
00350         # Test Navtree workflow state filtering
00351         self.setRoles(['Manager'])
00352         workflow = self.portal.portal_workflow
00353         ntp=self.portal.portal_properties.navtree_properties
00354         ntp.manage_changeProperties(wf_states_to_show=['published'])
00355         ntp.manage_changeProperties(enable_wf_state_filtering=True)
00356         view = self.renderer(self.portal.folder2)
00357         tree = view.getNavTree()
00358         self.failUnless(tree)
00359         self.failUnless(tree.has_key('children'))
00360         #Should only contain current object
00361         self.assertEqual(len(tree['children']), 4)
00362         #change workflow for folder1
00363         workflow.doActionFor(self.portal.folder1, 'publish')
00364         self.portal.folder1.reindexObject()
00365         view = self.renderer(self.portal.folder2)
00366         tree = view.getNavTree()
00367         #Should only contain current object and published folder
00368         self.assertEqual(len(tree['children']), 5)
00369     
00370     def testPrunedRootNode(self):
00371         ntp=self.portal.portal_properties.navtree_properties
00372         ntp.manage_changeProperties(parentMetaTypesNotToQuery=['Folder'])
00373         
00374         assignment = navigation.Assignment(topLevel=0)
00375         assignment.topLevel = 1
00376         view = self.renderer(self.portal.folder1, assignment=assignment)
00377         tree = view.getNavTree()
00378         self.failUnless(tree)
00379         self.assertEqual(len(tree['children']), 0)
00380         
00381     def testPrunedRootNodeShowsAllParents(self):
00382         ntp=self.portal.portal_properties.navtree_properties
00383         ntp.manage_changeProperties(parentMetaTypesNotToQuery=['Folder'])
00384         
00385         assignment = navigation.Assignment(topLevel=0)
00386         assignment.topLevel = 1
00387         view = self.renderer(self.portal.folder1.doc11, assignment=assignment)
00388         tree = view.getNavTree()
00389         self.failUnless(tree)
00390         self.assertEqual(len(tree['children']), 1)
00391         self.assertEqual(tree['children'][0]['item'].getPath(), '/plone/folder1/doc11')
00392     
00393     def testIsCurrentParentWithOverlapingNames(self):
00394         self.setRoles(['Manager',])
00395         self.portal.invokeFactory('Folder', 'folder2x')
00396         self.portal.folder2x.invokeFactory('Document', 'doc2x1')
00397         self.setRoles(['Member',])
00398         view = self.renderer(self.portal.folder2x.doc2x1)
00399         tree = view.getNavTree()
00400         self.failUnless(tree)
00401         
00402         folder2x_node = [n for n in tree['children'] if n['path'] == '/plone/folder2x'][0]
00403         self.failUnless(folder2x_node['currentParent'])
00404         
00405         folder2_node = [n for n in tree['children'] if n['path'] == '/plone/folder2'][0]
00406         self.failIf(folder2_node['currentParent'])
00407     
00408 def test_suite():
00409     from unittest import TestSuite, makeSuite
00410     suite = TestSuite()
00411     suite.addTest(makeSuite(TestPortlet))
00412     suite.addTest(makeSuite(TestRenderer))
00413     return suite