Back to index

plone3  3.1.7
test_metadata.py
Go to the documentation of this file.
00001 ################################################################################
00002 #
00003 # Copyright (c) 2002-2005, Benjamin Saller <bcsaller@ideasuite.com>, and
00004 #                              the respective authors. All rights reserved.
00005 # For a list of Archetypes contributors see docs/CREDITS.txt.
00006 #
00007 # Redistribution and use in source and binary forms, with or without
00008 # modification, are permitted provided that the following conditions are met:
00009 #
00010 # * Redistributions of source code must retain the above copyright notice, this
00011 #   list of conditions and the following disclaimer.
00012 # * Redistributions in binary form must reproduce the above copyright notice,
00013 #   this list of conditions and the following disclaimer in the documentation
00014 #   and/or other materials provided with the distribution.
00015 # * Neither the name of the author nor the names of its contributors may be used
00016 #   to endorse or promote products derived from this software without specific
00017 #   prior written permission.
00018 #
00019 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00020 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00022 # FOR A PARTICULAR PURPOSE.
00023 #
00024 ################################################################################
00025 
00026 from Acquisition import aq_base
00027 from Acquisition import aq_parent
00028 
00029 from Products.Archetypes.tests.atsitetestcase import ATSiteTestCase
00030 from Products.Archetypes.tests.utils import mkDummyInContext
00031 from Products.Archetypes.tests.utils import gen_class
00032 from Products.Archetypes.tests.test_classgen import Dummy
00033 from Products.Archetypes.tests.test_classgen import schema
00034 
00035 from types import FunctionType, ListType, TupleType
00036 
00037 from Products.Archetypes.atapi import *
00038 from Products.Archetypes import config
00039 from Products.Archetypes.interfaces.field import IObjectField
00040 from Products.Archetypes.config import PKG_NAME
00041 from ComputedAttribute import ComputedAttribute
00042 from DateTime import DateTime
00043 from Products.CMFCore.utils import getToolByName
00044 
00045 fieldList = [
00046     # (accessor, mutator, field),
00047     ('Title', 'setTitle',                    ''),
00048     ('Creator', '',                          ''),
00049     ('Subject','setSubject',                 'subject'),
00050     ('Description','setDescription',         'description'),
00051     ('Publisher', '',                        ''),
00052     ('Contributors','setContributors',       'contributors'),
00053     ('Date', '',                             ''),
00054     ('CreationDate', '',                     ''),
00055     ('EffectiveDate','setEffectiveDate',     'effectiveDate'),
00056     ('ExpirationDate','setExpirationDate',   'expirationDate'),
00057     ('ModificationDate', '',                 ''),
00058     ('Type', '',                             ''),
00059     ('Format', 'setFormat',                  ''),
00060     ('Identifier', '',                       ''),
00061     ('Language','setLanguage',               'language'),
00062     ('Rights','setRights',                   'rights'),
00063 
00064     # allowDiscussion is not part of the official DC metadata set
00065     ('allowDiscussion','isDiscussable','allowDiscussion'),
00066   ]
00067 
00068 class DummyPortalMembership:
00069     def checkPermission(self, *args, **kwargs):
00070         return True
00071 
00072 def addMetadataTo(obj, data='default', mimetype='application/octet-stream', time=1000):
00073     """ """
00074     obj.setTitle(data)
00075     obj.setSubject([data])
00076     obj.setDescription(data)
00077     obj.setContributors([data])
00078     obj.setEffectiveDate(DateTime(time, 0))
00079     obj.setExpirationDate(DateTime(time, 0))
00080     obj.setFormat(mimetype)
00081     obj.setLanguage(data)
00082     obj.setRights(data)
00083 
00084 def compareMetadataOf(test, obj, data='default',
00085                       mimetype='application/octet-stream', time=1000):
00086     l_data = (data,)
00087     test.failUnless(obj.Title() == data, 'Title')
00088     test.failUnless(obj.Subject() == l_data,
00089                     'Subject: %s, %s' % (obj.Subject(), l_data))
00090     test.failUnless(obj.Description() == data, 'Description')
00091     test.failUnless(obj.Contributors() == l_data, 'Contributors')
00092     test.failUnless(obj.EffectiveDate() == DateTime(time, 0).ISO(),
00093                     'effective date')
00094     test.failUnless(obj.ExpirationDate() == DateTime(time, 0).ISO(),
00095                     'expiration date')
00096     if aq_base(obj) is obj:
00097         # If the object is not acquisition wrapped, then those
00098         # ComputedAttributes won't get executed because the
00099         # declaration requires it to be wrapped
00100         # like: ComputedAttribute(method, 1)
00101         test.failUnless(isinstance(obj.effective_date, ComputedAttribute))
00102         test.failUnless(isinstance(obj.expiration_date, ComputedAttribute))
00103     else:
00104         test.failUnlessEqual(str(obj.effective_date),  str(DateTime(time, 0)))
00105         test.failUnlessEqual(str(obj.expiration_date), str(DateTime(time, 0)))
00106     # XXX BROKEN! test.failUnless(obj.Format() == data,
00107     #                             'Format: %s, %s' % (obj.Format(), mimetype))
00108     test.failUnless(obj.Language() == data, 'Language')
00109     test.failUnless(obj.Rights() == data, 'Rights')
00110 
00111 
00112 class DummyFolder(BaseFolder):
00113 
00114     portal_membership = DummyPortalMembership()
00115 
00116 
00117 class ExtensibleMetadataTest(ATSiteTestCase):
00118 
00119     def afterSetUp(self):
00120         ATSiteTestCase.afterSetUp(self)
00121         self._dummy = mkDummyInContext(klass=Dummy, oid='dummy',
00122                                        context=self.portal, schema=schema)
00123         # to enable overrideDiscussionFor
00124         self.setRoles(['Manager'])
00125         self.makeDummy()
00126         addMetadataTo(self._dummy)
00127 
00128     def makeDummy(self):
00129         return self._dummy
00130 
00131     def testAccessors(self):
00132         obj = self._dummy
00133         for field in fieldList:
00134             accessor = field[0]
00135             fobj = getattr(obj, accessor, None)
00136             if not fobj:
00137                 self.fail('Missing accessor for field: %s' % str(field))
00138             self.failUnless(hasattr(obj, accessor),
00139                             'Missing accessor %s' % accessor)
00140             self.failUnless((type(fobj) is FunctionType or
00141                              hasattr(fobj, '__call__')),
00142                             'Accessor %s is not callable' % accessor)
00143 
00144     def testMutators(self):
00145         obj = self._dummy
00146         for field in fieldList:
00147             mutator = field[1]
00148             if not mutator: continue
00149             fobj = getattr(obj, mutator, None)
00150             self.failUnless(hasattr(obj, mutator),
00151                             'Missing mutator %s' % mutator)
00152             self.failUnless((type(fobj) is FunctionType
00153                              or hasattr(fobj, '__call__')),
00154                             'Mutator %s is not callable' % mutator)
00155 
00156     def testMetaFields(self):
00157         obj = self._dummy
00158         for field in fieldList:
00159             meta = field[2]
00160             if not meta: continue
00161             md = aq_base(obj)._md
00162             field = aq_base(obj).Schema()[meta]
00163             self.failUnless(md.has_key(meta), 'Missing field %s' % meta)
00164             _marker = []
00165             value = md.get(meta, _marker)
00166             # We are checking here if the metadata
00167             # for a given field has been correctly initialized.
00168             self.failIf(value is _marker,
00169                         'Metadata field %s has not been correctly '
00170                         'initialized.' % meta)
00171             self.failUnless(field.isMetadata,
00172                             'isMetadata not set correctly for field %s.' % meta)
00173 
00174 
00175 class ExtMetadataContextTest(ATSiteTestCase):
00176 
00177     def afterSetUp(self):
00178         ATSiteTestCase.afterSetUp(self)
00179         self._dummy = mkDummyInContext(klass=Dummy, oid='dummy',
00180                                        context=self.portal, schema=schema)
00181         gen_class(DummyFolder)
00182         portal = self.portal
00183 
00184         # to enable overrideDiscussionFor
00185         self.setRoles(['Manager'])
00186 
00187         parent = mkDummyInContext(klass=DummyFolder, oid='parent',
00188                                   context=portal, schema=None)
00189         self._parent = parent
00190 
00191         # create dummy in context of a plone folder
00192         self._dummy = mkDummyInContext(klass=Dummy, oid='dummy',
00193                                        context=parent, schema=None)
00194 
00195     def testContext(self):
00196         addMetadataTo(self._parent, data='parent', time=1001)
00197         addMetadataTo(self._parent.dummy, data='dummy', time=9998)
00198 
00199         compareMetadataOf(self, self._parent, data='parent', time=1001)
00200         compareMetadataOf(self, self._parent.dummy, data='dummy', time=9998)
00201 
00202     def testUnwrappedContext(self):
00203         addMetadataTo(self._parent, data='parent', time=1001)
00204         addMetadataTo(self._parent.dummy, data='dummy', time=9998)
00205 
00206         compareMetadataOf(self, aq_base(self._parent), data='parent', time=1001)
00207         compareMetadataOf(self, aq_base(self._parent.dummy), data='dummy', time=9998)
00208 
00209     def testIsParent(self):
00210         portal = self.portal
00211         self.failUnless(aq_parent(self._parent) == portal)
00212         dummy_parent = aq_base(aq_parent(self._parent.dummy))
00213         parent = aq_base(self._parent)
00214         self.failUnless(dummy_parent is parent,
00215                         ('Parent is not the parent of dummy! '
00216                          'Some tests will give you false results!'))
00217 
00218 
00219 class ExtMetadataDefaultLanguageTest(ATSiteTestCase):
00220 
00221     def testDefaultLanguage(self):
00222         # This is handled at creation time, so the prop must be set
00223         # then, its not a runtime fallback to the property
00224         self.folder.invokeFactory(id="dummy",
00225                                   type_name="SimpleType")
00226         dummy = getattr(self.folder, 'dummy')
00227         self.failUnlessEqual(dummy.Language(), config.LANGUAGE_DEFAULT)
00228 
00229 
00230 class ExtMetadataSetFormatTest(ATSiteTestCase):
00231 
00232     value = "fooooo"
00233     filename = 'foo.txt'
00234 
00235     def afterSetUp(self):
00236         portal = self.portal
00237 
00238         # to enable overrideDiscussionFor
00239         self.setRoles(['Manager'])
00240 
00241         parent = mkDummyInContext(DummyFolder, oid='parent', context=portal, schema=None)
00242         self._parent = parent
00243 
00244         # create dummy in context of a plone folder
00245         dummy = mkDummyInContext(Dummy, oid='dummy', context=parent, schema=None)
00246         self._dummy = dummy
00247 
00248         pfield = dummy.getPrimaryField()
00249         # tests do need afilefield
00250         self.failUnlessEqual(pfield.getName(), 'afilefield')
00251         pfield.set(dummy, self.value, filename=self.filename, mimetype='text/plain')
00252 
00253         self._parent.dummy = dummy
00254 
00255     def testSetFormat(self):
00256         dummy = self._parent.dummy
00257         pfield = dummy.getPrimaryField()
00258 
00259         self.failUnlessEqual(dummy.Format(), 'text/plain')
00260         self.failUnlessEqual(dummy.getContentType(), 'text/plain')
00261         self.failUnlessEqual(dummy.content_type, 'text/plain')
00262         self.failUnlessEqual(dummy.get_content_type(), 'text/plain')
00263         self.failUnlessEqual(pfield.getContentType(dummy), 'text/plain')
00264         self.failUnlessEqual(pfield.get(dummy).content_type, 'text/plain')
00265 
00266         dummy.setFormat('image/gif')
00267         self.failUnlessEqual(dummy.Format(), 'image/gif')
00268         self.failUnlessEqual(dummy.getContentType(), 'image/gif')
00269         self.failUnlessEqual(dummy.content_type, 'image/gif')
00270         self.failUnlessEqual(dummy.get_content_type(), 'image/gif')
00271         self.failUnlessEqual(pfield.getContentType(dummy), 'image/gif')
00272         self.failUnlessEqual(pfield.get(dummy).content_type, 'image/gif')
00273 
00274     def testSetContentType(self):
00275         dummy = self._parent.dummy
00276         pfield = dummy.getPrimaryField()
00277 
00278         dummy.setContentType('text/plain')
00279         self.failUnlessEqual(dummy.Format(), 'text/plain')
00280         self.failUnlessEqual(dummy.getContentType(), 'text/plain')
00281         self.failUnlessEqual(dummy.content_type, 'text/plain')
00282         self.failUnlessEqual(dummy.get_content_type(), 'text/plain')
00283         self.failUnlessEqual(pfield.getContentType(dummy), 'text/plain')
00284         self.failUnlessEqual(pfield.get(dummy).content_type, 'text/plain')
00285 
00286         dummy.setContentType('image/gif')
00287         self.failUnlessEqual(dummy.Format(), 'image/gif')
00288         self.failUnlessEqual(dummy.getContentType(), 'image/gif')
00289         self.failUnlessEqual(dummy.content_type, 'image/gif')
00290         self.failUnlessEqual(dummy.get_content_type(), 'image/gif')
00291         self.failUnlessEqual(pfield.getContentType(dummy), 'image/gif')
00292         self.failUnlessEqual(pfield.get(dummy).content_type, 'image/gif')
00293 
00294 
00295     def testMultipleChanges(self):
00296         dummy = self._parent.dummy
00297         pfield = dummy.getPrimaryField()
00298 
00299         dummy.setContentType('image/gif')
00300         self.failUnlessEqual(dummy.getContentType(), 'image/gif')
00301         dummy.setFormat('application/pdf')
00302         self.failUnlessEqual(dummy.Format(), 'application/pdf')
00303         dummy.setContentType('image/jpeg')
00304         self.failUnlessEqual(dummy.Format(), 'image/jpeg')
00305 
00306         self.failUnlessEqual(pfield.get(dummy).filename, self.filename)
00307         self.failUnlessEqual(pfield.get(dummy).data, self.value)
00308 
00309     def testChangesOnFieldChangesObject(self):
00310         dummy = self._parent.dummy
00311         pfield = dummy.getPrimaryField()
00312 
00313         data = pfield.get(dummy)
00314         self.failUnlessEqual(data.content_type, 'text/plain')
00315 
00316         data.content_type = 'image/jpeg'
00317 
00318         self.failUnlessEqual(data.content_type, 'image/jpeg')
00319 
00320         pfield.set(dummy, data)
00321         self.failUnlessEqual(dummy.Format(), 'image/jpeg')
00322         self.failUnlessEqual(dummy.getContentType(), 'image/jpeg')
00323         self.failUnlessEqual(dummy.content_type, 'image/jpeg')
00324         self.failUnlessEqual(dummy.get_content_type(), 'image/jpeg')
00325         self.failUnlessEqual(pfield.getContentType(dummy), 'image/jpeg')
00326 
00327     def testDiscussionEditAccessorDoesConversions(self):
00328         # Use a DDocument because the dummy is too dumb for this
00329         self.folder.invokeFactory('DDocument','bogus_item')
00330         dummy = self.folder.bogus_item
00331         # Set Allow discussion
00332         dummy.allowDiscussion(True)
00333         self.failUnless(dummy.isDiscussable())
00334         self.assertEqual(dummy.editIsDiscussable(), True)
00335         dummy.allowDiscussion(None)
00336         self.assertEqual(dummy.editIsDiscussable(), False)
00337         self.assertEqual(dummy.rawIsDiscussable(), None)
00338         dummy.allowDiscussion(False)
00339         self.failIf(dummy.isDiscussable())
00340         self.assertEqual(dummy.editIsDiscussable(), False)
00341         
00342     def testDiscussionOverride(self):
00343         # Make sure that if allowed_discussion is set on the class
00344         # we can still use allowDiscussion to override it.
00345         #
00346         # Use a DDocument because the dummy is too dumb for this
00347         # but temporarily set an allow_discussion attribute on the class.
00348         from Products.Archetypes.examples.DDocument import DDocument
00349         DDocument.allow_discussion = True
00350         self.folder.invokeFactory('DDocument','bogus_item')
00351         dummy = self.folder.bogus_item
00352         dummy.allowDiscussion(None)
00353         # clear our bogus attribute
00354         del DDocument.allow_discussion
00355 
00356 
00357 class TimeZoneTest(ATSiteTestCase):
00358     def _makeDummyContent(self, name):
00359         return mkDummyInContext(
00360             klass=Dummy, oid=name, context=self.portal, schema=schema)
00361 
00362     def test_Date_with_explicit_timezone(self):
00363         item = self._makeDummyContent('item')
00364         item.setModificationDate(DateTime('2007-01-01T12:00:00Z'))
00365         self.assertEqual(item.Date('US/Eastern'),
00366                          '2007-01-01 07:00:00')
00367 
00368     def test_CreationDate_with_explicit_timezone(self):
00369         item = self._makeDummyContent('item')
00370         item.setCreationDate(DateTime('2007-01-01T12:00:00Z'))
00371         self.assertEqual(item.CreationDate('US/Eastern'),
00372                          '2007-01-01 07:00:00')
00373 
00374     def test_ModificationDate_with_explicit_timezone(self):
00375         item = self._makeDummyContent('item')
00376         item.setModificationDate(DateTime('2007-01-01T12:00:00Z'))
00377         self.assertEqual(item.ModificationDate('US/Eastern'),
00378                          '2007-01-01 07:00:00')
00379 
00380     def test_EffectiveDate_with_explicit_timezone(self):
00381         item = self._makeDummyContent('item')
00382         item.setEffectiveDate(DateTime('2007-01-01T12:00:00Z'))
00383         self.assertEqual(item.EffectiveDate('US/Eastern'),
00384                          '2007-01-01 07:00:00')
00385 
00386     def test_ExpirationDate_with_explicit_timezone(self):
00387         item = self._makeDummyContent('item')
00388         item.setExpirationDate(DateTime('2007-01-01T12:00:00Z'))
00389         self.assertEqual(item.ExpirationDate('US/Eastern'),
00390                          '2007-01-01 07:00:00')
00391 
00392 def test_suite():
00393     from unittest import TestSuite, makeSuite
00394     suite = TestSuite()
00395     suite.addTest(makeSuite(ExtensibleMetadataTest))
00396     suite.addTest(makeSuite(ExtMetadataContextTest))
00397     suite.addTest(makeSuite(ExtMetadataDefaultLanguageTest))
00398     suite.addTest(makeSuite(ExtMetadataSetFormatTest))
00399     suite.addTest(makeSuite(TimeZoneTest))
00400     return suite