testERP5Base.py 65.3 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
##############################################################################
#
# Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved.
#                    Kevin Deldycke <kevin_AT_nexedi_DOT_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.
#
##############################################################################


30
import os
Jérome Perrin's avatar
Jérome Perrin committed
31
import unittest
32
from unittest import expectedFailure
Jérome Perrin's avatar
Jérome Perrin committed
33

34 35 36 37
from DateTime import DateTime
from Products.ERP5Type.Utils import convertToUpperCase
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from Products.ERP5Type.tests.Sequence import SequenceList
38
from Products.ERP5Type.tests.utils import createZODBPythonScript, FileUpload
39 40
from AccessControl.SecurityManagement import newSecurityManager

41 42
class TestERP5Base(ERP5TypeTestCase):
  """ERP5 Base tests.
Jérome Perrin's avatar
Jérome Perrin committed
43

44
  Those are tests for erp5_base business template.
45 46 47 48 49 50 51
  """


  def getBusinessTemplateList(self):
    """
      Return the list of required business templates.
    """
Sebastien Robin's avatar
Sebastien Robin committed
52
    return ('erp5_base',)
53 54


55
  def afterSetUp(self):
56 57 58 59
    """
      Initialize the ERP5 site.
    """
    self.login()
60
    self.datetime          = DateTime()
61 62 63
    self.portal            = self.getPortal()
    self.portal_categories = self.getCategoryTool()
    self.portal_catalog    = self.getCatalogTool()
64
    self.portal_preferences = self.getPreferenceTool()
65 66
    self.createCategories()

67
  def beforeTearDown(self):
68
    self.abort()
69 70 71 72
    for module in ( self.portal.person_module,
                    self.portal.organisation_module, ):
      module.manage_delObjects(list(module.objectIds()))
    self.tic()
73 74 75 76 77

  ##################################
  ##  Usefull methods
  ##################################

78 79 80
  def makeImageFileUpload(self, filename):
    return FileUpload(
            os.path.join(os.path.dirname(__file__),
81
            'test_data', 'images', filename))
82

Jérome Perrin's avatar
Jérome Perrin committed
83 84
  def login(self):
    """Create a new manager user and login.
85 86 87 88 89 90 91
    """
    user_name = 'kevin'
    user_folder = self.getPortal().acl_users
    user_folder._doAddUser(user_name, '', ['Manager', 'Owner', 'Assignor'], [])
    user = user_folder.getUserById(user_name).__of__(user_folder)
    newSecurityManager(None, user)

92 93
  def login_as_auditor(self):
    """Create a new member user with Auditor role, and login
94
    """
95 96
    user_name = 'auditor_user'
    user_folder = self.portal.acl_users
97
    user_folder._doAddUser(user_name, '', ['Member', 'Auditor'], [])
98 99
    user = user_folder.getUserById(user_name).__of__(user_folder)
    newSecurityManager(None, user)
100 101 102 103 104 105 106

  def createCategories(self):
    """
      Create some categories for testing.
    """
    self.category_list = [
                         # Grade categories
107 108
                           {'base_category' : 'grade'
                           ,'category_relative_url': 'director'
109 110
                           ,'title': 'Director'
                           }
111 112
                         , {'base_category' : 'grade'
                           ,'category_relative_url': 'engineer'
113 114 115 116
                           ,'title': 'Engineer'
                           }

                         # Function categories
117 118
                         , {'base_category' : 'function'
                           ,'category_relative_url': 'hq'
119 120
                           ,'title': 'Headquarters'
                           }
121 122
                         , {'base_category' : 'functionwarehouse'
                           ,'category_relative_url': 'warehouse'
123 124
                           ,'title': 'Warehouse'
                           }
125 126
                         , {'base_category' : 'function'
                           ,'category_relative_url': 'research_center'
127 128 129 130
                           ,'title': 'Research Center'
                           }

                         # Activity categories
131 132
                         , {'base_category' : 'activity'
                           ,'category_relative_url': 'media'
133 134
                           ,'title': 'Media'
                           }
135 136
                         , {'base_category' : 'activity'
                           ,'category_relative_url': 'software'
137 138
                           ,'title': 'Software'
                           }
139 140
                         , {'base_category' : 'activity'
                           ,'category_relative_url': 'mechanics'
141 142
                           ,'title': 'Mechanics'
                           }
143 144
                         , {'base_category' : 'activity'
                           ,'category_relative_url': 'mechanics/aerospace'
145 146
                           ,'title': 'Aerospace'
                           }
147 148
                         , {'base_category' : 'activity'
                           ,'category_relative_url': 'mechanics/automotive'
149 150 151 152
                           ,'title': 'Automotive'
                           }

                         # Group categories
153 154
                         , {'base_category' : 'group'
                           ,'category_relative_url': 'nexedi'
155 156
                           ,'title': 'Nexedi'
                           }
157 158
                         , {'base_category' : 'group'
                           ,'category_relative_url': 'nexedi/storever'
159 160
                           ,'title': 'Storever'
                           }
161 162
                         , {'base_category' : 'group'
                           ,'category_relative_url': 'nexedi/rentalinux'
163 164 165 166
                           ,'title': 'Rentalinux'
                           }

                         # Role categories
167 168
                         , {'base_category' : 'role'
                           ,'category_relative_url': 'client'
169 170
                           ,'title': 'Client'
                           }
171 172
                         , {'base_category' : 'role'
                           ,'category_relative_url': 'supplier'
173 174
                           ,'title': 'Supplier'
                           }
175 176
                         , {'base_category' : 'role'
                           ,'category_relative_url': 'internal'
177 178 179 180
                           ,'title': 'Internal'
                           }

                         # Site categories
181 182
                         , {'base_category' : 'site'
                           ,'category_relative_url': 'production/madrid'
183 184
                           ,'title': 'Madrid Production Site'
                           }
185 186
                         , {'base_category' : 'site'
                           ,'category_relative_url': 'distibution/paris'
187 188
                           ,'title': 'Paris Distribution Site'
                           }
189 190
                         , {'base_category' : 'site'
                           ,'category_relative_url': 'distibution/tokyo'
191 192
                           ,'title': 'Tokyo Distribution Site'
                           }
193 194
                         , {'base_category' : 'site'
                           ,'category_relative_url': 'distibution/new_york'
195 196 197 198
                           ,'title': 'New York Distribution Site'
                           }

                         # Skill categories
199 200
                         , {'base_category' : 'skill'
                           ,'category_relative_url': 'design/graphic'
201 202
                           ,'title': 'Graphic'
                           }
203 204
                         , {'base_category' : 'skill'
                           ,'category_relative_url': 'design/sound'
205 206
                           ,'title': 'Sound'
                           }
207 208
                         , {'base_category' : 'skill'
                           ,'category_relative_url': 'it/consulting'
209 210
                           ,'title': 'Consulting'
                           }
211 212
                         , {'base_category' : 'skill'
                           ,'category_relative_url': 'it/programming'
213 214
                           ,'title': 'Programming'
                           }
215 216

                         # Region categories
217 218
                         , {'base_category' : 'region'
                           ,'category_relative_url': 'europe/france'
219 220
                           ,'title': 'France'
                           }
221 222
                         , {'base_category' : 'region'
                           ,'category_relative_url': 'europe/germany'
223 224
                           ,'title': 'Germany'
                           }
225 226
                         , {'base_category' : 'region'
                           ,'category_relative_url': 'america/canada'
227 228
                           ,'title': 'Canada'
                           }
229 230
                         , {'base_category' : 'region'
                           ,'category_relative_url': 'america/brazil'
231 232
                           ,'title': 'Brazil'
                           }
233 234

                         # Salary Level categories
235 236
                         , {'base_category' : 'salary_level'
                           ,'category_relative_url': 'france/1/A'
237 238
                           ,'title': '1.A'
                           }
239 240
                         , {'base_category' : 'salary_level'
                           ,'category_relative_url': 'france/1/B'
241 242
                           ,'title': '1.B'
                           }
243 244
                         , {'base_category' : 'salary_level'
                           ,'category_relative_url': 'france/1/C'
245 246
                           ,'title': '1.C'
                           }
247 248
                         , {'base_category' : 'salary_level'
                           ,'category_relative_url': 'france/2'
249 250
                           ,'title': '2'
                           }
251 252 253 254 255
                         ]

    # Create categories
    # Note : this code was taken from the CategoryTool_importCategoryFile python
    #        script (packaged in erp5_core).
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
    for category_dict in self.category_list:
      category_tool = self.portal_categories
      base_category_id = category_dict['base_category']
      if base_category_id not in category_tool.contentIds():
        category_tool.newContent(portal_type='Base Category',
                                 id=base_category_id)
      base_category_value = category_tool[base_category_id]
      category_relative_url = category_dict['category_relative_url']
      parent_value = base_category_value
      for category_id in category_relative_url.split('/'):
        # The current category is not existing
        if category_id not in parent_value.contentIds():
          parent_value.newContent(portal_type='Category',
                                  id=category_id)
        parent_value = parent_value[category_id]
      parent_value.setTitle(category_dict['title'])

  def getCategoryDictList(self, base_category):
