testOOoStyle.py 18.4 KB
Newer Older
1
# -*- coding: utf-8 -*-
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
# Copyright (c) 2007 Nexedi SA and Contributors. All Rights Reserved.
#          Jerome Perrin <jerome@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability 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
# garantees 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
31
import transaction
32 33
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase, \
     _getConversionServerDict
34
from Products.ERP5Form.Selection import Selection
35 36
from Testing import ZopeTestCase
from Products.ERP5OOo.tests.utils import Validator
37
import httplib
38

39
HTTP_OK = httplib.OK
40

41 42
# setting this to True allows the .publish() calls to provide tracebacks
debug = False
43 44 45 46 47 48 49 50 51 52 53 54

class TestOOoStyle(ERP5TypeTestCase, ZopeTestCase.Functional):
  """Tests ODF styles for ERP5."""
  skin = None
  content_type = None

  def getBusinessTemplateList(self):
    return ('erp5_base', 'erp5_ods_style', 'erp5_odt_style',)

  def afterSetUp(self):
    if not self.skin:
      raise NotImplementedError('Subclasses must define skin')
55 56 57

    self.setDefaultSitePreference()

58 59 60 61 62
    gender = self.portal.portal_categories.gender
    if 'male' not in gender.objectIds():
      gender.newContent(id='male')
      self.portal.portal_caches.clearAllCache()

63 64
    self.auth = 'ERP5TypeTestCase:'
    person_module = self.portal.person_module
65
    if person_module._getOb('pers', None) is None:
66
      person_module.newContent(id='pers', portal_type='Person')
67
      transaction.commit()
68
      self.tic()
69
    person_module.pers.setFirstName('Bob')
70 71 72
    person_module.pers.setGender(None)
    person_module.pers.setCareerRole(None)

73
    if person_module.pers._getOb('img', None) is None:
74
      person_module.pers.newContent(portal_type='Embedded File', id='img')
75 76 77 78 79 80 81 82

    if person_module._getOb('pers_without_image', None) is None:
      person = person_module.newContent(
                              portal_type='Person',
                              id = 'pers_without_image',
                              first_name = 'Test')
      self.stepTic()

83 84
    self.portal.changeSkin(self.skin)
    self.validator = Validator()
85 86
    # make sure selections are empty
    self.portal.portal_selections.setSelectionFor(
87 88
                        'person_module_selection', Selection())

89 90 91 92 93 94 95 96 97
  def setDefaultSitePreference(self):
    default_pref = self.portal.portal_preferences.default_site_preference
    conversion_dict = _getConversionServerDict()
    default_pref.setPreferredOoodocServerAddress(conversion_dict['hostname'])
    default_pref.setPreferredOoodocServerPortNumber(conversion_dict['port'])
    if self.portal.portal_workflow.isTransitionPossible(default_pref, 'enable'):
      default_pref.enable()
    return default_pref

98 99
  def publish(self, *args, **kw):
    kw['handle_errors'] = not debug
100
    return super(TestOOoStyle, self).publish(*args, **kw)
101 102 103 104 105

  def _validate(self, odf_file_data):
    error_list = self.validator.validate(odf_file_data)
    if error_list:
      self.fail(''.join(error_list))
106 107 108 109 110 111 112 113 114 115
  
  def _assertFieldInGroup(self, field_type, form_id, group):
    for f in self.portal[form_id].get_fields_in_group(group):
      if f.meta_type == 'ProxyField':
        if f.getRecursiveTemplateField().meta_type == field_type:
          break
      if f.meta_type == field_type:
        break
    else:
      self.fail('No %s found in %s (%s group)' % (field_type, form_id, group))
116 117 118 119 120

  def test_skin_selection(self):
    self.assertTrue(self.skin in
              self.portal.portal_skins.getSkinSelections())

