[CMF-checkins] CVS: CMF/CMFSetup/tests - common.py:1.10 test_workflow.py:1.6

Tres Seaver tseaver at zope.com
Fri Jun 4 23:17:21 EDT 2004


Update of /cvs-repository/CMF/CMFSetup/tests
In directory cvs.zope.org:/tmp/cvs-serv32305/tests

Modified Files:
	common.py test_workflow.py 
Log Message:


  - tests/common.py:

    o Harden DOMComparator against spurious whitespace diffs.

  - workflow.py:

    o Implement / test export of workflow definition.

    o Note that this required changing semantics of some dump info
      in order better to fit the "normalized" XML we are aiming for.


=== CMF/CMFSetup/tests/common.py 1.9 => 1.10 ===
--- CMF/CMFSetup/tests/common.py:1.9	Sun May 30 16:29:50 2004
+++ CMF/CMFSetup/tests/common.py	Fri Jun  4 23:16:49 2004
@@ -12,6 +12,12 @@
 
     def _compareDOM( self, found_text, expected_text, debug=False ):
 
+        found_lines = [ x.strip() for x in found_text.splitlines() ]
+        found_text = '\n'.join( filter( None, found_lines ) )
+
+        expected_lines = [ x.strip() for x in expected_text.splitlines() ]
+        expected_text = '\n'.join( filter( None, expected_lines ) )
+
         from xml.dom.minidom import parseString
         found = parseString( found_text )
         expected = parseString( expected_text )


=== CMF/CMFSetup/tests/test_workflow.py 1.5 => 1.6 ===
--- CMF/CMFSetup/tests/test_workflow.py:1.5	Thu Jun  3 19:11:35 2004
+++ CMF/CMFSetup/tests/test_workflow.py	Fri Jun  4 23:16:49 2004
@@ -45,17 +45,27 @@
 
     def _assertGuard( self, info, permissions, roles, groups, expr ):
 
-        self.assertEqual( info[ 'guard_permissions' ]
-                        , '; '.join( permissions ) )
+        self.assertEqual( len( info[ 'guard_permissions' ] )
+                        , len( permissions ) )
 
-        self.assertEqual( info[ 'guard_roles' ]
-                        , '; '.join( roles ) )
+        for expected in permissions:
+            self.failUnless( expected in info[ 'guard_permissions' ] )
 
-        self.assertEqual( info[ 'guard_groups' ]
-                        , '; '.join( groups ) )
+        self.assertEqual( len( info[ 'guard_roles' ] )
+                        , len( roles ) )
+
+        for expected in roles:
+            self.failUnless( expected in info[ 'guard_roles' ] )
+
+        self.assertEqual( len( info[ 'guard_groups' ] )
+                        , len( groups ) )
+
+        for expected in groups:
+            self.failUnless( expected in info[ 'guard_groups' ] )
 
         self.assertEqual( info[ 'guard_expr' ], expr )
 
+
 class _WorkflowSetup( BaseRegistryTests ):
 
     def _initSite( self ):
@@ -94,6 +104,8 @@
 
     def _initStates( self, dcworkflow ):
         
+        dcworkflow.groups = _WF_GROUPS
+
         for k, v in _WF_STATES.items():
 
             dcworkflow.states.addState( k )
@@ -324,6 +336,18 @@
                 for ep_role in ep_roles:
                     self.failUnless( ep_role in fp[ 'roles' ] )
 
+            groups = info[ 'groups' ]
+            self.assertEqual( len( groups ), len( expected[ 4 ] ) )
+
+            for i in range( len( groups ) ):
+                self.assertEqual( groups[ i ], expected[ 4 ][ i ] )
+
+            variables = info[ 'variables' ]
+            self.assertEqual( len( variables ), len( expected[ 5 ] ) )
+
+            for var_id, expr in variables:
+                self.assertEqual( expr, expected[ 5 ][ var_id ] )
+
     def test_getWorkflowInfo_dcworkflow_transitions( self ):
 
         from Products.CMFSetup.workflow import TRIGGER_TYPES
@@ -576,8 +600,6 @@
 
     def test_generateToolXML_mixed( self ):
 
-        site = self._initSite()
-
         WF_ID_NON = 'non_dcworkflow'
         WF_TITLE_NON = 'Non-DCWorkflow'
         WF_ID_DC = 'dcworkflow'
