Back to index

plone3  3.1.7
test_TypesTool.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
00004 #
00005 # This software is subject to the provisions of the Zope Public License,
00006 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
00007 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00008 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00009 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00010 # FOR A PARTICULAR PURPOSE.
00011 #
00012 ##############################################################################
00013 """ Unit tests for TypesTool module.
00014 
00015 $Id: test_TypesTool.py 77186 2007-06-28 19:06:19Z yuppie $
00016 """
00017 
00018 import unittest
00019 import Testing
00020 
00021 from AccessControl import Unauthorized
00022 from AccessControl.SecurityManagement import newSecurityManager
00023 from AccessControl.SecurityManagement import noSecurityManager
00024 from AccessControl.SecurityManager import setSecurityPolicy
00025 from Acquisition import aq_base
00026 from Products.PythonScripts.PythonScript import PythonScript
00027 from Products.PythonScripts.standard import html_quote
00028 from webdav.NullResource import NullResource
00029 from zope.component import getSiteManager
00030 from zope.component.interfaces import IFactory
00031 from zope.testing.cleanup import cleanUp
00032 
00033 from Products.CMFCore.ActionInformation import ActionInformation
00034 from Products.CMFCore.PortalFolder import PortalFolder
00035 from Products.CMFCore.testing import FunctionalZCMLLayer
00036 from Products.CMFCore.tests.base.dummy import DummyFactory
00037 from Products.CMFCore.tests.base.dummy import DummyFactoryDispatcher
00038 from Products.CMFCore.tests.base.dummy import DummyContent
00039 from Products.CMFCore.tests.base.dummy import DummyFolder
00040 from Products.CMFCore.tests.base.dummy import DummySite
00041 from Products.CMFCore.tests.base.dummy import DummyUserFolder
00042 from Products.CMFCore.tests.base.security import OmnipotentUser
00043 from Products.CMFCore.tests.base.security import UserWithRoles
00044 from Products.CMFCore.tests.base.testcase import SecurityTest
00045 from Products.CMFCore.tests.base.testcase import WarningInterceptor
00046 from Products.CMFCore.tests.base.tidata import FTIDATA_ACTIONS
00047 from Products.CMFCore.tests.base.tidata import FTIDATA_CMF15
00048 from Products.CMFCore.tests.base.tidata import FTIDATA_DUMMY
00049 from Products.CMFCore.tests.base.tidata import STI_SCRIPT
00050 
00051 from zope.interface import implements
00052 from Products.CMFCore.interfaces import ITypeInformation
00053 
00054 class ActionTesterTypeInfo:
00055 
00056     implements(ITypeInformation)
00057 
00058     id = 'Dummy Content'
00059 
00060     def listActions(self, info=None, obj=None):
00061         self._action_info = info
00062         self._action_obj = obj
00063         return ()
00064 
00065 class TypesToolTests(SecurityTest, WarningInterceptor):
00066 
00067     layer = FunctionalZCMLLayer
00068 
00069     def _makeOne(self):
00070         from Products.CMFCore.TypesTool import TypesTool
00071 
00072         return TypesTool()
00073 
00074     def setUp(self):
00075         from Products.CMFCore.TypesTool import FactoryTypeInformation as FTI
00076 
00077         SecurityTest.setUp(self)
00078         self.site = DummySite('site').__of__(self.root)
00079         self.acl_users = self.site._setObject( 'acl_users', DummyUserFolder() )
00080         self.ttool = self.site._setObject( 'portal_types', self._makeOne() )
00081         fti = FTIDATA_DUMMY[0].copy()
00082         self.ttool._setObject( 'Dummy Content', FTI(**fti) )
00083 
00084     def tearDown(self):
00085         SecurityTest.tearDown(self)
00086         self._free_warning_output()
00087 
00088     def test_z2interfaces(self):
00089         from Interface.Verify import verifyClass
00090         from Products.CMFCore.interfaces.portal_actions \
00091                 import ActionProvider as IActionProvider
00092         from Products.CMFCore.interfaces.portal_types \
00093                 import portal_types as ITypesTool
00094         from Products.CMFCore.TypesTool import TypesTool
00095 
00096         verifyClass(IActionProvider, TypesTool)
00097         verifyClass(ITypesTool, TypesTool)
00098 
00099     def test_z3interfaces(self):
00100         from zope.interface.verify import verifyClass
00101         from Products.CMFCore.interfaces import IActionProvider
00102         from Products.CMFCore.interfaces import ITypesTool
00103         from Products.CMFCore.TypesTool import TypesTool
00104 
00105         verifyClass(IActionProvider, TypesTool)
00106         verifyClass(ITypesTool, TypesTool)
00107 
00108     def test_listActions(self):
00109         """test that a full set of context information is passed
00110            by the types tool
00111         """
00112         tool = self.ttool
00113         ti = ActionTesterTypeInfo()
00114         setattr( tool, 'Dummy Content', ti )
00115 
00116         dummy = self.site._setObject('dummy', DummyContent('dummy'))
00117         tool.listActions('fake_info', dummy)
00118 
00119         self.assertEqual(ti._action_info, 'fake_info')
00120         self.assertEqual(ti._action_obj, dummy)
00121 
00122     def test_allMetaTypes(self):
00123         """
00124         Test that everything returned by allMetaTypes can be
00125         traversed to.
00126         """
00127         tool = self.ttool
00128         meta_types={}
00129         # Seems we get NullResource if the method couldn't be traverse to
00130         # so we check for that. If we've got it, something is b0rked.
00131         for factype in tool.all_meta_types():
00132             meta_types[factype['name']]=1
00133             # The html_quote below is necessary 'cos of the one in
00134             # main.dtml. Could be removed once that is gone.
00135             act = tool.unrestrictedTraverse(html_quote(factype['action']))
00136             self.failIf(type(aq_base(act)) is NullResource)
00137 
00138         # Check the ones we're expecting are there
00139         self.failUnless(meta_types.has_key('Scriptable Type Information'))
00140         self.failUnless(meta_types.has_key('Factory-based Type Information'))
00141 
00142     def test_constructContent(self):
00143         from Products.CMFCore.TypesTool \
00144                 import ScriptableTypeInformation as STI
00145 
00146         site = self.site
00147         acl_users = self.acl_users
00148         ttool = self.ttool
00149         setSecurityPolicy(self._oldPolicy)
00150         newSecurityManager(None, acl_users.all_powerful_Oz)
00151         self.site._owner = (['acl_users'], 'all_powerful_Oz')
00152         sti_baz = STI('Baz',
00153                       permission='Add portal content',
00154                       constructor_path='addBaz')
00155         ttool._setObject('Baz', sti_baz)
00156         ttool._setObject( 'addBaz',  PythonScript('addBaz') )
00157         s = ttool.addBaz
00158         s.write(STI_SCRIPT)
00159 
00160         f = site._setObject( 'folder', PortalFolder(id='folder') )
00161         f.manage_addProduct = { 'FooProduct' : DummyFactoryDispatcher(f) }
00162         f._owner = (['acl_users'], 'user_foo')
00163         self.assertEqual( f.getOwner(), acl_users.user_foo )
00164 
00165         ttool.constructContent('Dummy Content', container=f, id='page1')
00166         try:
00167             ttool.constructContent('Baz', container=f, id='page2')
00168         except Unauthorized:
00169             self.fail('CMF Collector issue #165 (Ownership bug): '
00170                       'Unauthorized raised' )
00171 
00172 
00173 class TypeInfoTests(unittest.TestCase):
00174 
00175     def _makeTypesTool(self):
00176         from Products.CMFCore.TypesTool import TypesTool
00177 
00178         return TypesTool()
00179 
00180     def test_construction( self ):
00181         ti = self._makeInstance( 'Foo'
00182                                , description='Description'
00183                                , meta_type='Foo'
00184                                , icon='foo.gif'
00185                                )
00186         self.assertEqual( ti.getId(), 'Foo' )
00187         self.assertEqual( ti.Title(), 'Foo' )
00188         self.assertEqual( ti.Description(), 'Description' )
00189         self.assertEqual( ti.Metatype(), 'Foo' )
00190         self.assertEqual( ti.getIcon(), 'foo.gif' )
00191         self.assertEqual( ti.immediate_view, '' )
00192 
00193         ti = self._makeInstance( 'Foo'
00194                                , immediate_view='foo_view'
00195                                )
00196         self.assertEqual( ti.immediate_view, 'foo_view' )
00197 
00198     def _makeAndSetInstance(self, id, **kw):
00199         tool = self.tool
00200         t = self._makeInstance(id, **kw)
00201         tool._setObject(id,t)
00202         return tool[id]
00203 
00204     def test_allowType( self ):
00205         self.tool = self._makeTypesTool()
00206         ti = self._makeAndSetInstance( 'Foo' )
00207         self.failIf( ti.allowType( 'Foo' ) )
00208         self.failIf( ti.allowType( 'Bar' ) )
00209 
00210         ti = self._makeAndSetInstance( 'Foo2', allowed_content_types=( 'Bar', ) )
00211         self.failUnless( ti.allowType( 'Bar' ) )
00212 
00213         ti = self._makeAndSetInstance( 'Foo3', filter_content_types=0 )
00214         self.failUnless( ti.allowType( 'Foo3' ) )
00215 
00216     def test_GlobalHide( self ):
00217         self.tool = self._makeTypesTool()
00218         tnf = self._makeAndSetInstance( 'Folder', filter_content_types=0)
00219         taf = self._makeAndSetInstance( 'Allowing Folder'
00220                                       , allowed_content_types=( 'Hidden'
00221                                                               ,'Not Hidden'))
00222         tih = self._makeAndSetInstance( 'Hidden', global_allow=0)
00223         tnh = self._makeAndSetInstance( 'Not Hidden')
00224         # make sure we're normally hidden but everything else is visible
00225         self.failIf     ( tnf.allowType( 'Hidden' ) )
00226         self.failUnless ( tnf.allowType( 'Not Hidden') )
00227         # make sure we're available where we should be
00228         self.failUnless ( taf.allowType( 'Hidden' ) )
00229         self.failUnless ( taf.allowType( 'Not Hidden') )
00230         # make sure we're available in a non-content-type-filtered type
00231         # where we have been explicitly allowed
00232         taf2 = self._makeAndSetInstance( 'Allowing Folder2'
00233                                        , allowed_content_types=( 'Hidden'
00234                                                                , 'Not Hidden'
00235                                                                )
00236                                        , filter_content_types=0
00237                                        )
00238         self.failUnless ( taf2.allowType( 'Hidden' ) )
00239         self.failUnless ( taf2.allowType( 'Not Hidden') )
00240 
00241     def test_allowDiscussion( self ):
00242         ti = self._makeInstance( 'Foo' )
00243         self.failIf( ti.allowDiscussion() )
00244 
00245         ti = self._makeInstance( 'Foo', allow_discussion=1 )
00246         self.failUnless( ti.allowDiscussion() )
00247 
00248     def test_listActions( self ):
00249         ti = self._makeInstance( 'Foo' )
00250         self.failIf( ti.listActions() )
00251 
00252         ti = self._makeInstance( **FTIDATA_ACTIONS[0] )
00253         actions = ti.listActions()
00254         self.failUnless( actions )
00255 
00256         ids = [ x.getId() for x in actions ]
00257         self.failUnless( 'view' in ids )
00258         self.failUnless( 'edit' in ids )
00259         self.failUnless( 'objectproperties' in ids )
00260         self.failUnless( 'slot' in ids )
00261 
00262         names = [ x.Title() for x in actions ]
00263         self.failUnless( 'View' in names )
00264         self.failUnless( 'Edit' in names )
00265         self.failUnless( 'Object Properties' in names )
00266         self.failIf( 'slot' in names )
00267         self.failUnless( 'Slot' in names )
00268 
00269         visible = [ x.getId() for x in actions if x.getVisibility() ]
00270         self.failUnless( 'view' in visible )
00271         self.failUnless( 'edit' in visible )
00272         self.failUnless( 'objectproperties' in visible )
00273         self.failIf( 'slot' in visible )
00274 
00275     def test_MethodAliases_methods(self):
00276         ti = self._makeInstance( **FTIDATA_CMF15[0] )
00277         self.assertEqual( ti.getMethodAliases(), FTIDATA_CMF15[0]['aliases'] )
00278         self.assertEqual( ti.queryMethodID('view'), 'dummy_view' )
00279         self.assertEqual( ti.queryMethodID('view.html'), 'dummy_view' )
00280 
00281         ti.setMethodAliases( ti.getMethodAliases() )
00282         self.assertEqual( ti.getMethodAliases(), FTIDATA_CMF15[0]['aliases'] )
00283 
00284     def _checkContentTI(self, ti):
00285         wanted_aliases = { 'view': 'dummy_view', '(Default)': 'dummy_view' }
00286         wanted_actions_text0 = 'string:${object_url}/dummy_view'
00287         wanted_actions_text1 = 'string:${object_url}/dummy_edit_form'
00288         wanted_actions_text2 = 'string:${object_url}/metadata_edit_form'
00289 
00290         self.failUnless( isinstance( ti._actions[0], ActionInformation ) )
00291         self.assertEqual( len( ti._actions ), 3 )
00292         self.assertEqual(ti._aliases, wanted_aliases)
00293         self.assertEqual(ti._actions[0].action.text, wanted_actions_text0)
00294         self.assertEqual(ti._actions[1].action.text, wanted_actions_text1)
00295         self.assertEqual(ti._actions[2].action.text, wanted_actions_text2)
00296 
00297         action0 = ti._actions[0]
00298         self.assertEqual( action0.getId(), 'view' )
00299         self.assertEqual( action0.Title(), 'View' )
00300         self.assertEqual( action0.getActionExpression(), wanted_actions_text0 )
00301         self.assertEqual( action0.getCondition(), '' )
00302         self.assertEqual( action0.getPermissions(), ( 'View', ) )
00303         self.assertEqual( action0.getCategory(), 'object' )
00304         self.assertEqual( action0.getVisibility(), 1 )
00305 
00306     def _checkFolderTI(self, ti):
00307         wanted_aliases = { 'view': '(Default)' }
00308         wanted_actions_text0 = 'string:${object_url}'
00309         wanted_actions_text1 = 'string:${object_url}/dummy_edit_form'
00310         wanted_actions_text2 = 'string:${object_url}/folder_localrole_form'
00311 
00312         self.failUnless( isinstance( ti._actions[0], ActionInformation ) )
00313         self.assertEqual( len( ti._actions ), 3 )
00314         self.assertEqual(ti._aliases, wanted_aliases)
00315         self.assertEqual(ti._actions[0].action.text, wanted_actions_text0)
00316         self.assertEqual(ti._actions[1].action.text, wanted_actions_text1)
00317         self.assertEqual(ti._actions[2].action.text, wanted_actions_text2)
00318 
00319 
00320 class FTIDataTests( TypeInfoTests ):
00321 
00322     def _makeInstance(self, id, **kw):
00323         from Products.CMFCore.TypesTool import FactoryTypeInformation
00324 
00325         return FactoryTypeInformation(id, **kw)
00326 
00327     def test_z2interfaces(self):
00328         from Interface.Verify import verifyClass
00329         from Products.CMFCore.interfaces.portal_types \
00330                 import ContentTypeInformation as ITypeInformation
00331         from Products.CMFCore.TypesTool import FactoryTypeInformation
00332 
00333         verifyClass(ITypeInformation, FactoryTypeInformation)
00334 
00335     def test_z3interfaces(self):
00336         from zope.interface.verify import verifyClass
00337         from Products.CMFCore.interfaces import ITypeInformation
00338         from Products.CMFCore.TypesTool import FactoryTypeInformation
00339 
00340         verifyClass(ITypeInformation, FactoryTypeInformation)
00341 
00342     def test_properties( self ):
00343         ti = self._makeInstance( 'Foo' )
00344         self.assertEqual( ti.product, '' )
00345         self.assertEqual( ti.factory, '' )
00346 
00347         ti = self._makeInstance( 'Foo'
00348                                , product='FooProduct'
00349                                , factory='addFoo'
00350                                )
00351         self.assertEqual( ti.product, 'FooProduct' )
00352         self.assertEqual( ti.factory, 'addFoo' )
00353 
00354 
00355 class STIDataTests( TypeInfoTests ):
00356 
00357     def _makeInstance(self, id, **kw):
00358         from Products.CMFCore.TypesTool import ScriptableTypeInformation
00359 
00360         return ScriptableTypeInformation(id, **kw)
00361 
00362     def test_z2interfaces(self):
00363         from Interface.Verify import verifyClass
00364         from Products.CMFCore.interfaces.portal_types \
00365                 import ContentTypeInformation as ITypeInformation
00366         from Products.CMFCore.TypesTool import ScriptableTypeInformation
00367 
00368         verifyClass(ITypeInformation, ScriptableTypeInformation)
00369 
00370     def test_z3interfaces(self):
00371         from zope.interface.verify import verifyClass
00372         from Products.CMFCore.interfaces import ITypeInformation
00373         from Products.CMFCore.TypesTool import ScriptableTypeInformation
00374 
00375         verifyClass(ITypeInformation, ScriptableTypeInformation)
00376 
00377     def test_properties( self ):
00378         ti = self._makeInstance( 'Foo' )
00379         self.assertEqual( ti.permission, '' )
00380         self.assertEqual( ti.constructor_path, '' )
00381 
00382         ti = self._makeInstance( 'Foo'
00383                                , permission='Add Foos'
00384                                , constructor_path='foo_add'
00385                                )
00386         self.assertEqual( ti.permission, 'Add Foos' )
00387         self.assertEqual( ti.constructor_path, 'foo_add' )
00388 
00389 
00390 class FTIConstructionTestCase(unittest.TestCase):
00391 
00392     def _getTargetClass(self):
00393         from Products.CMFCore.TypesTool import FactoryTypeInformation
00394 
00395         return FactoryTypeInformation
00396 
00397     def _makeOne(self, *args, **kw):
00398         return self._getTargetClass()(*args, **kw)
00399 
00400     def test_isConstructionAllowed_wo_Container(self):
00401         self.failIf(self.ti.isConstructionAllowed(None))
00402 
00403     def test_isConstructionAllowed_wo_ProductFactory(self):
00404         ti = self._makeOne('foo')
00405         self.failIf(ti.isConstructionAllowed(self.f))
00406 
00407     def test_isConstructionAllowed_wo_Security(self):
00408         noSecurityManager()
00409         self.failIf(self.ti.isConstructionAllowed(self.f))
00410 
00411     def test_isConstructionAllowed_for_Omnipotent(self):
00412         newSecurityManager(None, OmnipotentUser().__of__(self.f))
00413         self.failUnless(self.ti.isConstructionAllowed(self.f))
00414 
00415     def test_isConstructionAllowed_w_Role(self):
00416         self.failUnless(self.ti.isConstructionAllowed(self.f))
00417 
00418     def test_isConstructionAllowed_wo_Role(self):
00419         newSecurityManager(None, UserWithRoles('FooViewer').__of__(self.f))
00420         self.failIf(self.ti.isConstructionAllowed(self.f))
00421 
00422     def test_constructInstance_wo_Roles(self):
00423         newSecurityManager(None, UserWithRoles('FooViewer').__of__(self.f))
00424         self.assertRaises(Unauthorized,
00425                           self.ti.constructInstance, self.f, 'foo')
00426 
00427     def test_constructInstance(self):
00428         self.ti.constructInstance(self.f, 'foo')
00429         foo = self.f._getOb('foo')
00430         self.assertEqual(foo.id, 'foo')
00431 
00432     def test_constructInstance_private(self):
00433         newSecurityManager(None, UserWithRoles('NotAFooAdder').__of__(self.f))
00434         self.ti._constructInstance(self.f, 'foo')
00435         foo = self.f._getOb('foo')
00436         self.assertEqual(foo.id, 'foo')
00437 
00438     def test_constructInstance_w_args_kw(self):
00439         self.ti.constructInstance(self.f, 'bar', 0, 1)
00440         bar = self.f._getOb('bar')
00441         self.assertEqual(bar.id, 'bar')
00442         self.assertEqual(bar._args, (0, 1))
00443 
00444         self.ti.constructInstance(self.f, 'baz', frickle='natz')
00445         baz = self.f._getOb('baz')
00446         self.assertEqual(baz.id, 'baz')
00447         self.assertEqual(baz._kw['frickle'], 'natz')
00448 
00449         self.ti.constructInstance(self.f, 'bam', 0, 1, frickle='natz')
00450         bam = self.f._getOb('bam')
00451         self.assertEqual(bam.id, 'bam')
00452         self.assertEqual(bam._args, (0, 1))
00453         self.assertEqual(bam._kw['frickle'], 'natz')
00454 
00455 
00456 class FTIOldstyleConstructionTests(FTIConstructionTestCase):
00457 
00458     def setUp(self):
00459         self.f = DummyFolder(fake_product=1)
00460         self.ti = self._makeOne('Foo', product='FooProduct', factory='addFoo')
00461         newSecurityManager(None, UserWithRoles('FooAdder').__of__(self.f))
00462 
00463     def tearDown(self):
00464         noSecurityManager()
00465 
00466     def test_constructInstance_w_id_munge(self):
00467         self.f._prefix = 'majyk'
00468         self.ti.constructInstance(self.f, 'dust')
00469         majyk_dust = self.f._getOb('majyk_dust')
00470         self.assertEqual(majyk_dust.id, 'majyk_dust')
00471 
00472 
00473 class FTINewstyleConstructionTests(FTIConstructionTestCase, SecurityTest):
00474 
00475     def setUp(self):
00476         SecurityTest.setUp(self)
00477         sm = getSiteManager()
00478         sm.registerUtility(DummyFactory, IFactory, 'test.dummy')
00479 
00480         self.f = DummyFolder()
00481         self.ti = self._makeOne('Foo', meta_type='Dummy',
00482                                 factory='test.dummy')
00483         newSecurityManager(None, UserWithRoles('FooAdder').__of__(self.f))
00484 
00485     def tearDown(self):
00486         cleanUp()
00487         SecurityTest.tearDown(self)
00488 
00489 
00490 def test_suite():
00491     return unittest.TestSuite((
00492         unittest.makeSuite(TypesToolTests),
00493         unittest.makeSuite(FTIDataTests),
00494         unittest.makeSuite(STIDataTests),
00495         unittest.makeSuite(FTIOldstyleConstructionTests),
00496         unittest.makeSuite(FTINewstyleConstructionTests),
00497         ))
00498 
00499 if __name__ == '__main__':
00500     from Products.CMFCore.testing import run
00501     run(test_suite())