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

Last change on this file since 3599 was 3599, checked in by vmaksymiv, 11 years ago

PPP fixes

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