source: products/quintagroup.canonicalpath/trunk/quintagroup/canonicalpath/tests.py @ 2972

Last change on this file since 2972 was 2972, checked in by mylan, 13 years ago

#234: Fixed absence of total string

  • Property svn:eol-style set to native
File size: 18.4 KB
RevLine 
[782]1import unittest
2
3from zope.testing import doctestunit
4from zope.component import testing
[2018]5from zope.component import queryAdapter, queryMultiAdapter, getMultiAdapter
[1922]6from zope.schema.interfaces import InvalidValue
[2018]7
8#for compatibility with older plone versions
9try:
10    from plone.indexer.interfaces import IIndexableObject
11    IS_NEW = True
12except:
13    from plone.app.content.interfaces import IIndexableObjectWrapper \
14        as _old_IIndexableObjectWrapper
15    IS_NEW = False
16
17
[2366]18from OFS.PropertyManager import PropertyManager
19from OFS.Traversable import Traversable
20
[782]21from Testing import ZopeTestCase as ztc
22
[1699]23from Products.Five import zcml
24from Products.Five import fiveconfigure
[1700]25from Products.CMFCore.utils import getToolByName
[1699]26from Products.PloneTestCase import PloneTestCase as ptc
27from Products.PloneTestCase.layer import PloneSite
28
[1702]29from Products.Archetypes.tests.utils import makeContent
30
[1700]31from quintagroup.canonicalpath.interfaces import ICanonicalPath
[1929]32from quintagroup.canonicalpath.interfaces import ICanonicalLink
33from quintagroup.canonicalpath.adapters import PROPERTY_PATH
34from quintagroup.canonicalpath.adapters import PROPERTY_LINK
[2366]35from quintagroup.canonicalpath.upgrades import CanonicalConvertor
[1699]36
[2972]37def registerCanonicalPathInReg():
38    import quintagroup.canonicalpath, Products.Five
39    fiveconfigure.debug_mode = True
40    zcml.load_config('meta.zcml', Products.Five)
41    zcml.load_config('configure.zcml', quintagroup.canonicalpath)
42    fiveconfigure.debug_mode = False
43
[1699]44class TestCase(ptc.PloneTestCase):
45    class layer(PloneSite):
46        @classmethod
47        def setUp(cls):
[2972]48            registerCanonicalPathInReg()
49            # import quintagroup.canonicalpath
50            # fiveconfigure.debug_mode = True
51            # zcml.load_config('configure.zcml', quintagroup.canonicalpath)
52            # fiveconfigure.debug_mode = False
[1699]53
[1700]54ptc.setupPloneSite()
[1699]55
[1922]56class TestIndexerRegistration(TestCase):
[1699]57
[1700]58    def afterSetUp(self):
[1705]59        self.loginAsPortalOwner()
[1922]60        self.catalog = getToolByName(self.portal, 'portal_catalog')
[1705]61        self.my_doc = makeContent(self.portal, portal_type='Document', id='my_doc')
[1922]62        self.logout()
63
[2018]64    def get_indexable_wrapper(self, obj):
65        if IS_NEW:
66            wrapper = None
67            if not IIndexableObject.providedBy(obj):
68                wrapper = queryMultiAdapter((obj, self.catalog), IIndexableObject)
69        else:
70            wf = getattr(self.portal, 'portal_workflow', None)
71            if wf is not None:
72                vars = wf.getCatalogVariablesFor(obj)
73            else:
74                vars = {}
75            wrapper = getMultiAdapter((obj, self.portal), _old_IIndexableObjectWrapper)
76            wrapper.update(vars)
77           
78        return wrapper and wrapper or obj
79
[1922]80    def testForAT(self):
[2018]81        wrapper = self.get_indexable_wrapper(self.my_doc)
[1922]82        self.assertFalse(wrapper is None, "No indexer registered for document object")
[1929]83
84    def testCanonicalPathForAT(self):
[2018]85        wrapper = self.get_indexable_wrapper(self.my_doc)
[1929]86        self.assertTrue(hasattr(wrapper, 'canonical_path'),
87            "'canonical_path' attribute not accessible with indexer wrapper for Document object")
88
89    def testCanonicalLinkForAT(self):
[2018]90        wrapper = self.get_indexable_wrapper(self.my_doc)
[1929]91        self.assertTrue(hasattr(wrapper, 'canonical_link'),
92            "'canonical_link' attribute not accessible with indexer wrapper for Document object")
93
94
[1922]95       
[1929]96class TestDefaultCanonicalPathAdapter(TestCase):
[1922]97
98    def afterSetUp(self):
99        self.loginAsPortalOwner()
[1700]100        self.purl = getToolByName(self.portal, 'portal_url')
[1922]101        self.my_doc = makeContent(self.portal, portal_type='Document', id='my_doc')
[1705]102        self.logout()
[782]103
[1922]104        self.mydoc_cp = '/'+'/'.join(self.purl.getRelativeContentPath(self.my_doc))
105        self.portal_cp = '/'+'/'.join(self.purl.getRelativeContentPath(self.portal))
106
107    def testRegistration4Portal(self):
[1700]108        cpadapter = queryAdapter(self.portal, ICanonicalPath)
109        self.assertFalse(cpadapter is None,
110            "Can't get canonical path adapter for the plone site object")
[782]111
[1922]112    def testRegistration4AT(self):
113        cpadapter = queryAdapter(self.my_doc, ICanonicalPath)
114        self.assertFalse(cpadapter is None,
115            "Can't get canonical path adapter for the Document object")
116       
[782]117
[1922]118    def testGetDefault4Portal(self):
119        cpadapter = queryAdapter(self.portal, ICanonicalPath)
120        self.assertTrue(cpadapter.canonical_path == self.portal_cp,
121            "Canonical path adapter return '%s' for portal, must be: '%s'" % (
122            cpadapter.canonical_path, self.portal_cp) )
[1699]123
[782]124
[1922]125    def testGetDefault4AT(self):
[1705]126        cpadapter = queryAdapter(self.my_doc, ICanonicalPath)
[1922]127        self.assertTrue(cpadapter.canonical_path == self.mydoc_cp,
128            "Canonical path adapter return '%s' for document, must be: '%s'" % (
129            cpadapter.canonical_path, self.mydoc_cp) )
[1700]130
131
[1922]132    def testSet4Portal(self):
133        cpadapter = queryAdapter(self.portal, ICanonicalPath)
134        newcp = self.portal_cp + '/new_portal_canonical'
[1701]135
[1922]136        cpadapter.canonical_path = newcp
[1929]137        prop = self.portal.getProperty(PROPERTY_PATH, None)
[1922]138        self.assertTrue(prop == newcp,
139            "Canonical path adapter setter NOT SET new '%s' value to '%s' " \
[1929]140            "propery for the portal" % (newcp, PROPERTY_PATH) )
[1701]141
[1922]142        self.assertTrue(cpadapter.canonical_path == newcp,
143            "Canonical path adapter GET '%s' canonical_path, for portal, " \
144            "must be: '%s'" % (cpadapter.canonical_path, newcp) )
145
146
147    def testSet4AT(self):
148        cpadapter = queryAdapter(self.my_doc, ICanonicalPath)
149        newcp = self.mydoc_cp + '/new_mydoc_canonical'
150
151        cpadapter.canonical_path = newcp
[1929]152        prop = self.my_doc.getProperty(PROPERTY_PATH, None)
[1922]153        self.assertTrue(prop == newcp,
154            "Canonical path adapter setter NOT SET new '%s' value to '%s' " \
[1929]155            "propery for the Document" % (newcp, PROPERTY_PATH) )
[1922]156
157        self.assertTrue(cpadapter.canonical_path == newcp,
158            "Canonical path adapter GET '%s' canonical_path, for Document, " \
159            "must be: '%s'" % (cpadapter.canonical_path, newcp) )
160
161
[1929]162    def testValidationWrong(self):
[1922]163        cpadapter = queryAdapter(self.my_doc, ICanonicalPath)
164        for wrong in ['new\nline','s p a c e','with\ttabs']:
165            try:
166                cpadapter.canonical_path = wrong
167            except InvalidValue:
168                continue
169            else:
[1934]170                raise self.failureException, "InvalidValue not raised when " \
171                      "'%s' wrong value try to set" % wrong
[1929]172       
173    def testValidationGood(self):
174        cpadapter = queryAdapter(self.my_doc, ICanonicalPath)
175        for good in ['./good','../good','/good', 'good']:
176            cpadapter.canonical_path = good
177
178
[1934]179    def testDeleteProperty(self):
180        hasprop = self.portal.hasProperty
181        cpadapter = queryAdapter(self.portal, ICanonicalPath)
182        cpadapter.canonical_path = '/new_portal_canonical'
183        assert hasprop(PROPERTY_PATH)
184
185        del cpadapter.canonical_path
186        self.assertFalse(hasprop(PROPERTY_PATH),
187            "Not deleted Canonical path customization property for the portal")
188
189
190    def testDelCustomization(self):
191        cpadapter = queryAdapter(self.portal, ICanonicalPath)
192        cpadapter.canonical_path = '/new_portal_canonical'
193        assert cpadapter.canonical_path == '/new_portal_canonical'
194
195        del cpadapter.canonical_path
196        self.assertTrue(cpadapter.canonical_path == self.portal_cp,
197            "After deleted Canonical path customization property not set to "
198            "default value for the portal")
199
200
[1929]201class TestDefaultCanonicalLinkAdapter(TestCase):
202
203    def afterSetUp(self):
204        self.loginAsPortalOwner()
205        self.purl = getToolByName(self.portal, 'portal_url')
206        self.my_doc = makeContent(self.portal, portal_type='Document', id='my_doc')
207        self.logout()
208
209        self.mydoc_cl = self.my_doc.absolute_url()
210
211    def testRegistration4Portal(self):
212        cladapter = queryAdapter(self.portal, ICanonicalLink)
213        self.assertFalse(cladapter is None,
214            "Can't get canonical link adapter for the plone site object")
215
216    def testRegistration4AT(self):
217        cladapter = queryAdapter(self.my_doc, ICanonicalLink)
218        self.assertFalse(cladapter is None,
219            "Can't get canonical link adapter for the Document object")
220       
221
222    def testGetDefault4Portal(self):
223        cladapter = queryAdapter(self.portal, ICanonicalLink)
224        self.assertTrue(cladapter.canonical_link == self.purl(),
225            "Canonical link adapter return '%s' for portal, must be: '%s'" % (
226            cladapter.canonical_link, self.purl()) )
227
228
229    def testGetDefault4AT(self):
230        cladapter = queryAdapter(self.my_doc, ICanonicalLink)
231        self.assertTrue(cladapter.canonical_link == self.mydoc_cl,
232            "Canonical link adapter return '%s' for document, must be: '%s'" % (
233            cladapter.canonical_link, self.mydoc_cl) )
234
235
236    def testSet4Portal(self):
237        cladapter = queryAdapter(self.portal, ICanonicalLink)
238        newcl = self.purl() + '/new_portal_canonical'
239
240        cladapter.canonical_link = newcl
241        prop = self.portal.getProperty(PROPERTY_LINK, None)
242        self.assertTrue(prop == newcl,
243            "Canonical link adapter setter NOT SET new '%s' value to '%s' " \
244            "propery for the portal" % (newcl, PROPERTY_LINK) )
245
246        self.assertTrue(cladapter.canonical_link == newcl,
247            "Canonical link adapter GET '%s' canonical_link, for portal, " \
248            "must be: '%s'" % (cladapter.canonical_link, newcl) )
249
250
251    def testSet4AT(self):
252        cladapter = queryAdapter(self.my_doc, ICanonicalLink)
253        newcl = self.mydoc_cl + '/new_mydoc_canonical'
254
255        cladapter.canonical_link = newcl
256        prop = self.my_doc.getProperty(PROPERTY_LINK, None)
257        self.assertTrue(prop == newcl,
258            "Canonical link adapter setter NOT SET new '%s' value to '%s' " \
259            "propery for the Document" % (newcl, PROPERTY_LINK) )
260
261        self.assertTrue(cladapter.canonical_link == newcl,
262            "Canonical link adapter GET '%s' canonical_link, for Document, " \
263            "must be: '%s'" % (cladapter.canonical_link, newcl) )
264
265    def testValidationWrong(self):
266        cladapter = queryAdapter(self.my_doc, ICanonicalLink)
267        for wrong in ['http://new\nline','s p a c e','with\ttabs']:
268            try:
269                cladapter.canonical_link = wrong
270            except InvalidValue:
271                continue
272            else:
[1922]273                raise self.failureException, "InvalidValue not raised when " \
[1929]274                    "'%s' wrong value try to set" % wrong
275       
276    def testValidationGood(self):
277        cladapter = queryAdapter(self.my_doc, ICanonicalLink)
278        for good in ['http://', './good','../good','/good', 'good']:
279            cladapter.canonical_link = good
[1922]280
281
[1934]282    def testDeleteProperty(self):
283        hasprop = self.portal.hasProperty
284        cladapter = queryAdapter(self.portal, ICanonicalLink)
285        cladapter.canonical_link = '/new_portal_canonical'
286        assert hasprop(PROPERTY_LINK)
287
288        del cladapter.canonical_link
289        self.assertFalse(hasprop(PROPERTY_LINK),
290            "Not deleted Canonical link customization property for the portal")
291
292
293    def test_DelCustomization(self):
294        cladapter = queryAdapter(self.portal, ICanonicalLink)
295        cladapter.canonical_link = '/new_portal_canonical'
296        assert cladapter.canonical_link == '/new_portal_canonical'
297
298        del cladapter.canonical_link
299        self.assertTrue(cladapter.canonical_link == self.purl(),
300            "After deleted Canonical link customization property not set to "
301            "default value for the portal")
302
[2366]303##
304## Dummy object for converter tests
305##
306class PortalURL:
307    def __call__(self):
308        return "http://nohost/plone"
309    def getRelativeContentPath(self, context):
[2371]310        return ("plone", context.getId())
[1934]311
[2366]312class BaseItem:
313    portal_url = PortalURL()
314
315    def __init__(self, id):
316        self.id = id
317
318    def getId(self):
319        return self.id
320
321    def absolute_url(self):
322        return self.portal_url() + '/'+ self.getId()
323
324class GoodItem(BaseItem, PropertyManager, Traversable):
325    """Property provider."""
326
[2372]327class NotPropertyProviderItem(BaseItem, Traversable):
[2366]328    """Not property provider."""
329
330class NotAdaptableItem(BaseItem):
331    """Not adaptable object."""
332
333
[2972]334class TestConvertor(unittest.TestCase):
335
[2366]336    def setUp(self):
[2972]337        registerCanonicalPathInReg()
[2366]338        self.convertor = CanonicalConvertor("http://domain.com")
339
[2370]340    def test_convertIPathToLink(self):
[2366]341        item = GoodItem("item")
342        item._setProperty(PROPERTY_PATH, "/www/some/path")
[2370]343        self.convertor.convertIPathToLink(item)
[2371]344        # 1. check canonical link in result object
[2366]345        result = ICanonicalLink(item).canonical_link
346        expect = "http://domain.com/www/some/path"
347        self.assertEqual(result, expect, "Got %s canonical link, " \
348                         "expect: %s" % (result, expect))
[2371]349        # 2. canonical path propery mast be delete from the object
350        self.assertEqual(item.hasProperty(ICanonicalPath(item).prop), False,
351                         "canonical path' property not deleted from the object")
352
353    def test_convertPPathToLink(self):
354        item = GoodItem("item")
355        item._setProperty("custom_property", "/www/some/path")
356        self.convertor.convertPPathToLink(item, prop="custom_property")
357        # 1. check canonical link in result object
358        result = ICanonicalLink(item).canonical_link
359        expect = "http://domain.com/www/some/path"
360        self.assertEqual(result, expect, "Got %s canonical link, " \
361                         "expect: %s" % (result, expect))
362        # 2. custom_property mast be deleted from the object
363        self.assertEqual(item.hasProperty("custom_property"), False,
364                         "custom_property not deleted from the object")
365
[2366]366    def test_convertBadItems(self):
[2372]367        bad = NotPropertyProviderItem("item")
[2370]368        self.convertor.convertIPathToLink(bad)
[2366]369        result = self.convertor.getLogs()
[2972]370        expect = "NotPropertyProviderItem instance has no attribute 'hasProperty'"
[2366]371        self.assertEqual(expect in result, True, "Wrong log: %s" % result)
372
373        bad = NotAdaptableItem("item")
[2370]374        self.convertor.convertIPathToLink(bad)
[2366]375        result = self.convertor.getLogs()
[2972]376        expect = "zope.component.interfaces.ComponentLookupError"
[2366]377        self.assertEqual(expect in result, True, "Wrong log: %s" % result)
378
379    def test_loggingSuccess(self):
380        good = GoodItem("item")
[2370]381        self.convertor.convertIPathToLink(good)
[2366]382        result = self.convertor.getLogs()
383        expect = "SUCCESS"
384        self.assertEqual(expect in result, True, "Wrong log: %s" % result)
385
386    def test_loggingGet(self):
387        # log must collect new errors
388        # and return full log anytime
[2372]389        bad = NotPropertyProviderItem("item")
[2370]390        self.convertor.convertIPathToLink(bad)
[2366]391        logs = self.convertor.getLogs()
392        logs2 = self.convertor.getLogs()
393        assert logs != ""
394        self.assertEqual(logs == logs2, True,
395             "logs not equal: \"%s\" != \"%s\"" % (logs, logs2))
[2370]396        self.convertor.convertIPathToLink(bad)
[2366]397        logs3 = self.convertor.getLogs()
398        self.assertEqual(logs3 > logs2, True,
399             "Log was not updated - last: \"%s\", previous: \"%s\"" % (logs3, logs2))
400       
401    def test_loggingCleanup(self):
[2372]402        bad = NotPropertyProviderItem("item")
[2370]403        self.convertor.convertIPathToLink(bad)
[2366]404        assert self.convertor.getLogs() != ""
405        self.convertor.cleanupLogs()
406        logs = self.convertor.getLogs()
407        self.assertEqual(logs, "", "Log not cleand-up: \"%s\"" % logs)
408
[2371]409
[2972]410class TestAdaptersRegistration(unittest.TestCase):
[2372]411    """Test of default adapters registration."""
412
413    def setUp(self):
[2972]414        registerCanonicalPathInReg()
[2372]415        self.cant = "Can't get \"%s\" adapter for object, which implement: "
416        self.doget = "Get \"%s\" adapter for object, which implement: "
417
418    def test_PropertyManagerAndTraversable(self):
419        class ProperyAndTraverseProvider(BaseItem, PropertyManager, Traversable):
420            """Property and Traversable provider."""
421        item = ProperyAndTraverseProvider("test")
422        self.assertNotEqual(queryAdapter(item, ICanonicalLink), None,
423           self.cant % ICanonicalLink.__name__ + "IPropertyManager and ITraversable.")
424        self.assertNotEqual(queryAdapter(item, ICanonicalPath), None,
425           self.cant % ICanonicalPath.__name__ + "IPropertyManager and ITraversable.")
426
427    def test_Traversable(self):
428        """Traversable enough for get adapter"""
429        class TraverseProvider(BaseItem, Traversable):
430            """Only Traversable provider."""
431        item = TraverseProvider("test")
432        self.assertNotEqual(queryAdapter(item, ICanonicalLink), None,
433           self.cant % ICanonicalLink.__name__ + "only ITraversable.")
434        self.assertNotEqual(queryAdapter(item, ICanonicalPath), None,
435           self.cant % ICanonicalPath.__name__ + "only ITraversable.")
436
437    def test_PropertyManager(self):
438        """Implementing only IPropertyManager - not enough, because of
439           the default value need ITraversable.
440        """
441        class PropertyManagerProvider(BaseItem, PropertyManager):
442            """Only PropertyManager provider."""
443        item = PropertyManagerProvider("test")
444        self.assertEqual(queryAdapter(item, ICanonicalLink), None,
445           self.doget % ICanonicalLink.__name__ + "only IPropertyManager.")
446        self.assertEqual(queryAdapter(item, ICanonicalPath), None,
447           self.doget % ICanonicalPath.__name__ + "only IPropertyManager.")
448
449    def test_NotProvider(self):
450        class NotProvider(BaseItem):
451            """Nor Traversable not PropertyManager provider."""
452        item = NotProvider("test")
453        self.assertEqual(queryAdapter(item, ICanonicalLink), None,
454           self.doget % ICanonicalLink.__name__ + "nor ITraversabe not IPropertyManager.")
455        self.assertEqual(queryAdapter(item, ICanonicalPath), None,
456           self.doget % ICanonicalPath.__name__ + "nor ITraversabe not IPropertyManager.")
457
458
[1700]459def test_suite():
460    return unittest.TestSuite([
[1922]461        unittest.makeSuite(TestIndexerRegistration),
[1929]462        unittest.makeSuite(TestDefaultCanonicalPathAdapter),
463        unittest.makeSuite(TestDefaultCanonicalLinkAdapter),
[2366]464        unittest.makeSuite(TestConvertor),
[2372]465        unittest.makeSuite(TestAdaptersRegistration),
[782]466        ])
467
468if __name__ == '__main__':
469    unittest.main(defaultTest='test_suite')
Note: See TracBrowser for help on using the repository browser.