test.erp5.testWebDavSupport.py 12 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2004, 2010 Nexedi SA and Contributors.
# All Rights Reserved.
#          Nicolas Delaby <nicolas@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################

import unittest
import os
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
34
from Products.ERP5Type.tests.utils import FileUpload
35
from unittest import expectedFailure
36

37 38
import six.moves.http_client
from six.moves import cStringIO as StringIO
39 40 41
from DateTime import DateTime

from lxml import etree
42
from six.moves import range
43 44

def makeFilePath(name):
45 46 47
  import Products.ERP5.tests
  return os.path.join(os.path.dirname(Products.ERP5.tests.__file__),
                      'test_data', name)
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

def makeFileUpload(name, as_name=None):
  if as_name is None:
    as_name = name
  path = makeFilePath(name)
  return FileUpload(path, as_name)

class TestWebDavSupport(ERP5TypeTestCase):
  """Test for WEBDAV access.
  """

  authentication = 'ERP5TypeTestCase:'

  def getTitle(self):
    return "Test WebDav Support"

  def getBusinessTemplateList(self):
    """
    Return the list of required business templates.
    """
    return ('erp5_base',
            'erp5_ingestion',
            'erp5_ingestion_mysql_innodb_catalog',
            'erp5_web',
            'erp5_dms',
            )

  def afterSetUp(self):
76
    pass
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91

  def clearModule(self, module):
    module.manage_delObjects(list(module.objectIds()))
    self.tic()

  def beforeTearDown(self):
    self.clearModule(self.portal.document_module)
    self.clearModule(self.portal.web_page_module)

  def getDocumentModule(self):
    return self.portal.getDefaultModule('Text')

  def getWebPageModule(self):
    return self.portal.getDefaultModule('Web Page')

92 93 94 95 96 97 98 99 100 101
  def test_PUT_embedded_file(self):
    """Test a file can be uploaded on a document allowing embedded files
    """
    person = self.portal.person_module.newContent()
    self.tic()
    file_object = makeFileUpload('images/erp5_logo.png')
    response = self.publish(person.getPath() + '/erp5_logo.png',
                            request_method='PUT',
                            stdin=file_object,
                            basic=self.authentication)
102
    self.assertEqual(response.getStatus(), six.moves.http_client.CREATED)
103 104 105 106 107 108
    image = person['erp5_logo.png']
    self.assertEqual(image.getPortalType(), 'Embedded File')
    self.assertEqual(image.getContentType(), 'image/png')
    file_object.seek(0)
    self.assertEqual(image.getData(), file_object.read())

109 110 111 112 113 114 115 116 117 118 119 120 121
  def test_PUT_on_contributionTool(self):
    """Test Portal Contribution through Webdav calls
    Create a document
    """
    # Create a new document via FTP/DAV
    path = self.portal.portal_contributions.getPath()
    filename = 'P-DMS-Presentation.3.Pages-001-en.odp'
    file_object = makeFileUpload(filename)
    response = self.publish('%s/%s' % (path, filename),
                            request_method='PUT',
                            stdin=file_object,
                            basic=self.authentication)

122
    self.assertEqual(response.getStatus(), six.moves.http_client.CREATED)
123
    document_module = self.getDocumentModule()
124
    self.assertIn(filename, document_module.objectIds())
125
    self.assertEqual(document_module[filename].getPortalType(), 'Presentation')
126
    file_object.seek(0)
127
    self.assertEqual(document_module[filename].getData(), file_object.read())
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143

  def test_GET_on_contributionTool(self):
    """Get a document through Contribution Tool.

    XXX not sure if this test is usefull as listing all Documents from ZODB
    can collapse the portal
    """
    # Create a new document via FTP/DAV
    path = self.portal.portal_contributions.getPath()
    filename = 'P-DMS-Presentation.3.Pages-001-en.odp'
    file_object = makeFileUpload(filename)
    response = self.publish('%s/%s' % (path, filename),
                            request_method='PUT',
                            stdin=file_object,
                            basic=self.authentication)

144
    self.assertEqual(response.getStatus(), six.moves.http_client.CREATED)
145 146 147 148 149 150
    self.tic()

    # check Document fetching
    document_module = self.getDocumentModule()
    document = document_module[filename]
    document_id = '%s-%s' % (document.getUid(), filename,)
151 152
    # This is HTTPServer.zhttp_server not HTTPServer.zwebdav_server
    # force usage of manage_FTPget like zwebdav_server does
153
    response = self.publish('%s/%s/manage_FTPget' % (path, document_id),
154 155 156
                            request_method='GET',
                            stdin=StringIO(),
                            basic=self.authentication)
157
    self.assertEqual(response.getStatus(), six.moves.http_client.OK)
158
    self.assertEqual(response.getBody(), document.getData(),
159
          'Error in getting data, get:%r' % response.getHeader('content-type'))
160 161 162 163 164 165 166 167 168 169 170 171

  def test_PUT_on_web_page(self):
    """Edit a web_page in webdav
    with encoded data in iso-8859-1
    """
    # Create a new document via FTP/DAV
    path = self.portal.portal_contributions.getPath()
    filename = 'my_document.html'
    response = self.publish('%s/%s' % (path, filename),
                            request_method='PUT',
                            basic=self.authentication)

172
    self.assertEqual(response.getStatus(), six.moves.http_client.CREATED)
173
    web_page_module = self.getWebPageModule()
174
    self.assertIn(filename, web_page_module.objectIds())