274 275 276
    """
      Get a list of categories with same base categories.
    """
277 278
    return [category_dict for category_dict in self.category_list if\
            base_category == category_dict['base_category']]
279

280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
  def _checkCategoryAccessorList(self, document, tested_base_category_list):
    """Check getters and setters on categories
    """
    for base_category in tested_base_category_list:
      category_dict_list = self.getCategoryDictList(base_category)
      base_accessor_id = convertToUpperCase(base_category)
      category_relative_url_list = []
      category_title_list = []
      category_value_list = []
      for category_dict in category_dict_list:
        category_relative_url = category_dict['category_relative_url']
        category_relative_url_list.append(category_relative_url)
        category_title = category_dict['title']
        category_title_list.append(category_title)
        category_path = '%s/%s' % (base_category, category_relative_url)
        category_document = self.portal_categories.resolveCategory(category_path)
        category_value_list.append(category_document)
        set_accessor = getattr(document, 'set' + base_accessor_id)
        set_accessor(category_relative_url)
299
        self.assertEqual(getattr(document, 'get' + base_accessor_id)(),
300
                          category_relative_url)
301
        self.assertEqual(getattr(document, 'get' + base_accessor_id + 'Title')(),
302
                          category_title)
303
        self.assertEqual(getattr(document, 'get' + base_accessor_id + 'Value')(),
304 305 306 307
                          category_document)
      set_accessor_list = 'set' + base_accessor_id + 'List'
      accessor_list = getattr(document, set_accessor_list)
      accessor_list(category_relative_url_list)
308
      self.assertEqual(getattr(document, 'get' + base_accessor_id + 'List')(),
309
                        category_relative_url_list)
310
      self.assertEqual(getattr(document, 'get' + base_accessor_id + 'TitleList')(),
311
                        category_title_list)
312
      self.assertEqual(getattr(document, 'get' + base_accessor_id + 'ValueList')(),
313
                        category_value_list)
314 315 316 317 318 319 320

  ##################################
  ##  Basic steps
  ##################################

  def stepCreateOrganisation(self, sequence=None, sequence_list=None, **kw):
    """
321
      Create an organisation.
322 323 324
    """
    portal_type = 'Organisation'
    organisation_module = self.portal.getDefaultModule(portal_type)
325 326
    organisation = organisation_module.newContent(portal_type=portal_type,
                                                  title='A new organisation')
327
    sequence.edit(organisation = organisation)
328

329 330
  def stepSetOrganisationCategories(self, sequence=None,
                                    sequence_list=None, **kw):
331
    """
332
      Set & Check default organisation categories
333
      (function, activity, site, group...).
334
    """
335 336
    organisation = sequence.get('organisation')

337 338 339
    tested_base_category_list = ('function', 'activity', 'group', 'role',
                                 'site', 'skill')
    self._checkCategoryAccessorList(organisation, tested_base_category_list)
340 341


342 343
  def stepResetOrganisationCategories(self, sequence=None,
                                      sequence_list=None, **kw):
344
    """
345
      Reset default organisation categories (function, activity, site, group...).
346
    """
347 348 349 350 351 352 353 354 355
    organisation = sequence.get('organisation')

    organisation.setFunction(None)
    organisation.setActivity(None)
    organisation.setGroup(None)
    organisation.setRole(None)
    organisation.setSite(None)
    organisation.setSkillList(None)

356 357 358 359 360 361
    self.assertEqual(organisation.getFunction()       , None)
    self.assertEqual(organisation.getActivity()       , None)
    self.assertEqual(organisation.getGroup()          , None)
    self.assertEqual(organisation.getRole()           , None)
    self.assertEqual(organisation.getSite()           , None)
    self.assertEqual(organisation.getSkillList(), [])
362

363 364 365 366 367 368
    self.assertEqual(organisation.getFunctionTitle()       , None)
    self.assertEqual(organisation.getActivityTitle()       , None)
    self.assertEqual(organisation.getGroupTitle()          , None)
    self.assertEqual(organisation.getRoleTitle()           , None)
    self.assertEqual(organisation.getSiteTitle()           , None)
    self.assertEqual(organisation.getSkillTitleList(), [])
369

370 371 372 373 374 375
    self.assertEqual(organisation.getFunctionValue()       , None)
    self.assertEqual(organisation.getActivityValue()       , None)
    self.assertEqual(organisation.getGroupValue()          , None)
    self.assertEqual(organisation.getRoleValue()           , None)
    self.assertEqual(organisation.getSiteValue()           , None)
    self.assertEqual(organisation.getSkillValueList(), [])
376 377 378 379


  def stepSetOrganisationAddress(self, sequence=None, sequence_list=None, **kw):
    """
380 381
      Set organisation address and test acquired properties and categories
      from the Address sub-object.
382 383 384
    """
    organisation = sequence.get('organisation')

385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
    self.assertFalse(organisation.hasDefaultAddress())
    self.assertFalse(organisation.hasDefaultAddressCoordinateText())
    self.assertFalse(organisation.hasDefaultAddressRegion())
    self.assertFalse(organisation.hasDefaultAddressCity())

    self.assertFalse(organisation.hasDefaultTelephone())
    self.assertFalse(organisation.hasDefaultTelephoneCoordinateText())
    self.assertFalse(organisation.hasDefaultFax())
    self.assertFalse(organisation.hasDefaultFaxCoordinateText())

    self.assertFalse(organisation.hasDefaultEmail())
    self.assertFalse(organisation.hasDefaultEmailText())
    self.assertFalse(organisation.hasDefaultEmailCoordinateText())
    self.assertFalse(organisation.hasDefaultEmailUrlString())

400 401
    region = self.getCategoryDictList(base_category='region')[0]
    region_path   = region["category_relative_url"]
402
    region_title  = region["title"]
403
    region_object = self.portal_categories.resolveCategory('region/'+region_path)
404 405 406 407
    organisation.setDefaultAddressCity('Lille')
    organisation.setDefaultAddressRegion(region_path)
    organisation.setDefaultAddressZipCode('59000')
    organisation.setDefaultAddressStreetAddress('42, rue des gnous')
408 409
    organisation.setDefaultTelephoneText('+55(0)66-5555') # Phone follows default conventions
    organisation.setDefaultFaxText('+55(0)69-1337')
410 411
    organisation.setDefaultEmailText('kevin@truc-bidule.com')

412
    self.assertTrue('default_address' in organisation.contentIds())
413
    default_address = organisation.default_address
414 415
    self.assertEqual(default_address.getPortalType(), 'Address')
    self.assertEqual(organisation.getDefaultAddressValue(), default_address)
416

417
    self.assertEqual( organisation.getDefaultAddressCity()
418 419
                     , default_address.getCity()
                     )
420
    self.assertEqual( organisation.getDefaultAddressRegion()
421 422
                     , default_address.getRegion()
                     )
423
    self.assertEqual( organisation.getDefaultAddressRegionTitle()
424 425
                     , default_address.getRegionTitle()
                     )
426
    self.assertEqual( default_address.getRegionValue()
427 428
                     , region_object
                     )
429
    self.assertEqual( organisation.getDefaultAddressZipCode()
430 431
                     , default_address.getZipCode()
                     )
432
    self.assertEqual( organisation.getDefaultAddressStreetAddress()
433 434
                     , default_address.getStreetAddress()
                     )
435

436
    # Organisation's region is acquired from the Address object
437
    self.assertEqual( organisation.getRegion()
438 439
                     , default_address.getRegion()
                     )
