entities/test/unittest_wfobjs.py
branch3.5
changeset 2992 a5b8bf107a1a
parent 2985 79185b3ccf2c
child 3023 7864fee8b4ec
child 3206 5a51ac97f1d3
equal deleted inserted replaced
2991:dab951c08896 2992:a5b8bf107a1a
     1 from cubicweb.devtools.apptest import EnvBasedTC
     1 from cubicweb.devtools.apptest import EnvBasedTC
     2 from cubicweb import ValidationError
     2 from cubicweb import ValidationError
     3 
     3 
     4 def add_wf(self, etype, name=None):
     4 def add_wf(self, etype, name=None, default=False):
     5     if name is None:
     5     if name is None:
     6         name = unicode(etype)
     6         name = etype
     7     wf = self.execute('INSERT Workflow X: X name %(n)s', {'n': name}).get_entity(0, 0)
     7     wf = self.execute('INSERT Workflow X: X name %(n)s', {'n': unicode(name)}).get_entity(0, 0)
     8     self.execute('SET WF workflow_of ET WHERE WF eid %(wf)s, ET name %(et)s',
     8     self.execute('SET WF workflow_of ET WHERE WF eid %(wf)s, ET name %(et)s',
     9                  {'wf': wf.eid, 'et': etype})
     9                  {'wf': wf.eid, 'et': etype})
       
    10     if default:
       
    11         self.execute('SET ET default_workflow WF WHERE WF eid %(wf)s, ET name %(et)s',
       
    12                      {'wf': wf.eid, 'et': etype})
    10     return wf
    13     return wf
    11 
    14 
    12 def parse_hist(wfhist):
    15 def parse_hist(wfhist):
    13     return [(ti.previous_state.name, ti.new_state.name,
    16     return [(ti.previous_state.name, ti.new_state.name,
    14              ti.transition and ti.transition.name, ti.comment)
    17              ti.transition and ti.transition.name, ti.comment)
   153         self.execute('INSERT RQLExpression X: X exprtype "ERQLExpression", '
   156         self.execute('INSERT RQLExpression X: X exprtype "ERQLExpression", '
   154                      'X expression "U has_update_permission X", T condition X '
   157                      'X expression "U has_update_permission X", T condition X '
   155                      'WHERE T name "deactivate"')
   158                      'WHERE T name "deactivate"')
   156         self._test_stduser_deactivate()
   159         self._test_stduser_deactivate()
   157 
   160 
       
   161     def test_subworkflow_base(self):
       
   162         """subworkflow
       
   163 
       
   164         +-----------+  tr1   +-----------+
       
   165         | swfstate1 | ------>| swfstate2 |
       
   166         +-----------+        +-----------+
       
   167                   |  tr2  +-----------+
       
   168                   `------>| swfstate3 |
       
   169                           +-----------+
       
   170 
       
   171         main workflow
       
   172 
       
   173         +--------+  swftr1             +--------+
       
   174         | state1 | -------[swfstate2]->| state2 |
       
   175         +--------+     |               +--------+
       
   176                        |               +--------+
       
   177                        `-[swfstate3]-->| state3 |
       
   178                                        +--------+
       
   179         """
       
   180         # sub-workflow
       
   181         swf = add_wf(self, 'CWGroup', name='subworkflow')
       
   182         swfstate1 = swf.add_state(u'swfstate1', initial=True)
       
   183         swfstate2 = swf.add_state(u'swfstate2')
       
   184         swfstate3 = swf.add_state(u'swfstate3')
       
   185         tr1 = swf.add_transition(u'tr1', (swfstate1,), swfstate2)
       
   186         tr2 = swf.add_transition(u'tr2', (swfstate1,), swfstate3)
       
   187         # main workflow
       
   188         mwf = add_wf(self, 'CWGroup', name='main workflow', default=True)
       
   189         state1 = mwf.add_state(u'state1', initial=True)
       
   190         state2 = mwf.add_state(u'state2')
       
   191         state3 = mwf.add_state(u'state3')
       
   192         swftr1 = mwf.add_wftransition(u'swftr1', swf, state1,
       
   193                                       [(swfstate2, state2), (swfstate3, state3)])
       
   194         self.assertEquals(swftr1.destination().eid, swfstate1.eid)
       
   195         # workflows built, begin test
       
   196         self.group = self.add_entity('CWGroup', name=u'grp1')
       
   197         self.commit()
       
   198         self.assertEquals(self.group.current_state.eid, state1.eid)
       
   199         self.assertEquals(self.group.current_workflow.eid, mwf.eid)
       
   200         self.assertEquals(self.group.main_workflow.eid, mwf.eid)
       
   201         self.assertEquals(self.group.subworkflow_input_transition(), None)
       
   202         self.group.fire_transition('swftr1', u'go')
       
   203         self.commit()
       
   204         self.group.clear_all_caches()
       
   205         self.assertEquals(self.group.current_state.eid, swfstate1.eid)
       
   206         self.assertEquals(self.group.current_workflow.eid, swf.eid)
       
   207         self.assertEquals(self.group.main_workflow.eid, mwf.eid)
       
   208         self.assertEquals(self.group.subworkflow_input_transition().eid, swftr1.eid)
       
   209         self.group.fire_transition('tr1', u'go')
       
   210         self.commit()
       
   211         self.group.clear_all_caches()
       
   212         self.assertEquals(self.group.current_state.eid, state2.eid)
       
   213         self.assertEquals(self.group.current_workflow.eid, mwf.eid)
       
   214         self.assertEquals(self.group.main_workflow.eid, mwf.eid)
       
   215         self.assertEquals(self.group.subworkflow_input_transition(), None)
       
   216         # force back to swfstate1 is impossible since we can't any more find
       
   217         # subworkflow input transition
       
   218         ex = self.assertRaises(ValidationError,
       
   219                                self.group.change_state, swfstate1, u'gadget')
       
   220         self.assertEquals(ex.errors, {'to_state': "state doesn't belong to entity's current workflow"})
       
   221         self.rollback()
       
   222         # force back to state1
       
   223         self.group.change_state('state1', u'gadget')
       
   224         self.group.fire_transition('swftr1', u'au')
       
   225         self.group.clear_all_caches()
       
   226         self.group.fire_transition('tr2', u'chapeau')
       
   227         self.commit()
       
   228         self.group.clear_all_caches()
       
   229         self.assertEquals(self.group.current_state.eid, state3.eid)
       
   230         self.assertEquals(self.group.current_workflow.eid, mwf.eid)
       
   231         self.assertEquals(self.group.main_workflow.eid, mwf.eid)
       
   232         self.assertListEquals(parse_hist(self.group.workflow_history),
       
   233                               [('state1', 'swfstate1', 'swftr1', 'go'),
       
   234                                ('swfstate1', 'swfstate2', 'tr1', 'go'),
       
   235                                ('swfstate2', 'state2', 'swftr1', 'exiting from subworkflow subworkflow'),
       
   236                                ('state2', 'state1', None, 'gadget'),
       
   237                                ('state1', 'swfstate1', 'swftr1', 'au'),
       
   238                                ('swfstate1', 'swfstate3', 'tr2', 'chapeau'),
       
   239                                ('swfstate3', 'state3', 'swftr1', 'exiting from subworkflow subworkflow'),
       
   240                                ])
       
   241 
       
   242     def test_subworkflow_exit_consistency(self):
       
   243         # sub-workflow
       
   244         swf = add_wf(self, 'CWGroup', name='subworkflow')
       
   245         swfstate1 = swf.add_state(u'swfstate1', initial=True)
       
   246         swfstate2 = swf.add_state(u'swfstate2')
       
   247         tr1 = swf.add_transition(u'tr1', (swfstate1,), swfstate2)
       
   248         # main workflow
       
   249         mwf = add_wf(self, 'CWGroup', name='main workflow', default=True)
       
   250         state1 = mwf.add_state(u'state1', initial=True)
       
   251         state2 = mwf.add_state(u'state2')
       
   252         state3 = mwf.add_state(u'state3')
       
   253         mwf.add_wftransition(u'swftr1', swf, state1,
       
   254                              [(swfstate2, state2), (swfstate2, state3)])
       
   255         ex = self.assertRaises(ValidationError, self.commit)
       
   256         self.assertEquals(ex.errors, {'subworkflow_exit': u"can't have multiple exits on the same state"})
   158 
   257 
   159 
   258 
   160 class CustomWorkflowTC(EnvBasedTC):
   259 class CustomWorkflowTC(EnvBasedTC):
   161 
   260 
   162     def setup_database(self):
   261     def setup_database(self):