Back to index

plone3  3.1.7
test_Topic.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 Topic module.
00014 
00015 $Id: test_Topic.py 76996 2007-06-24 00:18:49Z hannosch $
00016 """
00017 
00018 import unittest
00019 from Testing import ZopeTestCase
00020 ZopeTestCase.installProduct('CMFTopic', 1)
00021 
00022 from Acquisition import Implicit
00023 
00024 from zope.component import getSiteManager
00025 
00026 from Products.CMFCore.interfaces import ISyndicationTool
00027 from Products.CMFCore.testing import ConformsToFolder
00028 from Products.CMFCore.testing import EventZCMLLayer
00029 from Products.CMFCore.tests.base.dummy import DummySite
00030 from Products.CMFCore.tests.base.testcase import SecurityTest
00031 from Products.CMFCore.TypesTool import FactoryTypeInformation as FTI
00032 from Products.CMFCore.TypesTool import TypesTool
00033 
00034 
00035 class FauxBrain( Implicit ):
00036 
00037     def __init__( self, object ):
00038 
00039         self._object = object
00040 
00041     def getObject( self ):
00042 
00043         return self._object
00044 
00045 
00046 class DummyDocument( Implicit ):
00047 
00048     def __init__( self, id ):
00049 
00050         self._id = id
00051 
00052     def getId( self ):
00053 
00054         return self._id
00055 
00056 
00057 class DummyCatalog( Implicit ):
00058 
00059     def __init__( self, index_ids=() ):
00060 
00061         self._objects = []
00062         self._index_ids = index_ids
00063         self._indexes = {}
00064 
00065         for index_id in index_ids:
00066             self._indexes[ index_id ] = {}
00067 
00068     def _index( self, obj, idxs=[] ):
00069 
00070         marker = object()
00071         self._objects.append( obj )
00072 
00073         rid = len( self._objects ) - 1
00074 
00075         for index_id in self._index_ids:
00076 
00077             value = getattr( obj, index_id, marker )
00078 
00079             if value is not marker:
00080                 for word in value.split():
00081                     bucket = self._indexes[ index_id ].setdefault( word, [] )
00082                     bucket.append( rid )
00083 
00084     indexObject = _index
00085 
00086     reindexObject = _index
00087 
00088     def searchResults( self, REQUEST=None, **kw ):
00089 
00090         limit = None
00091 
00092         criteria = kw.copy()
00093 
00094         if REQUEST is not None:
00095             for k, v in REQUEST:
00096                 criteria[ k ] = v
00097 
00098         results = set(range(len(self._objects)))
00099 
00100         for k, v in criteria.items():
00101 
00102             if k == 'sort_limit':
00103                 limit = v
00104 
00105             else:
00106                 results &= set(self._indexes[k].get(v, []))
00107 
00108         results = [ x for x in results ]
00109 
00110         if limit is not None:
00111             results = results[ :limit ]
00112 
00113         return [ FauxBrain( self._objects[ rid ] ) for rid in results ]
00114 
00115 
00116 class DummySyndicationTool( Implicit ):
00117 
00118     def __init__( self, max_items ):
00119 
00120         self._max_items = max_items
00121 
00122     def getMaxItems( self, object ):
00123 
00124         return self._max_items
00125 
00126 
00127 class TestTopic(ConformsToFolder, SecurityTest):
00128 
00129     """ Test all the general Topic cases.
00130     """
00131 
00132     layer = EventZCMLLayer
00133 
00134     def _getTargetClass(self):
00135         from Products.CMFTopic.Topic import Topic
00136 
00137         return Topic
00138 
00139     def _makeOne(self, id, *args, **kw):
00140         return self.site._setObject(id,
00141                                     self._getTargetClass()(id, *args, **kw))
00142 
00143     def _initSite(self, max_items=15, index_ids=()):
00144         sm = getSiteManager()
00145         self.site.portal_catalog = DummyCatalog( index_ids )
00146         self.site.portal_syndication = DummySyndicationTool( max_items )
00147         sm.registerUtility(self.site.portal_syndication, ISyndicationTool)
00148 
00149     def _initDocuments(self, **kw):
00150         for k, v in kw.items():
00151 
00152             document = DummyDocument( k )
00153             document.description = v
00154 
00155             self.site._setObject( k, v )
00156             self.site.portal_catalog._index( document )
00157 
00158     def setUp(self):
00159         SecurityTest.setUp(self)
00160         self.site = DummySite('site').__of__(self.root)
00161 
00162     def test_z2interfaces(self):
00163         from Interface.Verify import verifyClass
00164         from OFS.IOrderSupport import IOrderedContainer
00165 
00166         verifyClass(IOrderedContainer, self._getTargetClass())
00167 
00168     def test_z3interfaces(self):
00169         from zope.interface.verify import verifyClass
00170         from OFS.interfaces import IOrderedContainer
00171         from Products.CMFCore.interfaces import IContentish
00172         from Products.CMFTopic.interfaces import IMutableTopic
00173         from Products.CMFTopic.interfaces import ITopic
00174 
00175         verifyClass(IContentish, self._getTargetClass())
00176         verifyClass(IMutableTopic, self._getTargetClass())
00177         verifyClass(ITopic, self._getTargetClass())
00178         verifyClass(IOrderedContainer, self._getTargetClass())
00179 
00180     def test_Empty( self ):
00181         topic = self._makeOne('top')
00182 
00183         query = topic.buildQuery()
00184         self.assertEqual( len( query ), 0 )
00185 
00186     def test_Simple( self ):
00187         topic = self._makeOne('top')
00188         topic.addCriterion( 'foo', 'String Criterion' )
00189         topic.getCriterion( 'foo' ).edit( 'bar' )
00190 
00191         query = topic.buildQuery()
00192         self.assertEqual( len(query), 1 )
00193         self.assertEqual( query['foo'], 'bar' )
00194 
00195         topic.addCriterion( 'baz', 'Integer Criterion' )
00196         topic.getCriterion( 'baz' ).edit( 43 )
00197 
00198         query = topic.buildQuery()
00199         self.assertEqual( len( query ), 2 )
00200         self.assertEqual( query[ 'foo' ], 'bar' )
00201         self.assertEqual( query[ 'baz' ], 43 )
00202 
00203     def test_Nested( self ):
00204         self.site._setObject( 'portal_types', TypesTool() )
00205         self.site.portal_types._setObject('Topic', FTI(id='Topic',
00206                                       product='CMFTopic', factory='addTopic'))
00207         topic = self._makeOne('top')
00208         topic._setPortalTypeName('Topic')
00209 
00210         topic.addCriterion( 'foo', 'String Criterion' )
00211         topic.getCriterion( 'foo' ).edit( 'bar' )
00212 
00213         topic.addSubtopic( 'qux' )
00214         subtopic = topic.qux
00215 
00216         subtopic.addCriterion( 'baz', 'String Criterion' )
00217         subtopic.getCriterion( 'baz' ).edit( 'bam' )
00218 
00219         query = subtopic.buildQuery()
00220         self.assertEqual( len( query ), 2 )
00221         self.assertEqual( query['foo'], 'bar' )
00222         self.assertEqual( query['baz'], 'bam' )
00223 
00224         subtopic.acquireCriteria = 0
00225         query = subtopic.buildQuery()
00226         self.assertEqual( len( query ), 1 )
00227         self.assertEqual( query['baz'], 'bam' )
00228 
00229     def test_selfIndexing(self):
00230         # The Topic object is CatalogAware and should be in the catalog
00231         # after it has beeen instantiated.
00232         self._initSite()
00233         topic = self._makeOne('top')
00234 
00235         # A topic without criteria will return a full catalog search result
00236         # set, so we should not have one result, for the Topic object itself.
00237         results = topic.queryCatalog()
00238 
00239         self.assertEquals(len(results), 1)
00240         self.assertEquals(results[0].getObject().getId(), topic.getId())
00241         self.assertEquals(results[0].getObject(), topic)
00242 
00243     def test_searchableText(self):
00244         # Test the catalog helper
00245         topic = self._makeOne('top')
00246         topic.edit(False, title='FOO', description='BAR')
00247 
00248         st = topic.SearchableText()
00249         self.failUnless(st.find('BAR') != -1)
00250         self.failUnless(st.find('FOO') != -1)
00251 
00252     def test_queryCatalog_noop( self ):
00253 
00254         self._initSite()
00255         self._initDocuments( **_DOCUMENTS )
00256         topic = self._makeOne('top')
00257 
00258         # Need to filter out the Topic object itself, which is also
00259         # CatalogAware and will index itself after instantiation.
00260         brains = [ x for x in topic.queryCatalog()
00261                       if x.getObject().getId() != 'top' ]
00262 
00263         self.assertEqual( len( brains ), len( _DOCUMENTS ) )
00264 
00265         objects = [ brain.getObject() for brain in brains ]
00266 
00267         for object in objects:
00268             self.failUnless( object.getId() in _DOCUMENTS.keys() )
00269             self.failUnless( object.description in _DOCUMENTS.values() )
00270 
00271     def test_queryCatalog_simple( self ):
00272 
00273         WORD = 'something'
00274 
00275         self._initSite( index_ids=( 'description', ) )
00276         self._initDocuments( **_DOCUMENTS )
00277         topic = self._makeOne('top')
00278 
00279         topic.addCriterion( 'description', 'String Criterion' )
00280         topic.getCriterion( 'description' ).edit( WORD )
00281 
00282         brains = topic.queryCatalog()
00283 
00284         self.assertEqual( len( brains )
00285                         , len( [ x for x in _DOCUMENTS.values()
00286                                   if WORD in x ] ) )
00287 
00288         objects = [ brain.getObject() for brain in brains ]
00289 
00290         for object in objects:
00291             self.failUnless( object.getId() in _DOCUMENTS.keys() )
00292             self.failUnless( object.description in _DOCUMENTS.values() )
00293 
00294     def test_synContentValues_simple( self ):
00295 
00296         self._initSite()
00297         self._initDocuments( **_DOCUMENTS )
00298         topic = self._makeOne('top')
00299 
00300         #brains = topic.synContentValues()
00301         # Need to filter out the Topic object itself, which is also
00302         # CatalogAware and will index itself after instantiation.
00303         brains = [ x for x in topic.synContentValues()
00304                       if x.getObject().getId() != 'top' ]
00305 
00306         self.assertEqual( len( brains ), len( _DOCUMENTS ) )
00307 
00308         objects = [ brain.getObject() for brain in brains ]
00309 
00310         for object in objects:
00311             self.failUnless( object.getId() in _DOCUMENTS.keys() )
00312             self.failUnless( object.description in _DOCUMENTS.values() )
00313 
00314     def test_synContentValues_limit( self ):
00315 
00316         LIMIT = 3
00317 
00318         self._initSite( max_items=LIMIT )
00319         self._initDocuments( **_DOCUMENTS )
00320         topic = self._makeOne('top')
00321 
00322         brains = topic.synContentValues()
00323 
00324         self.assertEqual( len( brains ), LIMIT )
00325 
00326         objects = [ brain.getObject() for brain in brains ]
00327 
00328         for object in objects:
00329             self.failUnless( object.getId() in _DOCUMENTS.keys() )
00330             self.failUnless( object.description in _DOCUMENTS.values() )
00331 
00332 
00333 _DOCUMENTS = \
00334 { 'one'     : "something in the way she moves"
00335 , 'two'     : "I don't know much about history"
00336 , 'three'   : "something about Mary"
00337 , 'four'    : "something tells me I'm in love"
00338 , 'five'    : "there's a certain wonderful something"
00339 , 'six'     : "gonna wash that man right out of my hair"
00340 , 'seven'   : "I'm so much in love"
00341 }
00342 
00343 
00344 def test_suite():
00345     return unittest.TestSuite((
00346         unittest.makeSuite(TestTopic),
00347         ))
00348 
00349 if __name__ == '__main__':
00350     from Products.CMFCore.testing import run
00351     run(test_suite())