[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() <= 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