440

441
    self.assertTrue('default_telephone' in organisation.contentIds())
442
    default_telephone = organisation.default_telephone
443 444
    self.assertEqual(default_telephone.getPortalType(), 'Telephone')
    self.assertEqual( organisation.getDefaultTelephoneText()
445 446
                     , default_telephone.asText()
                     )
447 448 449
    self.assertTrue(organisation.hasDefaultTelephone())
    self.assertTrue(organisation.hasDefaultTelephoneCoordinateText())

450
    self.assertTrue('default_fax' in organisation.contentIds())
451
    default_fax = organisation.default_fax
452 453
    self.assertEqual(default_fax.getPortalType(), 'Fax')
    self.assertEqual( organisation.getDefaultFaxText()
454 455
                     , default_fax.asText()
                     )
456 457 458
    self.assertTrue(organisation.hasDefaultFax())
    self.assertTrue(organisation.hasDefaultFaxCoordinateText())

459
    self.assertTrue('default_email' in organisation.contentIds())
460
    default_email = organisation.default_email
461 462
    self.assertEqual(default_email.getPortalType(), 'Email')
    self.assertEqual( organisation.getDefaultEmailText()
463 464
                     , default_email.asText()
                     )
465 466 467 468
    self.assertTrue(organisation.hasDefaultEmail())
    self.assertTrue(organisation.hasDefaultEmailText())
    self.assertTrue(organisation.hasDefaultEmailCoordinateText())
    self.assertTrue(organisation.hasDefaultEmailUrlString())
469

470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
  def stepCreatePerson(self, sequence=None, sequence_list=None, **kw):
    """
      Create a person.
    """
    portal_type = 'Person'
    person_module = self.portal.getDefaultModule(portal_type)
    person = person_module.newContent( portal_type       = portal_type
                                     )
    sequence.edit(person = person)


  def stepSetPersonCareer(self, sequence=None, sequence_list=None, **kw):
    """
      Set & Check default person properties acquired through default career.
    """
    person = sequence.get('person')
486
    organisation = sequence.get('organisation')
487

488 489
    # Set subordination
    person.setCareerSubordinationValue(organisation)
490
    self.assertEqual(person.getCareerSubordinationValue(), organisation)
491

492 493
    # Set & Check simple properties with 'Career' prefix
    person.setCareerTitle('A brand new career step')
494 495
    person.setCareerDescription(
        'This career step correspond to my arrival at Nexedi as employee')
496 497
    self.assertEqual(person.getCareerTitle()      , 'A brand new career step')
    self.assertEqual(person.getCareerDescription(),
498
        'This career step correspond to my arrival at Nexedi as employee')
499 500 501

    dummy_date1 = self.datetime + 10
    dummy_date2 = self.datetime + 20
502 503 504 505
    person.setCareerStopDate(dummy_date2)
    person.setCareerStartDate(dummy_date1)
    person.setCareerSalaryCoefficient(1)
    person.setCareerCollectiveAgreementTitle('SYNTEC convention')
506
    person.setCareerActivity('software')
507
    person.setCareerReference('1234')
508 509 510 511 512 513
    self.assertEqual(person.getCareerStopDate()                , dummy_date2)
    self.assertEqual(person.getCareerStartDate()               , dummy_date1)
    self.assertEqual(person.getCareerSalaryCoefficient()       , 1)
    self.assertEqual(person.getCareerCollectiveAgreementTitle(), 'SYNTEC convention')
    self.assertEqual(person.getCareerActivityTitle(), 'Software')
    self.assertEqual(person.getCareerReference(), '1234')
514

515
    # activity must be acquired on person
516 517
    self.assertEqual(person.getActivity(), person.getCareerActivity())
    self.assertEqual('Software', person.getActivityTitle())
518

519 520 521 522
    tested_base_category_list = ('function', 'role', 'grade', 'salary_level',
                                 'skill')
    self._checkCategoryAccessorList(person, tested_base_category_list)

523
    # skill must be acquired on person
524 525 526 527 528 529 530 531
    self.tic()
    category_dict_list = self.getCategoryDictList('skill')
    skill_object_list = []
    for category_dict in category_dict_list:
      category_path = '%s/%s' % (category_dict['base_category'],
                                 category_dict['category_relative_url'])
      category_value = self.portal_categories.resolveCategory(category_path)
      skill_object_list.append(category_value)
532
    for skill_object in skill_object_list:
533
      self.assertTrue(person in skill_object.getSkillRelatedValueList())
534
    self.assertEqual(person.getSkillValue(), skill_object_list[0])
535 536 537

  def stepCheckPersonCareer(self, sequence=None, sequence_list=None, **kw):
    """
538 539
      Check the consistency of default_career properties with person
      getters (= check the acquisition).
540 541 542 543
    """
    person = sequence.get('person')

    # Check default career sub-object
544
    self.assertTrue('default_career' in person.contentIds())
545
    default_career = person.default_career
546
    self.assertEqual(default_career.getPortalType(), 'Career')
547 548

    # Test getter with 'Career' prefix
549 550 551 552 553
    self.assertEqual(person.getCareer()           , default_career.getRelativeUrl())
    self.assertEqual(person.getCareerTitle()      , default_career.getTitle())
    self.assertEqual(person.getCareerReference(), default_career.getReference())
    self.assertEqual(person.getCareerValue()      , default_career)
    self.assertEqual(person.getCareerDescription(), default_career.getDescription())
554

555 556 557
    self.assertEqual(person.getCareerFunction()     , default_career.getFunction())
    self.assertEqual(person.getCareerFunctionTitle(), default_career.getFunctionTitle())
    self.assertEqual(person.getCareerFunctionValue(), default_career.getFunctionValue())
558 559 560

    # Test getter with no prefix (aka 'transparent' getters) on simple properties
    #   then on category properties
561 562 563 564 565 566 567 568 569 570 571 572
    self.assertEqual(person.getCareerStopDate()                , default_career.getStopDate())
    self.assertEqual(person.getCareerStartDate()               , default_career.getStartDate())
    self.assertEqual(person.getCareerSalaryCoefficient()       , default_career.getSalaryCoefficient())
    self.assertEqual(person.getCareerCollectiveAgreementTitle(), default_career.getCollectiveAgreementTitle())

    self.assertEqual(person.getCareerRole()     , default_career.getRole())
    self.assertEqual(person.getCareerRoleTitle(), default_career.getRoleTitle())
    self.assertEqual(person.getCareerRoleValue(), default_career.getRoleValue())

    self.assertEqual(person.getCareerGrade()     , default_career.getGrade())
    self.assertEqual(person.getCareerGradeTitle(), default_career.getGradeTitle())
    self.assertEqual(person.getCareerGradeValue(), default_career.getGradeValue())
573

574
    self.assertEqual(person.getCareerActivity(),
575
                      default_career.getActivity())
576
    self.assertEqual(person.getCareerActivityTitle(),
577
                      default_career.getActivityTitle())
578
    self.assertEqual(person.getCareerActivityValue(),
579
                      default_career.getActivityValue())
580

581 582 583
    self.assertEqual(person.getCareerSalaryLevel()     , default_career.getSalaryLevel())
    self.assertEqual(person.getCareerSalaryLevelTitle(), default_career.getSalaryLevelTitle())
    self.assertEqual(person.getCareerSalaryLevelValue(), default_career.getSalaryLevelValue())
584

585 586 587
    self.assertEqual(person.getCareerSkillList()     , default_career.getSkillList())
    self.assertEqual(person.getCareerSkillTitleList(), default_career.getSkillTitleList())
    self.assertEqual(person.getCareerSkillValueList(), default_career.getSkillValueList())
588

589
    self.assertEqual(person.getCareerSubordination(), default_career.getSubordination())
590
    # Person's subordination is acquired from default career
591
    self.assertEqual(person.getSubordination(), default_career.getSubordination())
592

593 594 595 596 597 598 599 600
  def stepAddCareerStepInAnotherOrganisation(self, sequence=None, **kw) :
    """Adds another career step on the person."""
    person = sequence.get('person')
    other_organisation = self.getOrganisationModule().newContent(
                            portal_type = 'Organisation',
                            title = 'Another Organistion')
    new_career_title = 'new career title'
    # Create a new career step.
601
    person.Person_shiftDefaultCareer()