@@ -597,6 +619,48 @@
 
         self._compareDOM( configurator.generateToolXML(), _NORMAL_TOOL_EXPORT )
 
+    def test_generateWorkflowXML_empty( self ):
+
+        WF_ID = 'empty'
+        WF_TITLE = 'Empty DCWorkflow'
+        WF_INITIAL_STATE = 'initial'
+
+        site = self._initSite()
+        dcworkflow = self._initDCWorkflow( WF_ID )
+        dcworkflow.title = WF_TITLE
+        dcworkflow.initial_state = WF_INITIAL_STATE
+
+        configurator = self._makeOne( site ).__of__( site )
+
+        self._compareDOM( configurator.generateWorkflowXML( WF_ID )
+                        , _EMPTY_WORKFLOW_EXPORT % ( WF_ID
+                                                   , WF_TITLE
+                                                   , WF_INITIAL_STATE
+                                                   ) )
+
+    def test_generateWorkflowXML_normal( self ):
+
+        WF_ID = 'normal'
+        WF_TITLE = 'Empty DCWorkflow'
+        WF_INITIAL_STATE = 'closed'
+
+        site = self._initSite()
+        dcworkflow = self._initDCWorkflow( WF_ID )
+        dcworkflow.title = WF_TITLE
+        dcworkflow.initial_state = WF_INITIAL_STATE
+        dcworkflow.permissions = _WF_PERMISSIONS
+        self._initVariables( dcworkflow )
+        self._initStates( dcworkflow )
+        self._initTransitions( dcworkflow )
+        self._initWorklists( dcworkflow )
+
+        configurator = self._makeOne( site ).__of__( site )
+
+        self._compareDOM( configurator.generateWorkflowXML( WF_ID )
+                        , _NORMAL_WORKFLOW_EXPORT % ( WF_ID
+                                                    , WF_TITLE
+                                                    , WF_INITIAL_STATE
+                                                    ) )
 
 
 _WF_PERMISSIONS = \
@@ -606,6 +670,11 @@
 , 'Restore expired content'
 )
 
