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

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

Updated tests with new converter by property functionality, fixed bug in converter

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