Back to index

plone3  3.1.7
testPortalCreation.py
Go to the documentation of this file.
00001 #
00002 # Tests portal creation
00003 #
00004 
00005 import os
00006 from Products.CMFPlone.tests import PloneTestCase
00007 from Products.CMFPlone.tests import dummy
00008 from Products.CMFCore.tests.base.testcase import WarningInterceptor
00009 
00010 from tempfile import mkstemp
00011 from zope.app.component.hooks import setSite, clearSite
00012 from zope.app.component.interfaces import ISite
00013 from zope.component import getGlobalSiteManager
00014 from zope.component import getSiteManager
00015 from zope.component import getMultiAdapter
00016 from zope.component import getUtility
00017 from zope.component import queryUtility
00018 from zope.component.interfaces import IComponentLookup
00019 from zope.component.interfaces import IComponentRegistry
00020 
00021 from Acquisition import aq_base
00022 from DateTime import DateTime
00023 
00024 from Products.CMFCore.CachingPolicyManager import CachingPolicyManager
00025 from Products.CMFCore.permissions import AccessInactivePortalContent
00026 from Products.CMFCore.utils import getToolByName
00027 from Products.CMFPlone import setuphandlers
00028 from Products.CMFPlone.interfaces import IControlPanel
00029 from Products.CMFPlone.UnicodeSplitter import Splitter, CaseNormalizer
00030 from Products.GenericSetup.interfaces import ISetupTool
00031 
00032 from Products.StandardCacheManagers.AcceleratedHTTPCacheManager import \
00033      AcceleratedHTTPCacheManager
00034 from Products.StandardCacheManagers.RAMCacheManager import \
00035      RAMCacheManager
00036 
00037 from plone.portlets.interfaces import IPortletManager
00038 from plone.portlets.interfaces import IPortletAssignmentMapping
00039 from plone.portlets.interfaces import IPortletManager
00040 from plone.portlets.interfaces import ILocalPortletAssignmentManager
00041 from plone.portlets.constants import CONTEXT_CATEGORY as CONTEXT_PORTLETS
00042 
00043 class TestPortalCreation(PloneTestCase.PloneTestCase, WarningInterceptor):
00044 
00045     def afterSetUp(self):
00046         self.membership = self.portal.portal_membership
00047         self.workflow = self.portal.portal_workflow
00048         self.types = self.portal.portal_types
00049         self.cp = self.portal.portal_controlpanel
00050         self.actions = self.portal.portal_actions
00051         self.icons = self.portal.portal_actionicons
00052         self.properties = self.portal.portal_properties
00053         self.memberdata = self.portal.portal_memberdata
00054         self.catalog = self.portal.portal_catalog
00055         self.groups = self.portal.portal_groups
00056         self.factory = self.portal.portal_factory
00057         self.skins = self.portal.portal_skins
00058         self.transforms = self.portal.portal_transforms
00059         self.javascripts = self.portal.portal_javascripts
00060         self.setup = self.portal.portal_setup
00061 
00062     def beforeTearDown(self):
00063         self._free_warning_output()
00064 
00065     def testInstanceVersion(self):
00066         # Test if the version of the instance has been set
00067         mt = self.portal.portal_migration
00068         self.assertEqual(mt._version, mt.getFileSystemVersion())
00069 
00070     def testPloneSkins(self):
00071         # Plone skins should have been set up
00072         self.failUnless(hasattr(self.folder, 'plone_powered.gif'))
00073 
00074     def testDefaultSkin(self):
00075         # index_html should render
00076         self.portal.index_html()
00077 
00078     def testNoIndexHtmlDocument(self):
00079         # The portal should not contain an index_html Document
00080         self.failIf('index_html' in self.portal.objectIds())
00081 
00082     def testCanViewManagementScreen(self):
00083         # Make sure the ZMI management screen works
00084         self.portal.manage_main()
00085 
00086     def testControlPanelGroups(self):
00087         # Test for http://dev.plone.org/plone/ticket/2749
00088         # Wake up object, in the case it was deactivated.
00089         dir(self.cp); dir(self.cp)
00090         self.failUnless(self.cp.__dict__.has_key('groups'))
00091 
00092     def testWorkflowIsActionProvider(self):
00093         # The workflow tool is one of the last remaining action providers.
00094         self.failUnless('portal_workflow' in self.actions.listActionProviders())
00095 
00096     def testLargePloneFolderWorkflow(self):
00097         # Large Plone Folder should use folder_workflow
00098         # http://dev.plone.org/plone/ticket/2744
00099         lpf_chain = self.workflow.getChainFor('Large Plone Folder')
00100         self.failUnless('folder_workflow' in lpf_chain)
00101         self.failIf('plone_workflow' in lpf_chain)
00102 
00103     def testMembersFolderMetaType(self):
00104         # Members folder should have meta_type 'ATBTreeFolder'
00105         members = self.membership.getMembersFolder()
00106         self.assertEqual(members.meta_type, 'ATBTreeFolder')
00107 
00108     def testMembersFolderPortalType(self):
00109         # Members folder should have portal_type 'Large Plone Folder'
00110         members = self.membership.getMembersFolder()
00111         self.assertEqual(members._getPortalTypeName(), 'Large Plone Folder')
00112 
00113     def testMembersFolderMeta(self):
00114         # Members folder should have title 'Users'
00115         members = self.membership.getMembersFolder()
00116         self.assertEqual(members.getId(), 'Members')
00117         self.assertEqual(members.Title(), 'Users')
00118 
00119     def testMembersFolderIsIndexed(self):
00120         # Members folder should be cataloged
00121         res = self.catalog(getId='Members')
00122         self.assertEqual(len(res), 1)
00123         self.assertEqual(res[0].getId, 'Members')
00124         self.assertEqual(res[0].Title, 'Users')
00125 
00126     def testSecureMailHost(self):
00127         # MailHost should be of the SMH variety
00128         mailhost = self.portal.plone_utils.getMailHost()
00129         self.assertEqual(mailhost.meta_type, 'Secure Mail Host')
00130 
00131     def testUseFolderContentsProperty(self):
00132         # The use_folder_contents site property should be emtpy
00133         props = self.portal.portal_properties.site_properties
00134         self.assertEqual(props.getProperty('use_folder_contents'), ())
00135 
00136     def testFolderEditActionHasEditTitle(self):
00137         # Edit tab of folders should be named 'edit', not 'properties'
00138         folder = self.types.getTypeInfo('Folder')
00139         for action in folder._cloneActions():
00140             if action.id == 'edit':
00141                 self.assertEqual(action.title, 'Edit')
00142                 break
00143         else:
00144             self.fail("Folder has no 'edit' action")
00145 
00146     def testFolderHasFolderListingAction(self):
00147         # Folders should have a 'folderlisting' action
00148         folder = self.types.getTypeInfo('Folder')
00149         for action in folder._cloneActions():
00150             if action.id == 'folderlisting':
00151                 break
00152         else:
00153             self.fail("Folder has no 'folderlisting' action")
00154 
00155     def testImagePatch(self):
00156         # Is it ok to remove the imagePatch? Probably not as we
00157         # don't want the border attribute ...
00158         self.folder.invokeFactory('Image', id='foo', file=dummy.Image())
00159         endswith = ' alt="" title="" height="16" width="16" />'
00160         self.assertEqual(self.folder.foo.tag()[-len(endswith):], endswith)
00161 
00162     def testNoPortalFormTool(self):
00163         # portal_form should have been removed
00164         self.failIf('portal_form' in self.portal.objectIds())
00165 
00166     def testNoPortalNavigationTool(self):
00167         # portal_navigation should have been removed
00168         self.failIf('portal_navigation' in self.portal.objectIds())
00169 
00170     def testNoFormProperties(self):
00171         # form_properties should have been removed
00172         self.failIf('form_properties' in self.properties.objectIds())
00173 
00174     def testNoNavigationProperties(self):
00175         # navigation_properties should have been removed
00176         self.failIf('navigation_properties' in self.properties.objectIds())
00177 
00178     def testFullScreenAction(self):
00179         # There should be a full_screen action
00180         self.failUnless(self.actions.getActionInfo('document_actions/full_screen') is not None)
00181 
00182     def testFullScreenActionIcon(self):
00183         # There should be a full_screen action icon
00184         for icon in self.icons.listActionIcons():
00185             if icon.getActionId() == 'full_screen':
00186                 break
00187         else:
00188             self.fail("Action icons tool has no 'full_screen' icon")
00189 
00190     def testVisibleIdsProperties(self):
00191         # visible_ids should be a site property and a memberdata property
00192         self.failUnless(self.properties.site_properties.hasProperty('visible_ids'))
00193         self.failUnless(self.memberdata.hasProperty('visible_ids'))
00194 
00195     def testFormToolTipsProperty(self):
00196         # formtooltips should have been removed
00197         self.failIf(self.memberdata.hasProperty('formtooltips'))
00198 
00199     def testNavTreeProperties(self):
00200         # navtree_properties should contain the new properties
00201         self.failUnless(self.properties.navtree_properties.hasProperty('metaTypesNotToList'))
00202         self.failUnless(self.properties.navtree_properties.hasProperty('parentMetaTypesNotToQuery'))
00203         self.failUnless('Large Plone Folder' in
00204                             self.properties.navtree_properties.getProperty('parentMetaTypesNotToQuery'))
00205         self.failUnless(self.properties.navtree_properties.hasProperty('sortAttribute'))
00206         self.failUnless(self.properties.navtree_properties.hasProperty('sortOrder'))
00207         self.failUnless(self.properties.navtree_properties.hasProperty('sitemapDepth'))
00208         self.failUnless(self.properties.navtree_properties.hasProperty('showAllParents'))
00209         self.failUnless(self.properties.navtree_properties.hasProperty('wf_states_to_show'))
00210         self.failUnless(self.properties.navtree_properties.hasProperty('enable_wf_state_filtering'))
00211 
00212     def testSitemapAction(self):
00213         # There should be a sitemap action
00214         for action in self.actions.listActions():
00215             if action.getId() == 'sitemap':
00216                 break
00217         else:
00218             self.fail("Actions tool has no 'sitemap' action")
00219 
00220     def testResourceRegistries(self):
00221         # We should have portal_css and portal_javascripts tools
00222         self.failUnless(hasattr(self.portal, 'portal_css'))
00223         self.failUnless(hasattr(self.portal, 'portal_kss'))
00224         self.failUnless(hasattr(self.portal, 'portal_javascripts'))
00225 
00226     def testUnfriendlyTypesProperty(self):
00227         # We should have an types_not_searched property
00228         self.failUnless(self.properties.site_properties.hasProperty('types_not_searched'))
00229         self.failUnless('Plone Site' in self.properties.site_properties.getProperty('types_not_searched'))
00230 
00231     def testNonDefaultPageTypes(self):
00232         # We should have a default_page_types property
00233         self.failUnless(self.properties.site_properties.hasProperty('default_page_types'))
00234         self.failUnless('Folder' not in self.properties.site_properties.getProperty('default_page_types'))
00235         self.failUnless('Large Plone Folder' not in self.properties.site_properties.getProperty('default_page_types'))
00236         self.failUnless('Topic' in self.properties.site_properties.getProperty('default_page_types'))
00237 
00238     def testNoMembersAction(self):
00239         # There should not be a Members action
00240         for action in self.actions.listActions():
00241             if action.getId() == 'Members':
00242                 self.fail("Actions tool still has 'Members' action")
00243 
00244     def testNoNewsAction(self):
00245         # There should not be a news action
00246         for action in self.actions.listActions():
00247             if action.getId() == 'news':
00248                 self.fail("Actions tool still has 'News' action")
00249 
00250     def testNewsTopicIsIndexed(self):
00251         # News (smart) folder should be cataloged
00252         res = self.catalog(path={'query' : '/plone/news/aggregator', 'depth' : 0})
00253         self.assertEqual(len(res), 1)
00254         self.assertEqual(res[0].getId, 'aggregator')
00255         self.assertEqual(res[0].Title, 'News')
00256         self.assertEqual(res[0].Description, 'Site News')
00257 
00258     def testEventsTopicIsIndexed(self):
00259         # Events (smart) folder should be cataloged
00260         res = self.catalog(path={'query' : '/plone/events/aggregator', 'depth' : 0})
00261         self.assertEqual(len(res), 1)
00262         self.assertEqual(res[0].getId, 'aggregator')
00263         self.assertEqual(res[0].Title, 'Events')
00264         self.assertEqual(res[0].Description, 'Site Events')
00265 
00266     def testNewsFolderIsIndexed(self):
00267         # News folder should be cataloged
00268         res = self.catalog(path={'query' : '/plone/news', 'depth' : 0})
00269         self.assertEqual(len(res), 1)
00270         self.assertEqual(res[0].getId, 'news')
00271         self.assertEqual(res[0].Title, 'News')
00272         self.assertEqual(res[0].Description, 'Site News')
00273 
00274     def testEventsFolderIsIndexed(self):
00275         # Events folder should be cataloged
00276         res = self.catalog(path={'query' : '/plone/events', 'depth' : 0})
00277         self.assertEqual(len(res), 1)
00278         self.assertEqual(res[0].getId, 'events')
00279         self.assertEqual(res[0].Title, 'Events')
00280         self.assertEqual(res[0].Description, 'Site Events')
00281 
00282     def testNewsFolder(self):
00283         self.failUnless('news' in self.portal.objectIds())
00284         folder = getattr(self.portal, 'news')
00285         self.assertEqual(folder.portal_type, 'Large Plone Folder')
00286         self.assertEqual(folder.getDefaultPage(), 'aggregator')
00287         self.assertEqual(folder.getRawLocallyAllowedTypes(), ('News Item',))
00288         self.assertEqual(folder.getRawImmediatelyAddableTypes(), ('News Item',))
00289         self.assertEqual(folder.checkCreationFlag(), False)
00290 
00291     def testEventsFolder(self):
00292         self.failUnless('events' in self.portal.objectIds())
00293         folder = getattr(self.portal, 'events')
00294         self.assertEqual(folder.portal_type, 'Large Plone Folder')
00295         self.assertEqual(folder.getDefaultPage(), 'aggregator')
00296         self.assertEqual(folder.getRawLocallyAllowedTypes(), ('Event',))
00297         self.assertEqual(folder.getRawImmediatelyAddableTypes(), ('Event',))
00298         self.assertEqual(folder.checkCreationFlag(), False)
00299 
00300     def testNewsTopic(self):
00301         # News topic is in place as default view and has a criterion to show
00302         # only News Items, and uses the folder_summary_view.
00303         self.assertEqual(['aggregator'], [i for i in self.portal.news.objectIds()])
00304         topic = getattr(self.portal.news, 'aggregator')
00305         self.assertEqual(topic._getPortalTypeName(), 'Topic')
00306         self.assertEqual(topic.buildQuery()['Type'], ('News Item',))
00307         self.assertEqual(topic.buildQuery()['review_state'], 'published')
00308         self.assertEqual(topic.getLayout(), 'folder_summary_view')
00309         self.assertEqual(topic.checkCreationFlag(), False)
00310 
00311     def testEventsTopic(self):
00312         # Events topic is in place as default view and has criterion to show
00313         # only future Events Items.
00314         self.assertEqual(['aggregator'], [i for i in self.portal.events.objectIds()])
00315         topic = getattr(self.portal.events, 'aggregator')
00316         self.assertEqual(topic._getPortalTypeName(), 'Topic')
00317         query = topic.buildQuery()
00318         self.assertEqual(query['Type'], ('Event',))
00319         self.assertEqual(query['review_state'], 'published')
00320         self.assertEqual(query['start']['query'].Date(), DateTime().Date())
00321         self.assertEqual(query['start']['range'], 'min')
00322         self.assertEqual(topic.checkCreationFlag(), False)
00323 
00324     def testEventsSubTopic(self):
00325         # past Events sub-topic is in place and has criteria to show
00326         # only past Events Items.
00327         events_topic = self.portal.events.aggregator
00328         self.failUnless('previous' in events_topic.objectIds())
00329         topic = getattr(events_topic, 'previous')
00330         self.assertEqual(topic._getPortalTypeName(), 'Topic')
00331         query = topic.buildQuery()
00332         self.assertEqual(query['Type'], ('Event',))
00333         self.assertEqual(query['review_state'], 'published')
00334         self.assertEqual(query['end']['query'].Date(), DateTime().Date())
00335         self.assertEqual(query['end']['range'], 'max')
00336         self.assertEqual(topic.checkCreationFlag(), False)
00337 
00338     def testObjectButtonActions(self):
00339         self.setRoles(['Manager', 'Member'])
00340         atool = self.actions
00341         self.failIf(atool.getActionInfo('object_buttons/cut') is None)
00342         self.failIf(atool.getActionInfo('object_buttons/copy') is None)
00343         self.failIf(atool.getActionInfo('object_buttons/paste') is None)
00344         self.failIf(atool.getActionInfo('object_buttons/delete') is None)
00345 
00346     def testContentsTabVisible(self):
00347         for a in self.actions.listActions():
00348             if a.getId() == 'folderContents':
00349                 self.failUnless(a.visible)
00350 
00351     def testDefaultGroupsAdded(self):
00352         self._trap_warning_output()
00353         self.failUnless('Administrators' in self.groups.listGroupIds())
00354         self.failUnless('Reviewers' in self.groups.listGroupIds())
00355 
00356     def testDefaultTypesInPortalFactory(self):
00357         types = self.factory.getFactoryTypes().keys()
00358         for metaType in ('Document', 'Event', 'File', 'Folder', 'Image',
00359                          'Folder', 'Large Plone Folder', 'Link', 'News Item',
00360                          'Topic'):
00361             self.failUnless(metaType in types)
00362 
00363     def testAllDependenciesMet(self):
00364         from Products.CMFPlone.setup import dependencies
00365         # filter out the unknown Zope version message
00366         msgs = [x for x in dependencies.messages if
00367                   not x['message'].startswith('Unable to detect Zope version.')]
00368         msgs = [x for x in msgs if not x['optional']]
00369         self.failUnlessEqual(msgs, [])
00370 
00371     def testDisableFolderSectionsSiteProperty(self):
00372         # The disable_folder_sections site property should be emtpy
00373         props = self.portal.portal_properties.site_properties
00374         self.failUnless(props.getProperty('disable_folder_sections', None) is not None)
00375         self.failIf(props.getProperty('disable_folder_sections'))
00376 
00377     def testSelectableViewsOnFolder(self):
00378         views = self.portal.portal_types.Folder.getAvailableViewMethods(None)
00379         self.failUnless('folder_listing' in views)
00380         self.failUnless('atct_album_view' in views)
00381 
00382     def testSelectableViewsOnTopic(self):
00383         views = self.portal.portal_types.Topic.getAvailableViewMethods(None)
00384         self.failUnless('folder_listing' in views)
00385         self.failUnless('atct_album_view' in views)
00386         self.failUnless('atct_topic_view' in views)
00387 
00388     def testLocationMemberdataProperty(self):
00389         # portal_memberdata should have a location property
00390         self.failUnless(self.memberdata.hasProperty('location'))
00391 
00392     def testLanguageMemberdataProperty(self):
00393         # portal_memberdata should have a language property
00394         self.failUnless(self.memberdata.hasProperty('language'))
00395 
00396     def testDescriptionMemberdataProperty(self):
00397         # portal_memberdata should have a description property
00398         self.failUnless(self.memberdata.hasProperty('description'))
00399 
00400     def testHome_PageMemberdataProperty(self):
00401         # portal_memberdata should have a home_page property
00402         self.failUnless(self.memberdata.hasProperty('home_page'))
00403 
00404     def testExtEditorMemberdataProperty(self):
00405         # portal_memberdata should have a location property
00406         self.assertEqual(self.memberdata.getProperty('ext_editor'), 0)
00407 
00408     def testChangeStateIsLastFolderButton(self):
00409         # Change state button should be the last
00410         actions = self.actions._getOb('folder_buttons').objectIds()
00411         self.assertEqual(actions[-1], 'change_state')
00412 
00413     def testTypesUseViewActionInListingsProperty(self):
00414         # site_properties should have the typesUseViewActionInListings property
00415         self.failUnless(self.properties.site_properties.hasProperty('typesUseViewActionInListings'))
00416 
00417     def testSiteSetupAction(self):
00418         # There should be a Site Setup action
00419         for action in self.actions.listActions():
00420             if action.getId() == 'plone_setup':
00421                 self.assertEqual(action.title, 'Site Setup')
00422                 break
00423         else:
00424             self.fail("Actions tool has no 'sitemap' action")
00425 
00426     def testFolderlistingAction(self):
00427         # Make sure the folderlisting action of a Folder is /view, to ensure
00428         # that the layout template will be resolved (see PloneTool.browserDefault)
00429         self.assertEqual(self.types['Folder'].getActionObject('folder/folderlisting').getActionExpression(),
00430                          'string:${folder_url}/view')
00431         self.assertEqual(self.types['Plone Site'].getActionObject('folder/folderlisting').getActionExpression(),
00432                          'string:${folder_url}/view')
00433 
00434     def testEnableLivesearchProperty(self):
00435         # site_properties should have enable_livesearch property
00436         self.failUnless(self.properties.site_properties.hasProperty('enable_livesearch'))
00437 
00438     def testSearchSettingsActionIcon(self):
00439         # There should be a SearchSettings action icon
00440         for icon in self.icons.listActionIcons():
00441             if icon.getActionId() == 'SearchSettings':
00442                 break
00443         else:
00444             self.fail("Action icons tool has no 'SearchSettings' icon")
00445 
00446     def testPortalFTIIsDynamicFTI(self):
00447         # Plone Site FTI should be a DynamicView FTI
00448         fti = self.portal.getTypeInfo()
00449         self.assertEqual(fti.meta_type, 'Factory-based Type Information with dynamic views')
00450 
00451     def testPloneSiteFTIHasMethodAliases(self):
00452         # Should add method aliases to the Plone Site FTI
00453         expected_aliases = {
00454                 '(Default)'  : '(dynamic view)',
00455                 'view'       : '(selected layout)',
00456                 'edit'       : 'folder_edit_form',
00457                 'sharing'    : '@@sharing',
00458               }
00459         fti = self.portal.getTypeInfo()
00460         aliases = fti.getMethodAliases()
00461         self.assertEqual(aliases, expected_aliases)
00462 
00463     def testSiteActions(self):
00464         self.setRoles(['Manager', 'Member'])
00465         atool = self.actions
00466         self.failIf(atool.getActionInfo('site_actions/sitemap') is None)
00467         self.failIf(atool.getActionInfo('site_actions/contact') is None)
00468         self.failIf(atool.getActionInfo('site_actions/accessibility') is None)
00469         self.failIf(atool.getActionInfo('site_actions/plone_setup') is None)
00470 
00471     def testNoMembershipToolPloneSetupAction(self):
00472         try:
00473             self.failUnless(self.actions.getActionInfo('user/plone_setup'))
00474         except ValueError:
00475             pass
00476         else:
00477             self.fail('Found plone_setup action in user category.')
00478 
00479     def testTypesHaveSelectedLayoutViewAction(self):
00480         # Should add method aliases to the Plone Site FTI
00481         types = ('Document', 'Event', 'Favorite', 'File', 'Folder', 'Image', 'Link', 'News Item', 'Topic', 'Plone Site')
00482         for typeName in types:
00483             fti = getattr(self.types, typeName)
00484             aliases = fti.getMethodAliases()
00485             self.assertEqual(aliases['view'], '(selected layout)')
00486 
00487     def testPortalUsesMethodAliases(self):
00488         fti = self.portal.getTypeInfo()
00489         for action in fti.listActions():
00490             if action.getId() == 'edit':
00491                 self.assertEqual(action.getActionExpression(), 'string:${object_url}/edit')
00492             if action.getId() == 'sharing':
00493                 self.assertEqual(action.getActionExpression(), 'string:${object_url}/sharing')
00494 
00495     def testNavigationSettingsActionIcon(self):
00496         # There should be a NavigationSettings action icon
00497         for icon in self.icons.listActionIcons():
00498             if icon.getActionId() == 'NavigationSettings':
00499                 break
00500         else:
00501             self.fail("Action icons tool has no 'NavigationSettings' icon")
00502 
00503     def testNavigationAndSearchPanelsInstalled(self):
00504         # Navigation and search panels should be installed
00505         haveSearch = False
00506         haveNavigation = False
00507         for panel in self.cp.listActions():
00508             if panel.getId() == 'SearchSettings':
00509                 haveSearch = True
00510             elif panel.getId() == 'NavigationSettings':
00511                 haveNavigation = True
00512         self.failUnless(haveSearch and haveNavigation)
00513 
00514     def testOwnerHasAccessInactivePermission(self):
00515         permission_on_role = [p for p in self.portal.permissionsOfRole('Owner')
00516             if p['name'] == AccessInactivePortalContent][0]
00517         self.failUnless(permission_on_role['selected'])
00518         cur_perms = self.portal.permission_settings(
00519                             AccessInactivePortalContent)[0]
00520         self.failUnless(cur_perms['acquire'])
00521 
00522     def testSyndicationEnabledByDefault(self):
00523         syn = self.portal.portal_syndication
00524         self.failUnless(syn.isSiteSyndicationAllowed())
00525 
00526     def testSyndicationEnabledOnNewsAndEvents(self):
00527         syn = self.portal.portal_syndication
00528         self.failUnless(syn.isSyndicationAllowed(self.portal.news.aggregator))
00529         self.failUnless(syn.isSyndicationAllowed(self.portal.events.aggregator))
00530 
00531     def testSyndicationTabDisabled(self):
00532         # Syndication tab should be disabled by default
00533         for action in self.actions.listActions():
00534             if action.getId() == 'syndication' and action.visible:
00535                 self.fail("Actions tool still has visible 'syndication' action")
00536 
00537     def testObjectButtonActionsInvisibleOnPortalRoot(self):
00538         # only a manager would have proper permissions
00539         self.setRoles(['Manager', 'Member'])
00540         acts = self.actions.listFilteredActionsFor(self.portal)
00541         buttons = acts.get('object_buttons',[])
00542         self.assertEquals(0, len(buttons))
00543 
00544     def testObjectButtonActionsInvisibleOnPortalDefaultDocument(self):
00545         # only a manager would have proper permissions
00546         self.setRoles(['Manager', 'Member'])
00547         self.portal.invokeFactory('Document','index_html')
00548         acts = self.actions.listFilteredActionsFor(self.portal.index_html)
00549         buttons = acts.get('object_buttons', [])
00550         self.assertEquals(0, len(buttons))
00551 
00552     def testObjectButtonActionsOnDefaultDocumentApplyToParent(self):
00553         # only a manager would have proper permissions
00554         self.setRoles(['Manager', 'Member'])
00555         self.folder.invokeFactory('Document','index_html')
00556         acts = self.actions.listFilteredActionsFor(self.folder.index_html)
00557         buttons = acts['object_buttons']
00558         self.assertEqual(len(buttons), 4)
00559         urls = [a['url'] for a in buttons]
00560         for url in urls:
00561             self.failIf('index_html' in url, 'Action wrongly applied to default page object %s'%url)
00562 
00563     def testObjectButtonActionsPerformCorrectAction(self):
00564         # only a manager would have proper permissions
00565         self.setRoles(['Manager', 'Member'])
00566         self.folder.invokeFactory('Document','index_html')
00567         acts = self.actions.listFilteredActionsFor(self.folder.index_html)
00568         buttons = acts['object_buttons']
00569         self.assertEqual(len(buttons), 4)
00570         # special case for delete which needs a confirmation form
00571         urls = [(a['id'],a['url']) for a in buttons
00572                 if a['id'] not in ('delete',)]
00573         for url in urls:
00574             # ensure that e.g. the 'copy' url contains object_copy
00575             self.failUnless('object_'+url[0] in url[1], "%s does not perform the expected object_%s action"%(url[0],url[0]))
00576 
00577         delete_action = [(a['id'],a['url']) for a in buttons
00578                 if a['id'] == 'delete'][0]
00579         self.failUnless('delete_confirmation' in delete_action[1],
00580                          "object_delete does not use the confirmation form")
00581 
00582     def testObjectButtonActionsInExpectedOrder(self):
00583         # The object buttons need to be in a standardized order
00584         self.setRoles(['Manager', 'Member'])
00585         # fill the copy buffer so we see all actions
00586         self.folder.cb_dataValid = True
00587         acts = self.actions.listFilteredActionsFor(self.folder)
00588         buttons = acts['object_buttons']
00589         self.assertEqual(len(buttons),5)
00590         ids = [(a['id']) for a in buttons]
00591         self.assertEqual(ids, ['cut','copy','paste','delete', 'rename',])
00592 
00593     def testPlone3rdPartyLayerInDefault(self):
00594         # plone_3rdParty layer should exist
00595         path = self.skins.getSkinPath('Plone Default')
00596         self.failUnless('plone_3rdParty' in path)
00597 
00598     def testPloneLoginLayerInDefault(self):
00599         # plone_login layer should exist
00600         path = self.skins.getSkinPath('Plone Default')
00601         self.failUnless('plone_login' in path)
00602 
00603     def testCMFLegacySkinComesLastInDefault(self):
00604         # cmf_legacy should be the last skin layer
00605         path = self.skins.getSkinPath('Plone Default')
00606         path = [x.strip() for x in path.split(',')]
00607         self.assertEqual(path[-1], 'cmf_legacy')
00608 
00609     def testCustomSkinFolderExists(self):
00610         # the custom skin needs to be created
00611         self.failUnless('custom' in self.skins.objectIds())
00612 
00613     def testCustomSkinFolderComesFirst(self):
00614         firstInDefaultSkin = (
00615             self.skins.getSkinPath('Plone Default').split(',')[0])
00616         self.assertEqual(
00617             firstInDefaultSkin, 'custom',
00618             "The 'custom' layer was not the first in the Plone Default skin. "
00619             "It was %r." % firstInDefaultSkin)
00620 
00621     def testMemberHasViewGroupsPermission(self):
00622         # Member should be granted the 'View Groups' permission
00623         member_has_permission = [p for p in
00624                 self.portal.permissionsOfRole('Member')
00625                                         if p['name'] == 'View Groups'][0]
00626         self.failUnless(member_has_permission['selected'])
00627 
00628     def testDiscussionItemHasNoWorkflow(self):
00629         self.assertEqual(self.workflow.getChainForPortalType('Discussion Item'), ())
00630 
00631     def testFolderHasFolderListingView(self):
00632         # Folder type should allow 'folder_listing'
00633         self.failUnless('folder_listing' in self.types.Folder.view_methods)
00634 
00635     def testFolderHasSummaryView(self):
00636         # Folder type should allow 'folder_summary_view'
00637         self.failUnless('folder_summary_view' in self.types.Folder.view_methods)
00638 
00639     def testFolderHasTabularView(self):
00640         # Folder type should allow 'folder_tabular_view'
00641         self.failUnless('folder_tabular_view' in self.types.Folder.view_methods)
00642 
00643     def testFolderHasAlbumView(self):
00644         # Folder type should allow 'atct_album_view'
00645         self.failUnless('atct_album_view' in self.types.Folder.view_methods)
00646 
00647     def testConfigurableSafeHtmlTransform(self):
00648         # The safe_html transformation should be configurable
00649         try:
00650             self.transforms.safe_html.get_parameter_value('disable_transform')
00651         except (AttributeError, KeyError):
00652             self.fail('safe_html transformation not updated')
00653 
00654     def testNavtreePropertiesNormalized(self):
00655         ntp = self.portal.portal_properties.navtree_properties
00656         toRemove = ['skipIndex_html', 'showMyUserFolderOnly', 'showFolderishSiblingsOnly',
00657                     'showFolderishChildrenOnly', 'showNonFolderishObject', 'showTopicResults',
00658                     'rolesSeeContentView', 'rolesSeeUnpublishedContent', 'rolesSeeContentsView ',
00659                     'batchSize', 'sortCriteria', 'croppingLength', 'forceParentsInBatch',
00660                     'rolesSeeHiddenContent', 'typesLinkToFolderContents']
00661         toAdd = {'name' : '', 'root' : '/', 'currentFolderOnlyInNavtree' : False}
00662         for property in toRemove:
00663             self.assertEqual(ntp.getProperty(property, None), None)
00664         for property, value in toAdd.items():
00665             self.assertEqual(ntp.getProperty(property), value)
00666         self.assertEqual(ntp.getProperty('bottomLevel'), 0)
00667 
00668     def testvcXMLRPCRemoved(self):
00669         # vcXMLRPC.js should no longer be registered
00670         self.failIf('vcXMLRPC.js' in self.javascripts.getResourceIds())
00671 
00672     def testActionDropDownMenuIcons(self):
00673         # Object buttons should have icons
00674         icons = self.icons.listActionIcons()
00675         def assertIcon(action_id):
00676             for icon in icons:
00677                 if (icon.getActionId() == action_id and
00678                     icon.getCategory() == 'object_buttons'):
00679                     break
00680             else:
00681                 self.fail("Action icons tool has no '%s' icon" % action_id)
00682         assertIcon('cut')
00683         assertIcon('copy')
00684         assertIcon('paste')
00685         assertIcon('delete')
00686 
00687     def testCacheManagers(self):
00688         # The cache and caching policy managers should exist
00689         httpcache = self.portal._getOb('HTTPCache', None)
00690         ramcache = self.portal._getOb('RAMCache', None)
00691         cpm = self.portal._getOb('caching_policy_manager', None)
00692         self.failUnless(isinstance(httpcache, AcceleratedHTTPCacheManager))
00693         self.failUnless(isinstance(ramcache, RAMCacheManager))
00694         self.failUnless(isinstance(cpm, CachingPolicyManager))
00695 
00696     def testHomeActionUsesView(self):
00697         actions = self.actions.listActions()
00698         homeAction = [x for x in actions if x.id == 'index_html'][0]
00699         self.assertEquals(homeAction.getInfoData()[0]['url'].text, 'string:${globals_view/navigationRootUrl}')
00700 
00701     def testPloneLexicon(self):
00702         # Plone lexicon should use new splitter and case normalizer
00703         pipeline = self.catalog.plone_lexicon._pipeline
00704         self.failUnless(len(pipeline) >= 2)
00705         self.failUnless(isinstance(pipeline[0], Splitter))
00706         self.failUnless(isinstance(pipeline[1], CaseNormalizer))
00707 
00708     def testMakeSnapshot(self):
00709         # GenericSetup snapshot should work
00710         self.setRoles(['Manager'])
00711         snapshot_id = self.setup._mangleTimestampName('test')
00712         self.setup.createSnapshot(snapshot_id)
00713 
00714     def testValidateEmail(self):
00715         # validate_email should be on by default
00716         self.failUnless(self.portal.getProperty('validate_email'))
00717 
00718     def testSiteManagerSetup(self):
00719         clearSite()
00720         # The portal should be an ISite
00721         self.failUnless(ISite.providedBy(self.portal))
00722         # There should be a IComponentRegistry
00723         comp = IComponentLookup(self.portal)
00724         IComponentRegistry.providedBy(comp)
00725 
00726         # Test if we get the right site managers
00727         gsm = getGlobalSiteManager()
00728         sm = getSiteManager()
00729         # Without setting the site we should get the global site manager
00730         self.failUnless(sm is gsm)
00731 
00732         # Now we set the site, as it is done in url traversal normally
00733         setSite(self.portal)
00734         # And should get the local site manager
00735         sm = getSiteManager()
00736         self.failUnless(aq_base(sm) is aq_base(comp))
00737 
00738     def testUtilityRegistration(self):
00739         gsm = getGlobalSiteManager()
00740         global_util = dummy.DummyUtility()
00741 
00742         # Register a global utility and see if we can get it
00743         gsm.registerUtility(global_util, dummy.IDummyUtility)
00744         getutil = getUtility(dummy.IDummyUtility)
00745         self.assertEquals(getutil, global_util)
00746 
00747         # Register a local utility and see if we can get it
00748         sm = getSiteManager()
00749         local_util = dummy.DummyUtility()
00750 
00751         sm.registerUtility(local_util, dummy.IDummyUtility)
00752         getutil = getUtility(dummy.IDummyUtility)
00753         self.assertEquals(getutil, local_util)
00754         # Clean up the site again
00755         clearSite()
00756 
00757         # Without a site we get the global utility
00758         getutil = getUtility(dummy.IDummyUtility)
00759         self.assertEquals(getutil, global_util)
00760 
00761         # Clean up again and unregister the utilites
00762         gsm.unregisterUtility(provided=dummy.IDummyUtility)
00763         sm.unregisterUtility(provided=dummy.IDummyUtility)
00764 
00765         # Make sure unregistration was successful
00766         util = queryUtility(dummy.IDummyUtility)
00767         self.failUnless(util is None)
00768 
00769     def testPortletManagersInstalled(self):
00770         sm = getSiteManager(self.portal)
00771         registrations = [r.name for r in sm.registeredUtilities()
00772                             if IPortletManager == r.provided]
00773         self.assertEquals(['plone.dashboard1', 'plone.dashboard2', 'plone.dashboard3', 'plone.dashboard4',
00774                             'plone.leftcolumn', 'plone.rightcolumn'], sorted(registrations))
00775 
00776     def testPortletAssignmentsAtRoot(self):
00777         leftColumn = getUtility(IPortletManager, name=u'plone.leftcolumn')
00778         rightColumn = getUtility(IPortletManager, name=u'plone.rightcolumn')
00779 
00780         left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping)
00781         right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping)
00782 
00783         self.assertEquals(len(left), 2)
00784         self.assertEquals(len(right), 4)
00785 
00786     def testPortletBlockingForMembersFolder(self):
00787         members = self.portal.Members
00788         rightColumn = getUtility(IPortletManager, name=u'plone.rightcolumn')
00789         portletAssignments = getMultiAdapter((members, rightColumn,), ILocalPortletAssignmentManager)
00790         self.assertEquals(True, portletAssignments.getBlacklistStatus(CONTEXT_PORTLETS))
00791 
00792     def testAddablePortletsInColumns(self):
00793         for name in (u'plone.leftcolumn', u'plone.rightcolumn'):
00794             column = getUtility(IPortletManager, name=name)
00795             addable_types = [
00796               p.addview for p in column.getAddablePortletTypes()
00797               ]
00798             addable_types.sort()
00799             self.assertEqual([
00800                 'plone.portlet.collection.Collection',
00801                 'plone.portlet.static.Static',
00802                 'portlets.Calendar',
00803                 'portlets.Classic',
00804                 'portlets.Events',
00805                 'portlets.Login',
00806                 'portlets.Navigation',
00807                 'portlets.News',
00808                 'portlets.Recent',
00809                 'portlets.Review',
00810                 'portlets.Search',
00811                 'portlets.rss'], addable_types)
00812 
00813     def testAddablePortletsInDashboard(self):
00814         for name in ('plone.dashboard1', 'plone.dashboard2',
00815           'plone.dashboard3', 'plone.dashboard4'):
00816             column = getUtility(IPortletManager, name=name)
00817             addable_types = [
00818               p.addview for p in column.getAddablePortletTypes()
00819               ]
00820             addable_types.sort()
00821             self.assertEqual([
00822               'plone.portlet.collection.Collection',
00823               'plone.portlet.static.Static',
00824               'portlets.Calendar',
00825               'portlets.Classic',
00826               'portlets.Events',
00827               'portlets.News',
00828               'portlets.Recent',
00829               'portlets.Review',
00830               'portlets.Search',
00831               'portlets.rss'
00832               ], addable_types)
00833 
00834     def testReaderEditorRoles(self):
00835         self.failUnless('Reader' in self.portal.valid_roles())
00836         self.failUnless('Editor' in self.portal.valid_roles())
00837         self.failUnless('Reader' in self.portal.acl_users.portal_role_manager.listRoleIds())
00838         self.failUnless('Editor' in self.portal.acl_users.portal_role_manager.listRoleIds())
00839         self.failUnless('View' in [r['name'] for r in self.portal.permissionsOfRole('Reader') if r['selected']])
00840         self.failUnless('Modify portal content' in [r['name'] for r in self.portal.permissionsOfRole('Editor') if r['selected']])
00841 
00842     def testWorkflowsInstalled(self):
00843         for wf in ['intranet_workflow', 'intranet_folder_workflow',
00844                 'one_state_workflow', 'simple_publication_workflow']:
00845             self.failUnless(wf in self.portal.portal_workflow.objectIds())
00846 
00847     def testAddPermisssionsGivenToContributorRole(self):
00848         self.failUnless('Contributor' in self.portal.valid_roles())
00849         self.failUnless('Contributor' in self.portal.acl_users.portal_role_manager.listRoleIds())
00850         for p in ['Add portal content', 'Add portal folders', 'ATContentTypes: Add Document',
00851                     'ATContentTypes: Add Event', 'ATContentTypes: Add Favorite',
00852                     'ATContentTypes: Add File', 'ATContentTypes: Add Folder',
00853                     'ATContentTypes: Add Image', 'ATContentTypes: Add Large Plone Folder',
00854                     'ATContentTypes: Add Link', 'ATContentTypes: Add News Item', ]:
00855             self.failUnless(p in [r['name'] for r in
00856                                 self.portal.permissionsOfRole('Contributor') if r['selected']])
00857 
00858     def testSharingAction(self):
00859         # Should be in portal_actions
00860         self.failUnless('local_roles' in self.actions.object.objectIds())
00861 
00862         # Should not be in any of the default FTIs
00863         for fti in self.types.objectValues():
00864             self.failIf('local_roles' in [a.id for a in fti.listActions()])
00865 
00866     def testSecondaryEditorPermissionsGivenToEditorRole(self):
00867         for p in ['Manage properties', 'Modify view template', 'Request review']:
00868             self.failUnless(p in [r['name'] for r in
00869                                 self.portal.permissionsOfRole('Editor') if r['selected']])
00870 
00871     def testNonFolderishTabsProperty(self):
00872         self.assertEquals(False, self.properties.site_properties.disable_nonfolderish_sections)
00873 
00874     def testPortalContentLanguage(self):
00875         from zope.app.testing.ztapi import provideUtility
00876         from zope.i18n.interfaces import ITranslationDomain
00877         from zope.i18n.simpletranslationdomain import SimpleTranslationDomain
00878 
00879         # Let's fake the news title translations
00880         messages = {
00881             ('de', u'news-title'): u'Foo',
00882             ('pt_BR', u'news-title'): u'Bar',
00883         }
00884         pfp = SimpleTranslationDomain('plonefrontpage', messages)
00885         provideUtility(ITranslationDomain, pfp, 'plonefrontpage')
00886 
00887         # Setup the generator and the new placeholder folders
00888         gen = setuphandlers.PloneGenerator()
00889         self.folder.invokeFactory('Folder', 'brazilian')
00890         self.folder.invokeFactory('Folder', 'german')
00891 
00892         # Check if the content is being created in German
00893         self.app.REQUEST['HTTP_ACCEPT_LANGUAGE'] = 'de'
00894         gen.setupPortalContent(self.folder.german)
00895         self.failUnlessEqual(self.folder.german.news.Title(), 'Foo')
00896 
00897         # Check if the content is being created in a composite
00898         # language code, in this case Brazilian Portuguese
00899         self.app.REQUEST['HTTP_ACCEPT_LANGUAGE'] = 'pt-br'
00900         gen.setupPortalContent(self.folder.brazilian)
00901         self.failUnlessEqual(self.folder.brazilian.news.Title(), 'Bar')
00902 
00903 
00904 class TestPortalBugs(PloneTestCase.PloneTestCase):
00905 
00906     def afterSetUp(self):
00907         self.membership = self.portal.portal_membership
00908         self.members = self.membership.getMembersFolder()
00909         self.catalog = self.portal.portal_catalog
00910         self.mem_index_type = "Script (Python)"
00911         self.setupAuthenticator()
00912 
00913     def testMembersIndexHtml(self):
00914         # index_html for Members folder should be a Page Template
00915         members = self.members
00916         #self.assertEqual(aq_base(members).meta_type, 'Large Plone Folder')
00917         self.assertEqual(aq_base(members).meta_type, 'ATBTreeFolder')
00918         self.failUnless(hasattr(aq_base(members), 'index_html'))
00919         # getitem works
00920         self.assertEqual(aq_base(members)['index_html'].meta_type, self.mem_index_type)
00921         self.assertEqual(members['index_html'].meta_type, self.mem_index_type)
00922         # _getOb works
00923         self.assertEqual(aq_base(members)._getOb('index_html').meta_type, self.mem_index_type)
00924         self.assertEqual(members._getOb('index_html').meta_type, self.mem_index_type)
00925         # getattr works when called explicitly
00926         self.assertEqual(aq_base(members).__getattr__('index_html').meta_type, self.mem_index_type)
00927         self.assertEqual(members.__getattr__('index_html').meta_type, self.mem_index_type)
00928 
00929     def testLargePloneFolderHickup(self):
00930         # Attribute access for 'index_html' acquired the Document from the
00931         # portal instead of returning the local Page Template. This was due to
00932         # special treatment of 'index_html' in the PloneFolder base class and
00933         # got fixed by hazmat.
00934         members = self.members
00935         self.assertEqual(aq_base(members).meta_type, 'ATBTreeFolder')
00936         self.assertEqual(members.index_html.meta_type, self.mem_index_type)
00937 
00938     def testSubsequentProfileImportSucceeds(self):
00939         # Subsequent profile imports fail (#5439)
00940         self.loginAsPortalOwner()
00941         setup_tool = getToolByName(self.portal, "portal_setup")
00942         # this will raise an error if it fails
00943         profile = setup_tool.getBaselineContextID()
00944         setup_tool.runAllImportStepsFromProfile(profile, purge_old=True)
00945         self.failUnless(1 == 1)
00946 
00947     def testFinalStepsWithMembersFolderDeleted(self):
00948         # We want the final steps to work even if the 'Members' folder
00949         # is gone
00950         self.loginAsPortalOwner()
00951         portal = self.portal
00952         portal.manage_delObjects(['Members'])
00953         class FakeContext:
00954             def getSite(self):
00955                 return portal
00956             def readDataFile(self, filename):
00957                 return True # Anything other than None runs the step
00958 
00959         setuphandlers.importFinalSteps(FakeContext()) # raises error if fail
00960         self.failUnless(1 == 1)
00961 
00962     def testExportImportLosesTextIndexes(self):
00963         # Importing a portal .zexp loses text indexes? (#4803)
00964         self.loginAsPortalOwner()
00965         tempfile = mkstemp('.zexp')
00966         tempname = tempfile[1]
00967         try:
00968             # Export the portal
00969             self.portal._p_jar.exportFile(self.portal._p_oid, tempname)
00970             # Nuke it
00971             self.app._delObject(PloneTestCase.portal_name)
00972             # Import the portal
00973             self.app._importObjectFromFile(tempname, set_owner=0)
00974             # Now check the indexes are still present
00975             for index in ('Description', 'Title', 'SearchableText'):
00976                 try:
00977                     self.catalog.Indexes[index]
00978                 except KeyError:
00979                     self.fail('Index %s missing after export/import!' % index)
00980         finally:
00981             os.close(tempfile[0])
00982             os.remove(tempname)
00983 
00984 
00985 class TestManagementPageCharset(PloneTestCase.PloneTestCase):
00986 
00987     def afterSetUp(self):
00988         self.properties = self.portal.portal_properties
00989 
00990     def testManagementPageCharsetEqualsDefaultCharset(self):
00991         # Checks that 'management_page_charset' attribute of the portal
00992         # reflects 'portal_properties/site_properties/default_charset'.
00993         default_charset = self.properties.site_properties.getProperty('default_charset', None)
00994         self.failUnless(default_charset)
00995         manage_charset = getattr(self.portal, 'management_page_charset', None)
00996         self.failUnless(manage_charset)
00997         self.assertEqual(manage_charset, default_charset)
00998         self.assertEqual(manage_charset, 'utf-8')
00999 
01000     def testManagementPageCharsetIsComputedAttribute(self):
01001         # Checks that 'management_page_charset' attribute of the portal
01002         # is a ComputedAttribute and always follows the default_charset property.
01003         self.properties.site_properties.manage_changeProperties(default_charset='latin1')
01004         default_charset = self.properties.site_properties.getProperty('default_charset', None)
01005         manage_charset = getattr(self.portal, 'management_page_charset', None)
01006         self.assertEqual(manage_charset, default_charset)
01007         self.assertEqual(manage_charset, 'latin1')
01008 
01009     def testManagementPageCharsetFallbackNoProperty(self):
01010         self.properties.site_properties._delProperty('default_charset')
01011         manage_charset = getattr(self.portal, 'management_page_charset', None)
01012         self.assertEqual(manage_charset, 'utf-8')
01013 
01014     def testManagementPageCharsetFallbackNoPropertySheet(self):
01015         self.properties._delObject('site_properties')
01016         manage_charset = getattr(self.portal, 'management_page_charset', None)
01017         self.assertEqual(manage_charset, 'utf-8')
01018 
01019     def testManagementPageCharsetFallbackNotAPropertySheet(self):
01020         self.properties._delObject('site_properties')
01021         self.properties.site_properties = 'foo'
01022         manage_charset = getattr(self.portal, 'management_page_charset', None)
01023         self.assertEqual(manage_charset, 'utf-8')
01024 
01025     def testManagementPageCharsetFallbackNoPropertyTool(self):
01026         self.portal._delObject('portal_properties')
01027         manage_charset = getattr(self.portal, 'management_page_charset', None)
01028         self.assertEqual(manage_charset, 'utf-8')
01029 
01030 
01031 def test_suite():
01032     from unittest import TestSuite, makeSuite
01033     suite = TestSuite()
01034     suite.addTest(makeSuite(TestPortalCreation))
01035     suite.addTest(makeSuite(TestPortalBugs))
01036     suite.addTest(makeSuite(TestManagementPageCharset))
01037     return suite