602
    self.assertEqual( 2,
603
          len(person.contentValues(filter={'portal_type':'Career'})))
604 605
    person.setCareerSubordination(other_organisation.getRelativeUrl())
    person.setCareerTitle(new_career_title)
606

607
    # Get the new and the old career, as Person_shiftDefaultCareer changes
608 609 610 611 612 613 614 615 616 617
    # objects id, this may be the only safe way ...
    old_career_step = None
    new_career_step = None
    for career in person.contentValues(filter={'portal_type':'Career'}):
      if career.getTitle() == new_career_title :
        new_career_step = career
      else :
        old_career_step = career
    self.assertNotEquals(new_career_step, None)
    self.assertNotEquals(old_career_step, None)
618

619 620 621 622 623 624
    sequence.edit( old_career_step = old_career_step,
                   new_career_step = new_career_step,
                   new_organisation = other_organisation,
                   old_organisation = sequence.get('organisation') )

  def stepCheckCareerSubordination (self, sequence=None, **kw) :
625
    """checks that setting subordination on a career does not conflict
626 627 628 629 630 631 632 633
        with acquisition."""
    person = sequence.get('person')
    old_career_step = sequence.get('old_career_step')
    new_career_step = sequence.get('new_career_step')
    new_organisation = sequence.get('new_organisation')
    old_organisation = sequence.get('old_organisation')
    new_organisation_title = new_organisation.getTitle()
    old_organisation_title = old_organisation.getTitle()
634

635 636 637 638
    self.assert_( "subordination/%s" % old_organisation.getRelativeUrl() in
                    old_career_step.getCategoryList(),
                '%s not in %s' % (old_organisation.getRelativeUrl(),
                                  old_career_step.getCategoryList()))
639
    self.assertEqual( old_career_step.getSubordination(),
640
                       old_organisation.getRelativeUrl() )
641
    self.assertEqual( old_career_step.getSubordinationTitle(),
642
                       old_organisation_title )
643

644 645 646 647
    self.assert_( "subordination/%s" % new_organisation.getRelativeUrl() in
                    new_career_step.getCategoryList(),
                '%s not in %s' % (new_organisation.getRelativeUrl(),
                                  new_career_step.getCategoryList()))
648
    self.assertEqual( new_career_step.getSubordination(),
649
                       new_organisation.getRelativeUrl() )
650
    self.assertEqual( new_career_step.getSubordinationTitle(),
651
                       new_organisation_title )
652

653 654 655 656 657 658 659
  def stepCheckChangePersonAddress(self, sequence=None, **kw) :
    """
    We must make sure that if we change the address of a person,
    then it will not change the address of the organisation.
    """
    person = sequence.get('person')
    organisation = sequence.get('organisation')
660 661 662 663
    self.assertEqual(organisation.getDefaultAddressCity(),'Lille')
    self.assertEqual(organisation.getDefaultAddressZipCode(), '59000')
    self.assertEqual(person.getDefaultAddressCity(),'Lille')
    self.assertEqual(person.getDefaultAddressZipCode(), '59000')
664 665 666 667 668 669 670

    # here, the parameters we pass to edit are the same as the one acquired
    # from the organisation, edit shouldn't do anything
    person.edit(
        default_address_city='Lille',
        default_address_zip_code='59000')

671
    self.assertEqual(person.getDefaultAddress(),
672
        organisation.getDefaultAddress())
673 674
    self.assertEqual(person.getDefaultAddressCity(),'Lille')
    self.assertEqual(person.getDefaultAddressZipCode(), '59000')
675 676 677 678 679 680 681 682 683 684 685

    # here, the first parameter we pass will trigger the creation of a
    # subobject on person, and we need to make sure that the second one gets
    # copied (when calling edit from the interface, all displayed fields are
    # passed to edit)
    person.edit(
        default_address_city='La Garnache',
        default_address_zip_code='59000')

    self.assertNotEquals(person.getDefaultAddress(),
        organisation.getDefaultAddress())
686 687 688 689
    self.assertEqual(person.getDefaultAddressCity(),'La Garnache')
    self.assertEqual(person.getDefaultAddressZipCode(), '59000')
    self.assertEqual(organisation.getDefaultAddressCity(),'Lille')
    self.assertEqual(organisation.getDefaultAddressZipCode(), '59000')
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704

    # retry last action, inverting the modified property
    # XXX Whether this test is usefull or not completely depends on Python
    # implementation. Python currently does not guarantee the order of a dict,
    # so it might very well be that at some point, a change in the
    # implementation makes the test always succeed, where it would fail with
    # the curent implementation.
    person.manage_delObjects(['default_address'])

    person.edit(
        default_address_city='Lille',
        default_address_zip_code='69000')

    self.assertNotEquals(person.getDefaultAddress(),
        organisation.getDefaultAddress())
705 706 707 708
    self.assertEqual(person.getDefaultAddressCity(),'Lille')
    self.assertEqual(person.getDefaultAddressZipCode(), '69000')
    self.assertEqual(organisation.getDefaultAddressCity(),'Lille')
    self.assertEqual(organisation.getDefaultAddressZipCode(), '59000')
709

710 711 712 713 714
    # if the address of the person is the same of the organisation
    # there is no reason to create a subobject (default_address)
    person.manage_delObjects(['default_address'])
    person.edit(career_subordination_value=organisation)
    self.assertTrue('default_address' not in person.objectIds())
715
    self.assertEqual(person.getDefaultAddress(),
716
        organisation.getDefaultAddress())
717
    self.assertEqual(person.getDefaultAddressCity(),
718
        organisation.getDefaultAddressCity())
719
    self.assertEqual(person.getDefaultAddressZipCode(),
720 721 722 723 724 725 726 727 728
        organisation.getDefaultAddressZipCode())
    # if the address of the person is different then the subobject
    # (default_address) must be created.
    person.edit(default_address_city='La Garnache')
    self.assertTrue('default_address' in person.objectIds())
    self.assertNotEquals(person.getDefaultAddressCity(),
         organisation.getDefaultAddressCity())


729 730 731 732
  ##################################
  ##  Tests
  ##################################

733
  def test_Organisation(self):
734
    """
735
      Test basic behaviour of Organisation.
736 737
    """
    sequence_list = SequenceList()
738 739 740 741
    step_list = [ 'stepCreateOrganisation'
                , 'stepSetOrganisationCategories'
                , 'stepResetOrganisationCategories'
                , 'stepSetOrganisationAddress'
742 743 744
                ]
    sequence_string = ' '.join(step_list)
    sequence_list.addSequenceString(sequence_string)
745
    sequence_list.play(self)
746 747


748
  def test_Person(self):
749 750 751 752
    """
      Test basic behaviour of Person.
    """
    sequence_list = SequenceList()
753 754 755 756
    step_list = [ 'stepCreatePerson'
                , 'stepCreateOrganisation'
                , 'stepSetPersonCareer'
                , 'stepCheckPersonCareer'
757 758 759
                ]
    sequence_string = ' '.join(step_list)
    sequence_list.addSequenceString(sequence_string)
760
    sequence_list.play(self)
761

762
  def test_Subordination(self):
763 764 765 766
    """
      Tests that career steps subordination properties behave correctly
    """
    sequence_list = SequenceList()
767 768 769 770 771
    step_list = [ 'stepCreatePerson'
                , 'stepCreateOrganisation'
                , 'stepSetPersonCareer'
                , 'stepAddCareerStepInAnotherOrganisation'
                , 'stepCheckCareerSubordination'
772 773 774
                ]
    sequence_string = ' '.join(step_list)
    sequence_list.addSequenceString(sequence_string)
775
    sequence_list.play(self)
776

777
  def test_SubordinationAndAddress(self):
778 779 780 781
    """
      Tests that career steps subordination properties behave correctly
    """
    sequence_list = SequenceList()
782 783 784 785 786
    step_list = [ 'stepCreatePerson'
                , 'stepCreateOrganisation'
                , 'stepSetOrganisationAddress'
                , 'stepSetPersonCareer'
                , 'stepCheckChangePersonAddress'
787 788 789
                ]
    sequence_string = ' '.join(step_list)
    sequence_list.addSequenceString(sequence_string)
790
    sequence_list.play(self)
791

