Back to index

plone3  3.1.7
test_atdocument.py
Go to the documentation of this file.
00001 #  ATContentTypes http://plone.org/products/atcontenttypes/
00002 #  Archetypes reimplementation of the CMF core types
00003 #  Copyright (c) 2003-2006 AT Content Types development team
00004 #
00005 #  This program is free software; you can redistribute it and/or modify
00006 #  it under the terms of the GNU General Public License as published by
00007 #  the Free Software Foundation; either version 2 of the License, or
00008 #  (at your option) any later version.
00009 #
00010 #  This program is distributed in the hope that it will be useful,
00011 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 #  GNU General Public License for more details.
00014 #
00015 #  You should have received a copy of the GNU General Public License
00016 #  along with this program; if not, write to the Free Software
00017 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 #
00019 """
00020 """
00021 
00022 __author__ = 'Christian Heimes <tiran@cheimes.de>'
00023 __docformat__ = 'restructuredtext'
00024 
00025 from Testing import ZopeTestCase # side effect import. leave it here.
00026 from Products.ATContentTypes.tests import atcttestcase, atctftestcase
00027 
00028 import time, transaction
00029 from Products.CMFCore.permissions import View
00030 from Products.CMFCore.permissions import ModifyPortalContent
00031 from Products.Archetypes.interfaces.layer import ILayerContainer
00032 from Products.Archetypes.atapi import *
00033 from Products.ATContentTypes.tests.utils import dcEdit
00034 
00035 from Products.ATContentTypes.content.document import ATDocument
00036 from Products.ATContentTypes.lib.validators import TidyHtmlWithCleanupValidator
00037 from Products.ATContentTypes.tests.utils import NotRequiredTidyHTMLValidator
00038 from Products.ATContentTypes.tests.utils import input_file_path
00039 from Products.ATContentTypes.interfaces import IHistoryAware
00040 from Products.ATContentTypes.interfaces import ITextContent
00041 from Products.ATContentTypes.interfaces import IATDocument
00042 from Interface.Verify import verifyObject
00043 from cgi import FieldStorage
00044 from Products.ATContentTypes import config as atct_config
00045 from ZPublisher.HTTPRequest import FileUpload
00046 
00047 # z3 imports
00048 from Products.ATContentTypes.interface import IHistoryAware as Z3IHistoryAware
00049 from Products.ATContentTypes.interface import ITextContent as Z3TextContent
00050 from Products.ATContentTypes.interface import IATDocument as Z3IATDocument
00051 from zope.interface.verify import verifyObject as Z3verifyObject
00052 
00053 example_stx = """
00054 Header
00055 
00056  Text, Text, Text
00057 
00058    * List
00059    * List
00060 """
00061 
00062 example_rest = """
00063 Header
00064 ======
00065 
00066 Text, text, text
00067 
00068 * List
00069 * List
00070 """
00071 
00072 def editATCT(obj):
00073     text_format='text/structured'
00074     dcEdit(obj)
00075     obj.setText(example_stx, mimetype = text_format)
00076 
00077 tests = []
00078 
00079 class TestSiteATDocument(atcttestcase.ATCTTypeTestCase):
00080 
00081     klass = ATDocument
00082     portal_type = 'Document'
00083     title = 'Page'
00084     meta_type = 'ATDocument'
00085     icon = 'document_icon.gif'
00086 
00087     def test_doesImplementHistoryAware(self):
00088         iface = IHistoryAware
00089         self.failUnless(iface.isImplementedBy(self._ATCT))
00090         self.failUnless(verifyObject(iface, self._ATCT))
00091 
00092     def test_doesImplementZ3HistoryAware(self):
00093         iface = Z3IHistoryAware
00094         self.failUnless(Z3verifyObject(iface, self._ATCT))
00095 
00096     def test_implementsTextContent(self):
00097         iface = ITextContent
00098         self.failUnless(iface.isImplementedBy(self._ATCT))
00099         self.failUnless(verifyObject(iface, self._ATCT))
00100 
00101     def test_implementsZ3TextContent(self):
00102         iface = Z3TextContent
00103         self.failUnless(Z3verifyObject(iface, self._ATCT))
00104 
00105     def test_implementsATDocument(self):
00106         iface = IATDocument
00107         self.failUnless(iface.isImplementedBy(self._ATCT))
00108         self.failUnless(verifyObject(iface, self._ATCT))
00109 
00110     def test_implementsZ3ATDocument(self):
00111         iface = Z3IATDocument
00112         self.failUnless(Z3verifyObject(iface, self._ATCT))
00113 
00114     def test_edit(self):
00115         new = self._ATCT
00116         editATCT(new)
00117 
00118     def test_cmf_edit_failure(self):
00119         self._ATCT.edit(thisisnotcmfandshouldbeignored=1)
00120 
00121     def test_rename_keeps_contenttype(self):
00122         doc = self._ATCT
00123         doc.setText(example_rest, mimetype="text/x-rst")
00124         self.failUnless(str(doc.getField('text').getContentType(doc)) == "text/x-rst")
00125         #make sure we have _p_jar
00126         transaction.savepoint(optimistic=True)
00127 
00128         cur_id = 'ATCT'
00129         new_id = 'WasATCT'
00130         self.folder.manage_renameObject(cur_id, new_id)
00131         doc = getattr(self.folder, new_id)
00132         field = doc.getField('text')
00133         self.failUnless(str(field.getContentType(doc)) == "text/x-rst")
00134 
00135     def test_x_safe_html(self):
00136         doc = self._ATCT
00137         mimetypes = (
00138             ('text/html', '<p>test</p>'),
00139             # MTR doens't know about text/stx, and transforming
00140             # doubles the tags. Yuck.
00141             ('text/structured', '<p><p>test</p></p>\n'),
00142             # XXX
00143             # ('text/x-rst', ("<p>&lt;p&gt;test&lt;/p&gt;&lt;script&gt;"
00144             #                 "I'm a nasty boy&lt;p&gt;nested&lt;/p&gt;"
00145             #                 "&lt;/script&gt;</p>\n")),
00146             # ('text/python-source', '<p>test</p>'),
00147             # XXX
00148             # ('text/plain', ("<p>&lt;p&gt;test&lt;/p&gt;&lt;script&gt;"
00149             #                 "I'm a nasty boy&lt;p&gt;nested&lt;/p&gt;"
00150             #                 "&lt;/script&gt;</p>\n")),
00151             )
00152         for mimetype, expected in mimetypes:
00153             # scrub html is removing unallowed tags
00154             text = "<p>test</p><script>I'm a nasty boy<p>nested</p></script>"
00155             doc.setText(text, mimetype=mimetype)
00156             txt = doc.getText()
00157             self.failUnlessEqual(txt, expected, (txt, expected, mimetype))
00158 
00159     def test_get_size(self):
00160         atct = self._ATCT
00161         editATCT(atct)
00162         self.failUnlessEqual(atct.get_size(), len(example_stx))
00163 
00164     if atct_config.HAS_MX_TIDY:
00165         # this test is null and void if mx.Tidy isn't even installed
00166 
00167         def test_tidy_validator_with_upload_wrong_encoding(self): 
00168             doc = self._ATCT
00169     
00170             field = doc.getField('text')
00171             request = self.app.REQUEST
00172             setattr(request, 'text_text_format', 'text/html')
00173             input_file_name = 'tidy1-in.html'
00174             in_file = open(input_file_path(input_file_name))
00175             env = {'REQUEST_METHOD':'PUT'}
00176             headers = {'content-type':'text/html',
00177                        'content-length': len(in_file.read()),
00178                        'content-disposition':'attachment; filename=%s' % input_file_name}
00179             in_file.seek(0)
00180             fs = FieldStorage(fp=in_file, environ=env, headers=headers)
00181             f = FileUpload(fs)
00182     
00183             tcv = TidyHtmlWithCleanupValidator('tidy_validator_with_cleanup')
00184             result = tcv.__call__(f, field=field, REQUEST=request)
00185     
00186             self.assertEquals(result, 1)
00187     
00188             expected_file = open(input_file_path('tidy1-out.html'))
00189             expected = expected_file.read()
00190             expected_file.close()
00191             self.assertEquals(request['text_tidier_data'], expected)
00192         
00193 tests.append(TestSiteATDocument)
00194 
00195 class TestATDocumentFields(atcttestcase.ATCTFieldTestCase):
00196 
00197     def afterSetUp(self):
00198         atcttestcase.ATCTFieldTestCase.afterSetUp(self)
00199         self._dummy = self.createDummy(klass=ATDocument)
00200 
00201     def test_text_field_mutator_filename(self):
00202         dummy = self._dummy
00203         field = dummy.getField('text')
00204         mutator = field.getMutator(dummy)
00205         self.assertEquals(field.getFilename(dummy), '')
00206         self.assertEquals(field.getContentType(dummy), 'text/html')
00207         mutator('', filename='foo.txt')
00208         self.assertEquals(field.getFilename(dummy), 'foo.txt')
00209         self.assertEquals(field.getContentType(dummy), 'text/plain')
00210 
00211     def test_text_field_mutator_mime(self):
00212         dummy = self._dummy
00213         field = dummy.getField('text')
00214         mutator = field.getMutator(dummy)
00215         self.assertEquals(field.getFilename(dummy), '')
00216         self.assertEquals(field.getContentType(dummy), 'text/html')
00217         mutator('', mimetype='text/plain')
00218         self.assertEquals(field.getFilename(dummy), '')
00219         self.assertEquals(field.getContentType(dummy), 'text/plain')
00220 
00221     def test_text_field_mutator_none_mime(self):
00222         dummy = self._dummy
00223         field = dummy.getField('text')
00224         mutator = field.getMutator(dummy)
00225         self.assertEquals(field.getFilename(dummy), '')
00226         self.assertEquals(field.getContentType(dummy), 'text/html')
00227         mutator('', mimetype=None)
00228         self.assertEquals(field.getFilename(dummy), '')
00229         self.assertEquals(field.getContentType(dummy), 'text/plain')
00230 
00231     def test_text_field_mutator_none_filename(self):
00232         dummy = self._dummy
00233         field = dummy.getField('text')
00234         mutator = field.getMutator(dummy)
00235         self.assertEquals(field.getFilename(dummy), '')
00236         self.assertEquals(field.getContentType(dummy), 'text/html')
00237         mutator('', filename=None)
00238         self.assertEquals(field.getFilename(dummy), '')
00239         self.assertEquals(field.getContentType(dummy), 'text/plain')
00240 
00241     def test_text_setEmptyText(self):
00242         dummy = self._dummy
00243         field = dummy.getField('text')
00244 
00245         # set text to a non-trivial value
00246         mutator = field.getMutator(dummy)
00247         mutator('Hello World!')
00248 
00249         # now, set an empty text
00250         mutator('')
00251 
00252         # verify that text is indeed empty
00253         accessor = field.getAccessor(dummy)
00254         self.assertEquals(accessor(), '')
00255         
00256     def test_textField(self):
00257         dummy = self._dummy
00258         field = dummy.getField('text')
00259 
00260         self.failUnless(ILayerContainer.isImplementedBy(field))
00261         self.failUnless(field.required == 0, 'Value is %s' % field.required)
00262         self.failUnless(field.default == '', 'Value is %s' % str(field.default))
00263         self.failUnless(field.searchable == 1, 'Value is %s' % field.searchable)
00264         self.failUnless(field.vocabulary == (),
00265                         'Value is %s' % str(field.vocabulary))
00266         self.failUnless(field.enforceVocabulary == 0,
00267                         'Value is %s' % field.enforceVocabulary)
00268         self.failUnless(field.multiValued == 0,
00269                         'Value is %s' % field.multiValued)
00270         self.failUnless(field.isMetadata == 0, 'Value is %s' % field.isMetadata)
00271         self.failUnless(field.accessor == 'getText',
00272                         'Value is %s' % field.accessor)
00273         self.failUnless(field.mutator == 'setText',
00274                         'Value is %s' % field.mutator)
00275         self.failUnless(field.read_permission == View,
00276                         'Value is %s' % field.read_permission)
00277         self.failUnless(field.write_permission == ModifyPortalContent,
00278                         'Value is %s' % field.write_permission)
00279         self.failUnless(field.generateMode == 'veVc',
00280                         'Value is %s' % field.generateMode)
00281         self.failUnless(field.force == '', 'Value is %s' % field.force)
00282         self.failUnless(field.type == 'text', 'Value is %s' % field.type)
00283         self.failUnless(isinstance(field.storage, AnnotationStorage),
00284                         'Value is %s' % type(field.storage))
00285         self.failUnless(field.getLayerImpl('storage') == AnnotationStorage(migrate=True),
00286                         'Value is %s' % field.getLayerImpl('storage'))
00287         self.failUnless(ILayerContainer.isImplementedBy(field))
00288         self.failUnless(field.validators == NotRequiredTidyHTMLValidator,
00289                         'Value is %s' % repr(field.validators))
00290         self.failUnless(isinstance(field.widget, RichWidget),
00291                         'Value is %s' % id(field.widget))
00292         vocab = field.Vocabulary(dummy)
00293         self.failUnless(isinstance(vocab, DisplayList),
00294                         'Value is %s' % type(vocab))
00295         self.failUnless(tuple(vocab) == (), 'Value is %s' % str(tuple(vocab)))
00296 
00297         self.failUnless(field.primary == 1, 'Value is %s' % field.primary)
00298         self.failUnless(field.default_content_type is None,
00299                         'Value is %s' % field.default_content_type)
00300         self.failUnless(field.default_output_type == 'text/x-html-safe',
00301                         'Value is %s' % field.default_output_type)
00302 
00303         self.failUnless('text/html' in field.getAllowedContentTypes(dummy))
00304 
00305 tests.append(TestATDocumentFields)
00306 
00307 class TestATDocumentFunctional(atctftestcase.ATCTIntegrationTestCase):
00308     
00309     portal_type = 'Document'
00310     views = ('document_view', )
00311 
00312     def test_id_change_on_initial_edit(self):
00313         """Make sure Id is taken from title on initial edit and not otherwise"""
00314         # first create an object using the createObject script
00315 
00316         response = self.publish(self.folder_path +
00317                                 '/createObject?type_name=%s' % self.portal_type,
00318                                 self.basic_auth)
00319 
00320         self.assertStatusEqual(response.getStatus(), 302) # Redirect to edit
00321 
00322         location = response.getHeader('Location')
00323         self.failUnless(location.startswith(self.folder_url), location)
00324         self.failUnless(location.endswith('edit'), location)
00325 
00326         # Perform the redirect
00327         edit_form_path = location[len(self.app.REQUEST.SERVER_URL):]
00328         response = self.publish(edit_form_path, self.basic_auth)
00329         self.assertStatusEqual(response.getStatus(), 200) # OK
00330 
00331         #Change the title
00332         temp_id = location.split('/')[-2]
00333         obj_title = "New Title for Object"
00334         new_id = "new-title-for-object"
00335         new_obj = getattr(self.folder.aq_explicit, temp_id)
00336         new_obj_path = '/%s' % new_obj.absolute_url(1)
00337         self.failUnlessEqual(new_obj.checkCreationFlag(), True) # object is not yet edited
00338 
00339         response = self.publish('%s/atct_edit?form.submitted=1&title=%s&text=Blank' % (new_obj_path, obj_title,), self.basic_auth) # Edit object
00340         self.assertStatusEqual(response.getStatus(), 302) # OK
00341         self.failUnlessEqual(new_obj.getId(), new_id) # does id match
00342         self.failUnlessEqual(new_obj.checkCreationFlag(), False) # object is fully created
00343         new_title = "Second Title"
00344         response = self.publish('%s/atct_edit?form.submitted=1&title=%s&text=Blank' % ('/%s' % new_obj.absolute_url(1), new_title,), self.basic_auth) # Edit object
00345         self.assertStatusEqual(response.getStatus(), 302) # OK
00346         self.failUnlessEqual(new_obj.getId(), new_id) # id shouldn't have changed
00347 
00348 tests.append(TestATDocumentFunctional)
00349 
00350 import unittest
00351 def test_suite():
00352     suite = unittest.TestSuite()
00353     for test in tests:
00354         suite.addTest(unittest.makeSuite(test))
00355     return suite