Back to index

plone3  3.1.7
testQueryCatalog.py
Go to the documentation of this file.
00001 #
00002 # Test queryCatalog and plone search forms
00003 #
00004 
00005 from Products.CMFPlone.tests import PloneTestCase
00006 
00007 from Products.ZCTextIndex.ParseTree import ParseError
00008 
00009 import types
00010 
00011 
00012 class TestQueryCatalog(PloneTestCase.PloneTestCase):
00013     """Test queryCatalog script.
00014 
00015     Test function of queryCatalog script, **not** the
00016     functionality of the catalog itself. Therefore, we'll replace
00017     the actual call to the catalog to a dummy routine that just
00018     returns the catalog search dictionary so we can examine what
00019     would be searched.
00020     """
00021 
00022     def dummyCatalog(self,REQUEST=None,**kw):
00023         return kw
00024 
00025     def stripStuff(self, query_dict):
00026         # strip portal_types and show_inactive parameter which is
00027         # auto-set with types blacklisting. Useful to simplify test
00028         # assertions when we don't care
00029         if type(query_dict) == types.DictType:
00030             for ignore in ['portal_type', 'show_inactive']:
00031                 if query_dict.has_key(ignore):
00032                     del query_dict[ignore]
00033         return query_dict
00034 
00035     def afterSetUp(self):
00036         self.portal.portal_catalog.__call__ = self.dummyCatalog
00037 
00038     def testEmptyRequest(self):
00039         request = {}
00040         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), [])
00041 
00042     def testNonexistantIndex(self):
00043         request = {'foo':'bar'}
00044         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), [])
00045 
00046     def testNonexistantIndex(self):
00047         request = {'foo':'bar'}
00048         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), [])
00049 
00050     def testRealIndex(self):
00051         request = {'SearchableText':'bar'}
00052         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), 
00053                             {'SearchableText':'bar'})
00054 
00055     def testTwoIndexes(self):
00056         request = {'SearchableText':'bar','foo':'bar'}
00057         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), 
00058                             {'SearchableText':'bar'})
00059 
00060     def testRealIndexes(self):
00061         request = {'SearchableText':'bar','Subject':'bar'}
00062         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), 
00063                             request)
00064 
00065     def testOnlySort(self):
00066         # if we only sort, we shouldn't actually call the catalog
00067         request = {'sort_on':'foozle'}
00068         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), [])
00069         request = {'sort_order':'foozle','sort_on':'foozle'}
00070         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), [])
00071         request = {'sort_order':'foozle'}
00072         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), [])
00073 
00074     def testOnlyUsage(self):
00075         request = {'date_usage':'range:min'}
00076         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), [])
00077 
00078     def testRealWithUsage(self):
00079         request = {'modified':'2004-01-01','modified_usage':'range:min'}
00080         expected = {'modified': {'query': '2004-01-01', 'range': 'min'}}
00081         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), 
00082                             expected)
00083 
00084     def testSortLimit(self):
00085         # the script ignored 'sort_limit'; test to show it no longer does.
00086         request = {'SearchableText':'bar','sort_on':'foozle','sort_limit':50}
00087         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), 
00088                             request)
00089 
00090     def testBlacklistedTypes(self):
00091         request = {'SearchableText':'a*'}
00092         siteProps = self.portal.portal_properties.site_properties
00093         siteProps.types_not_searched = ['Event', 'Unknown Type']
00094         qry = self.folder.queryCatalog(request,use_types_blacklist=True)
00095         self.failUnless('Document' in qry['portal_type'])
00096         self.failUnless('Event' not in qry['portal_type'])
00097 
00098     def testNavigationRoot(self):
00099         request = {'SearchableText':'a*'}
00100         ntp = self.portal.portal_properties.navtree_properties
00101         ntp.root = '/'
00102         qry = self.folder.queryCatalog(request, use_navigation_root=True)
00103         self.assertEquals('/'.join(self.portal.getPhysicalPath()), qry['path'])
00104         self.setRoles(('Manager',))
00105         self.portal.invokeFactory('Folder', 'foo')
00106         ntp.root = '/foo'
00107         qry = self.folder.queryCatalog(request, use_navigation_root=True)
00108         self.assertEquals('/'.join(self.portal.foo.getPhysicalPath()), qry['path'])
00109         
00110     def testNavigationRootDoesNotOverrideExplicitPath(self):
00111         request = {'SearchableText':'a*', 'path':'/yyy/zzz'}
00112         ntp = self.portal.portal_properties.navtree_properties
00113         self.setRoles(('Manager',))
00114         self.portal.invokeFactory('Folder', 'foo')
00115         ntp.root = '/foo'
00116         qry = self.folder.queryCatalog(request, use_navigation_root=True)
00117         self.assertEquals('/yyy/zzz', qry['path'])
00118 
00119 class TestQueryCatalogQuoting(PloneTestCase.PloneTestCase):
00120     """Test logic quoting features queryCatalog script.
00121 
00122     Test function of queryCatalog script, **not** the
00123     functionality of the catalog itself. Therefore, we'll replace
00124     the actual call to the catalog to a dummy routine that just
00125     returns the catalog search dictionary so we can examine what
00126     would be searched.
00127     """
00128 
00129     def dummyCatalog(self, REQUEST=None, **kw):
00130         return kw
00131         
00132     def stripStuff(self, query_dict):
00133         # strip portal_types and show_inactive parameter which is
00134         # auto-set with types blacklisting. Useful to simplify test
00135         # assertions when we don't care
00136         if type(query_dict) == types.DictType:
00137             for ignore in ['portal_type', 'show_inactive']:
00138                 if query_dict.has_key(ignore):
00139                     del query_dict[ignore]
00140         return query_dict
00141 
00142     def afterSetUp(self):
00143         self.portal.portal_catalog.__call__ = self.dummyCatalog
00144 
00145     def testQuotingNone(self):
00146         request = {'SearchableText':'Hello Joel'}
00147         expected = request
00148         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request, quote_logic=1)), expected)
00149 
00150     def testQuotingNotNeeded(self):
00151         request = {'SearchableText':'Hello or Joel'}
00152         expected = request
00153         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request, quote_logic=1)), expected)
00154 
00155     def testQuotingNotNeededWithNot(self):
00156         request = {'SearchableText':'Hello or not Joel'}
00157         expected = request
00158         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request, quote_logic=1)), expected)
00159 
00160     def testQuotingRequiredToEscape(self):
00161         request = {'SearchableText':'Hello Joel Or'}
00162         expected = {'SearchableText':'Hello Joel "Or"'}
00163         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request, quote_logic=1)), expected)
00164 
00165     def testQuotingRequiredToEscapeOptionOff(self):
00166         request = {'SearchableText':'Hello Joel Or'}
00167         expected = request
00168         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), expected)
00169 
00170     def testQuotingWithLeadingNot(self):
00171         request = {'SearchableText':'Not Hello Joel'}
00172         expected = request
00173         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), expected)
00174 
00175     def testEmptyItem(self):
00176         request = {'SearchableText':''}
00177         # queryCatalog will return empty result without calling the catalog tool
00178         expected = []
00179         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), expected)
00180 
00181     def testEmptyItemShowAll(self):
00182         request = {'SearchableText':''}
00183         # Catalog gets a blank search, and returns the empty dict
00184         expected = {}
00185         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request, show_all=1)), expected)
00186 
00187     def testBadCharsAreQuoted(self):
00188         request = {'SearchableText':'context(1)'}
00189         # Catalog gets ( or ) in search and quotes them to avoid parse error
00190         expected = {'SearchableText':'context"("1")"'}
00191         self.assertEqual(self.stripStuff(self.folder.queryCatalog(request)), expected)
00192 
00193 
00194 class TestQueryCatalogParseError(PloneTestCase.PloneTestCase):
00195     """Checks that the queryCatalog script returns an empty result set
00196        in case of ZCTextIndex ParseErrors.
00197 
00198        This testcase uses the real catalog, not a stub.
00199     """
00200 
00201     def afterSetUp(self):
00202         self.folder.invokeFactory('Document', id='doc', text='foo bar baz')
00203 
00204     def testSearchableText(self):
00205         request = {'SearchableText':'foo'}
00206         # We expect a non-empty result set
00207         self.failUnless(self.portal.queryCatalog(request))
00208 
00209     def testParseError(self):
00210         # ZCTextIndex raises ParseError
00211         self.assertRaises(ParseError, self.portal.portal_catalog, 
00212                           SearchableText='-foo')
00213 
00214     def testQueryCatalogParseError(self):
00215         request = {'SearchableText':'-foo'}
00216         # ZCTextIndex raises ParseError which translates to empty result
00217         expected = []
00218         self.assertEqual(self.portal.queryCatalog(request), expected)
00219 
00220     def testQueryCatalogParseError3050(self):
00221         # http://dev.plone.org/plone/ticket/3050
00222         request = {'SearchableText':'AND'}
00223         # ZCTextIndex raises ParseError which translates to empty result
00224         expected = []
00225         self.assertEqual(self.portal.queryCatalog(request), expected)
00226 
00227 
00228 
00229 AddPortalTopics = 'Add portal topics'
00230 
00231 class TestSearchForms(PloneTestCase.PloneTestCase):
00232     """Render all forms related to queryCatalog"""
00233 
00234     def testRenderSearchForm(self):
00235         self.portal.search_form()
00236 
00237     def testRenderSearchResults(self):
00238         self.portal.search()
00239 
00240     def testRenderSearchRSS(self):
00241         self.portal.search_rss(self.portal, self.app.REQUEST)
00242 
00243     def testRenderTopicView(self):
00244         self.setPermissions([AddPortalTopics])
00245         self.folder.invokeFactory('Topic', id='topic')
00246         self.folder.topic.atct_topic_view()
00247 
00248 
00249 def test_suite():
00250     from unittest import TestSuite, makeSuite
00251     suite = TestSuite()
00252     suite.addTest(makeSuite(TestQueryCatalog))
00253     suite.addTest(makeSuite(TestQueryCatalogQuoting))
00254     suite.addTest(makeSuite(TestQueryCatalogParseError))
00255     suite.addTest(makeSuite(TestSearchForms))
00256     return suite