792 793 794 795 796 797 798 799 800 801 802 803 804
  def test_SubordinationAcquisition(self):
    """
    Tests that persons acquire properties through subordination.
    """
    portal_categories = self.portal.portal_categories
    organisation = self.portal.organisation_module.newContent(
                            portal_type='Organisation',
                            role_value=portal_categories.role.client,
                            activity_value=portal_categories.activity.software,
                            group_value=portal_categories.group.nexedi,)
    person = self.portal.person_module.newContent(
                            portal_type='Person',
                            career_subordination_value=organisation)
805
    self.assertEqual(portal_categories.role.client,
806
                      person.getRoleValue())
807
    self.assertEqual(portal_categories.activity.software,
808
                      person.getActivityValue())
809
    self.assertEqual(portal_categories.group.nexedi,
810 811 812
                      person.getGroupValue())


Jérome Perrin's avatar
Jérome Perrin committed
813
  # Dates
814
  def test_DatesOnPerson(self):
815 816 817 818 819 820
    """Tests dates on Person objects.
    """
    pers = self.getPersonModule().newContent(portal_type='Person')
    birthday = DateTime(1999, 01, 01)
    now = DateTime()
    pers.edit(birthday = birthday)
821 822
    self.assertEqual(birthday, pers.getBirthday())
    self.assertEqual(birthday, pers.getStartDate())
823

824
    for slot in ['year', 'month', 'day', 'hour', 'minute']:
825
      self.assertEqual(getattr(now, slot)(),
826 827
                        getattr(pers.getCreationDate(), slot)(),
                        'Wrong creation date %s' % pers.getCreationDate())
828

829
  def test_DatesOnOrganisation(self):
830 831 832 833 834 835
    """Tests dates on Organisation objects.
    """
    org = self.getOrganisationModule().newContent(portal_type='Organisation')
    start_date = DateTime(1999, 01, 01)
    now = DateTime()
    org.edit(start_date = start_date)
836
    self.assertEqual(start_date, org.getStartDate())
837

838
    for slot in ['year', 'month', 'day', 'hour', 'minute']:
839
      self.assertEqual(getattr(now, slot)(),
840 841 842
                        getattr(org.getCreationDate(), slot)(),
                        'Wrong creation date %s' % org.getCreationDate())

843
  def test_BirthplaceOnPerson(self):
844 845 846 847
    """Tests birthplace on Person objects.
    """
    pers = self.getPersonModule().newContent(portal_type='Person')
    pers.setDefaultBirthplaceAddressCity('Lille')
848
    self.assertEqual('Lille', pers.getDefaultBirthplaceAddressCity())
849

850 851 852
  def test_getTranslatedId(self):
    pers = self.getPersonModule().newContent(
                portal_type='Person', id='default_email')
853
    self.assertEqual(None, pers.getTranslatedId())
854 855
    pers.setDefaultEmailText('nobody@example.com')
    email = pers.getDefaultEmailValue()
856
    self.assertEqual('Default Email', str(email.getTranslatedId()))
857

858 859 860 861 862 863 864 865 866 867 868 869 870 871
  def test_SubordinationAcquisitionAndFunction(self):
    # function is acquired from the subordination, organisation function are
    # usually only nodes, and persons functions are leaves.
    function_node = self.portal.portal_categories.function.newContent(
         portal_type='Category', id='function_node', title='Function Node')
    function_leave = function_node.newContent(
         portal_type='Category', id='function_leave', title='Function Leave')
    self.portal.portal_caches.clearAllCache()
    organisation = self.getOrganisationModule().newContent(
                                  portal_type='Organisation',
                                  function_value=function_node)
    person = self.getPersonModule().newContent(portal_type='Person',
                            career_subordination_value=organisation)
    # on Organisation_view, the user usually select node for functions:
872
    self.assertEqual([['', ''], ['Function Node', 'function_node']],
873
      organisation.Organisation_view.my_function.get_value('items'))
874

875 876 877 878 879 880
    # on Person_view, the user select leaves for functions:
    field = person.Person_view.my_career_function
    self.assertTrue('function_node' not in [x[1] for x in
                          field.get_value('items')])
    self.assertTrue('function_node/function_leave' in [x[1] for x in
                          field.get_value('items')])
881
    # person acquire function from the organisation
882
    self.assertEqual(person.getFunctionValue(), function_node)
883
    # but the user interface does not show the acquired value in this case
884
    self.assertEqual('', field.get_value('default'))
885 886
    # (the field is working)
    person.setDefaultCareerFunctionValue(function_leave)
887 888
    self.assertEqual(person.getFunctionValue(), function_leave)
    self.assertEqual('function_node/function_leave',
889
                      field.get_value('default'))
890

891

892 893 894 895 896
  def test_CreateBankAccount(self):
    # We can add Bank Accounts inside Persons and Organisation
    for entity in (self.getPersonModule().newContent(portal_type='Person'),
        self.getOrganisationModule().newContent(portal_type='Organisation')):
      bank_account = entity.newContent(portal_type='Bank Account')
897
      self.assertEqual([], bank_account.checkConsistency())
898
      bank_account.newContent(portal_type='Agent')
899
      self.assertEqual([], bank_account.checkConsistency())
900
      self.portal.portal_workflow.doActionFor(bank_account, 'validate_action')
901
      self.assertEqual('validated', bank_account.getValidationState())
902 903 904 905 906

  def test_CreateImage(self):
    # We can add Images inside Persons and Organisation
    for entity in (self.getPersonModule().newContent(portal_type='Person'),
        self.getOrganisationModule().newContent(portal_type='Organisation')):
907
      image = entity.newContent(portal_type='Embedded File')
908
      self.assertEqual([], image.checkConsistency())
909 910
      image.view() # viewing the image does not cause error

911 912 913
  def test_ConvertImage(self):
    image = self.portal.newContent(portal_type='Image', id='test_image')
    image.edit(file=self.makeImageFileUpload('erp5_logo.png'))
914 915 916 917 918 919 920 921 922 923 924 925 926 927
    self.assertEqual('image/png', image.getContentType())
    self.assertEqual((320, 250), (image.getWidth(), image.getHeight()))

    from Products.ERP5Type.Document import newTempImage
    def convert(**kw):
      image_type, image_data = image.convert('jpg', display='thumbnail', **kw)
      self.assertEqual('image/jpeg', image_type)
      thumbnail = newTempImage(self.portal, 'thumbnail', data=image_data)
      self.assertEqual(image_type, thumbnail.getContentType())
      self.assertEqual((128, 100), (thumbnail.getWidth(),
                                    thumbnail.getHeight()))
      return thumbnail.getSize()
    self.assertTrue(convert() < convert(quality=100))

928 929 930 931 932 933 934
  def test_ConvertImagePdata(self):
    image = self.portal.newContent(portal_type='Image', id='test_image')
    image.edit(file=self.makeImageFileUpload('erp5_logo.bmp'))
    from OFS.Image import Pdata
    self.assertTrue(isinstance(image.data, Pdata))

    image_type, image_data = image.convert('jpg', display='thumbnail')
935
    self.assertEqual('image/jpeg', image_type)
936
    # magic
937 938
    self.assertEqual('\xff', image_data[0])
    self.assertEqual('\xd8', image_data[1])
939

940 941 942
  def test_ImageSize(self):
    image = self.portal.newContent(portal_type='Image', id='test_image')
    image.edit(file=self.makeImageFileUpload('erp5_logo.png'))
943 944
    self.assertEqual(320, image.getWidth())
    self.assertEqual(250, image.getHeight())
945
    image.edit(file=self.makeImageFileUpload('erp5_logo_small.png'))
946 947
    self.assertEqual(160, image.getWidth())
    self.assertEqual(125, image.getHeight())
948

949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
  def test_Person_getCareerStartDate(self):
    # Person_getCareerStartDate scripts returns the date when an employee
    # started to work for an employer
    first_organisation = self.getOrganisationModule().newContent(
                                  portal_type='Organisation')
    second_organisation = self.getOrganisationModule().newContent(
                                  portal_type='Organisation')
    person = self.getPersonModule().newContent(
              portal_type='Person',
              default_career_subordination_value=first_organisation)
    current_career = person.getDefaultCareerValue()
    current_career.setStartDate(DateTime(2002, 1, 1))
    previous_career = person.newContent(
                              portal_type='Career',
                              subordination_value=first_organisation,
                              start_date=DateTime(2001, 1, 1))
    other_organisation_career= person.newContent(
                              portal_type='Career',
                              subordination_value=second_organisation,
                              start_date=DateTime(1999, 9, 9))
