Events in Archetypes
====================

This doctest makes sure that at relevant places in the Arcehtypes
code, events are fired.  To test events, we'll set up an event handler
that listens for object events for `IBaseObject`:

  >>> from pprint import pprint
  >>> from StringIO import StringIO
  >>> from Products.Archetypes.tests.utils import makeContent, aputrequest
  >>> from Products.Archetypes.interfaces import IBaseObject
  >>> from zope.component.interfaces import IObjectEvent

  >>> class Handler:
  ...     def __init__(self):
  ...         self.got = []
  ...     def __call__(self, *args):
  ...         self.got.append(args)
  ...     def print_and_flush(self):
  ...         print "%s events:" % len(self.got)
  ...         pprint(self.got)
  ...         self.got = []
  ...     def print_last_and_flush(self):
  ...	      self.got = self.got[-1:]
  ...         print "%s events:" % len(self.got)
  ...         pprint(self.got)
  ...         self.got = []
  >>> handler = Handler()

  >>> from zope.component import getGlobalSiteManager
  >>> gsm = getGlobalSiteManager()
  >>> gsm.registerHandler(handler, [IBaseObject, IObjectEvent], event=False)

Creating an AT object will a couple of events:

  >>> portal = layer['portal']
  >>> from plone.app.testing import TEST_USER_ID
  >>> folder = portal.portal_membership.getHomeFolder(TEST_USER_ID)
  >>> d = makeContent(folder, portal_type='DDocument', id='a')
  >>> handler.print_and_flush() #doctest: +ELLIPSIS
  5 events:
  [(<DDocument at /plone/Members/test_user_1_/a>,
    <zope.lifecycleevent.ObjectCreatedEvent object at ...>),
   (<DDocument at /plone/Members/test_user_1_/a>,
    <Products.DCWorkflow.events.BeforeTransitionEvent object at ...>),
   (<DDocument at /plone/Members/test_user_1_/a>,
    <Products.DCWorkflow.events.AfterTransitionEvent object at ...>),
   (<DDocument at /plone/Members/test_user_1_/a>,
    <zope.lifecycleevent.ObjectAddedEvent object at ...>),
   (<ATFolder at /plone/Members/test_user_1_>,
    <zope.container.contained.ContainerModifiedEvent object at ...>)]


Calling `processForm`, which is what happens on submitting a form,
will fire the modified event:

  >>> d.processForm()
  >>> handler.print_and_flush() #doctest: +ELLIPSIS
  1 events:
  [(<DDocument at /.../Members/test_user_1_/a>,
    <Products.Archetypes.event.ObjectInitializedEvent object at ...>)]


Setup Content Type Registry so that a 'DDocument' is created: 

  >>> contents = StringIO('some contents') 
  >>> request = aputrequest(contents, 'text/plain') 
  >>> request.processInputs() 
  >>> ignore = d.PUT(request, request.RESPONSE) 
  >>> from Products.CMFCore.utils import getToolByName 
  >>> ctr = getToolByName(portal, 'content_type_registry') 
  >>> p_id = 'at_dav_test' 
  >>> p_type = 'name_regex' 
  >>> ctr.addPredicate(p_id, p_type) 
  >>> class foo: pass 
  >>> p_dict = foo() 
  >>> p_dict.pattern = '.*' 
  >>> ctr.updatePredicate(p_id, p_dict, 'DDocument') 
  >>> ctr.reorderPredicate(p_id, 0)

Doing a `PUT` request that creates a brand new object should fire
IWebDAVObjectInitializedEvent:

  >>> from plone.app.testing import TEST_USER_NAME as user_name
  >>> from plone.app.testing import TEST_USER_PASSWORD as user_password
  >>> from plone.app.testing import setRoles
  >>> setRoles(portal, TEST_USER_ID, ['Manager'])

  >>> 'some-document' in folder.objectIds()
  False

  >>> from Testing.ZopeTestCase.zopedoctest.functional import http
  >>> from Testing.ZopeTestCase.sandbox import AppZapper 
  >>> AppZapper().set(layer['app'])
  >>> print http(r"""
  ... PUT /%s/some-document HTTP/1.1
  ... Authorization: Basic %s:%s
  ... Content-Type: text/plain; charset="utf-8"
  ...
  ... Some Content
  ... """ % ('/'.join(folder.getPhysicalPath()), user_name, user_password))
  HTTP/1.1 201 Created
  ...

  >>> 'some-document' in folder.objectIds()
  True

  >>> print str(folder['some-document']['body'])
  Some Content

  >>> handler.print_last_and_flush() #doctest: +ELLIPSIS
  1 events:
  [(<DDocument at /plone/Members/test_user_1_/some-document>,
    <Products.Archetypes.event.WebDAVObjectInitializedEvent object at ...>)...]

Doing another `PUT` request to update the same object should fire an
IWebDAVObjectEditedEvent:

  >>> print http(r"""
  ... PUT /%s/some-document HTTP/1.1
  ... Authorization: Basic %s:%s
  ... Content-Type: text/plain; charset="utf-8"
  ...
  ... Some Other Content
  ... """ % ('/'.join(folder.getPhysicalPath()), user_name, user_password))
  HTTP/1.1 204 No Content
  ...

  >>> print str(folder['some-document']['body'])
  Some Other Content

  >>> handler.print_and_flush() #doctest: +ELLIPSIS
  1 events:
  [(<DDocument at /plone/Members/test_user_1_/some-document>,
    <Products.Archetypes.event.WebDAVObjectEditedEvent object at ...>)]

Finally, cleanup the CTR predicate to not affect other tests: 

  >>> ctr.removePredicate(p_id)

Test that a MKCOL also fires an IWebDAVObjectInitialized event:

  >>> _ = folder.invokeFactory('SimpleFolder', 'f1')

  >>> print http(r"""
  ... MKCOL /%s/some-folder HTTP/1.1
  ... Authorization: Basic %s:%s
  ... """ % ('/'.join(folder.f1.getPhysicalPath()), user_name, user_password))
  HTTP/1.1 201 Created
  ...

  >>> handler.print_last_and_flush() #doctest: +ELLIPSIS
  1 events:
  [(<SimpleFolder at /plone/Members/test_user_1_/f1/some-folder>,
    <Products.Archetypes.event.WebDAVObjectInitializedEvent object at ...>)]

Clean up
  >>> AppZapper().clear()