+_WF_GROUPS = \
+( 'Content_owners'
+, 'Content_assassins'
+)
+
 _WF_VARIABLES = \
 { 'when_opened':  ( 'Opened when'
                   , ''
@@ -655,7 +724,7 @@
              , ( 'close', 'kill', 'expire' )
              , { 'Modify content':  [ 'Owner', 'Manager' ] }
              , [ ( 'Content_owners', ( 'Owner', ) ) ]
-             , { 'is_opened':  True, 'is_closed':  True }
+             , { 'is_opened':  True, 'is_closed':  False }
              )
 , 'killed':  ( 'Killed'
              , 'Permanently unavailable'
@@ -716,7 +785,7 @@
              , { 'killed_by' : 'string:${user/getId}' }
              , ()
              , ()
-             , ( 'Content assassins', )
+             , ( 'Content_assassins', )
              , ""
              )
 , 'expire':  ( 'Expire'
@@ -854,6 +923,221 @@
   </default>
  </bindings>
 </workflow-tool>
+"""
+
+_EMPTY_WORKFLOW_EXPORT = """\
+<?xml version="1.0"?>
+<dc-workflow
+    workflow_id="%s"
+    type="DCWorkflow"
+    title="%s"
+    state_variable="state" 
+    initial_state="%s">
+</dc-workflow>
+"""
+
+_NORMAL_WORKFLOW_EXPORT = """\
+<?xml version="1.0"?>
+<dc-workflow
+    workflow_id="%s"
+    type="DCWorkflow"
+    title="%s"
+    state_variable="state" 
+    initial_state="%s">
+ <permission>Open content for modifications</permission>
+ <permission>Modify content</permission>
+ <permission>Query history</permission>
+ <permission>Restore expired content</permission>
+ <variable
+    variable_id="killed_by"
+    for_catalog="True"
+    for_status="False"
+    update_always="True">
+   Killed by
+   <default>
+    <value>n/a</value>
+   </default>
+   <guard>
+    <role>Hangman</role>
+    <role>Sherrif</role>
+   </guard>
+ </variable>
+ <variable
+    variable_id="when_expired"
+    for_catalog="True"
+    for_status="False"
+    update_always="True">
+   Expired when
+   <default>
+    <expression>nothing</expression>
+   </default>
+   <guard>
+    <permission>Query history</permission>
+    <permission>Open content for modifications</permission>
+   </guard>
+ </variable>
+ <variable
+    variable_id="when_opened"
+    for_catalog="True"
+    for_status="False"
+    update_always="True">
+   Opened when
+   <default>
+    <expression>python:None</expression>
+   </default>
+   <guard>
+    <permission>Query history</permission>
+    <permission>Open content for modifications</permission>
+   </guard>
+ </variable>
+ <worklist
+    worklist_id="alive_list">
+  Worklist for content not yet expired / killed
+  <action
+    category="workflow"
+    url="string:${portal_url}/expired_items">Expired items</action>
+  <guard>
+   <permission>Restore expired content</permission>
+  </guard>
+  <match name="state" values="open; closed"/>
+ </worklist>
+ <worklist
+    worklist_id="expired_list">
+  Worklist for expired content
+  <action
+    category="workflow"
+    url="string:${portal_url}/expired_items">Expired items</action>
+  <guard>
+   <permission>Restore expired content</permission>
+  </guard>
+  <match name="state" values="expired"/>
+ </worklist>
+ <state
+    state_id="expired"
+    title="Expired">
+  Expiration date has passed
+  <permission
+    acquired="True"
+    name="Modify content">
+   <role>Owner</role>
+   <role>Manager</role>
+  </permission>
+  <exit-transition
+    transition_id="open"/>
+  <assignment
+    name="is_closed">False</assignment>
+  <assignment
+    name="is_opened">False</assignment>
+ </state>
+ <state
+    state_id="opened"
+    title="Opened">
+  Open for modifications
+  <permission
+    acquired="True"
+    name="Modify content">
+   <role>Owner</role>
+   <role>Manager</role>
+  </permission>
+  <exit-transition
+    transition_id="close"/>
+  <exit-transition
+    transition_id="kill"/>
+  <exit-transition
+    transition_id="expire"/>
+  <assignment
+    name="is_closed">False</assignment>
+  <assignment
+    name="is_opened">True</assignment>
+ </state>
+ <state
+    state_id="closed"
+    title="Closed">
+  Closed for modifications
+  <permission
+    acquired="False"
+    name="Modify content">
+  </permission>
+  <exit-transition
+    transition_id="open"/>
+  <exit-transition
+    transition_id="kill"/>
+  <exit-transition
+    transition_id="expire"/>
+  <assignment
+    name="is_closed">True</assignment>
+  <assignment
+    name="is_opened">False</assignment>
+ </state>
+ <state
+    state_id="killed"
+    title="Killed">
+  Permanently unavailable
+ </state>
+ <transition
+    transition_id="close"
+    title="Close"
+    trigger="USER"
+    new_state="closed"
+    before_script=""
+    after_script="after_close">
+  Close the object for modifications
+  <action
+    category="workflow"
+    url="string:${object_url}/close_for_modifications">Close</action>
+  <guard>
+   <role>Owner</role>
+   <role>Manager</role>
+  </guard>
+ </transition>
+ <transition
+    transition_id="expire"
+    title="Expire"
+    trigger="AUTOMATIC"
+    new_state="expired"
+    before_script=""
+    after_script="">
+  Retire objects whose expiration is past.
+  <guard>
+   <expression>python: object.expiration() &lt;= object.ZopeTime()</expression>
+  </guard>
+  <assignment
+    name="when_expired">object/ZopeTime</assignment>
+ </transition>
+ <transition
+    transition_id="open"
+    title="Open"
+    trigger="USER"
+    new_state="opened"
+    before_script="before_open"
+    after_script="">
+  Open the object for modifications
+  <action
+    category="workflow"
+    url="string:${object_url}/open_for_modifications">Open</action>
+  <guard>
+   <permission>Open content for modifications</permission>
+  </guard>
+  <assignment name="when_opened">object/ZopeTime</assignment>
+ </transition>
+ <transition
+    transition_id="kill"
+    title="Kill"
+    trigger="USER"
+    new_state="killed"
+    before_script=""
+    after_script="after_kill">
+  Make the object permanently unavailable.
+  <action
+    category="workflow"
+    url="string:${object_url}/kill_object">Kill</action>
+  <guard>
+   <group>Content_assassins</group>
+  </guard>
+  <assignment
+    name="killed_by">string:${user/getId}</assignment>
+ </transition>
+</dc-workflow>
 """
 
 




More information about the CMF-checkins mailing list