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
Line 
1import unittest
2
3from zope.testing import doctestunit
4from zope.component import testing
5from zope.component import queryAdapter, queryMultiAdapter, getMultiAdapter
6from zope.schema.interfaces import InvalidValue
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
18from OFS.PropertyManager import PropertyManager
19from OFS.Traversable import Traversable
20
21from Testing import ZopeTestCase as ztc
22
23from Products.Five import zcml
24from Products.Five import fiveconfigure
25from Products.CMFCore.utils import getToolByName
26from Products.PloneTestCase import PloneTestCase as ptc
27from Products.PloneTestCase.layer import PloneSite
28
29from Products.Archetypes.tests.utils import makeContent
30
31from quintagroup.canonicalpath.interfaces import ICanonicalPath
32from quintagroup.canonicalpath.interfaces import ICanonicalLink
33from quintagroup.canonicalpath.adapters import PROPERTY_PATH
34from quintagroup.canonicalpath.adapters import PROPERTY_LINK
35from quintagroup.canonicalpath.upgrades import CanonicalConvertor
36
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
44class TestCase(ptc.PloneTestCase):
45    class layer(PloneSite):
46        @classmethod
47        def setUp(cls):
48            registerCanonicalPathInReg()
49            # import quintagroup.canonicalpath
50            # fiveconfigure.debug_mode = True
51            # zcml.load_config('configure.zcml', quintagroup.canonicalpath)
52            # fiveconfigure.debug_mode = False
53
54ptc.setupPloneSite()
55
56class TestIndexerRegistration(TestCase):
57
58    def afterSetUp(self):
59        self.loginAsPortalOwner()
60        self.catalog = getToolByName(self.portal, 'portal_catalog')
61        self.my_doc = makeContent(self.portal, portal_type='Document', id='my_doc')
62        self.logout()
63
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
80    def testForAT(self):
81        wrapper = self.get_indexable_wrapper(self.my_doc)
82        self.assertFalse(wrapper is None, "No indexer registered for document object")
83
84    def testCanonicalPathForAT(self):
85        wrapper = self.get_indexable_wrapper(self.my_doc)
86        self.assertTrue(hasattr(wrapper, 'canonical_path'),
87            "'canonical_path' attribute not accessible with indexer wrapper for Document object")
88
89    def testCanonicalLinkForAT(self):
90        wrapper = self.get_indexable_wrapper(self.my_doc)
91        self.assertTrue(hasattr(wrapper, 'canonical_link'),
92            "'canonical_link' attribute not accessible with indexer wrapper for Document object")
93
94
95       
96class TestDefaultCanonicalPathAdapter(TestCase):
97
98    def afterSetUp(self):
99        self.loginAsPortalOwner()
100        self.purl = getToolByName(self.portal, 'portal_url')
101        self.my_doc = makeContent(self.portal, portal_type='Document', id='my_doc')
102        self.logout()
103
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):
108        cpadapter = queryAdapter(self.portal, ICanonicalPath)
109        self.assertFalse(cpadapter is None,
110            "Can't get canonical path adapter for the plone site object")
111
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       
117
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) )
123
124
125    def testGetDefault4AT(self):
126        cpadapter = queryAdapter(self.my_doc, ICanonicalPath)
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) )
130
131
132    def testSet4Portal(self):
133        cpadapter = queryAdapter(self.portal, ICanonicalPath)
134        newcp = self.portal_cp + '/new_portal_canonical'
135
136        cpadapter.canonical_path = newcp
137        prop = self.portal.getProperty(PROPERTY_PATH, None)
138        self.assertTrue(prop == newcp,
139            "Canonical path adapter setter NOT SET new '%s' value to '%s' " \
140            "propery for the portal" % (newcp, PROPERTY_PATH) )
141
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
152        prop = self.my_doc.getProperty(PROPERTY_PATH, None)
153        self.assertTrue(prop == newcp,
154            "Canonical path adapter setter NOT SET new '%s' value to '%s' " \
155            "propery for the Document" % (newcp, PROPERTY_PATH) )
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
162    def testValidationWrong(self):
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:
170                raise self.failureException, "InvalidValue not raised when " \
171                      "'%s' wrong value try to set" % wrong
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
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
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:
273                raise self.failureException, "InvalidValue not raised when " \
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
280
281
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
303##
304## Dummy object for converter tests
305##
306class PortalURL:
307    def __call__(self):
308        return "http://nohost/plone"
309    def getRelativeContentPath(self, context):
310        return ("plone", context.getId())
311
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
327class NotPropertyProviderItem(BaseItem, Traversable):
328    """Not property provider."""
329
330class NotAdaptableItem(BaseItem):
331    """Not adaptable object."""
332
333
334class TestConvertor(unittest.TestCase):
335
336    def setUp(self):
337        registerCanonicalPathInReg()
338        self.convertor = CanonicalConvertor("http://domain.com")
339
340    def test_convertIPathToLink(self):
341        item = GoodItem("item")
342        item._setProperty(PROPERTY_PATH, "/www/some/path")
343        self.convertor.convertIPathToLink(item)
344        # 1. check canonical link in result object
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))
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
366    def test_convertBadItems(self):
367        bad = NotPropertyProviderItem("item")
368        self.convertor.convertIPathToLink(bad)
369        result = self.convertor.getLogs()
370        expect = "NotPropertyProviderItem instance has no attribute 'hasProperty'"
371        self.assertEqual(expect in result, True, "Wrong log: %s" % result)
372
373        bad = NotAdaptableItem("item")
374        self.convertor.convertIPathToLink(bad)
375        result = self.convertor.getLogs()
376        expect = "zope.component.interfaces.ComponentLookupError"
377        self.assertEqual(expect in result, True, "Wrong log: %s" % result)
378
379    def test_loggingSuccess(self):
380        good = GoodItem("item")
381        self.convertor.convertIPathToLink(good)
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
389        bad = NotPropertyProviderItem("item")
390        self.convertor.convertIPathToLink(bad)
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))
396        self.convertor.convertIPathToLink(bad)
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):
402        bad = NotPropertyProviderItem("item")
403        self.convertor.convertIPathToLink(bad)
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
409
410class TestAdaptersRegistration(unittest.TestCase):
411    """Test of default adapters registration."""
412
413    def setUp(self):
414        registerCanonicalPathInReg()
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
459def test_suite():
460    return unittest.TestSuite([
461        unittest.makeSuite(TestIndexerRegistration),
462        unittest.makeSuite(TestDefaultCanonicalPathAdapter),
463        unittest.makeSuite(TestDefaultCanonicalLinkAdapter),
464        unittest.makeSuite(TestConvertor),
465        unittest.makeSuite(TestAdaptersRegistration),
466        ])
467
468if __name__ == '__main__':
469    unittest.main(defaultTest='test_suite')
Note: See TracBrowser for help on using the repository browser.