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

Last change on this file since 2372 was 2372, checked in by mylan, 14 years ago

Added tests of default adapters registration

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