Back to index

plone3  3.1.7
test_Discussions.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 Discussions.
00014 
00015 $Id: test_Discussions.py 77356 2007-07-03 14:55:11Z yuppie $
00016 """
00017 
00018 import unittest
00019 import Testing
00020 
00021 from zope.component import getSiteManager
00022 
00023 from Products.CMFCore.CatalogTool import CatalogTool
00024 from Products.CMFCore.interfaces import IDiscussionTool
00025 from Products.CMFCore.testing import EventZCMLLayer
00026 from Products.CMFCore.tests.base.dummy import DummyContent
00027 from Products.CMFCore.tests.base.dummy import DummySite
00028 from Products.CMFCore.tests.base.dummy import DummyTool
00029 from Products.CMFCore.tests.base.testcase import SecurityTest
00030 from Products.CMFCore.tests.base.tidata import FTIDATA_DUMMY
00031 from Products.CMFCore.tests.base.utils import has_path
00032 from Products.CMFCore.TypesTool import FactoryTypeInformation as FTI
00033 from Products.CMFCore.TypesTool import TypesTool
00034 from Products.CMFCore.utils import getToolByName
00035 from Products.CMFDefault.DiscussionTool import DiscussionTool
00036 from Products.CMFDefault.exceptions import DiscussionNotAllowed
00037 
00038 
00039 class DiscussionItemTests(unittest.TestCase):
00040 
00041     def test_z2interfaces(self):
00042         from Interface.Verify import verifyClass
00043         from Products.CMFCore.interfaces.Contentish \
00044                 import Contentish as IContentish
00045         from Products.CMFCore.interfaces.Discussions \
00046                 import DiscussionResponse as IDiscussionResponse
00047         from Products.CMFCore.interfaces.DublinCore \
00048                 import CatalogableDublinCore as ICatalogableDublinCore
00049         from Products.CMFCore.interfaces.DublinCore \
00050                 import DublinCore as IDublinCore
00051         from Products.CMFCore.interfaces.DublinCore \
00052                 import MutableDublinCore as IMutableDublinCore
00053         from Products.CMFCore.interfaces.Dynamic \
00054                 import DynamicType as IDynamicType
00055         from Products.CMFDefault.DiscussionItem import DiscussionItem
00056 
00057         verifyClass(ICatalogableDublinCore, DiscussionItem)
00058         verifyClass(IContentish, DiscussionItem)
00059         verifyClass(IDiscussionResponse, DiscussionItem)
00060         verifyClass(IDublinCore, DiscussionItem)
00061         verifyClass(IDynamicType, DiscussionItem)
00062         verifyClass(IMutableDublinCore, DiscussionItem)
00063 
00064     def test_z3interfaces(self):
00065         from zope.interface.verify import verifyClass
00066         from Products.CMFCore.interfaces import ICatalogableDublinCore
00067         from Products.CMFCore.interfaces import IContentish
00068         from Products.CMFCore.interfaces import IDiscussionResponse
00069         from Products.CMFCore.interfaces import IDublinCore
00070         from Products.CMFCore.interfaces import IDynamicType
00071         from Products.CMFCore.interfaces import IMutableDublinCore
00072         from Products.CMFDefault.DiscussionItem import DiscussionItem
00073 
00074         verifyClass(ICatalogableDublinCore, DiscussionItem)
00075         verifyClass(IContentish, DiscussionItem)
00076         verifyClass(IDiscussionResponse, DiscussionItem)
00077         verifyClass(IDublinCore, DiscussionItem)
00078         verifyClass(IDynamicType, DiscussionItem)
00079         verifyClass(IMutableDublinCore, DiscussionItem)
00080 
00081 
00082 class DiscussionItemContainerTests(unittest.TestCase):
00083 
00084     def _getTargetClass(self):
00085         from Products.CMFDefault.DiscussionItem import DiscussionItemContainer
00086 
00087         return DiscussionItemContainer
00088 
00089     def test_z2interfaces(self):
00090         from Interface.Verify import verifyClass
00091         from Products.CMFCore.interfaces.Discussions \
00092                 import Discussable as IDiscussable
00093 
00094         verifyClass(IDiscussable, self._getTargetClass())
00095 
00096     def test_z3interfaces(self):
00097         from zope.interface.verify import verifyClass
00098         from Products.CMFCore.interfaces import ICallableOpaqueItemEvents
00099         from Products.CMFCore.interfaces import IDiscussable
00100 
00101         verifyClass(ICallableOpaqueItemEvents, self._getTargetClass())
00102         verifyClass(IDiscussable, self._getTargetClass())
00103 
00104 
00105 class DiscussionTests(SecurityTest):
00106 
00107     layer = EventZCMLLayer
00108 
00109     def setUp(self):
00110         SecurityTest.setUp(self)
00111         self.site = DummySite('site').__of__(self.root)
00112         sm = getSiteManager()
00113         self.site._setObject( 'portal_discussion', DiscussionTool() )
00114         sm.registerUtility(self.site.portal_discussion, IDiscussionTool)
00115         self.site._setObject( 'portal_membership', DummyTool() )
00116         self.site._setObject( 'portal_types', TypesTool() )
00117 
00118     def _makeDummyContent(self, id, *args, **kw):
00119         return self.site._setObject( id, DummyContent(id, *args, **kw) )
00120 
00121     def test_policy( self ):
00122         dtool = self.site.portal_discussion
00123         ttool = self.site.portal_types
00124         test = self._makeDummyContent('test')
00125         self.assertRaises(DiscussionNotAllowed, dtool.getDiscussionFor, test)
00126         assert getattr( test, 'talkback', None ) is None
00127 
00128         test.allow_discussion = 1
00129         assert dtool.getDiscussionFor(test)
00130         assert test.talkback
00131 
00132         del test.talkback
00133         del test.allow_discussion
00134         fti = FTIDATA_DUMMY[0].copy()
00135         ttool._setObject( 'Dummy Content', FTI(**fti) )
00136         self.assertRaises(DiscussionNotAllowed, dtool.getDiscussionFor, test)
00137         assert getattr( test, 'talkback', None ) is None
00138 
00139         ti = getattr(ttool, 'Dummy Content')
00140         ti.allow_discussion = 1
00141         assert dtool.getDiscussionFor(test)
00142         assert test.talkback
00143 
00144         del test.talkback
00145         ti.allow_discussion = 0
00146         self.assertRaises(DiscussionNotAllowed, dtool.getDiscussionFor, test)
00147         assert getattr( test, 'talkback', None ) is None
00148 
00149         test.allow_discussion = 1
00150         assert dtool.getDiscussionFor(test)
00151         assert test.talkback
00152 
00153     def test_nestedReplies( self ):
00154         dtool = self.site.portal_discussion
00155         test = self._makeDummyContent('test')
00156         test.allow_discussion = 1
00157         talkback = dtool.getDiscussionFor(test)
00158         assert talkback._getDiscussable() == test
00159         assert talkback._getDiscussable( outer=1 ) == test
00160         assert not talkback.hasReplies( test )
00161         assert len( talkback.getReplies() ) == 0
00162 
00163         reply_id = talkback.createReply( title='test', text='blah' )
00164         assert talkback.hasReplies( test )
00165         assert len( talkback.getReplies() ) == 1
00166         assert talkback.getReply( reply_id )
00167 
00168         reply1 = talkback.getReplies()[0]
00169         items = talkback._container.items()
00170         self.assertEqual( reply1.getId(), items[0][0] )
00171         self.assertEqual( reply1.inReplyTo(), test )
00172         self.assertEqual( reply1.listCreators(), ('dummy',) )
00173 
00174         parents = reply1.parentsInThread()
00175         assert len( parents ) == 1
00176         assert test in parents
00177 
00178         talkback1 = dtool.getDiscussionFor(reply1)
00179         assert talkback == talkback1
00180         assert len( talkback1.getReplies() ) == 0
00181         assert len( talkback.getReplies() ) == 1
00182 
00183         talkback1.createReply( title='test2'
00184                              , text='blah2'
00185                              )
00186         assert len( talkback._container ) == 2
00187         assert talkback1.hasReplies( reply1 )
00188         assert len( talkback1.getReplies() ) == 1
00189         assert len( talkback.getReplies() ) == 1
00190 
00191         reply2 = talkback1.getReplies()[0]
00192         assert reply2.inReplyTo() == reply1
00193 
00194         parents = reply2.parentsInThread()
00195         assert len( parents ) == 2
00196         assert parents[ 0 ] == test
00197         assert parents[ 1 ] == reply1
00198 
00199         parents = reply2.parentsInThread( 1 )
00200         assert len( parents ) == 1
00201         assert parents[ 0 ] == reply1
00202 
00203     def test_itemCataloguing( self ):
00204         ctool = self.site._setObject( 'portal_catalog', CatalogTool() )
00205         dtool = self.site.portal_discussion
00206         catalog = ctool._catalog
00207         test = self._makeDummyContent('test', catalog=1)
00208         test.allow_discussion = 1
00209 
00210         self.assertEqual( len(ctool), 1 )
00211         self.failUnless( has_path( catalog, test.getPhysicalPath() ) )
00212         talkback = dtool.getDiscussionFor(test)
00213         self.assertEqual( talkback.getPhysicalPath(),
00214                           ('', 'bar', 'site', 'test', 'talkback') )
00215         talkback.createReply( title='test'
00216                             , text='blah'
00217                             )
00218         self.assertEqual( len(ctool), 2 )
00219         for reply in talkback.getReplies():
00220             self.failUnless( has_path( catalog, reply.getPhysicalPath() ) )
00221             self.failUnless( has_path( catalog,
00222                               '/bar/site/test/talkback/%s' % reply.getId() ) )
00223 
00224         reply1 = talkback.getReplies()[0]
00225         talkback1 = dtool.getDiscussionFor(reply1)
00226         talkback1.createReply( title='test2'
00227                              , text='blah2'
00228                              )
00229         for reply in talkback.getReplies():
00230             self.failUnless( has_path( catalog, reply.getPhysicalPath() ) )
00231             self.failUnless( has_path( catalog,
00232                               '/bar/site/test/talkback/%s' % reply.getId() ) )
00233         for reply in talkback1.getReplies():
00234             self.failUnless( has_path( catalog, reply.getPhysicalPath() ) )
00235             self.failUnless( has_path( catalog,
00236                               '/bar/site/test/talkback/%s' % reply.getId() ) )
00237 
00238     def test_itemWorkflowNotification(self):
00239         from Products.CMFDefault.DiscussionItem import DiscussionItem
00240 
00241         dtool = self.site.portal_discussion
00242         test = self._makeDummyContent('test')
00243         test.allow_discussion = 1
00244         talkback = dtool.getDiscussionFor(test)
00245 
00246         # Monkey patch into the class to test, urgh.
00247         def notifyWorkflowCreated(self):
00248             self.test_wf_notified = 1
00249             DiscussionItem.inheritedAttribute('notifyWorkflowCreated')(self)
00250         old_method = getattr(DiscussionItem, 'notifyWorkflowCreated', None)
00251         DiscussionItem.notifyWorkflowCreated = notifyWorkflowCreated
00252         DiscussionItem.test_wf_notified = 0
00253 
00254         try:
00255             reply_id = talkback.createReply(title='test', text='blah')
00256             reply = talkback.getReplies()[0]
00257             self.assertEqual(reply.test_wf_notified, 1)
00258         finally:
00259             delattr(DiscussionItem, 'test_wf_notified')
00260             if old_method is None:
00261                 delattr(DiscussionItem, 'notifyWorkflowCreated')
00262             else:
00263                 DiscussionItem.notifyWorkflowCreated = old_method
00264 
00265     def test_deletePropagation( self ):
00266         ctool = self.site._setObject( 'portal_catalog', CatalogTool() )
00267         dtool = self.site.portal_discussion
00268         test = self._makeDummyContent('test', catalog=1)
00269         test.allow_discussion = 1
00270 
00271         talkback = dtool.getDiscussionFor(test)
00272         talkback.createReply( title='test'
00273                             , text='blah'
00274                             )
00275         self.assertEqual( len(ctool), 2 )
00276         self.site._delObject('test')
00277         self.assertEqual( len(ctool), 0 )
00278 
00279     def test_deleteReplies(self):
00280         dtool = self.site.portal_discussion
00281         ctool = self.site._setObject( 'portal_catalog', CatalogTool() )
00282         test = self._makeDummyContent('test')
00283         test.allow_discussion = 1
00284 
00285         # Create a structure 6 levels deep for testing
00286         talkback = dtool.getDiscussionFor(test)
00287         id1 = talkback.createReply(title='test1', text='blah')
00288         reply1 = talkback.getReply(id1)
00289         talkback1 = dtool.getDiscussionFor(reply1)
00290         id2 = talkback1.createReply(title='test2', text='blah')
00291         reply2 = talkback1.getReply(id2)
00292         talkback2 = dtool.getDiscussionFor(reply2)
00293         id3 = talkback2.createReply(title='test3', text='blah')
00294         reply3 = talkback2.getReply(id3)
00295         talkback3 = dtool.getDiscussionFor(reply3)
00296         id4 = talkback3.createReply(title='test4', text='blah')
00297         reply4 = talkback3.getReply(id4)
00298         talkback4 = dtool.getDiscussionFor(reply4)
00299         id5 = talkback4.createReply(title='test5', text='blah')
00300         reply5 = talkback4.getReply(id5)
00301         talkback5 = dtool.getDiscussionFor(reply5)
00302         id6 = talkback5.createReply(title='test6', text='blah')
00303         reply6 = talkback5.getReply(id6)
00304         talkback6 = dtool.getDiscussionFor(reply6)
00305 
00306         self.assertEqual(len(talkback.getReplies()), 1)
00307         self.assertEqual(len(talkback1.getReplies()), 1)
00308         self.assertEqual(len(talkback2.getReplies()), 1)
00309         self.assertEqual(len(talkback3.getReplies()), 1)
00310         self.assertEqual(len(talkback4.getReplies()), 1)
00311         self.assertEqual(len(talkback5.getReplies()), 1)
00312         self.assertEqual(len(talkback6.getReplies()), 0)
00313         self.assertEqual(len(ctool), 7)
00314 
00315         talkback3.deleteReply(id4)
00316         self.assertEqual(len(talkback.getReplies()), 1)
00317         self.assertEqual(len(talkback1.getReplies()), 1)
00318         self.assertEqual(len(talkback2.getReplies()), 1)
00319         self.assertEqual(len(talkback3.getReplies()), 0)
00320         self.assertEqual(len(ctool), 4)
00321 
00322         talkback.deleteReply(id1)
00323         self.assertEqual(len(talkback.getReplies()), 0)
00324         self.assertEqual(len(ctool), 1)
00325 
00326     def test_newTalkbackIsWrapped(self):
00327         test = self._makeDummyContent('test')
00328         test.allow_discussion = 1
00329         dtool = self.site.portal_discussion
00330         talkback = dtool.getDiscussionFor(test)
00331         self.failUnless(hasattr(talkback, 'aq_base'))
00332         # Acquire a portal tool
00333         self.failUnless(getToolByName(talkback, 'portal_discussion'))
00334 
00335     def test_existingTalkbackIsWrapped(self):
00336         test = self._makeDummyContent('test')
00337         test.allow_discussion = 1
00338         dtool = self.site.portal_discussion
00339         talkback = dtool.getDiscussionFor(test)
00340         talkback = dtool.getDiscussionFor(test)
00341         self.failUnless(hasattr(talkback, 'aq_base'))
00342         # Acquire a portal tool
00343         self.failUnless(getToolByName(talkback, 'portal_discussion'))
00344 
00345 
00346 def test_suite():
00347     return unittest.TestSuite((
00348         unittest.makeSuite(DiscussionItemTests),
00349         unittest.makeSuite(DiscussionItemContainerTests),
00350         unittest.makeSuite(DiscussionTests),
00351         ))
00352 
00353 if __name__ == '__main__':
00354     from Products.CMFCore.testing import run
00355     run(test_suite())