175
    self.assertEqual(web_page_module[filename].getPortalType(), 'Web Page')
176 177 178 179 180 181 182 183 184 185 186 187 188 189

    # Edit a new document via FTP/DAV
    text_content= """<html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
      </head>
      <body>
        <p>Content edited through webdav in iso-8859-1</p>
        <p>éàèùêôîç</p>
      </body>
    </html>
    """
    iso_text_content = text_content.decode('utf-8').encode('iso-8859-1')
    path = web_page_module.getPath()
190
    for _ in range(2): # Run twice to check the code that compares
191 192 193 194 195
                        # old & new data when setting file attribute.
      response = self.publish('%s/%s' % (path, filename),
                              request_method='PUT',
                              stdin=StringIO(iso_text_content),
                              basic=self.authentication)
196
      self.assertEqual(response.getStatus(), six.moves.http_client.NO_CONTENT)
197
      self.assertEqual(web_page_module[filename].getData(), iso_text_content)
198 199 200 201
    # Convert to base format and run conversion into utf-8
    self.tic()
    # Content-Type header is replaced if sonversion encoding succeed
    new_text_content = text_content.replace('charset=iso-8859-1', 'charset=utf-8')
202
    self.assertEqual(web_page_module[filename].getTextContent(), new_text_content)
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219

  def test_GET_on_document(self):
    """Get data from document in webdav
    """
    path = self.portal.portal_contributions.getPath()
    filename = 'P-DMS-Presentation.3.Pages-001-en.odp'
    file_object = makeFileUpload(filename)
    response = self.publish('%s/%s' % (path, filename),
                            request_method='PUT',
                            stdin=file_object,
                            basic=self.authentication)
    # Convert to base format and run conversion into utf-8
    self.tic()

    document_module = self.getDocumentModule()
    document = document_module[filename]

220 221 222
    # This is HTTPServer.zhttp_server not HTTPServer.zwebdav_server
    # force usage of manage_FTPget like zwebdav_server does
    response = self.publish(document.getPath()+'/manage_FTPget',
223 224 225 226
                            request_method='GET',
                            stdin=StringIO(),
                            basic=self.authentication)

227
    self.assertEqual(response.getStatus(), six.moves.http_client.OK)
228
    self.assertEqual(response.getBody(), document.getData(),
229
             'Error in getting data, get:%r' % response.getHeader('content-type'))
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250

  def test_PROPFIND_on_document(self):
    """test Metadata extraction from webdav protocol
    """
    path = self.portal.portal_contributions.getPath()
    filename = 'P-DMS-Presentation.3.Pages-001-en.odp'
    file_object = makeFileUpload(filename)
    response = self.publish('%s/%s' % (path, filename),
                            request_method='PUT',
                            stdin=file_object,
                            basic=self.authentication)
    document_module = self.getDocumentModule()
    document = document_module[filename]

    # Do a PROPFIND on document, this needs to result in a 207
    response = self.publish(document.getPath(),
                            request_method='PROPFIND',
                            env={'HTTP_DEPTH': '0'},
                            stdin=StringIO(),
                            basic=self.authentication)

251
    self.assertEqual(response.getStatus(), six.moves.http_client.MULTI_STATUS)
252 253
    xml_metadata_string = response.getBody()
    xml_metadata = etree.fromstring(xml_metadata_string)
254
    self.assertEqual(xml_metadata.find('{DAV:}response/{DAV:}href').text,
255
                      document.getPath())
256
    self.assertEqual(xml_metadata.find(
257 258 259 260 261
                      '{DAV:}response/{DAV:}propstat/{DAV:}prop/'\
                      '{DAV:}getcontenttype').text,
                      document.getContentType())
    # Outputed string is not reproductable for comparaison.
    # So we need to parse the date and use the same format
262
    self.assertEqual(DateTime(xml_metadata.find('{DAV:}response/'\
263 264
                      '{DAV:}propstat/{DAV:}prop/{DAV:}getlastmodified')\
                      .text).ISO8601(),
265
                      DateTime(document._p_mtime).toZone('UTC').ISO8601())
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288

  @expectedFailure
  def test_PROPFIND_on_document_bis(self):
    """same test than test_PROPFIND_on_document
    But with expected failure which is non blocking.
    """
    path = self.portal.portal_contributions.getPath()
    filename = 'P-DMS-Presentation.3.Pages-001-en.odp'
    file_object = makeFileUpload(filename)
    response = self.publish('%s/%s' % (path, filename),
                            request_method='PUT',
                            stdin=file_object,
                            basic=self.authentication)
    document_module = self.getDocumentModule()
    document = document_module[filename]

    # Do a PROPFIND on document, this needs to result in a 207
    response = self.publish(document.getPath(),
                            request_method='PROPFIND',
                            env={'HTTP_DEPTH': '0'},
                            stdin=StringIO(),
                            basic=self.authentication)

289
    self.assertEqual(response.getStatus(), six.moves.http_client.MULTI_STATUS)
290 291
    xml_metadata_string = response.getBody()
    xml_metadata = etree.fromstring(xml_metadata_string)
292
    self.assertEqual(xml_metadata.find(
293 294 295 296 297 298 299
           '{DAV:}response/{DAV:}propstat/{DAV:}prop/{DAV:}creationdate').text,
                      document.getCreationDate().HTML4())

def test_suite():
  suite = unittest.TestSuite()
  suite.addTest(unittest.makeSuite(TestWebDavSupport))
  return suite