121 122 123 124 125 126 127 128
  def test_form_list(self):
    response = self.publish(
                   '/%s/person_module/PersonModule_viewPersonList'
                    % self.portal.getId(), self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
129
    self.assertEquals('attachment', content_disposition.split(';')[0])
130 131
    self._validate(response.getBody())

132
  def test_form_list_domain_tree(self):
133 134 135
    self.portal.portal_selections.setListboxDisplayMode(
                  self.portal.REQUEST, 'DomainTreeMode',
                  'person_module_selection')
136 137 138 139 140 141
    # XXX no proper API on selection / selection tool for this ?
    self.portal.portal_selections.setSelectionParamsFor(
                  selection_name='person_module_selection',
                  params=dict(domain_path='portal_categories',
                              domain_url='group',
                              domain_list=()))
142 143 144 145 146 147 148
    response = self.publish(
                   '/%s/person_module/PersonModule_viewPersonList'
                    % self.portal.getId(), self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
149
    self.assertEquals('attachment', content_disposition.split(';')[0])
150 151 152
    self._validate(response.getBody())

  def test_form_view(self):
153 154 155 156 157 158 159 160 161
    # form_view on a form without listbox
    self.portal.person_module.pers.setDefaultAddressZipCode(59000)
    response = self.publish(
        '/%s/person_module/pers/default_address/GeographicAddress_view'
        % self.portal.getId(), self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
162
    self.assertEquals('attachment', content_disposition.split(';')[0])
163 164 165 166 167 168 169 170 171 172 173 174 175
    self._validate(response.getBody())

  def test_form_view_empty_listbox(self):
    # form_view on a form with an empty listbox
    if hasattr(self.portal.person_module.pers, 'default_address'):
      self.portal.person_module.pers._delObject('default_address')
    response = self.publish(
                   '/%s/person_module/pers/Person_view'
                   % self.portal.getId(), self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
176
    self.assertEquals('attachment', content_disposition.split(';')[0])
177 178 179 180
    self._validate(response.getBody())

  def test_form_view_non_empty_listbox(self):
    self.portal.person_module.pers.setDefaultAddressZipCode(59000)
181 182 183 184 185 186 187
    response = self.publish(
                   '/%s/person_module/pers/Person_view'
                   % self.portal.getId(), self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
188
    self.assertEquals('attachment', content_disposition.split(';')[0])
189 190 191
    self._validate(response.getBody())

  def test_form_view_format(self):
192
    # empty format= does not use oood for conversion
193 194 195 196 197 198 199
    response = self.publish(
                   '/%s/person_module/pers/Person_view?format='
                   % self.portal.getId(), self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
200
    self.assertEquals('attachment', content_disposition.split(';')[0])
201
    self._validate(response.getBody())
202 203 204 205 206 207 208 209 210
    # format=pdf uses oood for conversion
    response = self.publish(
                   '/%s/person_module/pers/Person_view?format=pdf'
                   % self.portal.getId(), self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertEquals(content_type, 'application/pdf')
    content_disposition = response.getHeader('content-disposition')
    self.assertEquals('attachment', content_disposition.split(';')[0])
211

212 213 214
  def test_report_view_form_view(self):
    # Test report view rendering forms using form_view
    self.assertEquals('form_view', self.portal.Base_viewWorkflowHistory.pt)
215 216 217 218 219 220 221
    response = self.publish(
                   '/%s/person_module/pers/Base_viewHistory'
                    % self.portal.getId(), self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
222
    self.assertEquals('attachment', content_disposition.split(';')[0])
223 224
    self._validate(response.getBody())

225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
  def test_report_view_form_list(self):
    # Test report view rendering forms using form_list
    self.portal.Base_viewWorkflowHistory.pt = 'form_list'
    try:
      # publish commits a transaction, so we have to restore the original page
      # template on the form
      response = self.publish(
                   '/%s/person_module/pers/Base_viewHistory'
                    % self.portal.getId(), self.auth)
    finally:
      self.portal.Base_viewWorkflowHistory.pt = 'form_view'
      transaction.commit()
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
241
    self.assertEquals('attachment', content_disposition.split(';')[0])
242 243 244
    self._validate(response.getBody())


245 246 247 248 249 250 251 252
  def test_report_view_landscape(self):
    response = self.publish(
       '/%s/person_module/pers/Base_viewHistory?landscape=1'
        % self.portal.getId(), self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
253
    self.assertEquals('attachment', content_disposition.split(';')[0])
254 255 256 257 258 259 260 261 262 263
    self._validate(response.getBody())

  def test_report_view_sheet_per_report_section(self):
    response = self.publish(
       '/%s/person_module/pers/Base_viewHistory?sheet_per_report_section=1'
        % self.portal.getId(), self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
264
    self.assertEquals('attachment', content_disposition.split(';')[0])
265 266
    self._validate(response.getBody())

267 268 269 270 271 272 273 274
  def test_form_view_encoding(self):
    self.portal.person_module.pers.setFirstName('Jérome')
    response = self.publish('/%s/person_module/pers/Person_view'
                          % self.portal.getId(), basic=self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
275
    self.assertEquals('attachment', content_disposition.split(';')[0])
276 277 278 279 280 281 282 283 284 285
    self._validate(response.getBody())

  def test_form_view_category(self):
    self.portal.person_module.pers.setGender('male')
    response = self.publish('/%s/person_module/pers/Person_view'
                          % self.portal.getId(), basic=self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
286
    self.assertEquals('attachment', content_disposition.split(';')[0])
287 288 289 290 291 292 293 294 295 296 297
    self._validate(response.getBody())

  def test_form_view_broken_category(self):
    self.portal.person_module.pers.setGender('not exist')
    self.portal.person_module.pers.setCareerRole('not exist')
    response = self.publish('/%s/person_module/pers/Person_view'
                          % self.portal.getId(), basic=self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
298
    self.assertEquals('attachment', content_disposition.split(';')[0])
299 300 301 302 303 304 305 306 307 308
    self._validate(response.getBody())

  def test_form_view_embedded_image(self):
    # with image
    response = self.publish('/%s/person_module/pers/Person_viewDetails'
                          % self.portal.getId(), basic=self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
309
    self.assertEquals('attachment', content_disposition.split(';')[0])
310 311 312 313 314 315 316 317
    self._validate(response.getBody())
    # without image
    response = self.publish('/%s/person_module/pers_without_image/Person_viewDetails'
                          % self.portal.getId(), basic=self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
318
    self.assertEquals('attachment', content_disposition.split(';')[0])
319 320 321 322 323 324 325 326 327 328
    self._validate(response.getBody())

  def test_report_view_encoding(self):
    self.portal.person_module.pers.setFirstName('Jérome')
    response = self.publish('/%s/person_module/pers/Base_viewHistory'
                          % self.portal.getId(), basic=self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
329
    self.assertEquals('attachment', content_disposition.split(';')[0])
330 331 332 333 334 335 336 337 338 339 340
    self._validate(response.getBody())

  def test_form_list_encoding(self):
    self.portal.person_module.pers.setFirstName('Jérome')
    response = self.publish(
       '/%s/person_module/PersonModule_viewPersonList'
        % self.portal.getId(), basic=self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
341
    self.assertEquals('attachment', content_disposition.split(';')[0])
342 343
    self._validate(response.getBody())

344
  def test_image_field_form_view(self):
345
    self._assertFieldInGroup('ImageField', 'Image_view', 'right')
346 347 348 349 350 351 352
    response = self.publish(
       '/%s/person_module/pers/img/Image_view'
        % self.portal.getId(), basic=self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
353
    self.assertEquals('attachment', content_disposition.split(';')[0])
354 355 356
    self._validate(response.getBody())

  def test_image_field_form_view_bottom_group(self):
357 358
    self._assertFieldInGroup(
        'ImageField', 'Image_viewFullSizedImage', 'bottom')
359 360 361 362 363 364 365
    response = self.publish(
       '/%s/person_module/pers/img/Image_viewFullSizedImage'
        % self.portal.getId(), basic=self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
366
    self.assertEquals('attachment', content_disposition.split(';')[0])
367 368
    self._validate(response.getBody())

369 370 371 372 373 374 375 376 377 378 379 380
  def test_textarea_center_group(self):
    self._assertFieldInGroup('TextAreaField', 'Person_view', 'center')
    self.assert_('my_description' in [f.getId() for f in
        self.portal.Person_view.get_fields_in_group('center')])
    self.portal.person_module.pers.setDescription('<Escape>&\nnewline')
    response = self.publish(
                   '/%s/person_module/pers/Person_view'
                   % self.portal.getId(), self.auth)
    self.assertEquals(HTTP_OK, response.getStatus())
    content_type = response.getHeader('content-type')
    self.assertTrue(content_type.startswith(self.content_type), content_type)
    content_disposition = response.getHeader('content-disposition')
381
    self.assertEquals('attachment', content_disposition.split(';')[0])
382 383
    body = response.getBody()
    self._validate(body)
384

385 386 387 388 389 390 391 392
    if self.skin == 'ODT':
      # Is it good to do this only for ODT ?
      from Products.ERP5OOo.OOoUtils import OOoParser
      parser = OOoParser()
      parser.openFromString(body)
      content_xml = parser.oo_files['content.xml']
      self.assert_('&lt;Escape&gt;&amp;<text:line-break/>newline' in content_xml)
     
393 394 395 396 397 398 399 400 401 402 403 404 405 406

class TestODTStyle(TestOOoStyle):
  skin = 'ODT'
  content_type = 'application/vnd.oasis.opendocument.text'


class TestODSStyle(TestOOoStyle):
  skin = 'ODS'
  content_type = 'application/vnd.oasis.opendocument.spreadsheet'


def test_suite():
  suite = unittest.TestSuite()
  suite.addTest(unittest.makeSuite(TestODTStyle))
407
  suite.addTest(unittest.makeSuite(TestODSStyle))
408 409
  return suite