969
    self.assertEqual(DateTime(2001, 1, 1),
970 971
         person.Person_getCareerStartDate(
            subordination_relative_url=first_organisation.getRelativeUrl()))
972
    self.assertEqual(DateTime(1999, 9, 9),
973 974 975 976 977 978 979 980 981 982
         person.Person_getCareerStartDate(
            subordination_relative_url=second_organisation.getRelativeUrl()))

    # only validated careers are used (for conveniance, draft careers are
    # accepted as well)
    another_cancelled_career = person.newContent(
                              portal_type='Career',
                              subordination_value=first_organisation,
                              start_date=DateTime(1996, 9, 9))
    another_cancelled_career.cancel()
983
    self.assertEqual(DateTime(2001, 01, 01),
984 985 986 987 988 989 990 991
         person.Person_getCareerStartDate(
            subordination_relative_url=first_organisation.getRelativeUrl()))

  def test_Person_getAge(self):
    person = self.getPersonModule().newContent(
                                  portal_type='Person',
                                  start_date=DateTime(2001, 2, 3))

992
    self.assertEqual(1,
993 994 995 996 997
          person.Person_getAge(year=1, at_date=DateTime(2002, 2, 4)))
    self.assertTrue(person.Person_getAge(year=1) > 5)

    # if year is not passed, the script returns the age in a translated string.
    age_as_text = person.Person_getAge(at_date=DateTime(2002, 2, 4))
998
    self.assertEqual(age_as_text, "1 years old")
999

1000 1001 1002
  def test_AssignmentWorkflow(self):
    person = self.getPersonModule().newContent(portal_type='Person',)
    assignment = person.newContent(portal_type='Assignment')
1003
    self.assertEqual('draft', assignment.getValidationState())
1004
    self.portal.portal_workflow.doActionFor(assignment, 'open_action')
1005
    self.assertEqual('open', assignment.getValidationState())
1006
    self.portal.portal_workflow.doActionFor(assignment, 'update_action')
1007
    self.assertEqual('updated', assignment.getValidationState())
1008
    self.portal.portal_workflow.doActionFor(assignment, 'open_action')
1009
    self.assertEqual('open', assignment.getValidationState())
1010
    # date is set automatically when closing
1011
    self.assertEqual(None, assignment.getStopDate())
1012
    self.portal.portal_workflow.doActionFor(assignment, 'close_action')
1013
    self.assertEqual('closed', assignment.getValidationState())
1014
    self.assertNotEquals(None, assignment.getStopDate())
1015
    self.assertEqual(DateTime().day(), assignment.getStopDate().day())
1016

1017
  def test_ERP5Site_checkDataWithScript(self):
1018 1019 1020 1021 1022 1023
    # note the '/'.join(obj.getPhysicalPath()) idiom:

    # it's basically a obj.absolute_url(relative=1) without escaping:
    #  - getRelativeUrl() is not enough as it does not return a full
    #    path for portal_categories.action_type for instance
    #  - absolute_url escapes 'Foo Tool' into 'Foo%20Tool'
1024 1025
    test = 'test_ERP5Site_checkDataWithScript'
    createZODBPythonScript(self.getSkinsTool().custom, test, '',
1026
                           'return "/".join(context.getPhysicalPath()),')
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042

    organisation = self.getOrganisationModule() \
                       .newContent(portal_type='Organisation')
    organisation.setDefaultAddressCity('Lille')
    organisation.setDefaultAddressZipCode('59000')
    person = self.getPersonModule().newContent(portal_type='Person')
    person.setDefaultEmailText('nobody@example.com')

    portal_activities = self.getActivityTool()
    active_process = portal_activities.newActiveProcess()
    portal_activities.ERP5Site_checkDataWithScript(method_id=test, tag=test,
                                       active_process=active_process.getPath())
    self.tic()
    relative_url_list = sum((x.detail.split('\n')
                             for x in active_process.getResultList()), [])

1043
    self.assertEqual(len(relative_url_list), len(set(relative_url_list)))
1044
    for obj in organisation, person, person.getDefaultEmailValue():
1045
      self.assertTrue('/'.join(obj.getPhysicalPath()) in relative_url_list)
1046 1047 1048 1049
    for relative_url in relative_url_list:
      self.assertTrue('/' in relative_url)
      self.assertNotEquals(None, self.portal.unrestrictedTraverse(relative_url))

1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
  def test_standard_translated_related_keys(self):
    # make sure we can search by "translated_validation_state_title" and
    # "translated_portal_type"
    message_catalog = self.portal.Localizer.erp5_ui
    lang = 'fr'
    if lang not in [x['id'] for x in
        self.portal.Localizer.get_languages_map()]:
      self.portal.Localizer.manage_addLanguage(lang)

    message_catalog.gettext('Draft', add=1)
    message_catalog.gettext('Person', add=1)
    message_catalog.message_edit('Draft', lang, 'Brouillon', '')
    message_catalog.message_edit('Person', lang, 'Personne', '')

1064 1065
    self.portal.ERP5Site_updateTranslationTable()

1066 1067 1068 1069 1070 1071 1072 1073 1074 1075
    person_1 = self.portal.person_module.newContent(portal_type='Person')
    person_1.validate()
    person_2 = self.portal.person_module.newContent(portal_type='Person')
    organisation = self.portal.organisation_module.newContent(
                            portal_type='Organisation')
    self.tic()

    # patch the method, we'll abort later
    self.portal.Localizer.get_selected_language = lambda: lang

1076 1077 1078 1079 1080 1081
    self.assertEqual({person_1, person_2}, {x.getObject()
      for x in self.portal.portal_catalog(translated_portal_type='Personne')})
    self.assertEqual({person_2, organisation}, {x.getObject()
      for x in self.portal.portal_catalog(
        translated_validation_state_title='Brouillon',
        portal_type=('Person', 'Organisation'))})
1082
    self.assertEqual([person_2],
1083 1084 1085
        [x.getObject() for x in
          self.portal.portal_catalog(translated_validation_state_title='Brouillon',
                                     translated_portal_type='Personne')])
1086
    self.abort()
1087

1088 1089 1090 1091 1092
  def test_Base_createCloneDocument(self):
    module = self.portal.person_module
    module.manage_permission('Add portal content', ['Member'], 0)
    self.login_as_auditor()
    person = module.newContent(portal_type='Person',)
1093
    self.assertEqual(1, len(module))
1094
    person.Base_createCloneDocument()
1095
    self.assertEqual(2, len(module))
1096 1097 1098 1099 1100 1101 1102 1103

  def test_Base_createCloneDocument_document_in_document(self):
    module = self.portal.person_module
    module.manage_permission('Add portal content', ['Member'], 0)
    self.login_as_auditor()
    person = module.newContent(portal_type='Person',)
    # An address is a document, it cannot contain anything
    address = person.newContent(portal_type='Address')
1104
    self.assertEqual(0, len(address.allowedContentTypes()))
1105

1106
    self.assertEqual(1, len(person))
1107
    address.Base_createCloneDocument()
1108
    self.assertEqual(2, len(person))
1109 1110 1111 1112 1113 1114 1115

  def test_Base_createCloneDocument_folder_in_document(self):
    module = self.portal.person_module
    module.manage_permission('Add portal content', ['Member'], 0)
    self.login_as_auditor()
    person = module.newContent(portal_type='Person',)
    bank_account = person.newContent(portal_type='Bank Account')
Jérome Perrin's avatar
typo  
Jérome Perrin committed
1116
    # A bank account is a folder, it can contain other documents
1117 1118
    self.assertNotEquals(0, len(bank_account.allowedContentTypes()))

1119
    self.assertEqual(1, len(person))
1120
    bank_account.Base_createCloneDocument()
1121
    self.assertEqual(2, len(person))
1122

1123 1124 1125 1126 1127 1128 1129 1130
  def getWorkflowHistory(self, document, workflow_id):
    return self.portal.portal_workflow.getInfoFor(ob=document, name='history',
        wf_id=workflow_id)

  def test_comment_edit_workflow(self):
    comment = 'some comment'
    person = self.portal.person_module.newContent(portal_type='Person')
    person.edit(comment = comment)
