[Testbot] Plone 5.0 - Python 2.7 - Build # 3927 - Fixed! - 0 failure(s)
jenkins at plone.org
jenkins at plone.org
Wed Jan 7 14:03:02 UTC 2015
-------------------------------------------------------------------------------
Plone 5.0 - Python 2.7 - Build # 3927 - Fixed!
-------------------------------------------------------------------------------
http://jenkins.plone.org/job/plone-5.0-python-2.7/3927/
-------------------------------------------------------------------------------
CHANGES
-------------------------------------------------------------------------------
Repository: plone.app.upgrade
Branch: refs/heads/master
Date: 2015-01-07T14:28:06+01:00
Author: Timo Stollenwerk (tisto) <tisto at plone.org>
Commit: https://github.com/plone/plone.app.upgrade/commit/2be4aa9eed9e56c020d9b0ecf20865433aa4adfe
Revert "Ported to plone.app.testing"
Files changed:
A plone/app/upgrade/v25/tests.py
A plone/app/upgrade/v30/tests.py
A plone/app/upgrade/v31/tests.py
A plone/app/upgrade/v32/tests.py
A plone/app/upgrade/v33/tests.py
A plone/app/upgrade/v40/tests.py
A plone/app/upgrade/v41/tests.py
A plone/app/upgrade/v42/tests.py
M CHANGES.rst
M plone/app/upgrade/tests/base.py
M setup.py
diff --git a/CHANGES.rst b/CHANGES.rst
index 6e27679..1bf846a 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,7 +1,7 @@
Changelog
=========
-2.0 (unreleased)
+1.3.9 (unreleased)
------------------
- Add upgrade step for the security control panel.
@@ -13,11 +13,6 @@ Changelog
- Add upgrade steps for markup control panel.
[thet]
-- Ported tests to plone.app.testing
- [tomgross]
-
-- Removed all tests for migrations older than 4.3 -> 5.0
- [tomgross]
1.3.8 (2014-11-01)
------------------
diff --git a/plone/app/upgrade/tests/base.py b/plone/app/upgrade/tests/base.py
index f25f530..840416c 100644
--- a/plone/app/upgrade/tests/base.py
+++ b/plone/app/upgrade/tests/base.py
@@ -9,7 +9,10 @@
import transaction
from zope.site.hooks import setSite
-from plone.app.testing.bbb import PloneTestCase
+from Testing.ZopeTestCase.sandbox import Sandboxed
+from Products.PloneTestCase.layer import PloneSiteLayer
+from Products.PloneTestCase.ptc import PloneTestCase
+from Products.PloneTestCase.ptc import setupPloneSite
from Products.CMFCore.interfaces import IActionCategory
from Products.CMFCore.interfaces import IActionInfo
@@ -17,6 +20,8 @@
from Products.CMFCore.tests.base.testcase import WarningInterceptor
from Products.GenericSetup.context import TarballImportContext
+setupPloneSite()
+
class MigrationTest(PloneTestCase):
@@ -106,10 +111,21 @@ def removeSkinLayer(self, layer, skin='Plone Default'):
skins.addSkinSelection(skin, ','.join(path))
+class FunctionalUpgradeLayer(PloneSiteLayer):
+
+ @classmethod
+ def setUp(cls):
+ pass
+
+ @classmethod
+ def tearDown(cls):
+ pass
+
-class FunctionalUpgradeTestCase(PloneTestCase, WarningInterceptor):
+class FunctionalUpgradeTestCase(Sandboxed, PloneTestCase, WarningInterceptor):
_setup_fixture = 0
+ layer = FunctionalUpgradeLayer
site_id = 'test'
def afterSetUp(self):
diff --git a/plone/app/upgrade/v25/tests.py b/plone/app/upgrade/v25/tests.py
new file mode 100644
index 0000000..036e8b5
--- /dev/null
+++ b/plone/app/upgrade/v25/tests.py
@@ -0,0 +1,124 @@
+from Products.CMFPlone.UnicodeSplitter import Splitter
+from Products.CMFPlone.UnicodeSplitter import CaseNormalizer
+
+from plone.app.upgrade.tests.base import FunctionalUpgradeTestCase
+from plone.app.upgrade.tests.base import MigrationTest
+from plone.app.upgrade.utils import loadMigrationProfile
+
+from plone.app.upgrade.v25 import fixupPloneLexicon
+from plone.app.upgrade.v25 import setLoginFormInCookieAuth
+from plone.app.upgrade.v25 import addMissingMimeTypes
+
+
+class TestMigrations_v2_5_0(MigrationTest):
+
+ def afterSetUp(self):
+ self.profile = 'profile-plone.app.upgrade.v25:2.5final-2.5.1'
+ self.actions = self.portal.portal_actions
+ self.css = self.portal.portal_css
+
+ def tesFixObjDeleteAction(self):
+ # Prepare delete actions test
+ editActions = ('delete',)
+ for a in editActions:
+ self.removeActionFromTool(a, category='object_buttons')
+ loadMigrationProfile(self.portal, self.profile, ('actions', ))
+ # delete action tests
+ actions = [x.id for x in self.actions.object_buttons.listActions()
+ if x.id in editActions]
+ # check that all of our deleted actions are now present
+ for a in editActions:
+ self.assertTrue(a in actions)
+ # ensure that they are present only once
+ self.assertEqual(len(editActions), len(actions))
+
+ def testFixupPloneLexicon(self):
+ # Should update the plone_lexicon pipeline
+ lexicon = self.portal.portal_catalog.plone_lexicon
+ lexicon._pipeline = (object(), object())
+ # Test it twice
+ for i in range(2):
+ fixupPloneLexicon(self.portal)
+ self.assertTrue(isinstance(lexicon._pipeline[0], Splitter))
+ self.assertTrue(isinstance(lexicon._pipeline[1], CaseNormalizer))
+
+
+class TestMigrations_v2_5_1(MigrationTest):
+
+ def afterSetUp(self):
+ self.actions = self.portal.portal_actions
+ self.memberdata = self.portal.portal_memberdata
+ self.catalog = self.portal.portal_catalog
+ self.skins = self.portal.portal_skins
+ self.types = self.portal.portal_types
+ self.workflow = self.portal.portal_workflow
+ self.css = self.portal.portal_css
+
+ def testSetLoginFormInCookieAuth(self):
+ setLoginFormInCookieAuth(self.portal)
+ cookie_auth = self.portal.acl_users.credentials_cookie_auth
+ self.assertEqual(cookie_auth.getProperty('login_path'),
+ 'require_login')
+
+ def testSetLoginFormNoCookieAuth(self):
+ # Shouldn't error
+ uf = self.portal.acl_users
+ uf._delOb('credentials_cookie_auth')
+ setLoginFormInCookieAuth(self.portal)
+
+ def testSetLoginFormAlreadyChanged(self):
+ # Shouldn't change the value if it's not the default
+ cookie_auth = self.portal.acl_users.credentials_cookie_auth
+ cookie_auth.manage_changeProperties(login_path='foo')
+ setLoginFormInCookieAuth(self.portal)
+ self.assertTrue(cookie_auth.getProperty('login_path') != 'require_login')
+
+class TestMigrations_v2_5_2(MigrationTest):
+
+ def afterSetUp(self):
+ self.mimetypes = self.portal.mimetypes_registry
+
+ def testMissingMimeTypes(self):
+ # we're testing for 'text/x-web-markdown' and 'text/x-web-textile'
+ missing_types = ['text/x-web-markdown', 'text/x-web-textile']
+ # since we're running a full 2.5.4 instance in this test, the missing
+ # types might in fact already be there:
+ current_types = self.mimetypes.list_mimetypes()
+ types_to_delete = []
+ for mtype in missing_types:
+ if mtype in current_types:
+ types_to_delete.append(mtype)
+ if types_to_delete:
+ self.mimetypes.manage_delObjects(types_to_delete)
+ # now they're gone:
+ self.assertFalse(set(self.mimetypes.list_mimetypes()).issuperset(set(missing_types)))
+ addMissingMimeTypes(self.portal)
+ # now they're back:
+ self.assertTrue(set(self.mimetypes.list_mimetypes()).issuperset(set(missing_types)))
+
+
+class TestFunctionalMigrations(FunctionalUpgradeTestCase):
+
+ def testUpgrade(self):
+ self.importFile(__file__, 'test-base.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+ def testDCMIStorageUpdated(self):
+ self.importFile(__file__, 'test-base.zexp')
+ oldsite, result = self.migrate()
+
+ dcmi = getattr(oldsite.portal_metadata, 'DCMI', None)
+ self.assertFalse(dcmi is None)
+
+
+def test_suite():
+ from unittest import TestSuite, makeSuite
+ suite = TestSuite()
+ suite.addTest(makeSuite(TestMigrations_v2_5_0))
+ suite.addTest(makeSuite(TestMigrations_v2_5_1))
+ suite.addTest(makeSuite(TestMigrations_v2_5_2))
+ suite.addTest(makeSuite(TestFunctionalMigrations))
+ return suite
diff --git a/plone/app/upgrade/v30/tests.py b/plone/app/upgrade/v30/tests.py
new file mode 100644
index 0000000..9325d0d
--- /dev/null
+++ b/plone/app/upgrade/v30/tests.py
@@ -0,0 +1,1109 @@
+from Acquisition import aq_base
+
+from five.localsitemanager.registry import FiveVerifyingAdapterLookup
+
+from plone.contentrules.engine.interfaces import IRuleStorage
+from plone.app.i18n.locales.interfaces import IContentLanguages
+from plone.app.i18n.locales.interfaces import ICountries
+from plone.app.i18n.locales.interfaces import IMetadataLanguages
+from plone.app.portlets import portlets
+from plone.app.redirector.interfaces import IRedirectionStorage
+from plone.portlets.interfaces import IPortletManager
+from plone.portlets.interfaces import IPortletAssignmentMapping
+from plone.portlets.interfaces import ILocalPortletAssignmentManager
+from plone.portlets.constants import CONTEXT_CATEGORY as CONTEXT_PORTLETS
+
+from zope.location.interfaces import ISite
+from zope.component import getGlobalSiteManager
+from zope.component import getSiteManager
+from zope.component import getUtility, getMultiAdapter
+from zope.component.hooks import clearSite
+
+from Products.Archetypes.interfaces import IArchetypeTool
+from Products.Archetypes.interfaces import IReferenceCatalog
+from Products.Archetypes.interfaces import IUIDCatalog
+from Products.CMFActionIcons.interfaces import IActionIconsTool
+from Products.CMFCalendar.interfaces import ICalendarTool
+from Products.CMFCore.ActionInformation import Action
+from Products.CMFCore.ActionInformation import ActionCategory
+from Products.CMFCore.utils import getToolByName
+from Products.CMFCore.utils import getToolInterface
+from Products.CMFCore.Expression import Expression
+from Products.CMFCore.permissions import AccessInactivePortalContent
+from Products.CMFCore.interfaces import IActionsTool
+from Products.CMFCore.interfaces import ICachingPolicyManager
+from Products.CMFCore.interfaces import ICatalogTool
+from Products.CMFCore.interfaces import IContentTypeRegistry
+from Products.CMFCore.interfaces import IDiscussionTool
+from Products.CMFCore.interfaces import IMemberDataTool
+from Products.CMFCore.interfaces import IMembershipTool
+from Products.CMFCore.interfaces import IMetadataTool
+from Products.CMFCore.interfaces import IPropertiesTool
+from Products.CMFCore.interfaces import IRegistrationTool
+from Products.CMFCore.interfaces import ISiteRoot
+from Products.CMFCore.interfaces import ISkinsTool
+from Products.CMFCore.interfaces import ISyndicationTool
+from Products.CMFCore.interfaces import ITypesTool
+from Products.CMFCore.interfaces import IURLTool
+from Products.CMFCore.interfaces import IConfigurableWorkflowTool
+from Products.CMFCore.ActionInformation import ActionInformation
+from Products.CMFDiffTool.interfaces import IDiffTool
+from Products.CMFEditions.interfaces import IArchivistTool
+from Products.CMFEditions.interfaces import IPortalModifierTool
+from Products.CMFEditions.interfaces import IPurgePolicyTool
+from Products.CMFEditions.interfaces.IRepository import IRepositoryTool
+from Products.CMFEditions.interfaces import IStorageTool
+from Products.CMFFormController.interfaces import IFormControllerTool
+from Products.CMFQuickInstallerTool.interfaces import IQuickInstallerTool
+from Products.CMFPlone.interfaces import IPloneSiteRoot
+from Products.CMFPlone.interfaces import IPloneTool
+from Products.CMFPlone.interfaces import ITranslationServiceTool
+from Products.CMFUid.interfaces import IUniqueIdAnnotationManagement
+from Products.CMFUid.interfaces import IUniqueIdGenerator
+from Products.CMFUid.interfaces import IUniqueIdHandler
+from Products.GenericSetup.interfaces import ISetupTool
+from Products.MailHost.interfaces import IMailHost
+from Products.MimetypesRegistry.interfaces import IMimetypesRegistryTool
+from Products.PortalTransforms.interfaces import IPortalTransformsTool
+from Products.PloneLanguageTool.interfaces import ILanguageTool
+from Products.PlonePAS.interfaces.group import IGroupTool
+from Products.PlonePAS.interfaces.group import IGroupDataTool
+from Products.ResourceRegistries.interfaces import ICSSRegistry
+from Products.ResourceRegistries.interfaces import IJSRegistry
+
+from plone.app.upgrade.tests.base import FunctionalUpgradeTestCase
+from plone.app.upgrade.tests.base import MigrationTest
+from plone.app.upgrade.utils import loadMigrationProfile
+
+from plone.app.upgrade.v30.alphas import enableZope3Site
+from plone.app.upgrade.v30.alphas import migrateOldActions
+from plone.app.upgrade.v30.alphas import updateActionsI18NDomain
+from plone.app.upgrade.v30.alphas import updateFTII18NDomain
+from plone.app.upgrade.v30.alphas import convertLegacyPortlets
+from plone.app.upgrade.v30.alphas import registerToolsAsUtilities
+from plone.app.upgrade.v30.alphas import registration
+from plone.app.upgrade.v30.alphas import addReaderAndEditorRoles
+from plone.app.upgrade.v30.alphas import migrateLocalroleForm
+from plone.app.upgrade.v30.alphas import reorderUserActions
+from plone.app.upgrade.v30.alphas import updatePASPlugins
+from plone.app.upgrade.v30.alphas import updateConfigletTitles
+from plone.app.upgrade.v30.alphas import addCacheForResourceRegistry
+from plone.app.upgrade.v30.alphas import removeTablelessSkin
+from plone.app.upgrade.v30.alphas import addObjectProvidesIndex
+from plone.app.upgrade.v30.alphas import restorePloneTool
+from plone.app.upgrade.v30.alphas import installProduct
+
+from plone.app.upgrade.v30.betas import migrateHistoryTab
+from plone.app.upgrade.v30.betas import changeOrderOfActionProviders
+from plone.app.upgrade.v30.betas import cleanupOldActions
+from plone.app.upgrade.v30.betas import cleanDefaultCharset
+from plone.app.upgrade.v30.betas import addAutoGroupToPAS
+from plone.app.upgrade.v30.betas import removeS5Actions
+from plone.app.upgrade.v30.betas import addContributorToCreationPermissions
+from plone.app.upgrade.v30.betas import removeSharingAction
+from plone.app.upgrade.v30.betas import addEditorToSecondaryEditorPermissions
+from plone.app.upgrade.v30.betas import updateEditActionConditionForLocking
+from plone.app.upgrade.v30.betas import addOnFormUnloadJS
+
+from plone.app.upgrade.v30.betas import updateTopicTitle
+from plone.app.upgrade.v30.betas import cleanupActionProviders
+from plone.app.upgrade.v30.betas import hidePropertiesAction
+
+from plone.app.upgrade.v30.rcs import addIntelligentText
+
+from plone.app.upgrade.v30.final_three0x import installNewModifiers
+
+try:
+ from Products.ATContentTypes.interface import IATCTTool
+ HAS_ATCT = True
+except ImportError:
+ HAS_ATCT = False
+
+try:
+ from Products.CMFPlone.interfaces import IFactoryTool
+except:
+ from Products.ATContentTypes.interfaces import IFactoryTool
+
+
+class TestMigrations_v3_0_Actions(MigrationTest):
+
+ def afterSetUp(self):
+ self.actions = self.portal.portal_actions
+ self.types = self.portal.portal_types
+ self.workflow = self.portal.portal_workflow
+ self._migrate_reply_action()
+
+ def _migrate_reply_action(self):
+ # Create dummy old ActionInformation
+ reply = ActionInformation('reply',
+ title='Reply',
+ category='reply_actions',
+ condition='context/replyAllowed',
+ permissions=(AccessInactivePortalContent, ),
+ priority=10,
+ visible=True,
+ action='context/reply'
+ )
+
+ from OFS.SimpleItem import SimpleItem
+ class DummyTool(SimpleItem):
+ pass
+ dummy = DummyTool()
+ dummy._actions = (reply,)
+ self.portal._setObject('dummy', dummy)
+
+ def testMigrateActions(self):
+ # Test it twice
+ for i in range(2):
+ migrateOldActions(self.portal)
+ reply_actions = getattr(self.actions, 'reply_actions', None)
+ self.assertFalse(reply_actions is None)
+ reply = getattr(reply_actions, 'reply', None)
+ self.assertFalse(reply is None)
+ self.assertTrue(isinstance(reply, Action))
+ # Verify all data has been upgraded correctly to the new Action
+ data = reply.getInfoData()[0]
+ self.assertEqual(data['category'], 'reply_actions')
+ self.assertEqual(data['title'], 'Reply')
+ self.assertEqual(data['visible'], True)
+ self.assertEqual(data['permissions'], (AccessInactivePortalContent, ))
+ self.assertEqual(data['available'].text, 'context/replyAllowed')
+ self.assertEqual(data['url'].text, 'context/reply')
+ # Make sure the original action has been removed
+ self.assertEqual(len(self.portal.dummy._actions), 0)
+
+ def testUpdateActionsI18NDomain(self):
+ migrateOldActions(self.portal)
+ reply = self.actions.reply_actions.reply
+ self.assertEqual(reply.i18n_domain, '')
+ # Test it twice
+ for i in range(2):
+ updateActionsI18NDomain(self.portal)
+ self.assertEqual(reply.i18n_domain, 'plone')
+
+ def testUpdateActionsI18NDomainNonAscii(self):
+ migrateOldActions(self.portal)
+ reply = self.actions.reply_actions.reply
+ reply.title = 'Foo\xc3'
+ self.assertEqual(reply.i18n_domain, '')
+ self.assertEqual(reply.title, 'Foo\xc3')
+
+ updateActionsI18NDomain(self.portal)
+
+ self.assertEqual(reply.i18n_domain, '')
+
+ def testHistoryActionID(self):
+ # Test it twice
+ for i in range(2):
+ migrateHistoryTab(self.portal)
+ objects = getattr(self.actions, 'object', None)
+ self.assertFalse('rss' in objects.objectIds())
+
+ def testProviderCleanup(self):
+ self.actions.addActionProvider("portal_membership")
+ self.assertTrue("portal_membership" in self.actions.listActionProviders())
+ # Test it twice
+ for i in range(2):
+ cleanupActionProviders(self.portal)
+ self.assertFalse("portal_membership" in self.actions.listActionProviders())
+
+ def testRemovePropertiesActions(self):
+ ti = self.types.getTypeInfo("Document")
+ if ti.getActionObject("object/properties") is None:
+ ti.addAction("metadata", "name", "action", "condition",
+ "permission", "object",)
+ # Test it twice
+ for i in range(2):
+ hidePropertiesAction(self.portal)
+ self.assertTrue(ti.getActionObject("object/metadata") is None)
+
+ def tearDown(self):
+ self.portal._delObject('dummy')
+
+
+class TestMigrations_v2_5_x(MigrationTest):
+
+ def afterSetUp(self):
+ self.profile = 'profile-plone.app.upgrade.v30:2.5.x-3.0a1'
+ self.types = self.portal.portal_types
+ self.properties = self.portal.portal_properties
+
+ for legacy_tool in ('portal_discussion', 'portal_actionicons'):
+ if legacy_tool not in self.portal:
+ from OFS.SimpleItem import SimpleItem
+ self.portal._setObject(legacy_tool, SimpleItem())
+
+ def disableSite(self, obj, iface=ISite):
+ # We need our own disableSite method as the CMF portal implements
+ # ISite directly, so we cannot remove it, like the disableSite method
+ # in Five.component would have done
+ from ZPublisher.BeforeTraverse import unregisterBeforeTraverse
+ from Products.Five.component import HOOK_NAME
+ obj = aq_base(obj)
+ if not iface.providedBy(obj):
+ raise TypeError('Object must be a site.')
+ unregisterBeforeTraverse(obj, HOOK_NAME)
+ if hasattr(obj, HOOK_NAME):
+ delattr(obj, HOOK_NAME)
+
+ def testEnableZope3Site(self):
+ # First we remove the site and site manager
+ self.disableSite(self.portal)
+ clearSite(self.portal)
+ self.portal.setSiteManager(None)
+ gsm = getGlobalSiteManager()
+ # Test it twice
+ for i in range(2):
+ enableZope3Site(self.portal)
+ # And see if we have an ISite with a local site manager
+ self.assertTrue(ISite.providedBy(self.portal))
+ sm = getSiteManager(self.portal)
+ self.assertFalse(gsm is sm)
+ lc = sm.utilities.LookupClass
+ self.assertEqual(lc, FiveVerifyingAdapterLookup)
+
+ # Test the lookupclass migration
+ sm.utilities.LookupClass = None
+ # Test it twice
+ for i in range(2):
+ enableZope3Site(self.portal)
+ self.assertEqual(sm.utilities.LookupClass, FiveVerifyingAdapterLookup)
+ self.assertEqual(sm.utilities.__parent__, sm)
+ self.assertEqual(sm.__parent__, self.portal)
+
+ def testUpdateFTII18NDomain(self):
+ doc = self.types.Document
+ doc.i18n_domain = ''
+ # Test it twice
+ for i in range(2):
+ updateFTII18NDomain(self.portal)
+ self.assertEqual(doc.i18n_domain, 'plone')
+
+ def testUpdateFTII18NDomainNonAscii(self):
+ doc = self.types.Document
+ doc.i18n_domain = ''
+ doc.title = 'Foo\xc3'
+ # Update FTI's
+ updateFTII18NDomain(self.portal)
+ # domain should have been updated
+ self.assertEqual(doc.i18n_domain, '')
+
+ def testAddDefaultAndForbiddenContentTypesProperties(self):
+ # Should add the forbidden_contenttypes and default_contenttype property
+ self.removeSiteProperty('forbidden_contenttypes')
+ self.removeSiteProperty('default_contenttype')
+ self.assertFalse(self.properties.site_properties.hasProperty('forbidden_contenttypes'))
+ self.assertFalse(self.properties.site_properties.hasProperty('default_contenttype'))
+ # Test it twice
+ for i in range(2):
+ loadMigrationProfile(self.portal, self.profile, ('propertiestool', ))
+ self.assertTrue(self.properties.site_properties.hasProperty('forbidden_contenttypes'))
+ self.assertTrue(self.properties.site_properties.hasProperty('default_contenttype'))
+ self.assertEqual(self.properties.site_properties.forbidden_contenttypes,
+ ('text/structured', 'text/restructured', 'text/x-rst',
+ 'text/plain', 'text/plain-pre', 'text/x-python',
+ 'text/x-web-markdown', 'text/x-web-intelligent', 'text/x-web-textile')
+ )
+
+ def testTablelessRemoval(self):
+ st = getToolByName(self.portal, "portal_skins")
+ if "Plone Tableless" not in st.getSkinSelections():
+ st.addSkinSelection('Plone Tableless', 'one,two', make_default=True)
+ # Test it twice
+ for i in range(2):
+ removeTablelessSkin(self.portal)
+ self.assertFalse('Plone Tableless' in st.getSkinSelections())
+ self.assertFalse(st.default_skin == 'Plone Tableless')
+
+ def testLegacyPortletsConverted(self):
+ self.setRoles(('Manager',))
+ leftColumn = getUtility(IPortletManager, name=u'plone.leftcolumn', context=self.portal)
+ rightColumn = getUtility(IPortletManager, name=u'plone.rightcolumn', context=self.portal)
+
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ for k in left:
+ del left[k]
+ for k in right:
+ del right[k]
+
+ self.portal.left_slots = ['here/portlet_recent/macros/portlet',
+ 'here/portlet_news/macros/portlet',
+ 'here/portlet_related/macros/portlet']
+ self.portal.right_slots = ['here/portlet_login/macros/portlet',
+ 'here/portlet_languages/macros/portlet']
+
+ self.portal.Members.right_slots = []
+
+ # Test it twice
+ for i in range(2):
+ convertLegacyPortlets(self.portal)
+
+ self.assertEqual(self.portal.left_slots, [])
+ self.assertEqual(self.portal.right_slots, [])
+
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ lp = left.values()
+ self.assertEqual(2, len(lp))
+
+ self.assertTrue(isinstance(lp[0], portlets.recent.Assignment))
+ self.assertTrue(isinstance(lp[1], portlets.news.Assignment))
+
+ rp = right.values()
+ self.assertEqual(1, len(rp))
+ self.assertTrue(isinstance(rp[0], portlets.login.Assignment))
+
+ members = self.portal.Members
+ portletAssignments = getMultiAdapter((members, rightColumn,), ILocalPortletAssignmentManager)
+ self.assertEqual(True, portletAssignments.getBlacklistStatus(CONTEXT_PORTLETS))
+
+ def testLegacyPortletsConvertedNoSlots(self):
+ self.setRoles(('Manager',))
+ leftColumn = getUtility(IPortletManager, name=u'plone.leftcolumn', context=self.portal)
+ rightColumn = getUtility(IPortletManager, name=u'plone.rightcolumn', context=self.portal)
+
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ for k in left:
+ del left[k]
+ for k in right:
+ del right[k]
+
+ self.portal.left_slots = ['here/portlet_recent/macros/portlet',
+ 'here/portlet_news/macros/portlet']
+
+ self.portal.Members.right_slots = []
+
+ if hasattr(self.portal.aq_base, 'right_slots'):
+ delattr(self.portal, 'right_slots')
+
+ convertLegacyPortlets(self.portal)
+
+ self.assertEqual(self.portal.left_slots, [])
+
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ lp = left.values()
+ self.assertEqual(2, len(lp))
+
+ self.assertTrue(isinstance(lp[0], portlets.recent.Assignment))
+ self.assertTrue(isinstance(lp[1], portlets.news.Assignment))
+
+ rp = right.values()
+ self.assertEqual(0, len(rp))
+
+ members = self.portal.Members
+ portletAssignments = getMultiAdapter((members, rightColumn,), ILocalPortletAssignmentManager)
+ self.assertEqual(True, portletAssignments.getBlacklistStatus(CONTEXT_PORTLETS))
+
+ def testLegacyPortletsConvertedBadSlots(self):
+ self.setRoles(('Manager',))
+ leftColumn = getUtility(IPortletManager, name=u'plone.leftcolumn', context=self.portal)
+ rightColumn = getUtility(IPortletManager, name=u'plone.rightcolumn', context=self.portal)
+
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ for k in left:
+ del left[k]
+ for k in right:
+ del right[k]
+
+ self.portal.left_slots = ['here/portlet_recent/macros/portlet',
+ 'here/portlet_news/macros/portlet',
+ 'foobar',]
+ self.portal.right_slots = ['here/portlet_login/macros/portlet']
+
+ self.portal.Members.right_slots = []
+
+ convertLegacyPortlets(self.portal)
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ self.assertEqual(self.portal.left_slots, [])
+ self.assertEqual(self.portal.right_slots, [])
+
+ lp = left.values()
+ self.assertEqual(2, len(lp))
+
+ self.assertTrue(isinstance(lp[0], portlets.recent.Assignment))
+ self.assertTrue(isinstance(lp[1], portlets.news.Assignment))
+
+ rp = right.values()
+ self.assertEqual(1, len(rp))
+ self.assertTrue(isinstance(rp[0], portlets.login.Assignment))
+
+ members = self.portal.Members
+ portletAssignments = getMultiAdapter((members, rightColumn,), ILocalPortletAssignmentManager)
+ self.assertEqual(True, portletAssignments.getBlacklistStatus(CONTEXT_PORTLETS))
+
+ def testLegacyPortletsConvertedNoMembersFolder(self):
+ self.setRoles(('Manager',))
+ leftColumn = getUtility(IPortletManager, name=u'plone.leftcolumn', context=self.portal)
+ rightColumn = getUtility(IPortletManager, name=u'plone.rightcolumn', context=self.portal)
+
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ for k in left:
+ del left[k]
+ for k in right:
+ del right[k]
+
+ self.portal.left_slots = ['here/portlet_recent/macros/portlet',
+ 'here/portlet_news/macros/portlet',
+ 'foobar',]
+ self.portal.right_slots = ['here/portlet_login/macros/portlet']
+
+ self.portal._delObject('Members')
+
+ convertLegacyPortlets(self.portal)
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ self.assertEqual(self.portal.left_slots, [])
+ self.assertEqual(self.portal.right_slots, [])
+
+ lp = left.values()
+ self.assertEqual(2, len(lp))
+
+ self.assertTrue(isinstance(lp[0], portlets.recent.Assignment))
+ self.assertTrue(isinstance(lp[1], portlets.news.Assignment))
+
+ rp = right.values()
+ self.assertEqual(1, len(rp))
+ self.assertTrue(isinstance(rp[0], portlets.login.Assignment))
+
+ def testRegisterToolsAsUtilities(self):
+ sm = getSiteManager(self.portal)
+ interfaces = (ISiteRoot, IPloneSiteRoot,
+ IActionIconsTool, ISyndicationTool,
+ IMetadataTool, IPropertiesTool, IMailHost,
+ IUniqueIdAnnotationManagement, IUniqueIdGenerator,
+ IDiffTool, IMimetypesRegistryTool,
+ IPortalTransformsTool, IDiscussionTool, )
+ if HAS_ATCT:
+ interfaces += (IATCTTool,)
+ for i in interfaces:
+ sm.unregisterUtility(provided=i)
+ registerToolsAsUtilities(self.portal)
+ for i in interfaces:
+ self.assertFalse(sm.queryUtility(i) is None)
+
+ for i in interfaces:
+ sm.unregisterUtility(provided=i)
+ registerToolsAsUtilities(self.portal)
+ registerToolsAsUtilities(self.portal)
+ for i in interfaces:
+ self.assertFalse(sm.queryUtility(i) is None)
+
+ def testDontRegisterToolsAsUtilities(self):
+ sm = getSiteManager(self.portal)
+ interfaces = (ILanguageTool, IArchivistTool, IPortalModifierTool,
+ IPurgePolicyTool, IRepositoryTool, IStorageTool,
+ IFormControllerTool, IReferenceCatalog, IUIDCatalog,
+ ICalendarTool, IActionsTool, ICatalogTool,
+ IContentTypeRegistry, ISkinsTool, ITypesTool, IURLTool,
+ IConfigurableWorkflowTool, IPloneTool, ICSSRegistry,
+ IJSRegistry, IUniqueIdHandler, IFactoryTool,
+ IMembershipTool, IGroupTool, IGroupDataTool,
+ IMemberDataTool, IArchetypeTool, ICachingPolicyManager,
+ IRegistrationTool, ITranslationServiceTool,
+ ISetupTool, IQuickInstallerTool,
+ )
+ for i in interfaces:
+ sm.unregisterUtility(provided=i)
+ registerToolsAsUtilities(self.portal)
+ for i in interfaces:
+ self.assertTrue(sm.queryUtility(i) is None)
+
+ for i in interfaces:
+ sm.unregisterUtility(provided=i)
+ registerToolsAsUtilities(self.portal)
+ registerToolsAsUtilities(self.portal)
+ for i in interfaces:
+ self.assertTrue(sm.queryUtility(i) is None)
+
+ def testToolRegistration(self):
+ for (tool_id, interface) in registration:
+ self.assertEqual(getToolInterface(tool_id), interface)
+
+
+class TestMigrations_v3_0_alpha1(MigrationTest):
+
+ def afterSetUp(self):
+ self.profile = 'profile-plone.app.upgrade.v30:3.0a1-3.0a2'
+ self.actions = self.portal.portal_actions
+
+ def testInstallRedirectorUtility(self):
+ sm = getSiteManager(self.portal)
+ sm.unregisterUtility(provided=IRedirectionStorage)
+ # Test it twice
+ for i in range(2):
+ loadMigrationProfile(self.portal, self.profile, ('componentregistry', ))
+ self.assertFalse(sm.queryUtility(IRedirectionStorage) is None)
+
+ def testAddReaderEditorRoles(self):
+ self.portal._delRoles(['Reader', 'Editor'])
+ # Test it twice
+ for i in range(2):
+ addReaderAndEditorRoles(self.portal)
+ self.assertTrue('Reader' in self.portal.valid_roles())
+ self.assertTrue('Editor' in self.portal.valid_roles())
+ self.assertTrue('Reader' in self.portal.acl_users.portal_role_manager.listRoleIds())
+ self.assertTrue('Editor' in self.portal.acl_users.portal_role_manager.listRoleIds())
+ self.assertTrue('View' in [r['name'] for r in self.portal.permissionsOfRole('Reader') if r['selected']])
+ self.assertTrue('Modify portal content' in [r['name'] for r in self.portal.permissionsOfRole('Editor') if r['selected']])
+
+ def testAddReaderEditorRolesPermissionOnly(self):
+ self.portal.manage_permission('View', [], True)
+ self.portal.manage_permission('Modify portal content', [], True)
+ # Test it twice
+ for i in range(2):
+ addReaderAndEditorRoles(self.portal)
+ self.assertTrue('Reader' in self.portal.valid_roles())
+ self.assertTrue('Editor' in self.portal.valid_roles())
+ self.assertTrue('Reader' in self.portal.acl_users.portal_role_manager.listRoleIds())
+ self.assertTrue('Editor' in self.portal.acl_users.portal_role_manager.listRoleIds())
+ self.assertTrue('View' in [r['name'] for r in self.portal.permissionsOfRole('Reader') if r['selected']])
+ self.assertTrue('Modify portal content' in [r['name'] for r in self.portal.permissionsOfRole('Editor') if r['selected']])
+
+ def testMigrateLocalroleForm(self):
+ fti = self.portal.portal_types['Document']
+ aliases = fti.getMethodAliases()
+ aliases['sharing'] = 'folder_localrole_form'
+ fti.setMethodAliases(aliases)
+ fti.addAction('test', 'Test', 'string:${object_url}/folder_localrole_form', None, 'View', 'object')
+ # Test it twice
+ for i in range(2):
+ migrateLocalroleForm(self.portal)
+ self.assertEqual('@@sharing', fti.getMethodAliases()['sharing'])
+ test_action = fti.listActions()[-1]
+ self.assertEqual('string:${object_url}/@@sharing', test_action.getActionExpression())
+
+ def testReorderUserActions(self):
+ self.actions.user.moveObjectsToTop(['logout', 'undo', 'join'])
+ # Test it twice
+ for i in range(2):
+ reorderUserActions(self.portal)
+ # build a dict that has the position as the value to make it easier
+ # to compare postions in the ordered list of actions
+ n = 0
+ sort = {}
+ for action in self.actions.user.objectIds():
+ sort[action] = n
+ n += 1
+ self.assertTrue(sort['preferences'] < sort['undo'])
+ self.assertTrue(sort['undo'] < sort['logout'])
+ self.assertTrue(sort['login'] < sort['join'])
+
+ def testReorderUserActionsIncompleteActions(self):
+ self.actions.user.moveObjectsToTop(['logout', 'undo', 'join'])
+ self.actions.user._delObject('preferences')
+ # Test it twice
+ for i in range(2):
+ reorderUserActions(self.portal)
+ n = 0
+ sort = {}
+ for action in self.actions.user.objectIds():
+ sort[action] = n
+ n += 1
+ self.assertTrue(sort['undo'] < sort['logout'])
+ self.assertTrue(sort['login'] < sort['join'])
+
+
+class TestMigrations_v3_0_alpha2(MigrationTest):
+
+ def afterSetUp(self):
+ self.profile = 'profile-plone.app.upgrade.v30:3.0a2-3.0b1'
+ self.actions = self.portal.portal_actions
+ self.properties = self.portal.portal_properties
+ self.cp = self.portal.portal_controlpanel
+
+ def testAddVariousProperties(self):
+ PROPERTIES = ('enable_link_integrity_checks', 'enable_sitemap',
+ 'external_links_open_new_window', 'many_groups',
+ 'number_of_days_to_keep', 'webstats_js')
+ for prop in PROPERTIES:
+ self.removeSiteProperty(prop)
+ sheet = self.properties.site_properties
+ # Test it twice
+ for i in range(2):
+ loadMigrationProfile(self.portal, self.profile, ('propertiestool', ))
+ for prop in PROPERTIES:
+ self.assertTrue(sheet.hasProperty(prop))
+
+ def testInstallContentrulesAndLanguageUtilities(self):
+ sm = getSiteManager()
+ INTERFACES = (IRuleStorage, ICountries, IContentLanguages,
+ IMetadataLanguages)
+ for i in INTERFACES:
+ sm.unregisterUtility(provided=i)
+ # Test it twice
+ for i in range(2):
+ loadMigrationProfile(self.portal, self.profile, ('componentregistry', ))
+ for i in INTERFACES:
+ self.assertFalse(sm.queryUtility(i) is None)
+
+ def testAddEmailCharsetProperty(self):
+ if self.portal.hasProperty('email_charset'):
+ self.portal.manage_delProperties(['email_charset'])
+ # Test it twice
+ for i in range(2):
+ loadMigrationProfile(self.portal, self.profile, ('properties', ))
+ self.assertTrue(self.portal.hasProperty('email_charset'))
+ self.assertEqual(self.portal.getProperty('email_charset'), 'utf-8')
+
+ def testUpdateMemberSecurity(self):
+ pprop = getToolByName(self.portal, 'portal_properties')
+ self.assertEqual(
+ pprop.site_properties.getProperty('allowAnonymousViewAbout'),
+ False)
+
+ pmembership = getToolByName(self.portal, 'portal_membership')
+ self.assertEqual(pmembership.memberareaCreationFlag, False)
+ self.assertEqual(self.portal.getProperty('validate_email'), True)
+
+ app_roles = self.portal.rolesOfPermission(permission='Add portal member')
+ app_perms = self.portal.permission_settings(permission='Add portal member')
+ acquire_check = app_perms[0]['acquire']
+ reg_roles = []
+ for appperm in app_roles:
+ if appperm['selected'] == 'SELECTED':
+ reg_roles.append(appperm['name'])
+ self.assertTrue('Manager' in reg_roles)
+ self.assertTrue('Owner' in reg_roles)
+ self.assertEqual(acquire_check, '')
+
+ def testPASPluginInterfaces(self):
+ pas = self.portal.acl_users
+ from Products.PluggableAuthService.interfaces.plugins import IUserEnumerationPlugin
+ pas.plugins.deactivatePlugin(IUserEnumerationPlugin, 'mutable_properties')
+ updatePASPlugins(self.portal)
+
+ plugin = pas.mutable_properties
+ for intf_id in plugin.listInterfaces():
+ try:
+ intf = pas.plugins._getInterfaceFromName(intf_id)
+ self.assertTrue('mutable_properties' in pas.plugins.listPluginIds(intf))
+ except KeyError:
+ # Ignore unregistered interface types
+ pass
+
+ def testUpdateConfigletTitles(self):
+ collection = self.cp.getActionObject('Plone/portal_atct')
+ language = self.cp.getActionObject('Plone/PloneLanguageTool')
+ navigation = self.cp.getActionObject('Plone/NavigationSettings')
+ types = self.cp.getActionObject('Plone/TypesSettings')
+ users = self.cp.getActionObject('Plone/UsersGroups')
+ users2 = self.cp.getActionObject('Plone/UsersGroups2')
+ # test it twice
+ for i in range(2):
+ updateConfigletTitles(self.portal)
+ self.assertEqual(collection.title, 'Collection')
+ self.assertEqual(language.title, 'Language')
+ self.assertEqual(navigation.title, 'Navigation')
+ self.assertEqual(types.title, 'Types')
+ self.assertEqual(users.title, 'Users and Groups')
+ self.assertEqual(users2.title, 'Users and Groups')
+
+ def testAddCacheForResourceRegistry(self):
+ ram_cache_id = 'ResourceRegistryCache'
+ # first remove the cache manager and make sure it's removed
+ self.portal._delObject(ram_cache_id)
+ self.assertFalse(ram_cache_id in self.portal.objectIds())
+ cssreg = self.portal.portal_css
+ cssreg.ZCacheable_setEnabled(0)
+ cssreg.ZCacheable_setManagerId(None)
+ self.assertFalse(cssreg.ZCacheable_enabled())
+ self.assertTrue(cssreg.ZCacheable_getManagerId() is None)
+ jsreg = self.portal.portal_javascripts
+ jsreg.ZCacheable_setEnabled(0)
+ jsreg.ZCacheable_setManagerId(None)
+ self.assertFalse(jsreg.ZCacheable_enabled())
+ self.assertTrue(jsreg.ZCacheable_getManagerId() is None)
+ # Test it twice
+ for i in range(2):
+ addCacheForResourceRegistry(self.portal)
+ self.assertTrue(ram_cache_id in self.portal.objectIds())
+ self.assertTrue(cssreg.ZCacheable_enabled())
+ self.assertFalse(cssreg.ZCacheable_getManagerId() is None)
+ self.assertTrue(jsreg.ZCacheable_enabled())
+ self.assertFalse(jsreg.ZCacheable_getManagerId() is None)
+
+ def testObjectProvidesIndex(self):
+ catalog = getToolByName(self.portal, 'portal_catalog')
+ if 'object_provides' in catalog.indexes():
+ catalog.delIndex('object_provides')
+ self.assertFalse('object_provides' in catalog.indexes())
+ # Test it twice
+ for i in range(2):
+ addObjectProvidesIndex(self.portal)
+ self.assertTrue('object_provides' in catalog.indexes())
+
+ def testMigratePloneTool(self):
+ tool = self.portal.plone_utils
+ tool.meta_type = 'PlonePAS Utilities Tool'
+ # Test it twice
+ for i in range(2):
+ restorePloneTool(self.portal)
+ tool = self.portal.plone_utils
+ self.assertEqual('Plone Utility Tool', tool.meta_type)
+
+ def testInstallPloneLanguageTool(self):
+ super(self.portal.__class__, self.portal).manage_delObjects(
+ ['portal_languages'])
+ self.uninstallProduct('PloneLanguageTool')
+ qi = getToolByName(self.portal, "portal_quickinstaller")
+ # Test it twice
+ for i in range(2):
+ installProduct('PloneLanguageTool', self.portal)
+ self.assertTrue(qi.isProductInstalled('PloneLanguageTool'))
+ self.assertTrue('portal_languages' in self.portal.keys())
+
+
+class TestMigrations_v3_0(MigrationTest):
+
+ def afterSetUp(self):
+ self.profile = 'profile-plone.app.upgrade.v30:3.0b1-3.0b2'
+ self.actions = self.portal.portal_actions
+ self.skins = self.portal.portal_skins
+ self.types = self.portal.portal_types
+ self.workflow = self.portal.portal_workflow
+ self.properties = getToolByName(self.portal, 'portal_properties')
+
+ def testAddContentRulesAction(self):
+ self.portal.portal_actions.object._delObject('contentrules')
+ # Test it twice
+ for i in range(2):
+ loadMigrationProfile(self.portal, self.profile, ('actions', ))
+ self.assertTrue('contentrules' in self.portal.portal_actions.object.objectIds())
+
+ def testChangeOrderOfActionProviders(self):
+ self.actions.deleteActionProvider('portal_types')
+ self.actions.addActionProvider('portal_types')
+ self.assertEqual(
+ self.actions.listActionProviders(),
+ ('portal_workflow', 'portal_actions', 'portal_types'))
+ # Test it twice
+ for i in range(2):
+ changeOrderOfActionProviders(self.portal)
+ self.assertEqual(
+ self.actions.listActionProviders(),
+ ('portal_workflow', 'portal_types', 'portal_actions'))
+
+ def testCleanupOldActions(self):
+ reply = Action('reply', title='Reply')
+ logged_in = Action('logged_in', title='Logged in')
+ change_ownership = Action('change_ownership', title='Change ownership')
+
+ object_ = self.actions.object
+ object_tabs = getattr(self.actions, 'object_tabs', None)
+ if object_tabs is None:
+ category = 'object_tabs'
+ self.actions._setObject(category, ActionCategory(id=category))
+ object_tabs = self.actions.object_tabs
+ if getattr(self.actions, 'global', None) is None:
+ category = 'global'
+ self.actions._setObject(category, ActionCategory(id=category))
+
+ if not 'reply' in object_.keys():
+ object_._setObject('reply', reply)
+ user = self.actions.user
+ if not 'logged_in' in user.keys():
+ user._setObject('logged_in', logged_in)
+ if not 'change_ownership' in object_tabs.keys():
+ object_tabs._setObject('change_ownership', change_ownership)
+ del object_tabs
+
+ # Test it twice
+ for i in range(2):
+ cleanupOldActions(self.portal)
+ self.assertFalse('reply' in object_.keys())
+ self.assertFalse('logged_in' in user.keys())
+ self.assertFalse('object_tabs' in self.actions.keys())
+ self.assertFalse('global' in self.actions.keys())
+
+ def testCharsetCleanup(self):
+ if not self.portal.hasProperty('default_charset'):
+ self.portal.manage_addProperty('default_charset', '', 'string')
+ # Test it twice
+ for i in range(2):
+ self.portal.manage_changeProperties(default_charset = 'latin1')
+ cleanDefaultCharset(self.portal)
+ self.assertEqual(self.portal.getProperty('default_charset', 'nothere'),
+ 'latin1')
+ # Test it twice
+ for i in range(2):
+ self.portal.manage_changeProperties(default_charset = '')
+ cleanDefaultCharset(self.portal)
+ self.assertEqual(self.portal.getProperty('default_charset', 'nothere'),
+ 'nothere')
+
+ def testAutoGroupCreated(self):
+ pas = self.portal.acl_users
+ ids = pas.objectIds(['Automatic Group Plugin'])
+ if ids:
+ pas.manage_delObjects(ids)
+ addAutoGroupToPAS(self.portal)
+ self.assertEqual(pas.objectIds(['Automatic Group Plugin']),
+ ['auto_group'])
+ plugin = pas.auto_group
+ interfaces = [info['interface'] for info in pas.plugins.listPluginTypeInfo()]
+ for iface in interfaces:
+ if plugin.testImplements(iface):
+ self.assertFalse('auto_group' not in pas.plugins.listPluginIds(iface))
+ self.assertEqual(len(pas.searchGroups(id='AuthenticatedUsers',
+ exact_match=True)), 1)
+
+ def testPloneS5(self):
+ pt = getToolByName(self.portal, "portal_types")
+ document = pt.restrictedTraverse('Document')
+ document.addAction('s5_presentation',
+ name='View as presentation',
+ action="string:${object/absolute_url}/document_s5_presentation",
+ condition='python:object.document_s5_alter(test=True)',
+ permission='View',
+ category='document_actions',
+ visible=1,
+ )
+ action_ids = [x.getId() for x in document.listActions()]
+ self.assertTrue("s5_presentation" in action_ids)
+ # Test it twice
+ for i in range(2):
+ removeS5Actions(self.portal)
+ action_ids = [x.getId() for x in document.listActions()]
+ self.assertFalse("s5_presentation" in action_ids)
+
+ def testAddContributorToCreationPermissions(self):
+ self.portal._delRoles(['Contributor',])
+ for p in ['Add portal content', 'Add portal folders', 'ATContentTypes: Add Document',
+ 'ATContentTypes: Add Event',
+ 'ATContentTypes: Add File', 'ATContentTypes: Add Folder',
+ 'ATContentTypes: Add Image', 'ATContentTypes: Add Link',
+ 'ATContentTypes: Add News Item', ]:
+ self.portal.manage_permission(p, ['Manager', 'Owner'], True)
+ # Test it twice
+ for i in range(2):
+ addContributorToCreationPermissions(self.portal)
+ self.assertTrue('Contributor' in self.portal.valid_roles())
+ self.assertTrue('Contributor' in self.portal.acl_users.portal_role_manager.listRoleIds())
+ for p in ['Add portal content', 'Add portal folders', 'ATContentTypes: Add Document',
+ 'ATContentTypes: Add Event',
+ 'ATContentTypes: Add File', 'ATContentTypes: Add Folder',
+ 'ATContentTypes: Add Image', 'ATContentTypes: Add Link',
+ 'ATContentTypes: Add News Item', ]:
+ self.assertTrue(p in [r['name'] for r in
+ self.portal.permissionsOfRole('Contributor') if r['selected']])
+
+ def testAddContributerToCreationPermissionsNoStomp(self):
+ self.portal.manage_permission('Add portal content', ['Manager'], False)
+ # Test it twice
+ for i in range(2):
+ addContributorToCreationPermissions(self.portal)
+ roles = sorted([r['name'] for r in self.portal.rolesOfPermission('Add portal content') if r['selected']])
+ self.assertEqual(['Contributor', 'Manager'], roles)
+ self.assertEqual(False, bool(self.portal.acquiredRolesAreUsedBy('Add portal content')))
+
+ def testAddBeta2VersioningPermissionsToNewRoles(self):
+ # This upgrade just uses GS to apply the role changes,
+ # these permissions will not have been installed previously,
+ # so this should be safe
+ for p in ['CMFEditions: Apply version control',
+ 'CMFEditions: Save new version',
+ 'CMFEditions: Access previous versions',
+ 'CMFEditions: Revert to previous versions',
+ 'CMFEditions: Checkout to location']:
+ self.portal.manage_permission(p, ['Manager', 'Owner'], True)
+ # Test it twice
+ for i in range(2):
+ loadMigrationProfile(self.portal,
+ 'profile-plone.app.upgrade.v30:3.0b1-3.0b2',
+ steps=["rolemap"])
+ for p in ['CMFEditions: Apply version control',
+ 'CMFEditions: Save new version',
+ 'CMFEditions: Access previous versions']:
+ self.assertTrue(p in [r['name'] for r in
+ self.portal.permissionsOfRole('Contributor') if r['selected']])
+ self.assertTrue(p in [r['name'] for r in
+ self.portal.permissionsOfRole('Editor') if r['selected']])
+ for p in ['CMFEditions: Revert to previous versions',
+ 'CMFEditions: Checkout to location']:
+ self.assertTrue(p in [r['name'] for r in
+ self.portal.permissionsOfRole('Editor') if r['selected']])
+
+ def testRemoveSharingAction(self):
+ fti = self.types['Document']
+ fti.addAction(id='local_roles', name='Sharing',
+ action='string:${object_url}/sharing',
+ condition=None, permission='Manage properties',
+ category='object')
+ # Test it twice
+ for i in range(2):
+ removeSharingAction(self.portal)
+ self.assertFalse('local_roles' in [a.id for a in fti.listActions()])
+
+ def testAddEditorToCreationPermissions(self):
+ for p in ['Manage properties', 'Modify view template', 'Request review']:
+ self.portal.manage_permission(p, ['Manager', 'Owner'], True)
+ # Test it twice
+ for i in range(2):
+ addEditorToSecondaryEditorPermissions(self.portal)
+ for p in ['Manage properties', 'Modify view template', 'Request review']:
+ self.assertTrue(p in [r['name'] for r in
+ self.portal.permissionsOfRole('Editor') if r['selected']])
+
+ def testAddEditorToCreationPermissionsNoStomp(self):
+ self.portal.manage_permission('Manage properties', ['Manager'], False)
+ # Test it twice
+ for i in range(2):
+ addEditorToSecondaryEditorPermissions(self.portal)
+ roles = sorted([r['name'] for r in self.portal.rolesOfPermission('Manage properties') if r['selected']])
+ self.assertEqual(['Editor', 'Manager'], roles)
+ self.assertEqual(False, bool(self.portal.acquiredRolesAreUsedBy('Manage properties')))
+
+ def testUpdateEditActionConditionForLocking(self):
+ lockable_types = ['Document', 'Event', 'File', 'Folder',
+ 'Image', 'Link', 'News Item', 'Topic']
+ for contentType in lockable_types:
+ fti = self.types.getTypeInfo(contentType)
+ for action in fti.listActions():
+ if action.getId() == 'edit':
+ action.condition = ''
+ # Test it twice
+ for i in range(2):
+ updateEditActionConditionForLocking(self.portal)
+ for contentType in lockable_types:
+ fti = self.types.getTypeInfo(contentType)
+ for action in fti.listActions():
+ if action.getId() == 'edit':
+ self.assertEqual(action.condition.text,
+ "not:object/@@plone_lock_info/is_locked_for_current_user|python:True")
+
+ def testUpdateEditExistingActionConditionForLocking(self):
+ fti = self.types.getTypeInfo('Document')
+ for action in fti.listActions():
+ if action.getId() == 'edit':
+ action.condition = Expression("foo")
+ # Test it twice
+ for i in range(2):
+ updateEditActionConditionForLocking(self.portal)
+ fti = self.types.getTypeInfo('Document')
+ for action in fti.listActions():
+ if action.getId() == 'edit':
+ self.assertEqual(action.condition.text, 'foo')
+
+ def testAddOnFormUnloadRegistrationJS(self):
+ jsreg = self.portal.portal_javascripts
+ # unregister first
+ jsreg.unregisterResource('unlockOnFormUnload.js')
+ script_ids = jsreg.getResourceIds()
+ self.assertFalse('unlockOnFormUnload.js' in script_ids)
+ # Test it twice
+ for i in range(2):
+ addOnFormUnloadJS(self.portal)
+ script_ids = jsreg.getResourceIds()
+ self.assertTrue('unlockOnFormUnload.js' in script_ids)
+
+ def testUpdateTopicTitle(self):
+ topic = self.types.get('Topic')
+ topic.title = 'Old'
+ # Test it twice
+ for i in range(2):
+ updateTopicTitle(self.portal)
+ self.assertEqual(topic.title, 'Collection')
+
+ def testAddIntelligentText(self):
+ # Before the upgrade, the mime type and transforms of intelligent text
+ # are not available. They *are* here in a fresh site, so we may need
+ # to remove them first for testing. First we remove the transforms,
+ # as they depend on the mimetype being there.
+ missing_transforms = ["web_intelligent_plain_text_to_html",
+ "html_to_web_intelligent_plain_text"]
+ ptr = self.portal.portal_transforms
+ current_transforms = ptr.objectIds()
+ for trans in missing_transforms:
+ if trans in current_transforms:
+ ptr.unregisterTransform(trans)
+ # Then we remove the mime type
+ mime_type = 'text/x-web-intelligent'
+ mtr = self.portal.mimetypes_registry
+ current_types = mtr.list_mimetypes()
+ if mime_type in current_types:
+ mtr.manage_delObjects((mime_type,))
+ # now all are gone:
+ self.assertFalse(mime_type in mtr.list_mimetypes())
+ self.assertFalse(set(ptr.objectIds()).issuperset(set(missing_transforms)))
+ # Test it twice
+ for i in range(2):
+ addIntelligentText(self.portal)
+ # now all are back:
+ self.assertTrue(mime_type in mtr.list_mimetypes())
+ self.assertTrue(set(ptr.objectIds()).issuperset(set(missing_transforms)))
+
+ def testInstallNewModifiers(self):
+ # ensure the new modifiers are installed
+ modifiers = self.portal.portal_modifier
+ self.assertTrue('AbortVersioningOfLargeFilesAndImages' in
+ modifiers.objectIds())
+ modifiers.manage_delObjects(['AbortVersioningOfLargeFilesAndImages',
+ 'SkipVersioningOfLargeFilesAndImages'])
+ self.assertFalse('AbortVersioningOfLargeFilesAndImages' in
+ modifiers.objectIds())
+ installNewModifiers(self.portal)
+ self.assertTrue('AbortVersioningOfLargeFilesAndImages' in
+ modifiers.objectIds())
+ self.assertTrue('SkipVersioningOfLargeFilesAndImages' in
+ modifiers.objectIds())
+
+ def testInstallNewModifiersTwice(self):
+ # ensure that we get no errors when run twice
+ installNewModifiers(self.portal)
+ installNewModifiers(self.portal)
+
+ def testInstallNewModifiersDoesNotStompChanges(self):
+ # ensure that reinstalling doesn't kill customizations
+ modifiers = self.portal.portal_modifier
+ modifiers.AbortVersioningOfLargeFilesAndImages.max_size = 1000
+ installNewModifiers(self.portal)
+ self.assertEqual(modifiers.AbortVersioningOfLargeFilesAndImages.max_size,
+ 1000)
+
+ def testInstallNewModifiersNoTool(self):
+ # make sure there are no errors if the tool is missing
+ self.portal._delObject('portal_modifier')
+ installNewModifiers(self.portal)
+
+
+class TestFunctionalMigrations(FunctionalUpgradeTestCase):
+
+ def testBaseUpgrade(self):
+ self.importFile(__file__, 'test-base.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+ def testFullUpgrade(self):
+ self.importFile(__file__, 'test-full.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+
+def test_suite():
+ from unittest import TestSuite, makeSuite
+ suite = TestSuite()
+ suite.addTest(makeSuite(TestMigrations_v2_5_x))
+ suite.addTest(makeSuite(TestMigrations_v3_0_Actions))
+ suite.addTest(makeSuite(TestMigrations_v3_0_alpha1))
+ suite.addTest(makeSuite(TestMigrations_v3_0_alpha2))
+ suite.addTest(makeSuite(TestMigrations_v3_0))
+ suite.addTest(makeSuite(TestFunctionalMigrations))
+ return suite
diff --git a/plone/app/upgrade/v31/tests.py b/plone/app/upgrade/v31/tests.py
new file mode 100644
index 0000000..01005b3
--- /dev/null
+++ b/plone/app/upgrade/v31/tests.py
@@ -0,0 +1,118 @@
+from borg.localrole.utils import replace_local_role_manager
+from zope.interface import noLongerProvides
+
+from Products.PlonePAS.interfaces.plugins import ILocalRolesPlugin
+
+from plone.app.upgrade.tests.base import FunctionalUpgradeTestCase
+from plone.app.upgrade.tests.base import MigrationTest
+
+from plone.app.upgrade.v31.betas import reinstallCMFPlacefulWorkflow
+
+
+class TestMigrations_v3_1(MigrationTest):
+
+ def afterSetUp(self):
+ self.qi = self.portal.portal_quickinstaller
+ self.wf = self.portal.portal_workflow
+ self.ps = self.portal.portal_setup
+
+ def testReinstallCMFPlacefulWorkflow(self):
+ try:
+ from Products.CMFPlacefulWorkflow.interfaces import IPlacefulMarker
+ except ImportError:
+ return
+ # first the product needs to be installed
+ self.qi.installProduct('CMFPlacefulWorkflow')
+ # Delete existing logs to prevent race condition
+ self.ps.manage_delObjects(self.ps.objectIds())
+ # We remove the new marker, to ensure it's added on reinstall
+ if IPlacefulMarker.providedBy(self.wf):
+ noLongerProvides(self.wf, IPlacefulMarker)
+ reinstallCMFPlacefulWorkflow(self.portal, [])
+ self.assertTrue(IPlacefulMarker.providedBy(self.wf))
+
+ def testReinstallCMFPlacefulWorkflowDoesNotInstall(self):
+ reinstallCMFPlacefulWorkflow(self.portal, [])
+ self.assertFalse(self.qi.isProductInstalled('CMFPlacefulWorkflow'))
+
+ def testReinstallCMFPlacefulWorkflowNoTool(self):
+ self.portal._delObject('portal_quickinstaller')
+ reinstallCMFPlacefulWorkflow(self.portal, [])
+
+ def testReplaceLocalRoleManager(self):
+ # first we replace the local role manager with the one from PlonePAS
+ uf = self.portal.acl_users
+ # deactivate and remove the borg plugin
+ uf.plugins.removePluginById('borg_localroles')
+ uf.manage_delObjects(['borg_localroles'])
+ # activate the standard plugin
+ uf.plugins.activatePlugin(ILocalRolesPlugin, 'local_roles')
+ # Bring things back to normal
+ replace_local_role_manager(self.portal)
+ plugins = uf.plugins.listPlugins(ILocalRolesPlugin)
+ self.assertEqual(len(plugins), 1)
+ self.assertEqual(plugins[0][0], 'borg_localroles')
+
+ def testReplaceLocalRoleManagerTwice(self):
+ # first we replace the local role manager with the one from PlonePAS
+ uf = self.portal.acl_users
+ # deactivate and remove the borg plugin
+ uf.plugins.removePluginById('borg_localroles')
+ uf.manage_delObjects(['borg_localroles'])
+ # activate the standard plugin
+ uf.plugins.activatePlugin(ILocalRolesPlugin, 'local_roles')
+ # run the upgrade twice
+ replace_local_role_manager(self.portal)
+ replace_local_role_manager(self.portal)
+ plugins = uf.plugins.listPlugins(ILocalRolesPlugin)
+ self.assertEqual(len(plugins), 1)
+ self.assertEqual(plugins[0][0], 'borg_localroles')
+
+ def testReplaceLocalRoleManagerNoPlugin(self):
+ # first we replace the local role manager with the one from PlonePAS
+ uf = self.portal.acl_users
+ # deactivate and remove the borg plugin
+ uf.plugins.removePluginById('borg_localroles')
+ uf.manage_delObjects(['borg_localroles'])
+ # delete the standard plugin
+ uf.manage_delObjects(['local_roles'])
+ # Run the upgrade, which shouldn't fail even if the expected
+ # plugin is missing
+ replace_local_role_manager(self.portal)
+ plugins = uf.plugins.listPlugins(ILocalRolesPlugin)
+ self.assertEqual(len(plugins), 1)
+ self.assertEqual(plugins[0][0], 'borg_localroles')
+
+ def testReplaceLocalRoleManagerNoPAS(self):
+ uf = self.portal.acl_users
+ # delete the plugin registry
+ uf._delObject('plugins')
+ replace_local_role_manager(self.portal)
+
+ def testReplaceLocalRoleManagerNoUF(self):
+ # Delete the user folder
+ replace_local_role_manager(self.portal)
+
+class TestFunctionalMigrations(FunctionalUpgradeTestCase):
+
+ def testBaseUpgrade(self):
+ self.importFile(__file__, 'test-base.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+ def testFullUpgrade(self):
+ self.importFile(__file__, 'test-full.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+
+def test_suite():
+ from unittest import TestSuite, makeSuite
+ suite = TestSuite()
+ suite.addTest(makeSuite(TestMigrations_v3_1))
+ suite.addTest(makeSuite(TestFunctionalMigrations))
+ return suite
diff --git a/plone/app/upgrade/v32/tests.py b/plone/app/upgrade/v32/tests.py
new file mode 100644
index 0000000..bc0e7a1
--- /dev/null
+++ b/plone/app/upgrade/v32/tests.py
@@ -0,0 +1,50 @@
+from plone.app.upgrade.tests.base import FunctionalUpgradeTestCase
+from plone.app.upgrade.tests.base import MigrationTest
+from plone.app.upgrade.v32.betas import three1_beta1
+
+class TestMigrations_v3_2(MigrationTest):
+
+ def afterSetUp(self):
+ self.qi = self.portal.portal_quickinstaller
+ self.actions = self.portal.portal_actions
+ self.migration = self.portal.portal_migration
+
+ def testIterateActionsMigratedIfIterateInstalled(self):
+ self.qi.installProduct('plone.app.iterate')
+ self.actions.object_buttons.iterate_checkin.permissions = (
+ 'Modify portal content',)
+ three1_beta1(self.portal)
+ self.assertEqual(
+ self.actions.object_buttons.iterate_checkin.permissions,
+ ('iterate : Check in content',))
+
+ def testIterateInstalledButActionMissing(self):
+ self.qi.installProduct('plone.app.iterate')
+ self.actions.object_buttons.manage_delObjects(['iterate_checkin'])
+ three1_beta1(self.portal)
+ self.assertFalse('iterate_checkin' in
+ self.actions.object_buttons.objectIds())
+
+class TestFunctionalMigrations(FunctionalUpgradeTestCase):
+
+ def testBaseUpgrade(self):
+ self.importFile(__file__, 'test-base.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+ def testFullUpgrade(self):
+ self.importFile(__file__, 'test-full.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+
+def test_suite():
+ from unittest import TestSuite, makeSuite
+ suite = TestSuite()
+ suite.addTest(makeSuite(TestMigrations_v3_2))
+ suite.addTest(makeSuite(TestFunctionalMigrations))
+ return suite
diff --git a/plone/app/upgrade/v33/tests.py b/plone/app/upgrade/v33/tests.py
new file mode 100644
index 0000000..01a5de8
--- /dev/null
+++ b/plone/app/upgrade/v33/tests.py
@@ -0,0 +1,93 @@
+from Products.CMFCore.utils import getToolByName
+
+from plone.app.upgrade.tests.base import FunctionalUpgradeTestCase
+from plone.app.upgrade.tests.base import MigrationTest
+from plone.app.upgrade.v33 import three2_three3
+
+class TestMigrations_v3_3(MigrationTest):
+
+ def afterSetUp(self):
+ self.types = self.portal.portal_types
+ self.properties = getToolByName(self.portal, 'portal_properties')
+
+ def _upgrade(self):
+ three2_three3(self.portal)
+
+ def testRedirectLinksProperty(self):
+ del self.properties.site_properties.redirect_links
+ self._upgrade()
+ self.assertEqual(True,
+ self.properties.site_properties.getProperty('redirect_links'))
+
+ def testLinkDefaultView(self):
+ self.types.Link.default_view = 'link_view'
+ self.types.Link.immediate_view = 'link_view'
+ self.types.Link.view_methods = ('link_view',)
+ self._upgrade()
+ self.assertEqual(self.types.Link.default_view, 'link_redirect_view')
+ self.assertEqual(self.types.Link.immediate_view, 'link_redirect_view')
+ self.assertEqual(self.types.Link.view_methods, ('link_redirect_view',))
+
+ def testCustomizedLinkDefaultView(self):
+ # but only change if old default was 'link_view'
+ self.types.Link.default_view = 'foobar'
+ self.types.Link.immediate_view = 'foobar'
+ self.types.Link.view_methods = ('foobar',)
+ self._upgrade()
+ self.assertEqual(self.types.Link.default_view, 'foobar')
+ self.assertEqual(self.types.Link.immediate_view, 'foobar')
+ self.assertEqual(self.types.Link.view_methods, ('foobar',))
+
+class TestFunctionalMigrations(FunctionalUpgradeTestCase):
+
+ def testBaseUpgrade(self):
+ self.importFile(__file__, 'test-base.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+ def testFullUpgrade(self):
+ self.importFile(__file__, 'test-full.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+ def testFolderUpgrade(self):
+ from plone.folder.interfaces import IOrderableFolder
+ self.importFile(__file__, 'test-full.zexp')
+ # `portal_type` and `Type` can be checked before migration...
+ oldsite = getattr(self.app, self.site_id)
+ ids = 'news', 'events', 'Members'
+ for id in ids:
+ obj = oldsite[id]
+ self.assertEqual(obj.portal_type, 'Large Plone Folder')
+ self.assertEqual(obj.Type(), 'Large Folder')
+ brain, = oldsite.portal_catalog(getId=id) # asserts only one
+ self.assertEqual(brain.portal_type, 'Large Plone Folder')
+ self.assertEqual(brain.Type, 'Large Folder')
+ # now let's migrate...
+ oldsite, result = self.migrate()
+ self.assertFalse(oldsite.portal_migration.needUpgrading())
+ # after migration `/news`, `/events` and `/Members` are based on
+ # `plone.(app.)folder`, but still have no ordering set...
+ for id in ids:
+ obj = oldsite[id]
+ self.assertTrue(IOrderableFolder.providedBy(obj),
+ '%s not orderable?' % id)
+ self.assertEqual(obj._ordering, 'unordered',
+ '%s has no `_ordering`?' % id)
+ self.assertEqual(obj.portal_type, 'Folder')
+ self.assertEqual(obj.Type(), 'Folder')
+ brain, = oldsite.portal_catalog(getId=id) # asserts only one
+ self.assertEqual(brain.portal_type, 'Folder')
+ self.assertEqual(brain.Type, 'Folder')
+
+
+def test_suite():
+ from unittest import TestSuite, makeSuite
+ suite = TestSuite()
+ suite.addTest(makeSuite(TestMigrations_v3_3))
+ suite.addTest(makeSuite(TestFunctionalMigrations))
+ return suite
diff --git a/plone/app/upgrade/v40/tests.py b/plone/app/upgrade/v40/tests.py
new file mode 100644
index 0000000..c350619
--- /dev/null
+++ b/plone/app/upgrade/v40/tests.py
@@ -0,0 +1,666 @@
+import time
+
+from zope.component import getMultiAdapter
+from zope.component import getSiteManager
+from zope.component import getUtility
+from zope.component import queryUtility
+from zope.ramcache.interfaces.ram import IRAMCache
+
+from Products.CMFCore.ActionInformation import Action
+from Products.CMFCore.Expression import Expression
+from Products.CMFCore.utils import getToolByName
+from Products.MailHost.interfaces import IMailHost
+
+from plone.app.upgrade.utils import loadMigrationProfile
+from plone.app.upgrade.v40.alphas import _KNOWN_ACTION_ICONS
+from plone.app.upgrade.v40.alphas import migrateActionIcons
+from plone.app.upgrade.v40.alphas import migrateTypeIcons
+from plone.app.upgrade.v40.alphas import addOrReplaceRamCache
+from plone.app.upgrade.v40.alphas import changeWorkflowActorVariableExpression
+from plone.app.upgrade.v40.alphas import changeAuthenticatedResourcesCondition
+from plone.app.upgrade.v40.alphas import setupReferencebrowser
+from plone.app.upgrade.v40.alphas import migrateMailHost
+from plone.app.upgrade.v40.alphas import migrateFolders
+from plone.app.upgrade.v40.alphas import renameJoinFormFields
+from plone.app.upgrade.v40.alphas import updateLargeFolderType
+from plone.app.upgrade.v40.alphas import addRecursiveGroupsPlugin
+from plone.app.upgrade.v40.alphas import cleanUpClassicThemeResources
+from plone.app.upgrade.v40.alphas import migrateStaticTextPortlets
+from plone.app.upgrade.v40.betas import repositionRecursiveGroupsPlugin
+from plone.app.upgrade.v40.betas import updateIconMetadata
+from plone.app.upgrade.v40.betas import removeLargePloneFolder
+from plone.app.upgrade.tests.base import MigrationTest
+
+from plone.portlet.static import static
+from plone.portlets.interfaces import IPortletAssignmentMapping
+from plone.portlets.interfaces import IPortletAssignmentSettings
+from plone.portlets.interfaces import IPortletManager
+
+
+class FakeSecureMailHost(object):
+
+ meta_type = 'Secure Mail Host'
+ id = 'MailHost'
+ title = 'Fake MailHost'
+ smtp_host = 'smtp.example.com'
+ smtp_port = 587
+ smtp_userid='me'
+ smtp_pass='secret'
+ smtp_notls=False
+
+ def manage_fixupOwnershipAfterAdd(self):
+ pass
+
+
+class TestMigrations_v4_0alpha1(MigrationTest):
+
+ profile = "profile-plone.app.upgrade.v40:3-4alpha1"
+
+ def afterSetUp(self):
+ self.atool = getToolByName(self.portal, 'portal_actions')
+ self.cptool = getToolByName(self.portal, 'portal_controlpanel')
+ self.wftool = getToolByName(self.portal, 'portal_workflow')
+ self.csstool = getToolByName(self.portal, 'portal_css')
+ self.jstool = getToolByName(self.portal, 'portal_javascripts')
+
+ if 'portal_actionicons' not in self.portal:
+ from plone.app.upgrade.bbb import ActionIconsTool
+ self.portal._setObject('portal_actionicons', ActionIconsTool())
+ self.aitool = self.portal.portal_actionicons
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ self.setRoles(['Manager'])
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+ def testMigrateActionIcons(self):
+ _KNOWN_ACTION_ICONS['object_buttons'].extend(['test_id', 'test2_id'])
+ self.aitool.addActionIcon(
+ category='object_buttons',
+ action_id='test_id',
+ icon_expr='test.gif',
+ title='Test my icon',
+ )
+ self.aitool.addActionIcon(
+ category='object_buttons',
+ action_id='test2_id',
+ icon_expr='python:context.getIcon()',
+ title='Test my second icon',
+ )
+ test_action = Action('test_id',
+ title='Test me',
+ description='',
+ url_expr='',
+ icon_expr='',
+ available_expr='',
+ permissions=('View', ),
+ visible = True)
+ test2_action = Action('test2_id',
+ title='Test me too',
+ description='',
+ url_expr='',
+ icon_expr='',
+ available_expr='',
+ permissions=('View', ),
+ visible = True)
+
+ object_buttons = self.atool.object_buttons
+ if getattr(object_buttons, 'test_id', None) is None:
+ object_buttons._setObject('test_id', test_action)
+ if getattr(object_buttons, 'test2_id', None) is None:
+ object_buttons._setObject('test2_id', test2_action)
+
+ self.assertEqual(object_buttons.test_id.icon_expr, '')
+ self.assertEqual(object_buttons.test2_id.icon_expr, '')
+ # Test it twice
+ for i in range(2):
+ migrateActionIcons(self.portal)
+ icons = [ic._action_id for ic in self.aitool.listActionIcons()]
+ self.assertFalse('test_id' in icons)
+ self.assertFalse('test2_id' in icons)
+ self.assertEqual(object_buttons.test_id.icon_expr,
+ 'string:$portal_url/test.gif')
+ self.assertEqual(object_buttons.test2_id.icon_expr,
+ 'python:context.getIcon()')
+
+ def testMigrateControlPanelActionIcons(self):
+ _KNOWN_ACTION_ICONS['controlpanel'].extend(['test_id'])
+ self.aitool.addActionIcon(
+ category='controlpanel',
+ action_id='test_id',
+ icon_expr='test.gif',
+ title='Test my icon',
+ )
+
+ self.cptool.registerConfiglet(
+ id='test_id',
+ name='Test Configlet',
+ action='string:${portal_url}/test',
+ permission='Manage portal',
+ category='Plone',
+ visible=True,
+ appId='',
+ icon_expr='',
+ )
+
+ action = self.cptool.getActionObject('Plone/test_id')
+ self.assertEqual(action.getIconExpression(), '')
+ # Test it twice
+ for i in range(2):
+ migrateActionIcons(self.portal)
+ icons = [ic._action_id for ic in self.aitool.listActionIcons()]
+ self.assertFalse('test_id' in icons)
+ self.assertEqual(action.getIconExpression(),
+ 'string:$portal_url/test.gif')
+
+ def testContentTypeIconExpressions(self):
+ """
+ FTIs should now be using icon_expr instead of content_icon.
+ (The former caches the expression object.)
+ """
+ tt = getToolByName(self.portal, "portal_types")
+ tt.Document.icon_expr = None
+ loadMigrationProfile(self.portal, self.profile, ('typeinfo', ))
+ self.assertEqual(tt.Document.icon_expr,
+ "string:${portal_url}/document_icon.png")
+
+ def testMigrateTypeIcons(self):
+ """
+ FTIs having content_icon should be upgraded to icon_expr.
+ """
+ tt = getToolByName(self.portal, "portal_types")
+ del tt.Document.icon_expr
+ tt.Document.content_icon = 'document_icon.gif'
+ migrateTypeIcons(self.portal)
+ self.assertEqual(tt.Document.icon_expr,
+ "string:${portal_url}/document_icon.gif")
+ self.assertTrue(hasattr(tt.Document, 'icon_expr_object'))
+
+ #Don't upgrade if there is already an icon_expr.
+ tt.Document.icon_expr = "string:${portal_url}/document_icon.png"
+ tt.Document.content_icon = 'document_icon.gif'
+ migrateTypeIcons(self.portal)
+ self.assertEqual(tt.Document.icon_expr,
+ "string:${portal_url}/document_icon.png")
+
+ def testPngContentIcons(self):
+ tt = getToolByName(self.portal, "portal_types")
+ tt.Document.icon_expr = "string:${portal_url}/document_icon.gif"
+ loadMigrationProfile(self.portal, self.profile, ('typeinfo', ))
+ self.assertEqual(tt.Document.icon_expr,
+ "string:${portal_url}/document_icon.png")
+
+ def testAddRAMCache(self):
+ # Test it twice
+ for i in range(2):
+ sm = getSiteManager()
+ sm.unregisterUtility(provided=IRAMCache)
+ util = queryUtility(IRAMCache)
+ self.assertEqual(util.maxAge, 86400)
+ addOrReplaceRamCache(self.portal)
+ util = queryUtility(IRAMCache)
+ self.assertEqual(util.maxAge, 3600)
+
+ def testReplaceOldRamCache(self):
+ sm = getSiteManager()
+
+ # Test it twice
+ for i in range(2):
+ sm.unregisterUtility(provided=IRAMCache)
+ from zope.app.cache.interfaces.ram import IRAMCache as OldIRAMCache
+ from zope.app.cache.ram import RAMCache as OldRAMCache
+ sm.registerUtility(factory=OldRAMCache, provided=OldIRAMCache)
+
+ addOrReplaceRamCache(self.portal)
+ util = queryUtility(IRAMCache)
+ self.assertEqual(util.maxAge, 3600)
+
+ def testChangeWorkflowActorVariableExpression(self):
+ self.wftool.intranet_folder_workflow.variables.actor.setProperties('')
+
+ for i in range(2):
+ changeWorkflowActorVariableExpression(self.portal)
+ wf = self.wftool.intranet_folder_workflow
+ self.assertEqual(wf.variables.actor.getDefaultExprText(),
+ 'user/getId')
+ wf = self.wftool.one_state_workflow
+ self.assertEqual(wf.variables.actor.getDefaultExprText(),
+ 'user/getId')
+ wf = self.wftool.simple_publication_workflow
+ self.assertEqual(wf.variables.actor.getDefaultExprText(),
+ 'user/getId')
+
+ # make sure it doesn't break if the workflow is missing
+ wf = self.wftool.intranet_folder_workflow
+ self.wftool._delOb('intranet_folder_workflow')
+ changeWorkflowActorVariableExpression(self.portal)
+ self.wftool._setOb('intranet_folder_workflow', wf)
+
+ def testChangeAuthenticatedResourcesCondition(self):
+ # make sure CSS resource is updated
+ res = self.csstool.getResource('member.css')
+ if res is None:
+ return
+ res.setAuthenticated(False)
+ res.setExpression('not: portal/portal_membership/isAnonymousUser')
+ # test it twice
+ for i in range(2):
+ changeAuthenticatedResourcesCondition(self.portal)
+ self.assertEqual(res.getExpression(), '')
+ self.assertTrue(res.getAuthenticated())
+
+ # make sure it doesn't update it if the expression has been
+ # customized
+ res.setExpression('python:False')
+ changeAuthenticatedResourcesCondition(self.portal)
+ self.assertEqual(res.getExpression(), 'python:False')
+
+ def testAddedUseEmailProperty(self):
+ tool = getToolByName(self.portal, 'portal_properties')
+ sheet = getattr(tool, 'site_properties')
+ #self.assertEqual(sheet.getProperty('use_email_as_login'), False)
+ self.removeSiteProperty('use_email_as_login')
+ loadMigrationProfile(self.portal, self.profile, ('propertiestool', ))
+ self.assertEqual(sheet.getProperty('use_email_as_login'), False)
+
+ def testReplaceReferencebrowser(self):
+ self.setRoles(['Manager'])
+ skins_tool = getToolByName(self.portal, 'portal_skins')
+ if 'referencebrowser' not in skins_tool:
+ return
+ sels = skins_tool._getSelections()
+ for skinname, layer in sels.items():
+ layers = layer.split(',')
+ self.assertFalse('ATReferenceBrowserWidget' in layers)
+ layers.remove('referencebrowser')
+ new_layers = ','.join(layers)
+ sels[skinname] = new_layers
+
+ from .alphas import threeX_alpha1
+ threeX_alpha1(self.portal)
+ setupReferencebrowser(self.portal)
+
+ sels = skins_tool._getSelections()
+ for skinname, layer in sels.items():
+ layers = layer.split(',')
+ self.assertTrue('referencebrowser' in layers)
+
+ def testInstallNewDependencies(self):
+ from plone.app.upgrade.v40.alphas import threeX_alpha1
+ self.setRoles(['Manager'])
+ # test for running the TinyMCE profile by checking for the skin layer
+ # it installs (the profile is marked as noninstallable, so we can't
+ # ask the quick installer)
+ skins_tool = getToolByName(self.portal, 'portal_skins')
+ if 'tinymce' not in skins_tool:
+ # Skip test in new Plones that don't have tinymce to begin with
+ return
+ del skins_tool['tinymce']
+ for i in range(2):
+ threeX_alpha1(self.portal)
+ self.assertTrue('tinymce' in skins_tool)
+ # sleep to avoid a GS log filename collision :-o
+ time.sleep(1)
+
+ def testReplaceSecureMailHost(self):
+ portal = self.portal
+ sm = getSiteManager(context=portal)
+ # try it with an unmodified site to ensure it doesn't give any errors
+ migrateMailHost(portal.portal_setup)
+ portal._delObject('MailHost')
+ # Run it with our MailHost replaced
+ portal._setObject('MailHost', FakeSecureMailHost())
+ self.assertEqual(portal.MailHost.meta_type, 'Secure Mail Host')
+ sm.unregisterUtility(provided=IMailHost)
+ sm.registerUtility(portal.MailHost, provided=IMailHost)
+ migrateMailHost(portal)
+ new_mh = portal.MailHost
+ self.assertEqual(new_mh.meta_type, 'Mail Host')
+ self.assertEqual(new_mh.title, 'Fake MailHost')
+ self.assertEqual(new_mh.smtp_host, 'smtp.example.com')
+ self.assertEqual(new_mh.smtp_port, 587)
+ self.assertEqual(new_mh.smtp_uid, 'me')
+ self.assertEqual(new_mh.smtp_pwd, 'secret')
+ #Force TLS is always false, because SMH has no equivalent option
+ self.assertEqual(new_mh.force_tls, False)
+
+ def testFolderMigration(self):
+ from plone.app.folder.tests.content import create
+ from plone.app.folder.tests.test_migration import reverseMigrate
+ from plone.app.folder.tests.test_migration import isSaneBTreeFolder
+ # create a folder in an unmigrated state & check it's broken...
+ folder = create('Folder', self.portal, 'foo', title='Foo')
+ reverseMigrate(self.portal)
+ self.assertFalse(isSaneBTreeFolder(self.portal.foo))
+ # now run the migration step...
+ migrateFolders(self.portal)
+ folder = self.portal.foo
+ self.assertTrue(isSaneBTreeFolder(folder))
+ self.assertEqual(folder.getId(), 'foo')
+ self.assertEqual(folder.Title(), 'Foo')
+
+ def testMigrateStaticTextPortlets(self):
+ class HiddenAssignment(static.Assignment):
+ hide = True
+
+ self.setRoles(["Manager"])
+ self.portal.invokeFactory('Folder', id="statictest")
+ folder = self.portal['statictest']
+
+ manager = getUtility(
+ IPortletManager, name='plone.rightcolumn',
+ context=folder)
+ assignments = getMultiAdapter(
+ (folder, manager), IPortletAssignmentMapping)
+ hidden_portlet = HiddenAssignment()
+ visible_portlet = static.Assignment()
+ assignments['hidden'] = hidden_portlet
+ assignments['visible'] = visible_portlet
+
+ migrateStaticTextPortlets(self.portal)
+
+ self.assertFalse(
+ IPortletAssignmentSettings(hidden_portlet).get(
+ 'visible', True))
+ self.assertTrue(
+ IPortletAssignmentSettings(visible_portlet).get(
+ 'visible', True))
+
+
+
+class TestMigrations_v4_0alpha2(MigrationTest):
+
+ def testMigrateJoinFormFields(self):
+ ptool = getToolByName(self.portal, 'portal_properties')
+ sheet = getattr(ptool, 'site_properties')
+ self.removeSiteProperty('user_registration_fields')
+ self.addSiteProperty('join_form_fields')
+ sheet.join_form_fields = (
+ 'username', 'password', 'email', 'mail_me', 'groups')
+ renameJoinFormFields(self)
+ self.assertEqual(sheet.hasProperty('join_form_fields'), False)
+ self.assertEqual(sheet.hasProperty('user_registration_fields'), True)
+ self.assertEqual(sheet.getProperty('user_registration_fields'),
+ ('username', 'password', 'email', 'mail_me'))
+
+
+class TestMigrations_v4_0alpha3(MigrationTest):
+
+ profile = "profile-plone.app.upgrade.v40:4alpha2-4alpha3"
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+ def testJoinActionURL(self):
+ self.portal.portal_actions.user.join.url_expr = 'foo'
+ loadMigrationProfile(self.portal, self.profile, ('actions', ))
+ self.assertEqual(self.portal.portal_actions.user.join.url_expr,
+ 'string:${globals_view/navigationRootUrl}/@@register')
+
+
+class TestMigrations_v4_0alpha5(MigrationTest):
+
+ profile = "profile-plone.app.upgrade.v40:4alpha4-4alpha5"
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+ def testMigrateLargeFolderType(self):
+ portal = self.portal
+ catalog = getToolByName(portal, 'portal_catalog')
+ # set things up in the old way...
+ ids = 'news', 'events', 'Members'
+ for id in ids:
+ obj = portal[id]
+ obj._setPortalTypeName('Large Plone Folder')
+ obj.reindexObject()
+ self.assertEqual(obj.portal_type, 'Large Plone Folder')
+ # Type falls back to meta_type since there's no
+ # Large Plone Folder FTI
+ self.assertEqual(obj.Type(), 'ATFolder')
+ brain, = catalog(getId=id)
+ self.assertEqual(brain.portal_type, 'Large Plone Folder')
+ self.assertEqual(brain.Type, 'ATFolder')
+ # migrate & check again...
+ updateLargeFolderType(self.portal)
+ for id in ids:
+ obj = portal[id]
+ self.assertEqual(obj.portal_type, 'Folder')
+ self.assertEqual(obj.Type(), 'Folder')
+ brain, = catalog(getId=id)
+ self.assertEqual(brain.portal_type, 'Folder')
+ self.assertEqual(brain.Type, 'Folder')
+
+ def testAddRecursiveGroupsPlugin(self):
+ acl = getToolByName(self.portal, 'acl_users')
+ addRecursiveGroupsPlugin(self.portal)
+ self.assertTrue('recursive_groups' in acl)
+ # Now that we have an existing one, let's make sure it's handled
+ # properly if this migration is run again.
+ addRecursiveGroupsPlugin(self.portal)
+ self.assertTrue('recursive_groups' in acl)
+
+ def testClassicThemeResourcesCleanUp(self):
+ """Test that the plonetheme.classic product doesn't have any
+ registered CSS resource in its metadata after migration.
+ """
+ portal = self.portal
+ qi = getToolByName(portal, 'portal_quickinstaller')
+ qi.installProduct('plonetheme.classic')
+ classictheme = qi['plonetheme.classic']
+ classictheme.resources_css = ['something'] # add a random resource
+ cleanUpClassicThemeResources(portal)
+ self.assertEqual(classictheme.resources_css, [])
+
+ def testGetObjPositionInParentIndex(self):
+ from plone.app.folder.nogopip import GopipIndex
+ catalog = self.portal.portal_catalog
+ catalog.delIndex('getObjPositionInParent')
+ catalog.addIndex('getObjPositionInParent', 'FieldIndex')
+ self.assertFalse(isinstance(catalog.Indexes['getObjPositionInParent'],
+ GopipIndex))
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue('getObjPositionInParent' in catalog.indexes())
+ self.assertTrue(isinstance(catalog.Indexes['getObjPositionInParent'],
+ GopipIndex))
+
+ def testGetEventTypeIndex(self):
+ catalog = self.portal.portal_catalog
+ catalog.addIndex('getEventType', 'KeywordIndex')
+ self.assertTrue('getEventType' in catalog.indexes())
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertFalse('getEventType' in catalog.indexes())
+
+
+class TestMigrations_v4_0beta1(MigrationTest):
+
+ profile = "profile-plone.app.upgrade.v40:4alpha5-4beta1"
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+ def testRepositionRecursiveGroupsPlugin(self):
+ # Ensure that the recursive groups plugin is moved to the bottom
+ # of the IGroups plugins list, if active.
+ addRecursiveGroupsPlugin(self.portal)
+ # Plugin is installed, but not active, run against this state.
+ from Products.PluggableAuthService.interfaces.plugins import \
+ IGroupsPlugin
+ acl = getToolByName(self.portal, 'acl_users')
+ plugins = acl.plugins
+ # The plugin was originally moved to the top of the list of
+ # IGroupsPlugin plugins by p.a.controlpanel. Recreate that state.
+ while (plugins.getAllPlugins('IGroupsPlugin')['active'].index(
+ 'recursive_groups') > 0):
+ plugins.movePluginsUp(IGroupsPlugin, ['recursive_groups'])
+
+ active_groups = plugins.getAllPlugins('IGroupsPlugin')['active']
+ self.assertEqual(active_groups[0], 'recursive_groups')
+
+ # Rerun the migration, making sure that it's now the last item in the
+ # list of IGroupsPlugin plugins.
+ repositionRecursiveGroupsPlugin(self.portal)
+ active_groups = plugins.getAllPlugins('IGroupsPlugin')['active']
+ self.assertEqual(active_groups[-1], 'recursive_groups')
+
+
+class TestMigrations_v4_0beta2(MigrationTest):
+
+ profile = "profile-plone.app.upgrade.v40:4beta1-4beta2"
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+ def testCoreContentIconExprCleared(self):
+ types = getToolByName(self.portal, 'portal_types')
+ catalog = getToolByName(self.portal, 'portal_catalog')
+ # Reinstate the now-empty icon expression for the Document type
+ doc_icon_expr = Expression('string:${portal_url}/document_icon.png')
+ types['Document'].icon_expr_object = doc_icon_expr
+ front = self.portal['front-page']
+ catalog.reindexObject(front)
+ old_modified = front.modified()
+ # Make sure the getIcon metadata column shows the "original" value
+ brains = catalog(id='front-page')
+ self.assertEqual(brains[0].getIcon, 'document_icon.png')
+ # Run the migration
+ loadMigrationProfile(self.portal, self.profile)
+ updateIconMetadata(self.portal)
+ # The getIcon column should now be empty
+ self.assertEqual(catalog(id='front-page')[0].getIcon, '')
+ self.assertEqual(front.modified(), old_modified)
+
+
+class TestMigrations_v4_0beta4(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4beta3-4beta4'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+ def testRemoveLargePloneFolder(self):
+ # re-create pre-migration settings
+ ptool = self.portal.portal_properties
+ nav_props = ptool.navtree_properties
+ l = list(nav_props.parentMetaTypesNotToQuery)
+ nav_props.parentMetaTypesNotToQuery = l + ['Large Plone Folder']
+ site_props = ptool.site_properties
+ l = list(site_props.typesLinkToFolderContentsInFC)
+ site_props.typesLinkToFolderContentsInFC = l + ['Large Plone Folder']
+ temp_folder_fti = self.portal.portal_types['TempFolder']
+ l = list(temp_folder_fti.allowed_content_types)
+ temp_folder_fti.allowed_content_types = l + ['Large Plone Folder']
+ l = set(self.portal.portal_factory.getFactoryTypes())
+ l.add('Large Plone Folder')
+ ftool = self.portal.portal_factory
+ ftool.manage_setPortalFactoryTypes(listOfTypeIds=list(l))
+
+ for i in xrange(2):
+ loadMigrationProfile(self.portal, self.profile)
+ removeLargePloneFolder(self.portal)
+ self.assertFalse('Large Plone Folder' in self.portal.portal_types)
+ self.assertFalse('Large Plone Folder' in
+ temp_folder_fti.allowed_content_types)
+ self.assertTrue('Folder' in temp_folder_fti.allowed_content_types)
+ self.assertFalse('Large Plone Folder' in ftool.getFactoryTypes())
+ self.assertTrue('Folder' in ftool.getFactoryTypes())
+ self.assertFalse('Large Plone Folder' in
+ nav_props.parentMetaTypesNotToQuery)
+ self.assertTrue('TempFolder' in
+ nav_props.parentMetaTypesNotToQuery)
+ self.assertFalse('Large Plone Folder' in
+ site_props.typesLinkToFolderContentsInFC)
+ self.assertTrue('Folder' in
+ site_props.typesLinkToFolderContentsInFC)
+ # sleep to avoid a GS log filename collision :-o
+ time.sleep(1)
+
+
+class TestMigrations_v4_0beta5(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4beta4-4beta5'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+
+class TestMigrations_v4_0rc1(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4beta5-4rc1'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+class TestMigrations_v4_0(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4rc1-4final'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+class TestMigrations_v4_0_1(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4.0-4.0.1'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+class TestMigrations_v4_0_2(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4.0.1-4.0.2'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+class TestMigrations_v4_0_3(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4.0.2-4.0.3'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+class TestMigrations_v4_0_4(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4.0.3-4.0.4'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+class TestMigrations_v4_0_5(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4.0.4-4.0.5'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+
+def test_suite():
+ from unittest import defaultTestLoader
+ return defaultTestLoader.loadTestsFromName(__name__)
diff --git a/plone/app/upgrade/v41/tests.py b/plone/app/upgrade/v41/tests.py
new file mode 100644
index 0000000..4570a4c
--- /dev/null
+++ b/plone/app/upgrade/v41/tests.py
@@ -0,0 +1,19 @@
+import unittest
+from Products.ZCatalog.ZCatalog import ZCatalog
+from Products.ZCTextIndex.ZCTextIndex import ZCTextIndex, PLexicon
+from Products.ZCTextIndex.OkapiIndex import OkapiIndex
+
+
+class MigrationUnitTests(unittest.TestCase):
+
+ def test_fixOkapiIndexes(self):
+ catalog = ZCatalog('catalog')
+ catalog.lexicon = PLexicon('lexicon')
+ catalog.addIndex('test',
+ ZCTextIndex('test', index_factory=OkapiIndex,
+ caller=catalog, lexicon_id='lexicon'))
+ catalog.Indexes['test'].index._totaldoclen = -1000
+
+ from plone.app.upgrade.v41.final import fixOkapiIndexes
+ fixOkapiIndexes(catalog)
+ self.assertEqual(0L, catalog.Indexes['test'].index._totaldoclen())
diff --git a/plone/app/upgrade/v42/tests.py b/plone/app/upgrade/v42/tests.py
new file mode 100644
index 0000000..0ff501e
--- /dev/null
+++ b/plone/app/upgrade/v42/tests.py
@@ -0,0 +1,20 @@
+from plone.app.upgrade.tests.base import MigrationTest
+from plone.app.upgrade.utils import loadMigrationProfile
+
+
+class TestMigrations_v4_2beta1(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v42:to42beta1'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+ def testAddSiteAdminToKeywordRoles(self):
+ ptool = self.portal.portal_properties
+ site_props = ptool.site_properties
+ site_props.allowRolesToAddKeywords = ('Manager', 'Reviewer')
+ loadMigrationProfile(self.portal, self.profile)
+ roles = site_props.allowRolesToAddKeywords
+ self.assertEqual(roles, ('Manager', 'Reviewer', 'Site Administrator'))
diff --git a/setup.py b/setup.py
index c500ee7..1dd33a5 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages
-version = '2.0.dev0'
+version = '1.3.9.dev0'
setup(name='plone.app.upgrade',
version=version,
@@ -10,12 +10,10 @@
classifiers=[
"Environment :: Web Environment",
"Framework :: Plone",
- "Framework :: Plone :: 5.0",
"Framework :: Zope2",
"License :: OSI Approved :: GNU General Public License (GPL)",
"Operating System :: OS Independent",
"Programming Language :: Python",
- "Programming Language :: Python :: 2.7",
],
keywords='Plone upgrade migration',
author='Plone Foundation',
@@ -30,13 +28,13 @@
test=[
'Products.CMFPlacefulWorkflow',
'Products.CMFQuickInstallerTool',
+ 'Products.PloneTestCase',
'plone.contentrules',
'plone.app.i18n',
'plone.app.iterate',
'plone.app.openid',
'plone.app.redirector',
'plone.app.viewletmanager',
- 'plone.app.testing',
'plone.app.theming',
]
),
Repository: plone.app.upgrade
Branch: refs/heads/master
Date: 2015-01-07T14:28:14+01:00
Author: Timo Stollenwerk (tisto) <tisto at plone.org>
Commit: https://github.com/plone/plone.app.upgrade/commit/8de8c57b74520df8d7241ea63109cd1271f39acb
Merge pull request #23 from plone/revert-22-tomgross-noptc
Revert "Ported to plone.app.testing"
Files changed:
A plone/app/upgrade/v25/tests.py
A plone/app/upgrade/v30/tests.py
A plone/app/upgrade/v31/tests.py
A plone/app/upgrade/v32/tests.py
A plone/app/upgrade/v33/tests.py
A plone/app/upgrade/v40/tests.py
A plone/app/upgrade/v41/tests.py
A plone/app/upgrade/v42/tests.py
M CHANGES.rst
M plone/app/upgrade/tests/base.py
M setup.py
diff --git a/CHANGES.rst b/CHANGES.rst
index 6e27679..1bf846a 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,7 +1,7 @@
Changelog
=========
-2.0 (unreleased)
+1.3.9 (unreleased)
------------------
- Add upgrade step for the security control panel.
@@ -13,11 +13,6 @@ Changelog
- Add upgrade steps for markup control panel.
[thet]
-- Ported tests to plone.app.testing
- [tomgross]
-
-- Removed all tests for migrations older than 4.3 -> 5.0
- [tomgross]
1.3.8 (2014-11-01)
------------------
diff --git a/plone/app/upgrade/tests/base.py b/plone/app/upgrade/tests/base.py
index f25f530..840416c 100644
--- a/plone/app/upgrade/tests/base.py
+++ b/plone/app/upgrade/tests/base.py
@@ -9,7 +9,10 @@
import transaction
from zope.site.hooks import setSite
-from plone.app.testing.bbb import PloneTestCase
+from Testing.ZopeTestCase.sandbox import Sandboxed
+from Products.PloneTestCase.layer import PloneSiteLayer
+from Products.PloneTestCase.ptc import PloneTestCase
+from Products.PloneTestCase.ptc import setupPloneSite
from Products.CMFCore.interfaces import IActionCategory
from Products.CMFCore.interfaces import IActionInfo
@@ -17,6 +20,8 @@
from Products.CMFCore.tests.base.testcase import WarningInterceptor
from Products.GenericSetup.context import TarballImportContext
+setupPloneSite()
+
class MigrationTest(PloneTestCase):
@@ -106,10 +111,21 @@ def removeSkinLayer(self, layer, skin='Plone Default'):
skins.addSkinSelection(skin, ','.join(path))
+class FunctionalUpgradeLayer(PloneSiteLayer):
+
+ @classmethod
+ def setUp(cls):
+ pass
+
+ @classmethod
+ def tearDown(cls):
+ pass
+
-class FunctionalUpgradeTestCase(PloneTestCase, WarningInterceptor):
+class FunctionalUpgradeTestCase(Sandboxed, PloneTestCase, WarningInterceptor):
_setup_fixture = 0
+ layer = FunctionalUpgradeLayer
site_id = 'test'
def afterSetUp(self):
diff --git a/plone/app/upgrade/v25/tests.py b/plone/app/upgrade/v25/tests.py
new file mode 100644
index 0000000..036e8b5
--- /dev/null
+++ b/plone/app/upgrade/v25/tests.py
@@ -0,0 +1,124 @@
+from Products.CMFPlone.UnicodeSplitter import Splitter
+from Products.CMFPlone.UnicodeSplitter import CaseNormalizer
+
+from plone.app.upgrade.tests.base import FunctionalUpgradeTestCase
+from plone.app.upgrade.tests.base import MigrationTest
+from plone.app.upgrade.utils import loadMigrationProfile
+
+from plone.app.upgrade.v25 import fixupPloneLexicon
+from plone.app.upgrade.v25 import setLoginFormInCookieAuth
+from plone.app.upgrade.v25 import addMissingMimeTypes
+
+
+class TestMigrations_v2_5_0(MigrationTest):
+
+ def afterSetUp(self):
+ self.profile = 'profile-plone.app.upgrade.v25:2.5final-2.5.1'
+ self.actions = self.portal.portal_actions
+ self.css = self.portal.portal_css
+
+ def tesFixObjDeleteAction(self):
+ # Prepare delete actions test
+ editActions = ('delete',)
+ for a in editActions:
+ self.removeActionFromTool(a, category='object_buttons')
+ loadMigrationProfile(self.portal, self.profile, ('actions', ))
+ # delete action tests
+ actions = [x.id for x in self.actions.object_buttons.listActions()
+ if x.id in editActions]
+ # check that all of our deleted actions are now present
+ for a in editActions:
+ self.assertTrue(a in actions)
+ # ensure that they are present only once
+ self.assertEqual(len(editActions), len(actions))
+
+ def testFixupPloneLexicon(self):
+ # Should update the plone_lexicon pipeline
+ lexicon = self.portal.portal_catalog.plone_lexicon
+ lexicon._pipeline = (object(), object())
+ # Test it twice
+ for i in range(2):
+ fixupPloneLexicon(self.portal)
+ self.assertTrue(isinstance(lexicon._pipeline[0], Splitter))
+ self.assertTrue(isinstance(lexicon._pipeline[1], CaseNormalizer))
+
+
+class TestMigrations_v2_5_1(MigrationTest):
+
+ def afterSetUp(self):
+ self.actions = self.portal.portal_actions
+ self.memberdata = self.portal.portal_memberdata
+ self.catalog = self.portal.portal_catalog
+ self.skins = self.portal.portal_skins
+ self.types = self.portal.portal_types
+ self.workflow = self.portal.portal_workflow
+ self.css = self.portal.portal_css
+
+ def testSetLoginFormInCookieAuth(self):
+ setLoginFormInCookieAuth(self.portal)
+ cookie_auth = self.portal.acl_users.credentials_cookie_auth
+ self.assertEqual(cookie_auth.getProperty('login_path'),
+ 'require_login')
+
+ def testSetLoginFormNoCookieAuth(self):
+ # Shouldn't error
+ uf = self.portal.acl_users
+ uf._delOb('credentials_cookie_auth')
+ setLoginFormInCookieAuth(self.portal)
+
+ def testSetLoginFormAlreadyChanged(self):
+ # Shouldn't change the value if it's not the default
+ cookie_auth = self.portal.acl_users.credentials_cookie_auth
+ cookie_auth.manage_changeProperties(login_path='foo')
+ setLoginFormInCookieAuth(self.portal)
+ self.assertTrue(cookie_auth.getProperty('login_path') != 'require_login')
+
+class TestMigrations_v2_5_2(MigrationTest):
+
+ def afterSetUp(self):
+ self.mimetypes = self.portal.mimetypes_registry
+
+ def testMissingMimeTypes(self):
+ # we're testing for 'text/x-web-markdown' and 'text/x-web-textile'
+ missing_types = ['text/x-web-markdown', 'text/x-web-textile']
+ # since we're running a full 2.5.4 instance in this test, the missing
+ # types might in fact already be there:
+ current_types = self.mimetypes.list_mimetypes()
+ types_to_delete = []
+ for mtype in missing_types:
+ if mtype in current_types:
+ types_to_delete.append(mtype)
+ if types_to_delete:
+ self.mimetypes.manage_delObjects(types_to_delete)
+ # now they're gone:
+ self.assertFalse(set(self.mimetypes.list_mimetypes()).issuperset(set(missing_types)))
+ addMissingMimeTypes(self.portal)
+ # now they're back:
+ self.assertTrue(set(self.mimetypes.list_mimetypes()).issuperset(set(missing_types)))
+
+
+class TestFunctionalMigrations(FunctionalUpgradeTestCase):
+
+ def testUpgrade(self):
+ self.importFile(__file__, 'test-base.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+ def testDCMIStorageUpdated(self):
+ self.importFile(__file__, 'test-base.zexp')
+ oldsite, result = self.migrate()
+
+ dcmi = getattr(oldsite.portal_metadata, 'DCMI', None)
+ self.assertFalse(dcmi is None)
+
+
+def test_suite():
+ from unittest import TestSuite, makeSuite
+ suite = TestSuite()
+ suite.addTest(makeSuite(TestMigrations_v2_5_0))
+ suite.addTest(makeSuite(TestMigrations_v2_5_1))
+ suite.addTest(makeSuite(TestMigrations_v2_5_2))
+ suite.addTest(makeSuite(TestFunctionalMigrations))
+ return suite
diff --git a/plone/app/upgrade/v30/tests.py b/plone/app/upgrade/v30/tests.py
new file mode 100644
index 0000000..9325d0d
--- /dev/null
+++ b/plone/app/upgrade/v30/tests.py
@@ -0,0 +1,1109 @@
+from Acquisition import aq_base
+
+from five.localsitemanager.registry import FiveVerifyingAdapterLookup
+
+from plone.contentrules.engine.interfaces import IRuleStorage
+from plone.app.i18n.locales.interfaces import IContentLanguages
+from plone.app.i18n.locales.interfaces import ICountries
+from plone.app.i18n.locales.interfaces import IMetadataLanguages
+from plone.app.portlets import portlets
+from plone.app.redirector.interfaces import IRedirectionStorage
+from plone.portlets.interfaces import IPortletManager
+from plone.portlets.interfaces import IPortletAssignmentMapping
+from plone.portlets.interfaces import ILocalPortletAssignmentManager
+from plone.portlets.constants import CONTEXT_CATEGORY as CONTEXT_PORTLETS
+
+from zope.location.interfaces import ISite
+from zope.component import getGlobalSiteManager
+from zope.component import getSiteManager
+from zope.component import getUtility, getMultiAdapter
+from zope.component.hooks import clearSite
+
+from Products.Archetypes.interfaces import IArchetypeTool
+from Products.Archetypes.interfaces import IReferenceCatalog
+from Products.Archetypes.interfaces import IUIDCatalog
+from Products.CMFActionIcons.interfaces import IActionIconsTool
+from Products.CMFCalendar.interfaces import ICalendarTool
+from Products.CMFCore.ActionInformation import Action
+from Products.CMFCore.ActionInformation import ActionCategory
+from Products.CMFCore.utils import getToolByName
+from Products.CMFCore.utils import getToolInterface
+from Products.CMFCore.Expression import Expression
+from Products.CMFCore.permissions import AccessInactivePortalContent
+from Products.CMFCore.interfaces import IActionsTool
+from Products.CMFCore.interfaces import ICachingPolicyManager
+from Products.CMFCore.interfaces import ICatalogTool
+from Products.CMFCore.interfaces import IContentTypeRegistry
+from Products.CMFCore.interfaces import IDiscussionTool
+from Products.CMFCore.interfaces import IMemberDataTool
+from Products.CMFCore.interfaces import IMembershipTool
+from Products.CMFCore.interfaces import IMetadataTool
+from Products.CMFCore.interfaces import IPropertiesTool
+from Products.CMFCore.interfaces import IRegistrationTool
+from Products.CMFCore.interfaces import ISiteRoot
+from Products.CMFCore.interfaces import ISkinsTool
+from Products.CMFCore.interfaces import ISyndicationTool
+from Products.CMFCore.interfaces import ITypesTool
+from Products.CMFCore.interfaces import IURLTool
+from Products.CMFCore.interfaces import IConfigurableWorkflowTool
+from Products.CMFCore.ActionInformation import ActionInformation
+from Products.CMFDiffTool.interfaces import IDiffTool
+from Products.CMFEditions.interfaces import IArchivistTool
+from Products.CMFEditions.interfaces import IPortalModifierTool
+from Products.CMFEditions.interfaces import IPurgePolicyTool
+from Products.CMFEditions.interfaces.IRepository import IRepositoryTool
+from Products.CMFEditions.interfaces import IStorageTool
+from Products.CMFFormController.interfaces import IFormControllerTool
+from Products.CMFQuickInstallerTool.interfaces import IQuickInstallerTool
+from Products.CMFPlone.interfaces import IPloneSiteRoot
+from Products.CMFPlone.interfaces import IPloneTool
+from Products.CMFPlone.interfaces import ITranslationServiceTool
+from Products.CMFUid.interfaces import IUniqueIdAnnotationManagement
+from Products.CMFUid.interfaces import IUniqueIdGenerator
+from Products.CMFUid.interfaces import IUniqueIdHandler
+from Products.GenericSetup.interfaces import ISetupTool
+from Products.MailHost.interfaces import IMailHost
+from Products.MimetypesRegistry.interfaces import IMimetypesRegistryTool
+from Products.PortalTransforms.interfaces import IPortalTransformsTool
+from Products.PloneLanguageTool.interfaces import ILanguageTool
+from Products.PlonePAS.interfaces.group import IGroupTool
+from Products.PlonePAS.interfaces.group import IGroupDataTool
+from Products.ResourceRegistries.interfaces import ICSSRegistry
+from Products.ResourceRegistries.interfaces import IJSRegistry
+
+from plone.app.upgrade.tests.base import FunctionalUpgradeTestCase
+from plone.app.upgrade.tests.base import MigrationTest
+from plone.app.upgrade.utils import loadMigrationProfile
+
+from plone.app.upgrade.v30.alphas import enableZope3Site
+from plone.app.upgrade.v30.alphas import migrateOldActions
+from plone.app.upgrade.v30.alphas import updateActionsI18NDomain
+from plone.app.upgrade.v30.alphas import updateFTII18NDomain
+from plone.app.upgrade.v30.alphas import convertLegacyPortlets
+from plone.app.upgrade.v30.alphas import registerToolsAsUtilities
+from plone.app.upgrade.v30.alphas import registration
+from plone.app.upgrade.v30.alphas import addReaderAndEditorRoles
+from plone.app.upgrade.v30.alphas import migrateLocalroleForm
+from plone.app.upgrade.v30.alphas import reorderUserActions
+from plone.app.upgrade.v30.alphas import updatePASPlugins
+from plone.app.upgrade.v30.alphas import updateConfigletTitles
+from plone.app.upgrade.v30.alphas import addCacheForResourceRegistry
+from plone.app.upgrade.v30.alphas import removeTablelessSkin
+from plone.app.upgrade.v30.alphas import addObjectProvidesIndex
+from plone.app.upgrade.v30.alphas import restorePloneTool
+from plone.app.upgrade.v30.alphas import installProduct
+
+from plone.app.upgrade.v30.betas import migrateHistoryTab
+from plone.app.upgrade.v30.betas import changeOrderOfActionProviders
+from plone.app.upgrade.v30.betas import cleanupOldActions
+from plone.app.upgrade.v30.betas import cleanDefaultCharset
+from plone.app.upgrade.v30.betas import addAutoGroupToPAS
+from plone.app.upgrade.v30.betas import removeS5Actions
+from plone.app.upgrade.v30.betas import addContributorToCreationPermissions
+from plone.app.upgrade.v30.betas import removeSharingAction
+from plone.app.upgrade.v30.betas import addEditorToSecondaryEditorPermissions
+from plone.app.upgrade.v30.betas import updateEditActionConditionForLocking
+from plone.app.upgrade.v30.betas import addOnFormUnloadJS
+
+from plone.app.upgrade.v30.betas import updateTopicTitle
+from plone.app.upgrade.v30.betas import cleanupActionProviders
+from plone.app.upgrade.v30.betas import hidePropertiesAction
+
+from plone.app.upgrade.v30.rcs import addIntelligentText
+
+from plone.app.upgrade.v30.final_three0x import installNewModifiers
+
+try:
+ from Products.ATContentTypes.interface import IATCTTool
+ HAS_ATCT = True
+except ImportError:
+ HAS_ATCT = False
+
+try:
+ from Products.CMFPlone.interfaces import IFactoryTool
+except:
+ from Products.ATContentTypes.interfaces import IFactoryTool
+
+
+class TestMigrations_v3_0_Actions(MigrationTest):
+
+ def afterSetUp(self):
+ self.actions = self.portal.portal_actions
+ self.types = self.portal.portal_types
+ self.workflow = self.portal.portal_workflow
+ self._migrate_reply_action()
+
+ def _migrate_reply_action(self):
+ # Create dummy old ActionInformation
+ reply = ActionInformation('reply',
+ title='Reply',
+ category='reply_actions',
+ condition='context/replyAllowed',
+ permissions=(AccessInactivePortalContent, ),
+ priority=10,
+ visible=True,
+ action='context/reply'
+ )
+
+ from OFS.SimpleItem import SimpleItem
+ class DummyTool(SimpleItem):
+ pass
+ dummy = DummyTool()
+ dummy._actions = (reply,)
+ self.portal._setObject('dummy', dummy)
+
+ def testMigrateActions(self):
+ # Test it twice
+ for i in range(2):
+ migrateOldActions(self.portal)
+ reply_actions = getattr(self.actions, 'reply_actions', None)
+ self.assertFalse(reply_actions is None)
+ reply = getattr(reply_actions, 'reply', None)
+ self.assertFalse(reply is None)
+ self.assertTrue(isinstance(reply, Action))
+ # Verify all data has been upgraded correctly to the new Action
+ data = reply.getInfoData()[0]
+ self.assertEqual(data['category'], 'reply_actions')
+ self.assertEqual(data['title'], 'Reply')
+ self.assertEqual(data['visible'], True)
+ self.assertEqual(data['permissions'], (AccessInactivePortalContent, ))
+ self.assertEqual(data['available'].text, 'context/replyAllowed')
+ self.assertEqual(data['url'].text, 'context/reply')
+ # Make sure the original action has been removed
+ self.assertEqual(len(self.portal.dummy._actions), 0)
+
+ def testUpdateActionsI18NDomain(self):
+ migrateOldActions(self.portal)
+ reply = self.actions.reply_actions.reply
+ self.assertEqual(reply.i18n_domain, '')
+ # Test it twice
+ for i in range(2):
+ updateActionsI18NDomain(self.portal)
+ self.assertEqual(reply.i18n_domain, 'plone')
+
+ def testUpdateActionsI18NDomainNonAscii(self):
+ migrateOldActions(self.portal)
+ reply = self.actions.reply_actions.reply
+ reply.title = 'Foo\xc3'
+ self.assertEqual(reply.i18n_domain, '')
+ self.assertEqual(reply.title, 'Foo\xc3')
+
+ updateActionsI18NDomain(self.portal)
+
+ self.assertEqual(reply.i18n_domain, '')
+
+ def testHistoryActionID(self):
+ # Test it twice
+ for i in range(2):
+ migrateHistoryTab(self.portal)
+ objects = getattr(self.actions, 'object', None)
+ self.assertFalse('rss' in objects.objectIds())
+
+ def testProviderCleanup(self):
+ self.actions.addActionProvider("portal_membership")
+ self.assertTrue("portal_membership" in self.actions.listActionProviders())
+ # Test it twice
+ for i in range(2):
+ cleanupActionProviders(self.portal)
+ self.assertFalse("portal_membership" in self.actions.listActionProviders())
+
+ def testRemovePropertiesActions(self):
+ ti = self.types.getTypeInfo("Document")
+ if ti.getActionObject("object/properties") is None:
+ ti.addAction("metadata", "name", "action", "condition",
+ "permission", "object",)
+ # Test it twice
+ for i in range(2):
+ hidePropertiesAction(self.portal)
+ self.assertTrue(ti.getActionObject("object/metadata") is None)
+
+ def tearDown(self):
+ self.portal._delObject('dummy')
+
+
+class TestMigrations_v2_5_x(MigrationTest):
+
+ def afterSetUp(self):
+ self.profile = 'profile-plone.app.upgrade.v30:2.5.x-3.0a1'
+ self.types = self.portal.portal_types
+ self.properties = self.portal.portal_properties
+
+ for legacy_tool in ('portal_discussion', 'portal_actionicons'):
+ if legacy_tool not in self.portal:
+ from OFS.SimpleItem import SimpleItem
+ self.portal._setObject(legacy_tool, SimpleItem())
+
+ def disableSite(self, obj, iface=ISite):
+ # We need our own disableSite method as the CMF portal implements
+ # ISite directly, so we cannot remove it, like the disableSite method
+ # in Five.component would have done
+ from ZPublisher.BeforeTraverse import unregisterBeforeTraverse
+ from Products.Five.component import HOOK_NAME
+ obj = aq_base(obj)
+ if not iface.providedBy(obj):
+ raise TypeError('Object must be a site.')
+ unregisterBeforeTraverse(obj, HOOK_NAME)
+ if hasattr(obj, HOOK_NAME):
+ delattr(obj, HOOK_NAME)
+
+ def testEnableZope3Site(self):
+ # First we remove the site and site manager
+ self.disableSite(self.portal)
+ clearSite(self.portal)
+ self.portal.setSiteManager(None)
+ gsm = getGlobalSiteManager()
+ # Test it twice
+ for i in range(2):
+ enableZope3Site(self.portal)
+ # And see if we have an ISite with a local site manager
+ self.assertTrue(ISite.providedBy(self.portal))
+ sm = getSiteManager(self.portal)
+ self.assertFalse(gsm is sm)
+ lc = sm.utilities.LookupClass
+ self.assertEqual(lc, FiveVerifyingAdapterLookup)
+
+ # Test the lookupclass migration
+ sm.utilities.LookupClass = None
+ # Test it twice
+ for i in range(2):
+ enableZope3Site(self.portal)
+ self.assertEqual(sm.utilities.LookupClass, FiveVerifyingAdapterLookup)
+ self.assertEqual(sm.utilities.__parent__, sm)
+ self.assertEqual(sm.__parent__, self.portal)
+
+ def testUpdateFTII18NDomain(self):
+ doc = self.types.Document
+ doc.i18n_domain = ''
+ # Test it twice
+ for i in range(2):
+ updateFTII18NDomain(self.portal)
+ self.assertEqual(doc.i18n_domain, 'plone')
+
+ def testUpdateFTII18NDomainNonAscii(self):
+ doc = self.types.Document
+ doc.i18n_domain = ''
+ doc.title = 'Foo\xc3'
+ # Update FTI's
+ updateFTII18NDomain(self.portal)
+ # domain should have been updated
+ self.assertEqual(doc.i18n_domain, '')
+
+ def testAddDefaultAndForbiddenContentTypesProperties(self):
+ # Should add the forbidden_contenttypes and default_contenttype property
+ self.removeSiteProperty('forbidden_contenttypes')
+ self.removeSiteProperty('default_contenttype')
+ self.assertFalse(self.properties.site_properties.hasProperty('forbidden_contenttypes'))
+ self.assertFalse(self.properties.site_properties.hasProperty('default_contenttype'))
+ # Test it twice
+ for i in range(2):
+ loadMigrationProfile(self.portal, self.profile, ('propertiestool', ))
+ self.assertTrue(self.properties.site_properties.hasProperty('forbidden_contenttypes'))
+ self.assertTrue(self.properties.site_properties.hasProperty('default_contenttype'))
+ self.assertEqual(self.properties.site_properties.forbidden_contenttypes,
+ ('text/structured', 'text/restructured', 'text/x-rst',
+ 'text/plain', 'text/plain-pre', 'text/x-python',
+ 'text/x-web-markdown', 'text/x-web-intelligent', 'text/x-web-textile')
+ )
+
+ def testTablelessRemoval(self):
+ st = getToolByName(self.portal, "portal_skins")
+ if "Plone Tableless" not in st.getSkinSelections():
+ st.addSkinSelection('Plone Tableless', 'one,two', make_default=True)
+ # Test it twice
+ for i in range(2):
+ removeTablelessSkin(self.portal)
+ self.assertFalse('Plone Tableless' in st.getSkinSelections())
+ self.assertFalse(st.default_skin == 'Plone Tableless')
+
+ def testLegacyPortletsConverted(self):
+ self.setRoles(('Manager',))
+ leftColumn = getUtility(IPortletManager, name=u'plone.leftcolumn', context=self.portal)
+ rightColumn = getUtility(IPortletManager, name=u'plone.rightcolumn', context=self.portal)
+
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ for k in left:
+ del left[k]
+ for k in right:
+ del right[k]
+
+ self.portal.left_slots = ['here/portlet_recent/macros/portlet',
+ 'here/portlet_news/macros/portlet',
+ 'here/portlet_related/macros/portlet']
+ self.portal.right_slots = ['here/portlet_login/macros/portlet',
+ 'here/portlet_languages/macros/portlet']
+
+ self.portal.Members.right_slots = []
+
+ # Test it twice
+ for i in range(2):
+ convertLegacyPortlets(self.portal)
+
+ self.assertEqual(self.portal.left_slots, [])
+ self.assertEqual(self.portal.right_slots, [])
+
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ lp = left.values()
+ self.assertEqual(2, len(lp))
+
+ self.assertTrue(isinstance(lp[0], portlets.recent.Assignment))
+ self.assertTrue(isinstance(lp[1], portlets.news.Assignment))
+
+ rp = right.values()
+ self.assertEqual(1, len(rp))
+ self.assertTrue(isinstance(rp[0], portlets.login.Assignment))
+
+ members = self.portal.Members
+ portletAssignments = getMultiAdapter((members, rightColumn,), ILocalPortletAssignmentManager)
+ self.assertEqual(True, portletAssignments.getBlacklistStatus(CONTEXT_PORTLETS))
+
+ def testLegacyPortletsConvertedNoSlots(self):
+ self.setRoles(('Manager',))
+ leftColumn = getUtility(IPortletManager, name=u'plone.leftcolumn', context=self.portal)
+ rightColumn = getUtility(IPortletManager, name=u'plone.rightcolumn', context=self.portal)
+
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ for k in left:
+ del left[k]
+ for k in right:
+ del right[k]
+
+ self.portal.left_slots = ['here/portlet_recent/macros/portlet',
+ 'here/portlet_news/macros/portlet']
+
+ self.portal.Members.right_slots = []
+
+ if hasattr(self.portal.aq_base, 'right_slots'):
+ delattr(self.portal, 'right_slots')
+
+ convertLegacyPortlets(self.portal)
+
+ self.assertEqual(self.portal.left_slots, [])
+
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ lp = left.values()
+ self.assertEqual(2, len(lp))
+
+ self.assertTrue(isinstance(lp[0], portlets.recent.Assignment))
+ self.assertTrue(isinstance(lp[1], portlets.news.Assignment))
+
+ rp = right.values()
+ self.assertEqual(0, len(rp))
+
+ members = self.portal.Members
+ portletAssignments = getMultiAdapter((members, rightColumn,), ILocalPortletAssignmentManager)
+ self.assertEqual(True, portletAssignments.getBlacklistStatus(CONTEXT_PORTLETS))
+
+ def testLegacyPortletsConvertedBadSlots(self):
+ self.setRoles(('Manager',))
+ leftColumn = getUtility(IPortletManager, name=u'plone.leftcolumn', context=self.portal)
+ rightColumn = getUtility(IPortletManager, name=u'plone.rightcolumn', context=self.portal)
+
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ for k in left:
+ del left[k]
+ for k in right:
+ del right[k]
+
+ self.portal.left_slots = ['here/portlet_recent/macros/portlet',
+ 'here/portlet_news/macros/portlet',
+ 'foobar',]
+ self.portal.right_slots = ['here/portlet_login/macros/portlet']
+
+ self.portal.Members.right_slots = []
+
+ convertLegacyPortlets(self.portal)
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ self.assertEqual(self.portal.left_slots, [])
+ self.assertEqual(self.portal.right_slots, [])
+
+ lp = left.values()
+ self.assertEqual(2, len(lp))
+
+ self.assertTrue(isinstance(lp[0], portlets.recent.Assignment))
+ self.assertTrue(isinstance(lp[1], portlets.news.Assignment))
+
+ rp = right.values()
+ self.assertEqual(1, len(rp))
+ self.assertTrue(isinstance(rp[0], portlets.login.Assignment))
+
+ members = self.portal.Members
+ portletAssignments = getMultiAdapter((members, rightColumn,), ILocalPortletAssignmentManager)
+ self.assertEqual(True, portletAssignments.getBlacklistStatus(CONTEXT_PORTLETS))
+
+ def testLegacyPortletsConvertedNoMembersFolder(self):
+ self.setRoles(('Manager',))
+ leftColumn = getUtility(IPortletManager, name=u'plone.leftcolumn', context=self.portal)
+ rightColumn = getUtility(IPortletManager, name=u'plone.rightcolumn', context=self.portal)
+
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ for k in left:
+ del left[k]
+ for k in right:
+ del right[k]
+
+ self.portal.left_slots = ['here/portlet_recent/macros/portlet',
+ 'here/portlet_news/macros/portlet',
+ 'foobar',]
+ self.portal.right_slots = ['here/portlet_login/macros/portlet']
+
+ self.portal._delObject('Members')
+
+ convertLegacyPortlets(self.portal)
+ left = getMultiAdapter((self.portal, leftColumn,), IPortletAssignmentMapping, context=self.portal)
+ right = getMultiAdapter((self.portal, rightColumn,), IPortletAssignmentMapping, context=self.portal)
+
+ self.assertEqual(self.portal.left_slots, [])
+ self.assertEqual(self.portal.right_slots, [])
+
+ lp = left.values()
+ self.assertEqual(2, len(lp))
+
+ self.assertTrue(isinstance(lp[0], portlets.recent.Assignment))
+ self.assertTrue(isinstance(lp[1], portlets.news.Assignment))
+
+ rp = right.values()
+ self.assertEqual(1, len(rp))
+ self.assertTrue(isinstance(rp[0], portlets.login.Assignment))
+
+ def testRegisterToolsAsUtilities(self):
+ sm = getSiteManager(self.portal)
+ interfaces = (ISiteRoot, IPloneSiteRoot,
+ IActionIconsTool, ISyndicationTool,
+ IMetadataTool, IPropertiesTool, IMailHost,
+ IUniqueIdAnnotationManagement, IUniqueIdGenerator,
+ IDiffTool, IMimetypesRegistryTool,
+ IPortalTransformsTool, IDiscussionTool, )
+ if HAS_ATCT:
+ interfaces += (IATCTTool,)
+ for i in interfaces:
+ sm.unregisterUtility(provided=i)
+ registerToolsAsUtilities(self.portal)
+ for i in interfaces:
+ self.assertFalse(sm.queryUtility(i) is None)
+
+ for i in interfaces:
+ sm.unregisterUtility(provided=i)
+ registerToolsAsUtilities(self.portal)
+ registerToolsAsUtilities(self.portal)
+ for i in interfaces:
+ self.assertFalse(sm.queryUtility(i) is None)
+
+ def testDontRegisterToolsAsUtilities(self):
+ sm = getSiteManager(self.portal)
+ interfaces = (ILanguageTool, IArchivistTool, IPortalModifierTool,
+ IPurgePolicyTool, IRepositoryTool, IStorageTool,
+ IFormControllerTool, IReferenceCatalog, IUIDCatalog,
+ ICalendarTool, IActionsTool, ICatalogTool,
+ IContentTypeRegistry, ISkinsTool, ITypesTool, IURLTool,
+ IConfigurableWorkflowTool, IPloneTool, ICSSRegistry,
+ IJSRegistry, IUniqueIdHandler, IFactoryTool,
+ IMembershipTool, IGroupTool, IGroupDataTool,
+ IMemberDataTool, IArchetypeTool, ICachingPolicyManager,
+ IRegistrationTool, ITranslationServiceTool,
+ ISetupTool, IQuickInstallerTool,
+ )
+ for i in interfaces:
+ sm.unregisterUtility(provided=i)
+ registerToolsAsUtilities(self.portal)
+ for i in interfaces:
+ self.assertTrue(sm.queryUtility(i) is None)
+
+ for i in interfaces:
+ sm.unregisterUtility(provided=i)
+ registerToolsAsUtilities(self.portal)
+ registerToolsAsUtilities(self.portal)
+ for i in interfaces:
+ self.assertTrue(sm.queryUtility(i) is None)
+
+ def testToolRegistration(self):
+ for (tool_id, interface) in registration:
+ self.assertEqual(getToolInterface(tool_id), interface)
+
+
+class TestMigrations_v3_0_alpha1(MigrationTest):
+
+ def afterSetUp(self):
+ self.profile = 'profile-plone.app.upgrade.v30:3.0a1-3.0a2'
+ self.actions = self.portal.portal_actions
+
+ def testInstallRedirectorUtility(self):
+ sm = getSiteManager(self.portal)
+ sm.unregisterUtility(provided=IRedirectionStorage)
+ # Test it twice
+ for i in range(2):
+ loadMigrationProfile(self.portal, self.profile, ('componentregistry', ))
+ self.assertFalse(sm.queryUtility(IRedirectionStorage) is None)
+
+ def testAddReaderEditorRoles(self):
+ self.portal._delRoles(['Reader', 'Editor'])
+ # Test it twice
+ for i in range(2):
+ addReaderAndEditorRoles(self.portal)
+ self.assertTrue('Reader' in self.portal.valid_roles())
+ self.assertTrue('Editor' in self.portal.valid_roles())
+ self.assertTrue('Reader' in self.portal.acl_users.portal_role_manager.listRoleIds())
+ self.assertTrue('Editor' in self.portal.acl_users.portal_role_manager.listRoleIds())
+ self.assertTrue('View' in [r['name'] for r in self.portal.permissionsOfRole('Reader') if r['selected']])
+ self.assertTrue('Modify portal content' in [r['name'] for r in self.portal.permissionsOfRole('Editor') if r['selected']])
+
+ def testAddReaderEditorRolesPermissionOnly(self):
+ self.portal.manage_permission('View', [], True)
+ self.portal.manage_permission('Modify portal content', [], True)
+ # Test it twice
+ for i in range(2):
+ addReaderAndEditorRoles(self.portal)
+ self.assertTrue('Reader' in self.portal.valid_roles())
+ self.assertTrue('Editor' in self.portal.valid_roles())
+ self.assertTrue('Reader' in self.portal.acl_users.portal_role_manager.listRoleIds())
+ self.assertTrue('Editor' in self.portal.acl_users.portal_role_manager.listRoleIds())
+ self.assertTrue('View' in [r['name'] for r in self.portal.permissionsOfRole('Reader') if r['selected']])
+ self.assertTrue('Modify portal content' in [r['name'] for r in self.portal.permissionsOfRole('Editor') if r['selected']])
+
+ def testMigrateLocalroleForm(self):
+ fti = self.portal.portal_types['Document']
+ aliases = fti.getMethodAliases()
+ aliases['sharing'] = 'folder_localrole_form'
+ fti.setMethodAliases(aliases)
+ fti.addAction('test', 'Test', 'string:${object_url}/folder_localrole_form', None, 'View', 'object')
+ # Test it twice
+ for i in range(2):
+ migrateLocalroleForm(self.portal)
+ self.assertEqual('@@sharing', fti.getMethodAliases()['sharing'])
+ test_action = fti.listActions()[-1]
+ self.assertEqual('string:${object_url}/@@sharing', test_action.getActionExpression())
+
+ def testReorderUserActions(self):
+ self.actions.user.moveObjectsToTop(['logout', 'undo', 'join'])
+ # Test it twice
+ for i in range(2):
+ reorderUserActions(self.portal)
+ # build a dict that has the position as the value to make it easier
+ # to compare postions in the ordered list of actions
+ n = 0
+ sort = {}
+ for action in self.actions.user.objectIds():
+ sort[action] = n
+ n += 1
+ self.assertTrue(sort['preferences'] < sort['undo'])
+ self.assertTrue(sort['undo'] < sort['logout'])
+ self.assertTrue(sort['login'] < sort['join'])
+
+ def testReorderUserActionsIncompleteActions(self):
+ self.actions.user.moveObjectsToTop(['logout', 'undo', 'join'])
+ self.actions.user._delObject('preferences')
+ # Test it twice
+ for i in range(2):
+ reorderUserActions(self.portal)
+ n = 0
+ sort = {}
+ for action in self.actions.user.objectIds():
+ sort[action] = n
+ n += 1
+ self.assertTrue(sort['undo'] < sort['logout'])
+ self.assertTrue(sort['login'] < sort['join'])
+
+
+class TestMigrations_v3_0_alpha2(MigrationTest):
+
+ def afterSetUp(self):
+ self.profile = 'profile-plone.app.upgrade.v30:3.0a2-3.0b1'
+ self.actions = self.portal.portal_actions
+ self.properties = self.portal.portal_properties
+ self.cp = self.portal.portal_controlpanel
+
+ def testAddVariousProperties(self):
+ PROPERTIES = ('enable_link_integrity_checks', 'enable_sitemap',
+ 'external_links_open_new_window', 'many_groups',
+ 'number_of_days_to_keep', 'webstats_js')
+ for prop in PROPERTIES:
+ self.removeSiteProperty(prop)
+ sheet = self.properties.site_properties
+ # Test it twice
+ for i in range(2):
+ loadMigrationProfile(self.portal, self.profile, ('propertiestool', ))
+ for prop in PROPERTIES:
+ self.assertTrue(sheet.hasProperty(prop))
+
+ def testInstallContentrulesAndLanguageUtilities(self):
+ sm = getSiteManager()
+ INTERFACES = (IRuleStorage, ICountries, IContentLanguages,
+ IMetadataLanguages)
+ for i in INTERFACES:
+ sm.unregisterUtility(provided=i)
+ # Test it twice
+ for i in range(2):
+ loadMigrationProfile(self.portal, self.profile, ('componentregistry', ))
+ for i in INTERFACES:
+ self.assertFalse(sm.queryUtility(i) is None)
+
+ def testAddEmailCharsetProperty(self):
+ if self.portal.hasProperty('email_charset'):
+ self.portal.manage_delProperties(['email_charset'])
+ # Test it twice
+ for i in range(2):
+ loadMigrationProfile(self.portal, self.profile, ('properties', ))
+ self.assertTrue(self.portal.hasProperty('email_charset'))
+ self.assertEqual(self.portal.getProperty('email_charset'), 'utf-8')
+
+ def testUpdateMemberSecurity(self):
+ pprop = getToolByName(self.portal, 'portal_properties')
+ self.assertEqual(
+ pprop.site_properties.getProperty('allowAnonymousViewAbout'),
+ False)
+
+ pmembership = getToolByName(self.portal, 'portal_membership')
+ self.assertEqual(pmembership.memberareaCreationFlag, False)
+ self.assertEqual(self.portal.getProperty('validate_email'), True)
+
+ app_roles = self.portal.rolesOfPermission(permission='Add portal member')
+ app_perms = self.portal.permission_settings(permission='Add portal member')
+ acquire_check = app_perms[0]['acquire']
+ reg_roles = []
+ for appperm in app_roles:
+ if appperm['selected'] == 'SELECTED':
+ reg_roles.append(appperm['name'])
+ self.assertTrue('Manager' in reg_roles)
+ self.assertTrue('Owner' in reg_roles)
+ self.assertEqual(acquire_check, '')
+
+ def testPASPluginInterfaces(self):
+ pas = self.portal.acl_users
+ from Products.PluggableAuthService.interfaces.plugins import IUserEnumerationPlugin
+ pas.plugins.deactivatePlugin(IUserEnumerationPlugin, 'mutable_properties')
+ updatePASPlugins(self.portal)
+
+ plugin = pas.mutable_properties
+ for intf_id in plugin.listInterfaces():
+ try:
+ intf = pas.plugins._getInterfaceFromName(intf_id)
+ self.assertTrue('mutable_properties' in pas.plugins.listPluginIds(intf))
+ except KeyError:
+ # Ignore unregistered interface types
+ pass
+
+ def testUpdateConfigletTitles(self):
+ collection = self.cp.getActionObject('Plone/portal_atct')
+ language = self.cp.getActionObject('Plone/PloneLanguageTool')
+ navigation = self.cp.getActionObject('Plone/NavigationSettings')
+ types = self.cp.getActionObject('Plone/TypesSettings')
+ users = self.cp.getActionObject('Plone/UsersGroups')
+ users2 = self.cp.getActionObject('Plone/UsersGroups2')
+ # test it twice
+ for i in range(2):
+ updateConfigletTitles(self.portal)
+ self.assertEqual(collection.title, 'Collection')
+ self.assertEqual(language.title, 'Language')
+ self.assertEqual(navigation.title, 'Navigation')
+ self.assertEqual(types.title, 'Types')
+ self.assertEqual(users.title, 'Users and Groups')
+ self.assertEqual(users2.title, 'Users and Groups')
+
+ def testAddCacheForResourceRegistry(self):
+ ram_cache_id = 'ResourceRegistryCache'
+ # first remove the cache manager and make sure it's removed
+ self.portal._delObject(ram_cache_id)
+ self.assertFalse(ram_cache_id in self.portal.objectIds())
+ cssreg = self.portal.portal_css
+ cssreg.ZCacheable_setEnabled(0)
+ cssreg.ZCacheable_setManagerId(None)
+ self.assertFalse(cssreg.ZCacheable_enabled())
+ self.assertTrue(cssreg.ZCacheable_getManagerId() is None)
+ jsreg = self.portal.portal_javascripts
+ jsreg.ZCacheable_setEnabled(0)
+ jsreg.ZCacheable_setManagerId(None)
+ self.assertFalse(jsreg.ZCacheable_enabled())
+ self.assertTrue(jsreg.ZCacheable_getManagerId() is None)
+ # Test it twice
+ for i in range(2):
+ addCacheForResourceRegistry(self.portal)
+ self.assertTrue(ram_cache_id in self.portal.objectIds())
+ self.assertTrue(cssreg.ZCacheable_enabled())
+ self.assertFalse(cssreg.ZCacheable_getManagerId() is None)
+ self.assertTrue(jsreg.ZCacheable_enabled())
+ self.assertFalse(jsreg.ZCacheable_getManagerId() is None)
+
+ def testObjectProvidesIndex(self):
+ catalog = getToolByName(self.portal, 'portal_catalog')
+ if 'object_provides' in catalog.indexes():
+ catalog.delIndex('object_provides')
+ self.assertFalse('object_provides' in catalog.indexes())
+ # Test it twice
+ for i in range(2):
+ addObjectProvidesIndex(self.portal)
+ self.assertTrue('object_provides' in catalog.indexes())
+
+ def testMigratePloneTool(self):
+ tool = self.portal.plone_utils
+ tool.meta_type = 'PlonePAS Utilities Tool'
+ # Test it twice
+ for i in range(2):
+ restorePloneTool(self.portal)
+ tool = self.portal.plone_utils
+ self.assertEqual('Plone Utility Tool', tool.meta_type)
+
+ def testInstallPloneLanguageTool(self):
+ super(self.portal.__class__, self.portal).manage_delObjects(
+ ['portal_languages'])
+ self.uninstallProduct('PloneLanguageTool')
+ qi = getToolByName(self.portal, "portal_quickinstaller")
+ # Test it twice
+ for i in range(2):
+ installProduct('PloneLanguageTool', self.portal)
+ self.assertTrue(qi.isProductInstalled('PloneLanguageTool'))
+ self.assertTrue('portal_languages' in self.portal.keys())
+
+
+class TestMigrations_v3_0(MigrationTest):
+
+ def afterSetUp(self):
+ self.profile = 'profile-plone.app.upgrade.v30:3.0b1-3.0b2'
+ self.actions = self.portal.portal_actions
+ self.skins = self.portal.portal_skins
+ self.types = self.portal.portal_types
+ self.workflow = self.portal.portal_workflow
+ self.properties = getToolByName(self.portal, 'portal_properties')
+
+ def testAddContentRulesAction(self):
+ self.portal.portal_actions.object._delObject('contentrules')
+ # Test it twice
+ for i in range(2):
+ loadMigrationProfile(self.portal, self.profile, ('actions', ))
+ self.assertTrue('contentrules' in self.portal.portal_actions.object.objectIds())
+
+ def testChangeOrderOfActionProviders(self):
+ self.actions.deleteActionProvider('portal_types')
+ self.actions.addActionProvider('portal_types')
+ self.assertEqual(
+ self.actions.listActionProviders(),
+ ('portal_workflow', 'portal_actions', 'portal_types'))
+ # Test it twice
+ for i in range(2):
+ changeOrderOfActionProviders(self.portal)
+ self.assertEqual(
+ self.actions.listActionProviders(),
+ ('portal_workflow', 'portal_types', 'portal_actions'))
+
+ def testCleanupOldActions(self):
+ reply = Action('reply', title='Reply')
+ logged_in = Action('logged_in', title='Logged in')
+ change_ownership = Action('change_ownership', title='Change ownership')
+
+ object_ = self.actions.object
+ object_tabs = getattr(self.actions, 'object_tabs', None)
+ if object_tabs is None:
+ category = 'object_tabs'
+ self.actions._setObject(category, ActionCategory(id=category))
+ object_tabs = self.actions.object_tabs
+ if getattr(self.actions, 'global', None) is None:
+ category = 'global'
+ self.actions._setObject(category, ActionCategory(id=category))
+
+ if not 'reply' in object_.keys():
+ object_._setObject('reply', reply)
+ user = self.actions.user
+ if not 'logged_in' in user.keys():
+ user._setObject('logged_in', logged_in)
+ if not 'change_ownership' in object_tabs.keys():
+ object_tabs._setObject('change_ownership', change_ownership)
+ del object_tabs
+
+ # Test it twice
+ for i in range(2):
+ cleanupOldActions(self.portal)
+ self.assertFalse('reply' in object_.keys())
+ self.assertFalse('logged_in' in user.keys())
+ self.assertFalse('object_tabs' in self.actions.keys())
+ self.assertFalse('global' in self.actions.keys())
+
+ def testCharsetCleanup(self):
+ if not self.portal.hasProperty('default_charset'):
+ self.portal.manage_addProperty('default_charset', '', 'string')
+ # Test it twice
+ for i in range(2):
+ self.portal.manage_changeProperties(default_charset = 'latin1')
+ cleanDefaultCharset(self.portal)
+ self.assertEqual(self.portal.getProperty('default_charset', 'nothere'),
+ 'latin1')
+ # Test it twice
+ for i in range(2):
+ self.portal.manage_changeProperties(default_charset = '')
+ cleanDefaultCharset(self.portal)
+ self.assertEqual(self.portal.getProperty('default_charset', 'nothere'),
+ 'nothere')
+
+ def testAutoGroupCreated(self):
+ pas = self.portal.acl_users
+ ids = pas.objectIds(['Automatic Group Plugin'])
+ if ids:
+ pas.manage_delObjects(ids)
+ addAutoGroupToPAS(self.portal)
+ self.assertEqual(pas.objectIds(['Automatic Group Plugin']),
+ ['auto_group'])
+ plugin = pas.auto_group
+ interfaces = [info['interface'] for info in pas.plugins.listPluginTypeInfo()]
+ for iface in interfaces:
+ if plugin.testImplements(iface):
+ self.assertFalse('auto_group' not in pas.plugins.listPluginIds(iface))
+ self.assertEqual(len(pas.searchGroups(id='AuthenticatedUsers',
+ exact_match=True)), 1)
+
+ def testPloneS5(self):
+ pt = getToolByName(self.portal, "portal_types")
+ document = pt.restrictedTraverse('Document')
+ document.addAction('s5_presentation',
+ name='View as presentation',
+ action="string:${object/absolute_url}/document_s5_presentation",
+ condition='python:object.document_s5_alter(test=True)',
+ permission='View',
+ category='document_actions',
+ visible=1,
+ )
+ action_ids = [x.getId() for x in document.listActions()]
+ self.assertTrue("s5_presentation" in action_ids)
+ # Test it twice
+ for i in range(2):
+ removeS5Actions(self.portal)
+ action_ids = [x.getId() for x in document.listActions()]
+ self.assertFalse("s5_presentation" in action_ids)
+
+ def testAddContributorToCreationPermissions(self):
+ self.portal._delRoles(['Contributor',])
+ for p in ['Add portal content', 'Add portal folders', 'ATContentTypes: Add Document',
+ 'ATContentTypes: Add Event',
+ 'ATContentTypes: Add File', 'ATContentTypes: Add Folder',
+ 'ATContentTypes: Add Image', 'ATContentTypes: Add Link',
+ 'ATContentTypes: Add News Item', ]:
+ self.portal.manage_permission(p, ['Manager', 'Owner'], True)
+ # Test it twice
+ for i in range(2):
+ addContributorToCreationPermissions(self.portal)
+ self.assertTrue('Contributor' in self.portal.valid_roles())
+ self.assertTrue('Contributor' in self.portal.acl_users.portal_role_manager.listRoleIds())
+ for p in ['Add portal content', 'Add portal folders', 'ATContentTypes: Add Document',
+ 'ATContentTypes: Add Event',
+ 'ATContentTypes: Add File', 'ATContentTypes: Add Folder',
+ 'ATContentTypes: Add Image', 'ATContentTypes: Add Link',
+ 'ATContentTypes: Add News Item', ]:
+ self.assertTrue(p in [r['name'] for r in
+ self.portal.permissionsOfRole('Contributor') if r['selected']])
+
+ def testAddContributerToCreationPermissionsNoStomp(self):
+ self.portal.manage_permission('Add portal content', ['Manager'], False)
+ # Test it twice
+ for i in range(2):
+ addContributorToCreationPermissions(self.portal)
+ roles = sorted([r['name'] for r in self.portal.rolesOfPermission('Add portal content') if r['selected']])
+ self.assertEqual(['Contributor', 'Manager'], roles)
+ self.assertEqual(False, bool(self.portal.acquiredRolesAreUsedBy('Add portal content')))
+
+ def testAddBeta2VersioningPermissionsToNewRoles(self):
+ # This upgrade just uses GS to apply the role changes,
+ # these permissions will not have been installed previously,
+ # so this should be safe
+ for p in ['CMFEditions: Apply version control',
+ 'CMFEditions: Save new version',
+ 'CMFEditions: Access previous versions',
+ 'CMFEditions: Revert to previous versions',
+ 'CMFEditions: Checkout to location']:
+ self.portal.manage_permission(p, ['Manager', 'Owner'], True)
+ # Test it twice
+ for i in range(2):
+ loadMigrationProfile(self.portal,
+ 'profile-plone.app.upgrade.v30:3.0b1-3.0b2',
+ steps=["rolemap"])
+ for p in ['CMFEditions: Apply version control',
+ 'CMFEditions: Save new version',
+ 'CMFEditions: Access previous versions']:
+ self.assertTrue(p in [r['name'] for r in
+ self.portal.permissionsOfRole('Contributor') if r['selected']])
+ self.assertTrue(p in [r['name'] for r in
+ self.portal.permissionsOfRole('Editor') if r['selected']])
+ for p in ['CMFEditions: Revert to previous versions',
+ 'CMFEditions: Checkout to location']:
+ self.assertTrue(p in [r['name'] for r in
+ self.portal.permissionsOfRole('Editor') if r['selected']])
+
+ def testRemoveSharingAction(self):
+ fti = self.types['Document']
+ fti.addAction(id='local_roles', name='Sharing',
+ action='string:${object_url}/sharing',
+ condition=None, permission='Manage properties',
+ category='object')
+ # Test it twice
+ for i in range(2):
+ removeSharingAction(self.portal)
+ self.assertFalse('local_roles' in [a.id for a in fti.listActions()])
+
+ def testAddEditorToCreationPermissions(self):
+ for p in ['Manage properties', 'Modify view template', 'Request review']:
+ self.portal.manage_permission(p, ['Manager', 'Owner'], True)
+ # Test it twice
+ for i in range(2):
+ addEditorToSecondaryEditorPermissions(self.portal)
+ for p in ['Manage properties', 'Modify view template', 'Request review']:
+ self.assertTrue(p in [r['name'] for r in
+ self.portal.permissionsOfRole('Editor') if r['selected']])
+
+ def testAddEditorToCreationPermissionsNoStomp(self):
+ self.portal.manage_permission('Manage properties', ['Manager'], False)
+ # Test it twice
+ for i in range(2):
+ addEditorToSecondaryEditorPermissions(self.portal)
+ roles = sorted([r['name'] for r in self.portal.rolesOfPermission('Manage properties') if r['selected']])
+ self.assertEqual(['Editor', 'Manager'], roles)
+ self.assertEqual(False, bool(self.portal.acquiredRolesAreUsedBy('Manage properties')))
+
+ def testUpdateEditActionConditionForLocking(self):
+ lockable_types = ['Document', 'Event', 'File', 'Folder',
+ 'Image', 'Link', 'News Item', 'Topic']
+ for contentType in lockable_types:
+ fti = self.types.getTypeInfo(contentType)
+ for action in fti.listActions():
+ if action.getId() == 'edit':
+ action.condition = ''
+ # Test it twice
+ for i in range(2):
+ updateEditActionConditionForLocking(self.portal)
+ for contentType in lockable_types:
+ fti = self.types.getTypeInfo(contentType)
+ for action in fti.listActions():
+ if action.getId() == 'edit':
+ self.assertEqual(action.condition.text,
+ "not:object/@@plone_lock_info/is_locked_for_current_user|python:True")
+
+ def testUpdateEditExistingActionConditionForLocking(self):
+ fti = self.types.getTypeInfo('Document')
+ for action in fti.listActions():
+ if action.getId() == 'edit':
+ action.condition = Expression("foo")
+ # Test it twice
+ for i in range(2):
+ updateEditActionConditionForLocking(self.portal)
+ fti = self.types.getTypeInfo('Document')
+ for action in fti.listActions():
+ if action.getId() == 'edit':
+ self.assertEqual(action.condition.text, 'foo')
+
+ def testAddOnFormUnloadRegistrationJS(self):
+ jsreg = self.portal.portal_javascripts
+ # unregister first
+ jsreg.unregisterResource('unlockOnFormUnload.js')
+ script_ids = jsreg.getResourceIds()
+ self.assertFalse('unlockOnFormUnload.js' in script_ids)
+ # Test it twice
+ for i in range(2):
+ addOnFormUnloadJS(self.portal)
+ script_ids = jsreg.getResourceIds()
+ self.assertTrue('unlockOnFormUnload.js' in script_ids)
+
+ def testUpdateTopicTitle(self):
+ topic = self.types.get('Topic')
+ topic.title = 'Old'
+ # Test it twice
+ for i in range(2):
+ updateTopicTitle(self.portal)
+ self.assertEqual(topic.title, 'Collection')
+
+ def testAddIntelligentText(self):
+ # Before the upgrade, the mime type and transforms of intelligent text
+ # are not available. They *are* here in a fresh site, so we may need
+ # to remove them first for testing. First we remove the transforms,
+ # as they depend on the mimetype being there.
+ missing_transforms = ["web_intelligent_plain_text_to_html",
+ "html_to_web_intelligent_plain_text"]
+ ptr = self.portal.portal_transforms
+ current_transforms = ptr.objectIds()
+ for trans in missing_transforms:
+ if trans in current_transforms:
+ ptr.unregisterTransform(trans)
+ # Then we remove the mime type
+ mime_type = 'text/x-web-intelligent'
+ mtr = self.portal.mimetypes_registry
+ current_types = mtr.list_mimetypes()
+ if mime_type in current_types:
+ mtr.manage_delObjects((mime_type,))
+ # now all are gone:
+ self.assertFalse(mime_type in mtr.list_mimetypes())
+ self.assertFalse(set(ptr.objectIds()).issuperset(set(missing_transforms)))
+ # Test it twice
+ for i in range(2):
+ addIntelligentText(self.portal)
+ # now all are back:
+ self.assertTrue(mime_type in mtr.list_mimetypes())
+ self.assertTrue(set(ptr.objectIds()).issuperset(set(missing_transforms)))
+
+ def testInstallNewModifiers(self):
+ # ensure the new modifiers are installed
+ modifiers = self.portal.portal_modifier
+ self.assertTrue('AbortVersioningOfLargeFilesAndImages' in
+ modifiers.objectIds())
+ modifiers.manage_delObjects(['AbortVersioningOfLargeFilesAndImages',
+ 'SkipVersioningOfLargeFilesAndImages'])
+ self.assertFalse('AbortVersioningOfLargeFilesAndImages' in
+ modifiers.objectIds())
+ installNewModifiers(self.portal)
+ self.assertTrue('AbortVersioningOfLargeFilesAndImages' in
+ modifiers.objectIds())
+ self.assertTrue('SkipVersioningOfLargeFilesAndImages' in
+ modifiers.objectIds())
+
+ def testInstallNewModifiersTwice(self):
+ # ensure that we get no errors when run twice
+ installNewModifiers(self.portal)
+ installNewModifiers(self.portal)
+
+ def testInstallNewModifiersDoesNotStompChanges(self):
+ # ensure that reinstalling doesn't kill customizations
+ modifiers = self.portal.portal_modifier
+ modifiers.AbortVersioningOfLargeFilesAndImages.max_size = 1000
+ installNewModifiers(self.portal)
+ self.assertEqual(modifiers.AbortVersioningOfLargeFilesAndImages.max_size,
+ 1000)
+
+ def testInstallNewModifiersNoTool(self):
+ # make sure there are no errors if the tool is missing
+ self.portal._delObject('portal_modifier')
+ installNewModifiers(self.portal)
+
+
+class TestFunctionalMigrations(FunctionalUpgradeTestCase):
+
+ def testBaseUpgrade(self):
+ self.importFile(__file__, 'test-base.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+ def testFullUpgrade(self):
+ self.importFile(__file__, 'test-full.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+
+def test_suite():
+ from unittest import TestSuite, makeSuite
+ suite = TestSuite()
+ suite.addTest(makeSuite(TestMigrations_v2_5_x))
+ suite.addTest(makeSuite(TestMigrations_v3_0_Actions))
+ suite.addTest(makeSuite(TestMigrations_v3_0_alpha1))
+ suite.addTest(makeSuite(TestMigrations_v3_0_alpha2))
+ suite.addTest(makeSuite(TestMigrations_v3_0))
+ suite.addTest(makeSuite(TestFunctionalMigrations))
+ return suite
diff --git a/plone/app/upgrade/v31/tests.py b/plone/app/upgrade/v31/tests.py
new file mode 100644
index 0000000..01005b3
--- /dev/null
+++ b/plone/app/upgrade/v31/tests.py
@@ -0,0 +1,118 @@
+from borg.localrole.utils import replace_local_role_manager
+from zope.interface import noLongerProvides
+
+from Products.PlonePAS.interfaces.plugins import ILocalRolesPlugin
+
+from plone.app.upgrade.tests.base import FunctionalUpgradeTestCase
+from plone.app.upgrade.tests.base import MigrationTest
+
+from plone.app.upgrade.v31.betas import reinstallCMFPlacefulWorkflow
+
+
+class TestMigrations_v3_1(MigrationTest):
+
+ def afterSetUp(self):
+ self.qi = self.portal.portal_quickinstaller
+ self.wf = self.portal.portal_workflow
+ self.ps = self.portal.portal_setup
+
+ def testReinstallCMFPlacefulWorkflow(self):
+ try:
+ from Products.CMFPlacefulWorkflow.interfaces import IPlacefulMarker
+ except ImportError:
+ return
+ # first the product needs to be installed
+ self.qi.installProduct('CMFPlacefulWorkflow')
+ # Delete existing logs to prevent race condition
+ self.ps.manage_delObjects(self.ps.objectIds())
+ # We remove the new marker, to ensure it's added on reinstall
+ if IPlacefulMarker.providedBy(self.wf):
+ noLongerProvides(self.wf, IPlacefulMarker)
+ reinstallCMFPlacefulWorkflow(self.portal, [])
+ self.assertTrue(IPlacefulMarker.providedBy(self.wf))
+
+ def testReinstallCMFPlacefulWorkflowDoesNotInstall(self):
+ reinstallCMFPlacefulWorkflow(self.portal, [])
+ self.assertFalse(self.qi.isProductInstalled('CMFPlacefulWorkflow'))
+
+ def testReinstallCMFPlacefulWorkflowNoTool(self):
+ self.portal._delObject('portal_quickinstaller')
+ reinstallCMFPlacefulWorkflow(self.portal, [])
+
+ def testReplaceLocalRoleManager(self):
+ # first we replace the local role manager with the one from PlonePAS
+ uf = self.portal.acl_users
+ # deactivate and remove the borg plugin
+ uf.plugins.removePluginById('borg_localroles')
+ uf.manage_delObjects(['borg_localroles'])
+ # activate the standard plugin
+ uf.plugins.activatePlugin(ILocalRolesPlugin, 'local_roles')
+ # Bring things back to normal
+ replace_local_role_manager(self.portal)
+ plugins = uf.plugins.listPlugins(ILocalRolesPlugin)
+ self.assertEqual(len(plugins), 1)
+ self.assertEqual(plugins[0][0], 'borg_localroles')
+
+ def testReplaceLocalRoleManagerTwice(self):
+ # first we replace the local role manager with the one from PlonePAS
+ uf = self.portal.acl_users
+ # deactivate and remove the borg plugin
+ uf.plugins.removePluginById('borg_localroles')
+ uf.manage_delObjects(['borg_localroles'])
+ # activate the standard plugin
+ uf.plugins.activatePlugin(ILocalRolesPlugin, 'local_roles')
+ # run the upgrade twice
+ replace_local_role_manager(self.portal)
+ replace_local_role_manager(self.portal)
+ plugins = uf.plugins.listPlugins(ILocalRolesPlugin)
+ self.assertEqual(len(plugins), 1)
+ self.assertEqual(plugins[0][0], 'borg_localroles')
+
+ def testReplaceLocalRoleManagerNoPlugin(self):
+ # first we replace the local role manager with the one from PlonePAS
+ uf = self.portal.acl_users
+ # deactivate and remove the borg plugin
+ uf.plugins.removePluginById('borg_localroles')
+ uf.manage_delObjects(['borg_localroles'])
+ # delete the standard plugin
+ uf.manage_delObjects(['local_roles'])
+ # Run the upgrade, which shouldn't fail even if the expected
+ # plugin is missing
+ replace_local_role_manager(self.portal)
+ plugins = uf.plugins.listPlugins(ILocalRolesPlugin)
+ self.assertEqual(len(plugins), 1)
+ self.assertEqual(plugins[0][0], 'borg_localroles')
+
+ def testReplaceLocalRoleManagerNoPAS(self):
+ uf = self.portal.acl_users
+ # delete the plugin registry
+ uf._delObject('plugins')
+ replace_local_role_manager(self.portal)
+
+ def testReplaceLocalRoleManagerNoUF(self):
+ # Delete the user folder
+ replace_local_role_manager(self.portal)
+
+class TestFunctionalMigrations(FunctionalUpgradeTestCase):
+
+ def testBaseUpgrade(self):
+ self.importFile(__file__, 'test-base.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+ def testFullUpgrade(self):
+ self.importFile(__file__, 'test-full.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+
+def test_suite():
+ from unittest import TestSuite, makeSuite
+ suite = TestSuite()
+ suite.addTest(makeSuite(TestMigrations_v3_1))
+ suite.addTest(makeSuite(TestFunctionalMigrations))
+ return suite
diff --git a/plone/app/upgrade/v32/tests.py b/plone/app/upgrade/v32/tests.py
new file mode 100644
index 0000000..bc0e7a1
--- /dev/null
+++ b/plone/app/upgrade/v32/tests.py
@@ -0,0 +1,50 @@
+from plone.app.upgrade.tests.base import FunctionalUpgradeTestCase
+from plone.app.upgrade.tests.base import MigrationTest
+from plone.app.upgrade.v32.betas import three1_beta1
+
+class TestMigrations_v3_2(MigrationTest):
+
+ def afterSetUp(self):
+ self.qi = self.portal.portal_quickinstaller
+ self.actions = self.portal.portal_actions
+ self.migration = self.portal.portal_migration
+
+ def testIterateActionsMigratedIfIterateInstalled(self):
+ self.qi.installProduct('plone.app.iterate')
+ self.actions.object_buttons.iterate_checkin.permissions = (
+ 'Modify portal content',)
+ three1_beta1(self.portal)
+ self.assertEqual(
+ self.actions.object_buttons.iterate_checkin.permissions,
+ ('iterate : Check in content',))
+
+ def testIterateInstalledButActionMissing(self):
+ self.qi.installProduct('plone.app.iterate')
+ self.actions.object_buttons.manage_delObjects(['iterate_checkin'])
+ three1_beta1(self.portal)
+ self.assertFalse('iterate_checkin' in
+ self.actions.object_buttons.objectIds())
+
+class TestFunctionalMigrations(FunctionalUpgradeTestCase):
+
+ def testBaseUpgrade(self):
+ self.importFile(__file__, 'test-base.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+ def testFullUpgrade(self):
+ self.importFile(__file__, 'test-full.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+
+def test_suite():
+ from unittest import TestSuite, makeSuite
+ suite = TestSuite()
+ suite.addTest(makeSuite(TestMigrations_v3_2))
+ suite.addTest(makeSuite(TestFunctionalMigrations))
+ return suite
diff --git a/plone/app/upgrade/v33/tests.py b/plone/app/upgrade/v33/tests.py
new file mode 100644
index 0000000..01a5de8
--- /dev/null
+++ b/plone/app/upgrade/v33/tests.py
@@ -0,0 +1,93 @@
+from Products.CMFCore.utils import getToolByName
+
+from plone.app.upgrade.tests.base import FunctionalUpgradeTestCase
+from plone.app.upgrade.tests.base import MigrationTest
+from plone.app.upgrade.v33 import three2_three3
+
+class TestMigrations_v3_3(MigrationTest):
+
+ def afterSetUp(self):
+ self.types = self.portal.portal_types
+ self.properties = getToolByName(self.portal, 'portal_properties')
+
+ def _upgrade(self):
+ three2_three3(self.portal)
+
+ def testRedirectLinksProperty(self):
+ del self.properties.site_properties.redirect_links
+ self._upgrade()
+ self.assertEqual(True,
+ self.properties.site_properties.getProperty('redirect_links'))
+
+ def testLinkDefaultView(self):
+ self.types.Link.default_view = 'link_view'
+ self.types.Link.immediate_view = 'link_view'
+ self.types.Link.view_methods = ('link_view',)
+ self._upgrade()
+ self.assertEqual(self.types.Link.default_view, 'link_redirect_view')
+ self.assertEqual(self.types.Link.immediate_view, 'link_redirect_view')
+ self.assertEqual(self.types.Link.view_methods, ('link_redirect_view',))
+
+ def testCustomizedLinkDefaultView(self):
+ # but only change if old default was 'link_view'
+ self.types.Link.default_view = 'foobar'
+ self.types.Link.immediate_view = 'foobar'
+ self.types.Link.view_methods = ('foobar',)
+ self._upgrade()
+ self.assertEqual(self.types.Link.default_view, 'foobar')
+ self.assertEqual(self.types.Link.immediate_view, 'foobar')
+ self.assertEqual(self.types.Link.view_methods, ('foobar',))
+
+class TestFunctionalMigrations(FunctionalUpgradeTestCase):
+
+ def testBaseUpgrade(self):
+ self.importFile(__file__, 'test-base.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+ def testFullUpgrade(self):
+ self.importFile(__file__, 'test-full.zexp')
+ oldsite, result = self.migrate()
+
+ mig = oldsite.portal_migration
+ self.assertFalse(mig.needUpgrading())
+
+ def testFolderUpgrade(self):
+ from plone.folder.interfaces import IOrderableFolder
+ self.importFile(__file__, 'test-full.zexp')
+ # `portal_type` and `Type` can be checked before migration...
+ oldsite = getattr(self.app, self.site_id)
+ ids = 'news', 'events', 'Members'
+ for id in ids:
+ obj = oldsite[id]
+ self.assertEqual(obj.portal_type, 'Large Plone Folder')
+ self.assertEqual(obj.Type(), 'Large Folder')
+ brain, = oldsite.portal_catalog(getId=id) # asserts only one
+ self.assertEqual(brain.portal_type, 'Large Plone Folder')
+ self.assertEqual(brain.Type, 'Large Folder')
+ # now let's migrate...
+ oldsite, result = self.migrate()
+ self.assertFalse(oldsite.portal_migration.needUpgrading())
+ # after migration `/news`, `/events` and `/Members` are based on
+ # `plone.(app.)folder`, but still have no ordering set...
+ for id in ids:
+ obj = oldsite[id]
+ self.assertTrue(IOrderableFolder.providedBy(obj),
+ '%s not orderable?' % id)
+ self.assertEqual(obj._ordering, 'unordered',
+ '%s has no `_ordering`?' % id)
+ self.assertEqual(obj.portal_type, 'Folder')
+ self.assertEqual(obj.Type(), 'Folder')
+ brain, = oldsite.portal_catalog(getId=id) # asserts only one
+ self.assertEqual(brain.portal_type, 'Folder')
+ self.assertEqual(brain.Type, 'Folder')
+
+
+def test_suite():
+ from unittest import TestSuite, makeSuite
+ suite = TestSuite()
+ suite.addTest(makeSuite(TestMigrations_v3_3))
+ suite.addTest(makeSuite(TestFunctionalMigrations))
+ return suite
diff --git a/plone/app/upgrade/v40/tests.py b/plone/app/upgrade/v40/tests.py
new file mode 100644
index 0000000..c350619
--- /dev/null
+++ b/plone/app/upgrade/v40/tests.py
@@ -0,0 +1,666 @@
+import time
+
+from zope.component import getMultiAdapter
+from zope.component import getSiteManager
+from zope.component import getUtility
+from zope.component import queryUtility
+from zope.ramcache.interfaces.ram import IRAMCache
+
+from Products.CMFCore.ActionInformation import Action
+from Products.CMFCore.Expression import Expression
+from Products.CMFCore.utils import getToolByName
+from Products.MailHost.interfaces import IMailHost
+
+from plone.app.upgrade.utils import loadMigrationProfile
+from plone.app.upgrade.v40.alphas import _KNOWN_ACTION_ICONS
+from plone.app.upgrade.v40.alphas import migrateActionIcons
+from plone.app.upgrade.v40.alphas import migrateTypeIcons
+from plone.app.upgrade.v40.alphas import addOrReplaceRamCache
+from plone.app.upgrade.v40.alphas import changeWorkflowActorVariableExpression
+from plone.app.upgrade.v40.alphas import changeAuthenticatedResourcesCondition
+from plone.app.upgrade.v40.alphas import setupReferencebrowser
+from plone.app.upgrade.v40.alphas import migrateMailHost
+from plone.app.upgrade.v40.alphas import migrateFolders
+from plone.app.upgrade.v40.alphas import renameJoinFormFields
+from plone.app.upgrade.v40.alphas import updateLargeFolderType
+from plone.app.upgrade.v40.alphas import addRecursiveGroupsPlugin
+from plone.app.upgrade.v40.alphas import cleanUpClassicThemeResources
+from plone.app.upgrade.v40.alphas import migrateStaticTextPortlets
+from plone.app.upgrade.v40.betas import repositionRecursiveGroupsPlugin
+from plone.app.upgrade.v40.betas import updateIconMetadata
+from plone.app.upgrade.v40.betas import removeLargePloneFolder
+from plone.app.upgrade.tests.base import MigrationTest
+
+from plone.portlet.static import static
+from plone.portlets.interfaces import IPortletAssignmentMapping
+from plone.portlets.interfaces import IPortletAssignmentSettings
+from plone.portlets.interfaces import IPortletManager
+
+
+class FakeSecureMailHost(object):
+
+ meta_type = 'Secure Mail Host'
+ id = 'MailHost'
+ title = 'Fake MailHost'
+ smtp_host = 'smtp.example.com'
+ smtp_port = 587
+ smtp_userid='me'
+ smtp_pass='secret'
+ smtp_notls=False
+
+ def manage_fixupOwnershipAfterAdd(self):
+ pass
+
+
+class TestMigrations_v4_0alpha1(MigrationTest):
+
+ profile = "profile-plone.app.upgrade.v40:3-4alpha1"
+
+ def afterSetUp(self):
+ self.atool = getToolByName(self.portal, 'portal_actions')
+ self.cptool = getToolByName(self.portal, 'portal_controlpanel')
+ self.wftool = getToolByName(self.portal, 'portal_workflow')
+ self.csstool = getToolByName(self.portal, 'portal_css')
+ self.jstool = getToolByName(self.portal, 'portal_javascripts')
+
+ if 'portal_actionicons' not in self.portal:
+ from plone.app.upgrade.bbb import ActionIconsTool
+ self.portal._setObject('portal_actionicons', ActionIconsTool())
+ self.aitool = self.portal.portal_actionicons
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ self.setRoles(['Manager'])
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+ def testMigrateActionIcons(self):
+ _KNOWN_ACTION_ICONS['object_buttons'].extend(['test_id', 'test2_id'])
+ self.aitool.addActionIcon(
+ category='object_buttons',
+ action_id='test_id',
+ icon_expr='test.gif',
+ title='Test my icon',
+ )
+ self.aitool.addActionIcon(
+ category='object_buttons',
+ action_id='test2_id',
+ icon_expr='python:context.getIcon()',
+ title='Test my second icon',
+ )
+ test_action = Action('test_id',
+ title='Test me',
+ description='',
+ url_expr='',
+ icon_expr='',
+ available_expr='',
+ permissions=('View', ),
+ visible = True)
+ test2_action = Action('test2_id',
+ title='Test me too',
+ description='',
+ url_expr='',
+ icon_expr='',
+ available_expr='',
+ permissions=('View', ),
+ visible = True)
+
+ object_buttons = self.atool.object_buttons
+ if getattr(object_buttons, 'test_id', None) is None:
+ object_buttons._setObject('test_id', test_action)
+ if getattr(object_buttons, 'test2_id', None) is None:
+ object_buttons._setObject('test2_id', test2_action)
+
+ self.assertEqual(object_buttons.test_id.icon_expr, '')
+ self.assertEqual(object_buttons.test2_id.icon_expr, '')
+ # Test it twice
+ for i in range(2):
+ migrateActionIcons(self.portal)
+ icons = [ic._action_id for ic in self.aitool.listActionIcons()]
+ self.assertFalse('test_id' in icons)
+ self.assertFalse('test2_id' in icons)
+ self.assertEqual(object_buttons.test_id.icon_expr,
+ 'string:$portal_url/test.gif')
+ self.assertEqual(object_buttons.test2_id.icon_expr,
+ 'python:context.getIcon()')
+
+ def testMigrateControlPanelActionIcons(self):
+ _KNOWN_ACTION_ICONS['controlpanel'].extend(['test_id'])
+ self.aitool.addActionIcon(
+ category='controlpanel',
+ action_id='test_id',
+ icon_expr='test.gif',
+ title='Test my icon',
+ )
+
+ self.cptool.registerConfiglet(
+ id='test_id',
+ name='Test Configlet',
+ action='string:${portal_url}/test',
+ permission='Manage portal',
+ category='Plone',
+ visible=True,
+ appId='',
+ icon_expr='',
+ )
+
+ action = self.cptool.getActionObject('Plone/test_id')
+ self.assertEqual(action.getIconExpression(), '')
+ # Test it twice
+ for i in range(2):
+ migrateActionIcons(self.portal)
+ icons = [ic._action_id for ic in self.aitool.listActionIcons()]
+ self.assertFalse('test_id' in icons)
+ self.assertEqual(action.getIconExpression(),
+ 'string:$portal_url/test.gif')
+
+ def testContentTypeIconExpressions(self):
+ """
+ FTIs should now be using icon_expr instead of content_icon.
+ (The former caches the expression object.)
+ """
+ tt = getToolByName(self.portal, "portal_types")
+ tt.Document.icon_expr = None
+ loadMigrationProfile(self.portal, self.profile, ('typeinfo', ))
+ self.assertEqual(tt.Document.icon_expr,
+ "string:${portal_url}/document_icon.png")
+
+ def testMigrateTypeIcons(self):
+ """
+ FTIs having content_icon should be upgraded to icon_expr.
+ """
+ tt = getToolByName(self.portal, "portal_types")
+ del tt.Document.icon_expr
+ tt.Document.content_icon = 'document_icon.gif'
+ migrateTypeIcons(self.portal)
+ self.assertEqual(tt.Document.icon_expr,
+ "string:${portal_url}/document_icon.gif")
+ self.assertTrue(hasattr(tt.Document, 'icon_expr_object'))
+
+ #Don't upgrade if there is already an icon_expr.
+ tt.Document.icon_expr = "string:${portal_url}/document_icon.png"
+ tt.Document.content_icon = 'document_icon.gif'
+ migrateTypeIcons(self.portal)
+ self.assertEqual(tt.Document.icon_expr,
+ "string:${portal_url}/document_icon.png")
+
+ def testPngContentIcons(self):
+ tt = getToolByName(self.portal, "portal_types")
+ tt.Document.icon_expr = "string:${portal_url}/document_icon.gif"
+ loadMigrationProfile(self.portal, self.profile, ('typeinfo', ))
+ self.assertEqual(tt.Document.icon_expr,
+ "string:${portal_url}/document_icon.png")
+
+ def testAddRAMCache(self):
+ # Test it twice
+ for i in range(2):
+ sm = getSiteManager()
+ sm.unregisterUtility(provided=IRAMCache)
+ util = queryUtility(IRAMCache)
+ self.assertEqual(util.maxAge, 86400)
+ addOrReplaceRamCache(self.portal)
+ util = queryUtility(IRAMCache)
+ self.assertEqual(util.maxAge, 3600)
+
+ def testReplaceOldRamCache(self):
+ sm = getSiteManager()
+
+ # Test it twice
+ for i in range(2):
+ sm.unregisterUtility(provided=IRAMCache)
+ from zope.app.cache.interfaces.ram import IRAMCache as OldIRAMCache
+ from zope.app.cache.ram import RAMCache as OldRAMCache
+ sm.registerUtility(factory=OldRAMCache, provided=OldIRAMCache)
+
+ addOrReplaceRamCache(self.portal)
+ util = queryUtility(IRAMCache)
+ self.assertEqual(util.maxAge, 3600)
+
+ def testChangeWorkflowActorVariableExpression(self):
+ self.wftool.intranet_folder_workflow.variables.actor.setProperties('')
+
+ for i in range(2):
+ changeWorkflowActorVariableExpression(self.portal)
+ wf = self.wftool.intranet_folder_workflow
+ self.assertEqual(wf.variables.actor.getDefaultExprText(),
+ 'user/getId')
+ wf = self.wftool.one_state_workflow
+ self.assertEqual(wf.variables.actor.getDefaultExprText(),
+ 'user/getId')
+ wf = self.wftool.simple_publication_workflow
+ self.assertEqual(wf.variables.actor.getDefaultExprText(),
+ 'user/getId')
+
+ # make sure it doesn't break if the workflow is missing
+ wf = self.wftool.intranet_folder_workflow
+ self.wftool._delOb('intranet_folder_workflow')
+ changeWorkflowActorVariableExpression(self.portal)
+ self.wftool._setOb('intranet_folder_workflow', wf)
+
+ def testChangeAuthenticatedResourcesCondition(self):
+ # make sure CSS resource is updated
+ res = self.csstool.getResource('member.css')
+ if res is None:
+ return
+ res.setAuthenticated(False)
+ res.setExpression('not: portal/portal_membership/isAnonymousUser')
+ # test it twice
+ for i in range(2):
+ changeAuthenticatedResourcesCondition(self.portal)
+ self.assertEqual(res.getExpression(), '')
+ self.assertTrue(res.getAuthenticated())
+
+ # make sure it doesn't update it if the expression has been
+ # customized
+ res.setExpression('python:False')
+ changeAuthenticatedResourcesCondition(self.portal)
+ self.assertEqual(res.getExpression(), 'python:False')
+
+ def testAddedUseEmailProperty(self):
+ tool = getToolByName(self.portal, 'portal_properties')
+ sheet = getattr(tool, 'site_properties')
+ #self.assertEqual(sheet.getProperty('use_email_as_login'), False)
+ self.removeSiteProperty('use_email_as_login')
+ loadMigrationProfile(self.portal, self.profile, ('propertiestool', ))
+ self.assertEqual(sheet.getProperty('use_email_as_login'), False)
+
+ def testReplaceReferencebrowser(self):
+ self.setRoles(['Manager'])
+ skins_tool = getToolByName(self.portal, 'portal_skins')
+ if 'referencebrowser' not in skins_tool:
+ return
+ sels = skins_tool._getSelections()
+ for skinname, layer in sels.items():
+ layers = layer.split(',')
+ self.assertFalse('ATReferenceBrowserWidget' in layers)
+ layers.remove('referencebrowser')
+ new_layers = ','.join(layers)
+ sels[skinname] = new_layers
+
+ from .alphas import threeX_alpha1
+ threeX_alpha1(self.portal)
+ setupReferencebrowser(self.portal)
+
+ sels = skins_tool._getSelections()
+ for skinname, layer in sels.items():
+ layers = layer.split(',')
+ self.assertTrue('referencebrowser' in layers)
+
+ def testInstallNewDependencies(self):
+ from plone.app.upgrade.v40.alphas import threeX_alpha1
+ self.setRoles(['Manager'])
+ # test for running the TinyMCE profile by checking for the skin layer
+ # it installs (the profile is marked as noninstallable, so we can't
+ # ask the quick installer)
+ skins_tool = getToolByName(self.portal, 'portal_skins')
+ if 'tinymce' not in skins_tool:
+ # Skip test in new Plones that don't have tinymce to begin with
+ return
+ del skins_tool['tinymce']
+ for i in range(2):
+ threeX_alpha1(self.portal)
+ self.assertTrue('tinymce' in skins_tool)
+ # sleep to avoid a GS log filename collision :-o
+ time.sleep(1)
+
+ def testReplaceSecureMailHost(self):
+ portal = self.portal
+ sm = getSiteManager(context=portal)
+ # try it with an unmodified site to ensure it doesn't give any errors
+ migrateMailHost(portal.portal_setup)
+ portal._delObject('MailHost')
+ # Run it with our MailHost replaced
+ portal._setObject('MailHost', FakeSecureMailHost())
+ self.assertEqual(portal.MailHost.meta_type, 'Secure Mail Host')
+ sm.unregisterUtility(provided=IMailHost)
+ sm.registerUtility(portal.MailHost, provided=IMailHost)
+ migrateMailHost(portal)
+ new_mh = portal.MailHost
+ self.assertEqual(new_mh.meta_type, 'Mail Host')
+ self.assertEqual(new_mh.title, 'Fake MailHost')
+ self.assertEqual(new_mh.smtp_host, 'smtp.example.com')
+ self.assertEqual(new_mh.smtp_port, 587)
+ self.assertEqual(new_mh.smtp_uid, 'me')
+ self.assertEqual(new_mh.smtp_pwd, 'secret')
+ #Force TLS is always false, because SMH has no equivalent option
+ self.assertEqual(new_mh.force_tls, False)
+
+ def testFolderMigration(self):
+ from plone.app.folder.tests.content import create
+ from plone.app.folder.tests.test_migration import reverseMigrate
+ from plone.app.folder.tests.test_migration import isSaneBTreeFolder
+ # create a folder in an unmigrated state & check it's broken...
+ folder = create('Folder', self.portal, 'foo', title='Foo')
+ reverseMigrate(self.portal)
+ self.assertFalse(isSaneBTreeFolder(self.portal.foo))
+ # now run the migration step...
+ migrateFolders(self.portal)
+ folder = self.portal.foo
+ self.assertTrue(isSaneBTreeFolder(folder))
+ self.assertEqual(folder.getId(), 'foo')
+ self.assertEqual(folder.Title(), 'Foo')
+
+ def testMigrateStaticTextPortlets(self):
+ class HiddenAssignment(static.Assignment):
+ hide = True
+
+ self.setRoles(["Manager"])
+ self.portal.invokeFactory('Folder', id="statictest")
+ folder = self.portal['statictest']
+
+ manager = getUtility(
+ IPortletManager, name='plone.rightcolumn',
+ context=folder)
+ assignments = getMultiAdapter(
+ (folder, manager), IPortletAssignmentMapping)
+ hidden_portlet = HiddenAssignment()
+ visible_portlet = static.Assignment()
+ assignments['hidden'] = hidden_portlet
+ assignments['visible'] = visible_portlet
+
+ migrateStaticTextPortlets(self.portal)
+
+ self.assertFalse(
+ IPortletAssignmentSettings(hidden_portlet).get(
+ 'visible', True))
+ self.assertTrue(
+ IPortletAssignmentSettings(visible_portlet).get(
+ 'visible', True))
+
+
+
+class TestMigrations_v4_0alpha2(MigrationTest):
+
+ def testMigrateJoinFormFields(self):
+ ptool = getToolByName(self.portal, 'portal_properties')
+ sheet = getattr(ptool, 'site_properties')
+ self.removeSiteProperty('user_registration_fields')
+ self.addSiteProperty('join_form_fields')
+ sheet.join_form_fields = (
+ 'username', 'password', 'email', 'mail_me', 'groups')
+ renameJoinFormFields(self)
+ self.assertEqual(sheet.hasProperty('join_form_fields'), False)
+ self.assertEqual(sheet.hasProperty('user_registration_fields'), True)
+ self.assertEqual(sheet.getProperty('user_registration_fields'),
+ ('username', 'password', 'email', 'mail_me'))
+
+
+class TestMigrations_v4_0alpha3(MigrationTest):
+
+ profile = "profile-plone.app.upgrade.v40:4alpha2-4alpha3"
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+ def testJoinActionURL(self):
+ self.portal.portal_actions.user.join.url_expr = 'foo'
+ loadMigrationProfile(self.portal, self.profile, ('actions', ))
+ self.assertEqual(self.portal.portal_actions.user.join.url_expr,
+ 'string:${globals_view/navigationRootUrl}/@@register')
+
+
+class TestMigrations_v4_0alpha5(MigrationTest):
+
+ profile = "profile-plone.app.upgrade.v40:4alpha4-4alpha5"
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+ def testMigrateLargeFolderType(self):
+ portal = self.portal
+ catalog = getToolByName(portal, 'portal_catalog')
+ # set things up in the old way...
+ ids = 'news', 'events', 'Members'
+ for id in ids:
+ obj = portal[id]
+ obj._setPortalTypeName('Large Plone Folder')
+ obj.reindexObject()
+ self.assertEqual(obj.portal_type, 'Large Plone Folder')
+ # Type falls back to meta_type since there's no
+ # Large Plone Folder FTI
+ self.assertEqual(obj.Type(), 'ATFolder')
+ brain, = catalog(getId=id)
+ self.assertEqual(brain.portal_type, 'Large Plone Folder')
+ self.assertEqual(brain.Type, 'ATFolder')
+ # migrate & check again...
+ updateLargeFolderType(self.portal)
+ for id in ids:
+ obj = portal[id]
+ self.assertEqual(obj.portal_type, 'Folder')
+ self.assertEqual(obj.Type(), 'Folder')
+ brain, = catalog(getId=id)
+ self.assertEqual(brain.portal_type, 'Folder')
+ self.assertEqual(brain.Type, 'Folder')
+
+ def testAddRecursiveGroupsPlugin(self):
+ acl = getToolByName(self.portal, 'acl_users')
+ addRecursiveGroupsPlugin(self.portal)
+ self.assertTrue('recursive_groups' in acl)
+ # Now that we have an existing one, let's make sure it's handled
+ # properly if this migration is run again.
+ addRecursiveGroupsPlugin(self.portal)
+ self.assertTrue('recursive_groups' in acl)
+
+ def testClassicThemeResourcesCleanUp(self):
+ """Test that the plonetheme.classic product doesn't have any
+ registered CSS resource in its metadata after migration.
+ """
+ portal = self.portal
+ qi = getToolByName(portal, 'portal_quickinstaller')
+ qi.installProduct('plonetheme.classic')
+ classictheme = qi['plonetheme.classic']
+ classictheme.resources_css = ['something'] # add a random resource
+ cleanUpClassicThemeResources(portal)
+ self.assertEqual(classictheme.resources_css, [])
+
+ def testGetObjPositionInParentIndex(self):
+ from plone.app.folder.nogopip import GopipIndex
+ catalog = self.portal.portal_catalog
+ catalog.delIndex('getObjPositionInParent')
+ catalog.addIndex('getObjPositionInParent', 'FieldIndex')
+ self.assertFalse(isinstance(catalog.Indexes['getObjPositionInParent'],
+ GopipIndex))
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue('getObjPositionInParent' in catalog.indexes())
+ self.assertTrue(isinstance(catalog.Indexes['getObjPositionInParent'],
+ GopipIndex))
+
+ def testGetEventTypeIndex(self):
+ catalog = self.portal.portal_catalog
+ catalog.addIndex('getEventType', 'KeywordIndex')
+ self.assertTrue('getEventType' in catalog.indexes())
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertFalse('getEventType' in catalog.indexes())
+
+
+class TestMigrations_v4_0beta1(MigrationTest):
+
+ profile = "profile-plone.app.upgrade.v40:4alpha5-4beta1"
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+ def testRepositionRecursiveGroupsPlugin(self):
+ # Ensure that the recursive groups plugin is moved to the bottom
+ # of the IGroups plugins list, if active.
+ addRecursiveGroupsPlugin(self.portal)
+ # Plugin is installed, but not active, run against this state.
+ from Products.PluggableAuthService.interfaces.plugins import \
+ IGroupsPlugin
+ acl = getToolByName(self.portal, 'acl_users')
+ plugins = acl.plugins
+ # The plugin was originally moved to the top of the list of
+ # IGroupsPlugin plugins by p.a.controlpanel. Recreate that state.
+ while (plugins.getAllPlugins('IGroupsPlugin')['active'].index(
+ 'recursive_groups') > 0):
+ plugins.movePluginsUp(IGroupsPlugin, ['recursive_groups'])
+
+ active_groups = plugins.getAllPlugins('IGroupsPlugin')['active']
+ self.assertEqual(active_groups[0], 'recursive_groups')
+
+ # Rerun the migration, making sure that it's now the last item in the
+ # list of IGroupsPlugin plugins.
+ repositionRecursiveGroupsPlugin(self.portal)
+ active_groups = plugins.getAllPlugins('IGroupsPlugin')['active']
+ self.assertEqual(active_groups[-1], 'recursive_groups')
+
+
+class TestMigrations_v4_0beta2(MigrationTest):
+
+ profile = "profile-plone.app.upgrade.v40:4beta1-4beta2"
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+ def testCoreContentIconExprCleared(self):
+ types = getToolByName(self.portal, 'portal_types')
+ catalog = getToolByName(self.portal, 'portal_catalog')
+ # Reinstate the now-empty icon expression for the Document type
+ doc_icon_expr = Expression('string:${portal_url}/document_icon.png')
+ types['Document'].icon_expr_object = doc_icon_expr
+ front = self.portal['front-page']
+ catalog.reindexObject(front)
+ old_modified = front.modified()
+ # Make sure the getIcon metadata column shows the "original" value
+ brains = catalog(id='front-page')
+ self.assertEqual(brains[0].getIcon, 'document_icon.png')
+ # Run the migration
+ loadMigrationProfile(self.portal, self.profile)
+ updateIconMetadata(self.portal)
+ # The getIcon column should now be empty
+ self.assertEqual(catalog(id='front-page')[0].getIcon, '')
+ self.assertEqual(front.modified(), old_modified)
+
+
+class TestMigrations_v4_0beta4(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4beta3-4beta4'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+ def testRemoveLargePloneFolder(self):
+ # re-create pre-migration settings
+ ptool = self.portal.portal_properties
+ nav_props = ptool.navtree_properties
+ l = list(nav_props.parentMetaTypesNotToQuery)
+ nav_props.parentMetaTypesNotToQuery = l + ['Large Plone Folder']
+ site_props = ptool.site_properties
+ l = list(site_props.typesLinkToFolderContentsInFC)
+ site_props.typesLinkToFolderContentsInFC = l + ['Large Plone Folder']
+ temp_folder_fti = self.portal.portal_types['TempFolder']
+ l = list(temp_folder_fti.allowed_content_types)
+ temp_folder_fti.allowed_content_types = l + ['Large Plone Folder']
+ l = set(self.portal.portal_factory.getFactoryTypes())
+ l.add('Large Plone Folder')
+ ftool = self.portal.portal_factory
+ ftool.manage_setPortalFactoryTypes(listOfTypeIds=list(l))
+
+ for i in xrange(2):
+ loadMigrationProfile(self.portal, self.profile)
+ removeLargePloneFolder(self.portal)
+ self.assertFalse('Large Plone Folder' in self.portal.portal_types)
+ self.assertFalse('Large Plone Folder' in
+ temp_folder_fti.allowed_content_types)
+ self.assertTrue('Folder' in temp_folder_fti.allowed_content_types)
+ self.assertFalse('Large Plone Folder' in ftool.getFactoryTypes())
+ self.assertTrue('Folder' in ftool.getFactoryTypes())
+ self.assertFalse('Large Plone Folder' in
+ nav_props.parentMetaTypesNotToQuery)
+ self.assertTrue('TempFolder' in
+ nav_props.parentMetaTypesNotToQuery)
+ self.assertFalse('Large Plone Folder' in
+ site_props.typesLinkToFolderContentsInFC)
+ self.assertTrue('Folder' in
+ site_props.typesLinkToFolderContentsInFC)
+ # sleep to avoid a GS log filename collision :-o
+ time.sleep(1)
+
+
+class TestMigrations_v4_0beta5(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4beta4-4beta5'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+
+class TestMigrations_v4_0rc1(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4beta5-4rc1'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+class TestMigrations_v4_0(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4rc1-4final'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+class TestMigrations_v4_0_1(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4.0-4.0.1'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+class TestMigrations_v4_0_2(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4.0.1-4.0.2'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+class TestMigrations_v4_0_3(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4.0.2-4.0.3'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+class TestMigrations_v4_0_4(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4.0.3-4.0.4'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+class TestMigrations_v4_0_5(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v40:4.0.4-4.0.5'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+
+def test_suite():
+ from unittest import defaultTestLoader
+ return defaultTestLoader.loadTestsFromName(__name__)
diff --git a/plone/app/upgrade/v41/tests.py b/plone/app/upgrade/v41/tests.py
new file mode 100644
index 0000000..4570a4c
--- /dev/null
+++ b/plone/app/upgrade/v41/tests.py
@@ -0,0 +1,19 @@
+import unittest
+from Products.ZCatalog.ZCatalog import ZCatalog
+from Products.ZCTextIndex.ZCTextIndex import ZCTextIndex, PLexicon
+from Products.ZCTextIndex.OkapiIndex import OkapiIndex
+
+
+class MigrationUnitTests(unittest.TestCase):
+
+ def test_fixOkapiIndexes(self):
+ catalog = ZCatalog('catalog')
+ catalog.lexicon = PLexicon('lexicon')
+ catalog.addIndex('test',
+ ZCTextIndex('test', index_factory=OkapiIndex,
+ caller=catalog, lexicon_id='lexicon'))
+ catalog.Indexes['test'].index._totaldoclen = -1000
+
+ from plone.app.upgrade.v41.final import fixOkapiIndexes
+ fixOkapiIndexes(catalog)
+ self.assertEqual(0L, catalog.Indexes['test'].index._totaldoclen())
diff --git a/plone/app/upgrade/v42/tests.py b/plone/app/upgrade/v42/tests.py
new file mode 100644
index 0000000..0ff501e
--- /dev/null
+++ b/plone/app/upgrade/v42/tests.py
@@ -0,0 +1,20 @@
+from plone.app.upgrade.tests.base import MigrationTest
+from plone.app.upgrade.utils import loadMigrationProfile
+
+
+class TestMigrations_v4_2beta1(MigrationTest):
+
+ profile = 'profile-plone.app.upgrade.v42:to42beta1'
+
+ def testProfile(self):
+ # This tests the whole upgrade profile can be loaded
+ loadMigrationProfile(self.portal, self.profile)
+ self.assertTrue(True)
+
+ def testAddSiteAdminToKeywordRoles(self):
+ ptool = self.portal.portal_properties
+ site_props = ptool.site_properties
+ site_props.allowRolesToAddKeywords = ('Manager', 'Reviewer')
+ loadMigrationProfile(self.portal, self.profile)
+ roles = site_props.allowRolesToAddKeywords
+ self.assertEqual(roles, ('Manager', 'Reviewer', 'Site Administrator'))
diff --git a/setup.py b/setup.py
index c500ee7..1dd33a5 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages
-version = '2.0.dev0'
+version = '1.3.9.dev0'
setup(name='plone.app.upgrade',
version=version,
@@ -10,12 +10,10 @@
classifiers=[
"Environment :: Web Environment",
"Framework :: Plone",
- "Framework :: Plone :: 5.0",
"Framework :: Zope2",
"License :: OSI Approved :: GNU General Public License (GPL)",
"Operating System :: OS Independent",
"Programming Language :: Python",
- "Programming Language :: Python :: 2.7",
],
keywords='Plone upgrade migration',
author='Plone Foundation',
@@ -30,13 +28,13 @@
test=[
'Products.CMFPlacefulWorkflow',
'Products.CMFQuickInstallerTool',
+ 'Products.PloneTestCase',
'plone.contentrules',
'plone.app.i18n',
'plone.app.iterate',
'plone.app.openid',
'plone.app.redirector',
'plone.app.viewletmanager',
- 'plone.app.testing',
'plone.app.theming',
]
),
-------------------------------------------------------------------------------
More information about the Testbot
mailing list