############################################################################## # # Copyright (c) 2007 Nexedi SA and Contributors. All Rights Reserved. # Mikolaj Antoszkiewicz <mikolaj@erp5.pl> # # 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 from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from AccessControl.SecurityManagement import newSecurityManager from DateTime import DateTime from Products.DCWorkflow.DCWorkflow import ValidationFailed from Products.ERP5Type.tests.Sequence import SequenceList, Sequence from Testing.ZopeTestCase.PortalTestCase import PortalTestCase class TestTaskMixin: default_quantity = 99.99999999 default_price = 555.88888888 person_portal_type = 'Person' organisation_portal_type = 'Organisation' resource_portal_type = 'Service' project_portal_type = 'Project' requirement_portal_type = 'Requirement' requirement_document_portal_type = 'Requirement Document' task_portal_type = 'Task' task_description = 'Task Description %s' task_line_portal_type = 'Task Line' task_report_portal_type = 'Task Report' task_report_line_portal_type = 'Task Report Line' datetime = DateTime() task_workflow_id='task_workflow' default_task_sequence = '\ stepLogin \ stepCreateOrganisation \ stepCreateOrganisation \ stepCreateResource \ stepCreateProject \ stepCreateRequirement \ stepCreateSimpleTask \ stepCreateCurrency \ stepFillTaskWithData \ stepSetTaskPriceCurrency \ stepConfirmTask \ stepTic \ stepSetTaskReport ' default_task_no_price_sequence = '\ stepLogin \ stepCreateOrganisation \ stepCreateOrganisation \ stepCreateResource \ stepCreateProject \ stepCreateRequirement \ stepCreateSimpleTask \ stepFillTaskWithData \ stepConfirmTask \ stepTic \ stepSetTaskReport ' default_task_sequence_two_lines = '\ stepLogin \ stepCreateOrganisation \ stepCreateOrganisation \ stepCreateResource \ stepCreateResource \ stepCreateProject \ stepCreateSimpleTask \ stepCreateCurrency \ stepFillTaskWithData \ stepSetTaskPriceCurrency \ stepCreateTaskLine \ stepFillTaskLineWithData \ stepConfirmTask \ stepTic \ stepSetTaskReport ' default_task_report_sequence = '\ stepLogin \ stepCreateOrganisation \ stepCreateOrganisation \ stepCreateResource \ stepCreateProject \ stepCreateSimpleTaskReport \ stepCreateCurrency \ stepFillTaskReportWithData \ stepSetTaskReportPriceCurrency \ stepCreateTaskReportLine ' login = PortalTestCase.login def getBusinessTemplateList(self): """ """ return ('erp5_base','erp5_pdm', 'erp5_trade', 'erp5_project',) # def stepLogin(self, **kw): # portal = self.getPortal() # uf = portal.acl_users # if not uf.getUser('dummy'): # uf._doAddUser('manager', '', ['Manager'], []) # self.login('manager') # person_module = portal.getDefaultModule(self.person_portal_type) # person = person_module.newContent(id='dummy', title='dummy', # reference='dummy') # portal.portal_categories.group.newContent(id='dummy', # codification='DUMMY') # # assignment = person.newContent(title='dummy', group='dummy', # portal_type='Assignment', # start_date='1980-01-01', # stop_date='2099-12-31') # assignment.open() # get_transaction().commit() # self.tic() # module_list = [] # portal_type_list = [] # for portal_type in (self.resource_portal_type, # self.project_portal_type, # self.requirement_document_portal_type, # self.organisation_portal_type, # self.task_portal_type, # self.task_report_portal_type, # self.category_portal_type,): # module = portal.getDefaultModule(portal_type) # module_list.append(module) # portal_type_list.append(portal_type) # portal_type_list.append(module.getPortalType()) # # for portal_type in portal_type_list: # ti = portal.portal_types[portal_type] # ti.addRole('Auditor;Author;Assignee;Assignor', '', 'Dummy', # '', 'group/dummy', 'ERP5Type_getSecurityCategoryFromAssignment', # '') # ti.updateRoleMapping() # # get_transaction().commit() # self.tic() # portal.portal_caches.clearAllCache() # # self.login('dummy') def stepLogin(self, quiet=0, run=1, **kw): uf = self.getPortal().acl_users uf._doAddUser('alex', '', ['Manager', 'Assignee', 'Assignor', 'Associate', 'Auditor', 'Author'], []) user = uf.getUserById('alex').__of__(uf) newSecurityManager(None, user) def stepCreateResource(self,sequence=None, sequence_list=None, \ **kw): """ Create a resource_list with no variation """ resource_list = sequence.get('resource_list', []) portal = self.getPortal() resource_module = portal.getDefaultModule(self.resource_portal_type) resource = resource_module.newContent( portal_type=self.resource_portal_type, title = 'Resource%s' % len(resource_list), ) resource_list.append(resource) sequence.edit(resource_list=resource_list) def stepCreateProject(self,sequence=None, sequence_list=None, \ **kw): """ Create a project """ portal = self.getPortal() module = portal.getDefaultModule(self.project_portal_type) obj = module.newContent( portal_type=self.project_portal_type, title = 'Project', ) sequence.edit(project=obj) def stepCreateRequirement(self,sequence=None, sequence_list=None, \ **kw): """ Create a requirement """ portal = self.getPortal() module = portal.getDefaultModule(self.requirement_document_portal_type) obj = module.newContent( portal_type=self.requirement_document_portal_type, title = 'Requirement Document', ) subobj = obj.newContent( portal_type=self.requirement_portal_type, title = 'Requirement', ) sequence.edit(requirement=subobj) def stepCreateOrganisation(self, sequence=None, sequence_list=None, **kw): """ Create a empty organisation """ organisation_list = sequence.get('organisation_list', []) portal = self.getPortal() organisation_module = portal.getDefaultModule( portal_type=self.organisation_portal_type) organisation = organisation_module.newContent( portal_type=self.organisation_portal_type, title='Organization%s' % len(organisation_list), ) organisation_list.append(organisation) sequence.edit(organisation_list=organisation_list) def stepCreateSimpleTask(self,sequence=None, sequence_list=None, **kw): """ Create a task and fill it with dummy data. """ portal = self.getPortal() task_module = portal.getDefaultModule(portal_type=self.task_portal_type) task = task_module.newContent(portal_type=self.task_portal_type) # Check if no task lines are created at the start self.assertEquals(len(task.contentValues()), 0) task.edit( title = "Task", description = "This is a very simple task. You can do it quickly." ) sequence.edit(task=task) def stepCreateCurrency(self, sequence, **kw) : """Create a default currency. """ currency_module = self.getCurrencyModule() if len(currency_module.objectValues(id='EUR'))==0: currency = self.getCurrencyModule().newContent( portal_type='Currency', id="EUR", base_unit_quantity=0.01, ) else: currency = currency_module.objectValues(id='EUR')[0] sequence.edit(currency=currency) def stepSetTaskPriceCurrency(self, sequence, **kw) : """Set the price currency of the task. TODO : include a test with this step late. """ currency = sequence.get('currency') task = sequence.get('task') task.setPriceCurrency(currency.getRelativeUrl()) def stepSetTaskValues(self, sequence=None, sequence_list=None, **kw): """ Fill created task with some necessary data. """ task = sequence.get('task') project = sequence.get('project') resource = sequence.get('resource_list')[0] organisation_list = sequence.get('organisation_list') organisation1 = organisation_list[0] organisation2 = organisation_list[1] task.edit(source_value=organisation1, source_section_value=organisation1, destination_value=organisation2, destination_section_value=organisation2, source_project_value=project, destination_project_value=project, description=self.task_description % task.getId(), start_date = self.datetime + 10, stop_date = self.datetime + 20,) sequence.edit( task = task) def stepFillTaskWithData(self, sequence=None, sequence_list=None, **kw): """ Fill created task with some necessary data. """ self.stepSetTaskValues(sequence=sequence, sequence_list=sequence_list, **kw) task = sequence.get('task') project = sequence.get('project') resource = sequence.get('resource_list')[0] requirement = sequence.get('requirement') task.edit(task_line_resource_value = resource, task_line_quantity = self.default_quantity, task_line_price = self.default_price, task_line_requirement_value = requirement, task_line_description = 'Default Task Line Description', ) def stepCreateSimpleTaskReport(self,sequence=None, sequence_list=None, **kw): """ Create a task report. """ portal = self.getPortal() task_report_module = portal.getDefaultModule( portal_type=self.task_report_portal_type) task_report = task_report_module.newContent( portal_type=self.task_report_portal_type) # Check if no task lines are created at the start self.assertEquals(len(task_report.contentValues()), 0) task_report.edit( title = "Task Report", ) sequence.edit(task_report = task_report) def stepFillTaskReportWithData(self, sequence=None, sequence_list=None, **kw): """ Fill created task report with some necessary data. """ task_report = sequence.get('task_report') organisation_list = sequence.get('organisation_list') organisation1 = organisation_list[0] organisation2 = organisation_list[1] project = sequence.get('project') task_report.edit(source_value=organisation1, source_section_value=organisation1, destination_value=organisation1, destination_section_value=organisation2, source_project_value=project, destination_project_value=project, start_date = self.datetime + 10, stop_date = self.datetime + 20,) sequence.edit( task_report = task_report) def stepSetTaskReportPriceCurrency(self, sequence, **kw) : """Set the price currency of the task. This step is not necessary. TODO : - include a test without this step. - include a test with this step late. """ currency = sequence.get('currency') task_report = sequence.get('task_report') task_report.setPriceCurrency(currency.getRelativeUrl()) def stepCreateTaskReportLine(self, sequence=None, sequence_list=None, **kw): """ Create task report line and fill with dummy data. """ resource = sequence.get('resource_list')[0] portal = self.getPortal() task_report = sequence.get('task_report') task_report_line = task_report.newContent( portal_type=self.task_report_line_portal_type) task_report_line.edit( title = 'New Task Report Line', resource_value = resource, quantity = self.default_quantity, price = self.default_price) sequence.edit(task_report_line = task_report_line) def stepVerifyGeneratedByBuilderTaskReport(self, sequence=None, sequence_list=None, **kw): """ Verify that simulation generated report is correct. """ task = sequence.get('task') task_report = sequence.get('task_report') self.assertEquals('confirmed', task_report.getSimulationState()) self.assertEquals(task.getSource(), task_report.getSource()) self.assertEquals(task.getSourceSection(), task_report.getSourceSection()) self.assertEquals(task.getSourceProject(), task_report.getSourceProject()) self.assertEquals(task.getDestination(), task_report.getDestination()) self.assertEquals(task.getDestinationSection(), task_report.getDestinationSection()) self.assertEquals(task.getDestinationDecision(), task_report.getDestinationDecision()) self.assertEquals(task.getTitle(), task_report.getTitle()) self.assertEquals(task.getDescription(), task_report.getDescription()) self.assertEquals(task.getPredecessor(), task_report.getPredecessor()) self.assertEquals(task.getDescription(), task_report.getDescription()) self.assertEquals(task.getPriceCurrency(), task_report.getPriceCurrency()) self.assertEquals(len(task_report.contentValues()), 1) task_report_line = task_report.contentValues()[0] self.assertEquals(task.getTaskLineResource(), task_report_line.getResource()) self.assertEquals(task.getTaskLineQuantity(), task_report_line.getQuantity()) self.assertEquals(task.getTaskLinePrice(), task_report_line.getPrice()) self.assertEquals(task.getTaskLineRequirement(), task_report_line.getRequirement()) def stepCreateTaskLine(self, sequence=None, sequence_list=None, **kw): """ Create task line and fill with dummy data. """ task = sequence.get('task') task_line = task.newContent( portal_type=self.task_line_portal_type, title='New Task Line', description='New Task Line Description') sequence.edit(task_line=task_line) def stepFillTaskLineWithData(self, sequence=None, sequence_list=None, **kw): """ Fill task line with dummy data. """ organisation = sequence.get('organisation_list')[0] resource1 = sequence.get('resource_list')[1] task_line = sequence.get('task_line') task_line.edit( source_value=organisation, resource_value=resource1, quantity=self.default_quantity, price=self.default_price) def stepVerifyGeneratedTaskReportLines(self, sequence=None, sequence_list=None, **kw): """ Verify that simulation generated report is correct. """ task = sequence.get('task') task_report = sequence.get('task_report') task_content_list = task.contentValues() self.assertNotEquals(len(task_content_list), 0) self.assertEquals(len(task_report.contentValues()), len(task_content_list)) # Task report values not tested # XXX # Task line not precisely tested for task_line in task_content_list: task_report_resource_list = \ [line.getResource() for line in task_report.contentValues()] task_report_quantity_list = \ [line.getQuantity() for line in task_report.contentValues()] task_report_price_list = \ [line.getPrice() for line in task_report.contentValues()] self.assertTrue(task_line.getResource() in task_report_resource_list) self.assertTrue(task_line.getQuantity() in task_report_quantity_list) self.assertTrue(task_line.getPrice() in task_report_price_list) for task_report_line in task_report.contentValues(portal_type='Task Report Line'): simulation_movement = task_report_line.getDeliveryRelatedValue() task_line = simulation_movement.getDeliveryValue() self.assert_(task_line.getDescription()) self.assertEqual(task_line.getDescription(), task_report_line.getDescription()) def stepVerifyTaskReportCausalityState(self, sequence=None, sequence_list=None, **kw): """ Verify that confirmed task report starts building and gets solved. """ task_report = sequence.get('task_report') self.assertEqual(task_report.getCausalityState(), 'solved') def stepVerifyTaskReportNoPrice(self, sequence=None, sequence_list=None, **kw): task_report = sequence.get('task_report') self.assertEqual(None, task_report.getPriceCurrency()) self.assertEqual(1, len(task_report.getMovementList())) task_report_line = task_report.getMovementList()[0] self.assertEqual(None, task_report_line.getPrice()) def modifyState(self, object_name, transition_name, sequence=None, sequence_list=None): object_value = sequence.get(object_name) workflow_method = getattr(object_value, transition_name) workflow_method() def stepConfirmTask(self, sequence=None, sequence_list=None, **kw): self.modifyState('task', 'confirm', sequence=sequence) def stepConfirmTaskReport(self, sequence=None, sequence_list=None, **kw): self.modifyState('task_report', 'confirm', sequence=sequence) def stepStartTaskReport(self, sequence=None, sequence_list=None, **kw): self.modifyState('task_report', 'start', sequence=sequence) def stepFinishTaskReport(self, sequence=None, sequence_list=None, **kw): self.modifyState('task_report', 'stop', sequence=sequence) def stepCloseTaskReport(self, sequence=None, sequence_list=None, **kw): self.modifyState('task_report', 'deliver', sequence=sequence) def stepRestartTaskReport(self, sequence=None, sequence_list=None, **kw): self.modifyState('task_report', 'restart', sequence=sequence) def stepSetTaskReport(self, sequence=None, sequence_list=None, **kw): """ Set task report object in sequence. """ task = sequence.get('task') task_report = task.getCausalityRelatedValueList( portal_type='Task Report')[0] sequence.edit(task_report=task_report) def stepVerifyMergedTaskLine(self, sequence=None, sequence_list=None, **kw): """ Verify that simulation generated report is correct. """ task = sequence.get('task') task_report = sequence.get('task_report') self.assertEquals('confirmed', task_report.getSimulationState()) self.assertEquals(task.getSource(), task_report.getSource()) self.assertEquals(task.getSourceSection(), task_report.getSourceSection()) self.assertEquals(task.getSourceProject(), task_report.getSourceProject()) self.assertEquals(task.getDestination(), task_report.getDestination()) self.assertEquals(task.getDestinationSection(), task_report.getDestinationSection()) self.assertEquals(task.getDestinationDecision(), task_report.getDestinationDecision()) self.assertEquals(task.getTitle(), task_report.getTitle()) self.assertEquals(task.getDescription(), task_report.getDescription()) self.assertEquals(task.getPredecessor(), task_report.getPredecessor()) self.assertEquals(task.getDescription(), task_report.getDescription()) self.assertEquals(len(task_report.contentValues()), 2) for task_report_line in task_report.contentValues(): self.assertEquals(task.contentValues()[0].getResource(), task_report_line.getResource()) self.assertEquals(task.contentValues()[0].getQuantity(), task_report_line.getQuantity()) self.assertEquals(task.contentValues()[0].getPrice(), task_report_line.getPrice()) self.assertEquals(task.contentValues()[0].getRequirement(), task_report_line.getRequirement()) class TestTask(TestTaskMixin, ERP5TypeTestCase): """ Test task behaviour. """ run_all_test = 1 def afterSetUp(self): self.validateRules() def getTitle(self): return "Task" def enableLightInstall(self): """ You can override this. Return if we should do a light install (1) or not (0) """ return 1 def enableActivityTool(self): """ You can override this. Return if we should create (1) or not (0) an activity tool. """ return 1 def test_01_testTaskBasicUseCase(self, quiet=0, run=run_all_test): """ Test creation of task and (automatic) task_report """ if not run: return sequence_list = SequenceList() sequence_string = self.default_task_sequence + '\ stepVerifyGeneratedByBuilderTaskReport \ stepStartTaskReport \ stepFinishTaskReport \ stepCloseTaskReport \ ' sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_01_testTaskNoPrice(self, quiet=0, run=run_all_test): """ Test creation of task and (automatic) task_report when no price is defined on the task """ if not run: return self.default_price = None sequence_list = SequenceList() sequence_string = self.default_task_no_price_sequence + '\ stepVerifyGeneratedByBuilderTaskReport \ stepVerifyTaskReportNoPrice \ stepStartTaskReport \ stepFinishTaskReport \ stepCloseTaskReport \ ' sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_02_testMultipleLineTaskBasicUseCase(self, quiet=0, run=run_all_test): """ Test creation of task with multiple task lines \ and (automatic) creation of task_report. """ if not run: return sequence_list = SequenceList() sequence_string = self.default_task_sequence_two_lines + '\ stepVerifyGeneratedTaskReportLines \ stepStartTaskReport \ stepFinishTaskReport \ stepCloseTaskReport \ ' sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_03_testTaskReportBasicUseCase(self, quiet=0, run=run_all_test): """ Test creation of task report and task report lines. """ if not run: return sequence_list = SequenceList() sequence_string = self.default_task_report_sequence + '\ stepConfirmTaskReport \ stepTic \ stepVerifyTaskReportCausalityState \ stepStartTaskReport \ stepFinishTaskReport \ stepCloseTaskReport \ ' sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_04_checkNotMergedTaskReportLine(self, quiet=0, run=run_all_test): """ Check that a task report can not be the created from a merged of multiple task lines. """ if not run: return sequence_list = SequenceList() sequence_string = 'stepLogin \ stepCreateOrganisation \ stepCreateOrganisation \ stepCreateResource \ stepCreateResource \ stepCreateSimpleTask \ stepSetTaskValues \ stepCreateTaskLine \ stepFillTaskLineWithData \ stepCreateTaskLine \ stepFillTaskLineWithData \ stepConfirmTask \ stepTic \ stepSetTaskReport \ stepVerifyMergedTaskLine \ stepStartTaskReport \ stepFinishTaskReport \ stepCloseTaskReport \ ' sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_05_testStrictSimulationSecurity(self, quiet=0, run=run_all_test): """Test creation of task and (automatic) task_report with strict security in the simulation. """ if not run: return sequence_list = SequenceList() sequence_string = self.default_task_sequence + '\ stepVerifyGeneratedByBuilderTaskReport \ stepStartTaskReport \ stepFinishTaskReport \ stepCloseTaskReport \ ' sequence_list.addSequenceString(sequence_string) simulation_tool = self.getPortal().portal_simulation uf = self.getPortal().acl_users if not uf.getUser('manager'): uf._doAddUser('manager', '', ['Manager'], []) self.login('manager') try: simulation_tool.Base_setDefaultSecurity() self.logout() sequence_list.play(self) finally: self.login('manager') for permission in simulation_tool.possible_permissions(): simulation_tool.manage_permission(permission, roles=(), acquire=1) self.logout() def test_06_checkTaskReferenceOnCreationAndPaste(self, quiet=0, run=run_all_test): """Tests that task reference is set upon creation and coping""" if not run: return self.stepLogin() portal = self.getPortal() task_module = portal.getDefaultModule(portal_type=self.task_portal_type) task = task_module.newContent(portal_type=self.task_portal_type) self.assertEqual( task.getReference(), 'T %s'%(task.getId(),) ) cb_data = task_module.manage_copyObjects(ids=[task.getId()]) p_data = task_module.manage_pasteObjects(cb_data) new_task = task_module._getOb(p_data[0]['new_id']) self.assertEqual( new_task.getReference(), 'T %s'%(new_task.getId(),) ) def test_07_taskConstraints(self): """Check tasks constraints""" self.stepLogin() portal = self.getPortal() portal_type = portal.portal_types['Task'] original_property_sheet_list = portal_type.getTypePropertySheetList() try: sequence = Sequence(context=self) if not('TaskConstraint' in original_property_sheet_list): new_property_sheet_list = ['TaskConstraint'] + original_property_sheet_list portal_type.edit(type_property_sheet_list=new_property_sheet_list) task_module = portal.getDefaultModule(portal_type=self.task_portal_type) task = task_module.newContent(portal_type=self.task_portal_type) doActionFor = self.portal.portal_workflow.doActionFor self.assertRaises(ValidationFailed, doActionFor, task, 'confirm_action') sequence('CreateOrganisation') sequence('CreateOrganisation') sequence('CreateResource') (source, destination) = sequence.get('organisation_list') check_result = task.checkConsistency() self.assertEquals(len(check_result), 4) task.setDestinationValue(destination) task.setSourceValue(source) check_result = task.checkConsistency() self.assertEquals(len(check_result), 2) task.setStartDate(DateTime()) task.setStopDate(DateTime() + 1) check_result = task.checkConsistency() self.assertEquals(len(check_result), 1) resource = sequence.get('resource_list')[0] task.edit(task_line_resource_value = resource, task_line_quantity = self.default_quantity, task_line_price = self.default_price, ) check_result = task.checkConsistency() self.assertEquals(len(check_result), 0) finally: portal_type.setTypePropertySheetList(original_property_sheet_list) def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestTask)) return suite