1131
    workflow_history = self.getWorkflowHistory(person, 'edit_workflow')
1132 1133 1134
    # person has property comment with value
    self.assertEqual(person.comment, comment)
    # workflow has no artificial comment
1135 1136
    self.assertFalse(comment in [q['comment'] for q in workflow_history ])

1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
  def test_comment_edit_workflow_store_workflow(self):
    comment = 'some comment'
    person = self.portal.person_module.newContent(portal_type='Person')
    self.portal.portal_workflow.doActionFor(person, 'edit_action', comment=comment)
    workflow_history = self.getWorkflowHistory(person, 'edit_workflow')
    # person is not changed
    self.assertEqual(getattr(person, 'comment', None), None)
    # workflow is affected
    self.assertTrue(comment in [q['comment'] for q in workflow_history ])

1147 1148 1149 1150 1151
  def test_comment_validation_workflow(self):
    comment = 'some comment'
    person = self.portal.person_module.newContent(portal_type='Person')
    person.validate(comment = comment)
    workflow_history = self.getWorkflowHistory(person, 'validation_workflow')
1152
    # person is not changed
1153
    self.assertEqual(getattr(person, 'comment', None), None)
1154
    # workflow is affected
1155
    self.assertTrue(comment in [q['comment'] for q in workflow_history])
1156

1157 1158 1159
  def test_user_creation(self):
    person = self.portal.person_module.newContent(portal_type='Person')
    assignment = person.newContent(portal_type='Assignment',
1160
                                   group='nexedi/storever')
1161 1162 1163 1164 1165 1166 1167 1168 1169
    self.assertNotEquals(None, assignment.getGroupValue())
    assignment.open()
    self.portal.portal_workflow.doActionFor(person, 'create_user_action',
                  reference='user_login',
                  password='pass',
                  password_confirm='pass')
    self.tic()

    # a user is created
1170
    user = self.portal.acl_users.getUser('user_login')
1171 1172
    self.assertNotEquals(None, user)

1173
    # This user does not have a preference created automatically ...
1174
    newSecurityManager(None, user.__of__(self.portal.acl_users))
1175 1176 1177 1178 1179 1180 1181
    self.assertEquals(None,
        self.portal.portal_catalog.getResultValue(portal_type='Preference',
                                                  owner=user.getId()))
    # ... but only when `getActiveUserPreference`
    preference = self.portal.portal_preferences.getActiveUserPreference()
    self.assertNotEquals(None, preference)
    self.tic()
1182 1183
    self.assertNotEquals(None,
        self.portal.portal_catalog.getResultValue(portal_type='Preference',
1184
                                                  owner=user.getId()))
1185 1186 1187

    # for his assignment group
    self.assertEqual('group/nexedi/storever',
1188 1189
        self.portal.portal_preferences.getPreferredSectionCategory())

1190 1191 1192 1193
  def test_default_address_acquisition(self):
    # more complete version of test_04_SubordinationAndAddress
    organisation = \
      self.portal.organisation_module.newContent(portal_type='Organisation')
1194 1195 1196 1197
    self.assertEqual(None, organisation.getDefaultAddressStreetAddress())
    self.assertEqual(None, organisation.getDefaultAddressCity())
    self.assertEqual(None, organisation.getDefaultAddressZipCode())
    self.assertEqual(None, organisation.getDefaultAddressText())
1198

1199 1200
    self.assertEqual(None, organisation.getDefaultAddressRegion())
    self.assertEqual(None, organisation.getRegion())
1201 1202

    organisation.setDefaultAddressRegion('europe/france')
1203
    self.assertEqual('europe/france', organisation.getDefaultAddressRegion())
1204
    # region is acquired from default address
1205 1206 1207 1208
    self.assertEqual('europe/france', organisation.getRegion())
    self.assertEqual(None, organisation.getDefaultAddressStreetAddress())
    self.assertEqual(None, organisation.getDefaultAddressCity())
    self.assertEqual(None, organisation.getDefaultAddressZipCode())
1209 1210 1211 1212 1213

    organisation.setDefaultAddressStreetAddress('Street Address')
    organisation.setDefaultAddressCity('City')
    organisation.setDefaultAddressZipCode('Zip Code')

1214 1215 1216
    self.assertEqual('Street Address', organisation.getDefaultAddressStreetAddress())
    self.assertEqual('City', organisation.getDefaultAddressCity())
    self.assertEqual('Zip Code', organisation.getDefaultAddressZipCode())
1217 1218

    person = self.portal.person_module.newContent(portal_type='Person')
1219 1220 1221 1222 1223 1224
    self.assertEqual(None, person.getDefaultAddressStreetAddress())
    self.assertEqual(None, person.getDefaultAddressCity())
    self.assertEqual(None, person.getDefaultAddressZipCode())
    self.assertEqual(None, person.getDefaultAddressText())
    self.assertEqual(None, person.getDefaultAddressRegion())
    self.assertEqual(None, person.getRegion())
1225 1226 1227 1228

    # On persons, Address is acquired from the default carreer
    person.setDefaultCareerSubordinationValue(organisation)

1229 1230 1231 1232
    self.assertEqual('Street Address', person.getDefaultAddressStreetAddress())
    self.assertEqual('City', person.getDefaultAddressCity())
    self.assertEqual('Zip Code', person.getDefaultAddressZipCode())
    self.assertEqual('europe/france', person.getDefaultAddressRegion())
1233
    # region is acquired from default address
1234
    self.assertEqual('europe/france', person.getRegion())
1235 1236 1237 1238 1239 1240

    # we can set different values on the person address without modifying
    # organisation address
    person.setDefaultAddressStreetAddress('Person Street Address')
    person.setDefaultAddressCity('Person City')
    person.setDefaultAddressZipCode('Person Zip Code')
1241 1242 1243 1244 1245 1246
    self.assertEqual('Person Street Address', person.getDefaultAddressStreetAddress())
    self.assertEqual('Person City', person.getDefaultAddressCity())
    self.assertEqual('Person Zip Code', person.getDefaultAddressZipCode())
    self.assertEqual('Street Address', organisation.getDefaultAddressStreetAddress())
    self.assertEqual('City', organisation.getDefaultAddressCity())
    self.assertEqual('Zip Code', organisation.getDefaultAddressZipCode())
1247 1248 1249 1250

  def test_default_telephone_acquisition(self):
    organisation = \
      self.portal.organisation_module.newContent(portal_type='Organisation')
1251
    self.assertEqual(None, organisation.getDefaultTelephoneCoordinateText())
1252 1253 1254
    # There is no problem if this organisation has a region (this use to be a
    # problem)
    organisation.setDefaultAddressRegion('europe/france')
1255
    self.assertEqual(None, organisation.getDefaultTelephoneCoordinateText())
1256 1257

    organisation.setDefaultTelephoneText("12345")
1258
    self.assertEqual('12345', organisation.getDefaultTelephoneCoordinateText())
1259 1260

    person = self.portal.person_module.newContent(portal_type='Person')
1261
    self.assertEqual(None, person.getDefaultTelephoneCoordinateText())
1262 1263 1264

    # On persons, Telephone is acquired from the default carreer
    person.setDefaultCareerSubordinationValue(organisation)
1265
    self.assertEqual('12345', person.getDefaultTelephoneCoordinateText())
1266 1267 1268 1269

    # we can set different values on the person address without modifying
    # organisation address
    person.setDefaultTelephoneText('54321')
1270 1271
    self.assertEqual('54321', person.getDefaultTelephoneCoordinateText())
    self.assertEqual('12345', organisation.getDefaultTelephoneCoordinateText())
1272 1273 1274 1275

  def test_mobile_telephone_acquisition(self):
    organisation = \
      self.portal.organisation_module.newContent(portal_type='Organisation')
1276
    self.assertEqual(None, organisation.getMobileTelephoneCoordinateText())
1277 1278 1279
    # There is no problem if this organisation has a region (this use to be a
    # problem)
    organisation.setDefaultAddressRegion('europe/france')
1280
    self.assertEqual(None, organisation.getMobileTelephoneCoordinateText())
1281 1282

    organisation.setMobileTelephoneText("12345")
1283
    self.assertEqual('12345', organisation.getMobileTelephoneCoordinateText())
1284 1285

    person = self.portal.person_module.newContent(portal_type='Person')
1286
    self.assertEqual(None, person.getMobileTelephoneCoordinateText())
1287 1288 1289

    # On persons, Telephone is acquired from the default carreer
    person.setDefaultCareerSubordinationValue(organisation)
1290
    self.assertEqual('12345', person.getMobileTelephoneCoordinateText())
1291 1292 1293 1294

    # we can set different values on the person address without modifying
    # organisation address
    person.setMobileTelephoneText('54321')
1295 1296
    self.assertEqual('54321', person.getMobileTelephoneCoordinateText())
    self.assertEqual('12345', organisation.getMobileTelephoneCoordinateText())
1297 1298 1299 1300

  def test_default_fax_acquisition(self):
    organisation = \
      self.portal.organisation_module.newContent(portal_type='Organisation')
1301
    self.assertEqual(None, organisation.getDefaultTelephoneCoordinateText())
1302 1303 1304
    # There is no problem if this organisation has a region (this use to be a
    # problem)
    organisation.setDefaultAddressRegion('europe/france')
1305
    self.assertEqual(None, organisation.getDefaultFaxCoordinateText())
1306 1307

    organisation.setDefaultFaxText("12345")
1308
    self.assertEqual('12345', organisation.getDefaultFaxCoordinateText())
1309 1310

    person = self.portal.person_module.newContent(portal_type='Person')
1311
    self.assertEqual(None, person.getDefaultFaxCoordinateText())
1312 1313 1314

    # On persons, Fax is acquired from the default carreer
    person.setDefaultCareerSubordinationValue(organisation)
1315
    self.assertEqual('12345', person.getDefaultFaxCoordinateText())
1316 1317 1318 1319

    # we can set different values on the person address without modifying
    # organisation address
    person.setDefaultFaxText('54321')
1320 1321
    self.assertEqual('54321', person.getDefaultFaxCoordinateText())
    self.assertEqual('12345', organisation.getDefaultFaxCoordinateText())
1322 1323 1324 1325

  def test_default_email_acquisition(self):
    organisation = \
      self.portal.organisation_module.newContent(portal_type='Organisation')
1326
    self.assertEqual(None, organisation.getDefaultTelephoneCoordinateText())
1327 1328 1329
    # There is no problem if this organisation has a region (this use to be a
    # problem)
    organisation.setDefaultAddressRegion('europe/france')
1330
    self.assertEqual(None, organisation.getDefaultEmailCoordinateText())
1331 1332

    organisation.setDefaultEmailText("organisation@example.com")
1333
    self.assertEqual('organisation@example.com',
1334 1335 1336
      organisation.getDefaultEmailCoordinateText())

    person = self.portal.person_module.newContent(portal_type='Person')
1337
    self.assertEqual(None, person.getDefaultEmailCoordinateText())
1338
    self.assertFalse(person.hasDefaultEmailCoordinateText())
1339 1340 1341

    # On persons, Email is acquired from the default carreer
    person.setDefaultCareerSubordinationValue(organisation)
1342
    self.assertEqual('organisation@example.com',
1343
      person.getDefaultEmailCoordinateText())
1344
    self.assertFalse(person.hasDefaultEmailCoordinateText())
1345 1346 1347 1348

    # we can set different values on the person address without modifying
    # organisation address
    person.setDefaultEmailText('person@example.com')
1349 1350
    self.assertEqual('person@example.com', person.getDefaultEmailCoordinateText())
    self.assertEqual('organisation@example.com',
1351
      organisation.getDefaultEmailCoordinateText())
1352
    self.assertTrue(person.hasDefaultEmailCoordinateText())
1353 1354 1355 1356

  def test_alternate_email_acquisition(self):
    organisation = \
      self.portal.organisation_module.newContent(portal_type='Organisation')
1357
    self.assertEqual(None, organisation.getAlternateEmailCoordinateText())
1358 1359 1360
    # There is no problem if this organisation has a region (this use to be a
    # problem)
    organisation.setDefaultAddressRegion('europe/france')
1361
    self.assertEqual(None, organisation.getAlternateEmailCoordinateText())
1362 1363

    organisation.setAlternateEmailText("organisation@example.com")
1364
    self.assertEqual('organisation@example.com',
1365 1366 1367
      organisation.getAlternateEmailCoordinateText())

    person = self.portal.person_module.newContent(portal_type='Person')
1368
    self.assertEqual(None, person.getAlternateEmailCoordinateText())
1369 1370 1371

    # On persons, Email is acquired from the default carreer
    person.setDefaultCareerSubordinationValue(organisation)
1372
    self.assertEqual('organisation@example.com',
1373 1374 1375 1376 1377
      person.getAlternateEmailCoordinateText())

    # we can set different values on the person address without modifying
    # organisation address
    person.setAlternateEmailText('person@example.com')
1378 1379
    self.assertEqual('person@example.com', person.getAlternateEmailCoordinateText())
    self.assertEqual('organisation@example.com',
1380 1381
      organisation.getAlternateEmailCoordinateText())

1382 1383 1384
  # Marked as expectedFailure as it shall be never possible to use edit method to set
  # local property which would override existing method
  @expectedFailure
1385 1386 1387 1388
  def test_content_type_property(self):
    portal_type = 'Person'
    person_module = self.portal.getDefaultModule(portal_type)
    person = person_module.newContent(portal_type=portal_type)
1389

1390 1391 1392 1393 1394
    # assert that test has a sense
    self.assertEqual(getattr(person, 'getContentType', None), None)

    # edit content_type on document which has no content_type property configured
    person.edit(content_type='text/xml')
1395

1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421
  def test_BankAccount_validateIBAN(self):
    self.assertTrue(
        self.portal.BankAccount_validateIBAN(
        'GR1601101250000000012300695', request=None))
    # spaces are allowed
    self.assertTrue(
        self.portal.BankAccount_validateIBAN(
        'GR16 0110 1250 0000 0001 2300 695', request=None))
    self.assertFalse(
        self.portal.BankAccount_validateIBAN(
        'GR16 0110 1250 0000 0001 2300 696', request=None))
    self.assertFalse(
        self.portal.BankAccount_validateIBAN(
        '12345', request=None))

  def test_BankAccount_validateBIC(self):
    self.assertTrue(
        self.portal.BankAccount_validateBIC(
        'DEUTDEFF', request=None))
    self.assertTrue(
        self.portal.BankAccount_validateBIC(
        'NEDSZAJJ', request=None))
    self.assertFalse(
        self.portal.BankAccount_validateBIC(
        'X', request=None))

1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461
  def test_user_title(self):
    newContent = self.portal.person_module.newContent
    login = super(TestERP5Base, self).login
    # User 1 and 2 have the same title (picked from user 1's user id),
    # hopefully not shared with other users.
    # User 3 has a different title, also hopefully not shared.
    user_1 = newContent(portal_type='Person')
    common_user_title = user_1.Person_getUserId()
    user_1.setTitle(common_user_title)
    user_2 = newContent(portal_type='Person')
    user_2.setTitle(common_user_title)
    user_3 = newContent(portal_type='Person')
    user_3.setTitle(user_3.Person_getUserId())
    # any member can add persons
    self.portal.person_module.manage_permission(
      'Add portal content',
      roles=['Member', 'Manager'],
      acquire=0,
    )
    self.tic()
    # Create whatever documents.
    must_find_path_list = []
    login(user_1.Person_getUserId())
    must_find_path_list.append(newContent(portal_type='Person', title='Owned by user_1').getPath())
    login(user_2.Person_getUserId())
    must_find_path_list.append(newContent(portal_type='Person', title='Owned by user_2').getPath())
    login(user_3.Person_getUserId())
    newContent(portal_type='Person', title='Owned by user_3')
    login()
    self.tic()
    self.assertItemsEqual(
      must_find_path_list,
      [
        x.path
        for x in self.portal.portal_catalog(
          owner_title=common_user_title,
          portal_type='Person',
        )
      ],
    )
1462

Jérome Perrin's avatar
Jérome Perrin committed
1463 1464
def test_suite():
  suite = unittest.TestSuite()
1465
  suite.addTest(unittest.makeSuite(TestERP5Base))
Jérome Perrin's avatar
Jérome Perrin committed
1466
  return suite