diff --git a/plone/app/discussion/tests/test_contentrules.py b/plone/app/discussion/tests/test_contentrules.py
new file mode 100644
index 0000000..16618e2
--- /dev/null
+++ b/plone/app/discussion/tests/test_contentrules.py
@@ -0,0 +1,151 @@
+# -*- coding: utf-8 -*-
+
+import unittest2 as unittest
+from Testing import ZopeTestCase as ztc
+from zope.component import createObject, getAdapter
+from zope.event import notify
+from plone.app.testing import TEST_USER_ID, setRoles
+
+from plone.contentrules.rule.interfaces import IRuleEventType
+from plone.stringinterp.interfaces import IStringSubstitution
+
+from plone.app.discussion.interfaces import IConversation, IReplies
+from plone.app.discussion.interfaces import ICommentAddedEvent
+from plone.app.discussion.interfaces import ICommentRemovedEvent
+from plone.app.discussion.interfaces import IReplyAddedEvent
+from plone.app.discussion.interfaces import IReplyRemovedEvent
+
+from plone.app.discussion.testing import (
+ PLONE_APP_DISCUSSION_INTEGRATION_TESTING,
+)
+
+class CommentContentRulesTest(unittest.TestCase):
+ """ Test custom comments events
+ """
+ layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING
+
+ def setUp(self):
+ # Setup session manager
+ ztc.utils.setupCoreSessions(self.layer['app'])
+
+ # Setup sandbox
+ self.portal = self.layer['portal']
+ self.request = self.layer['request']
+
+ # Setup current user properties
+ member = self.portal.portal_membership.getMemberById(TEST_USER_ID)
+ member.setMemberProperties({
+ 'fullname': 'X Manager',
+ 'email': 'xmanager@example.com'
+ })
+
+ setRoles(self.portal, TEST_USER_ID, ['Manager'])
+ name = self.portal.invokeFactory(
+ id='doc1',
+ title='Document 1',
+ type_name='Document')
+
+ self.document = self.portal[name]
+
+ comment = createObject('plone.Comment')
+ comment.text = "This is a comment"
+ comment.author_username = "jim"
+ comment.author_name = "Jim"
+ comment.author_email = "jim@example.com"
+ conversation = IConversation(self.document)
+ conversation.addComment(comment)
+
+
+ def testEventTypesMarked(self):
+ self.assertTrue(IRuleEventType.providedBy(ICommentAddedEvent))
+ self.assertTrue(IRuleEventType.providedBy(ICommentRemovedEvent))
+ self.assertTrue(IRuleEventType.providedBy(IReplyAddedEvent))
+ self.assertTrue(IRuleEventType.providedBy(IReplyRemovedEvent))
+
+ def testCommentIdStringSubstitution(self):
+ comment_id = getAdapter(self.document, IStringSubstitution,
+ name=u"comment_id")
+ self.assertIsInstance(comment_id(), long)
+
+ def testCommentTextStringSubstitution(self):
+ comment_text = getAdapter(self.document, IStringSubstitution,
+ name=u"comment_text")
+ self.assertEqual(comment_text(), u"This is a comment")
+
+ def testCommentUserIdStringSubstitution(self):
+ comment_user_id = getAdapter(self.document, IStringSubstitution,
+ name=u"comment_user_id")
+ self.assertEqual(comment_user_id(), u"jim")
+
+ def testCommentUserFullNameStringSubstitution(self):
+ comment_user_fullname = getAdapter(self.document, IStringSubstitution,
+ name=u"comment_user_fullname")
+ self.assertEqual(comment_user_fullname(), u"Jim")
+
+ def testCommentUserEmailStringSubstitution(self):
+ comment_user_email = getAdapter(self.document, IStringSubstitution,
+ name=u"comment_user_email")
+ self.assertEqual(comment_user_email(), u"jim@example.com")
+
+
+class ReplyContentRulesTest(unittest.TestCase):
+ """ Test custom comments events
+ """
+ layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING
+
+ def setUp(self):
+ # Setup session manager
+ ztc.utils.setupCoreSessions(self.layer['app'])
+
+ # Setup sandbox
+ self.portal = self.layer['portal']
+ self.request = self.layer['request']
+ setRoles(self.portal, TEST_USER_ID, ['Manager'])
+ name = self.portal.invokeFactory(
+ id='doc1',
+ title='Document 1',
+ type_name='Document')
+
+ self.document = self.portal[name]
+ conversation = IConversation(self.document)
+ replies = IReplies(conversation)
+
+ comment = createObject('plone.Comment')
+ comment.text = 'This is a comment'
+ new_id = replies.addComment(comment)
+ comment = self.document.restrictedTraverse(
+ '++conversation++default/%s' % new_id)
+
+ re_comment = createObject('plone.Comment')
+ re_comment.text = 'This is a reply'
+ re_comment.author_username = "julia"
+ re_comment.author_name = "Juliana"
+ re_comment.author_email = "julia@example.com"
+
+ replies = IReplies(comment)
+ new_re_id = replies.addComment(re_comment)
+
+ def testReplyIdStringSubstitution(self):
+ reply_id = getAdapter(self.document, IStringSubstitution,
+ name=u"comment_id")
+ self.assertIsInstance(reply_id(), long)
+
+ def testReplyTextStringSubstitution(self):
+ reply_text = getAdapter(self.document, IStringSubstitution,
+ name=u"comment_text")
+ self.assertEqual(reply_text(), u"This is a reply")
+
+ def testReplyUserIdStringSubstitution(self):
+ reply_user_id = getAdapter(self.document, IStringSubstitution,
+ name=u"comment_user_id")
+ self.assertEqual(reply_user_id(), u"julia")
+
+ def testReplyUserFullNameStringSubstitution(self):
+ reply_user_fullname = getAdapter(self.document, IStringSubstitution,
+ name=u"comment_user_fullname")
+ self.assertEqual(reply_user_fullname(), u"Juliana")
+
+ def testReplyUserEmailStringSubstitution(self):
+ reply_user_email = getAdapter(self.document, IStringSubstitution,
+ name=u"comment_user_email")
+ self.assertEqual(reply_user_email(), u"julia@example.com")
diff --git a/plone/app/discussion/tests/test_events.py b/plone/app/discussion/tests/test_events.py
new file mode 100644
index 0000000..11ab4c9
--- /dev/null
+++ b/plone/app/discussion/tests/test_events.py
@@ -0,0 +1,179 @@
+# -*- coding: utf-8 -*-
+
+import unittest2 as unittest
+from zope.component import createObject
+from Zope2.App import zcml
+import Products.Five
+from plone.app.testing import TEST_USER_ID, setRoles
+from plone.app.discussion.interfaces import IConversation, IReplies
+from plone.app.discussion.testing import (
+ PLONE_APP_DISCUSSION_INTEGRATION_TESTING,
+)
+#
+# Fake events registry
+#
+class EventsRegistry(object):
+ """ Fake registry to be used while testing discussion events
+ """
+ commentAdded = False
+ commentRemoved = False
+ replyAdded = False
+ replyRemoved = False
+
+#
+# Fake event handlers
+#
+def comment_added(doc, evt):
+ EventsRegistry.commentAdded = True
+
+def comment_removed(doc, evt):
+ EventsRegistry.commentRemoved = True
+
+def reply_added(doc, evt):
+ EventsRegistry.replyAdded = True
+
+def reply_removed(doc, evt):
+ EventsRegistry.replyRemoved = True
+#
+# Tests
+#
+class CommentEventsTest(unittest.TestCase):
+ """ Test custom comments events
+ """
+ layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING
+
+ def setUp(self):
+
+ # Setup sandbox
+ self.portal = self.layer['portal']
+ self.request = self.layer['request']
+ self.registry = EventsRegistry
+
+ setRoles(self.portal, TEST_USER_ID, ['Manager'])
+ name = self.portal.invokeFactory(
+ id='doc1',
+ title='Document 1',
+ type_name='Document')
+
+ self.document = self.portal[name]
+
+ #
+ # Subscribers
+ #
+ configure = """
+
+
+
+
+
+
+
+ """
+ zcml.load_config("configure.zcml", Products.Five)
+ zcml.load_string(configure)
+
+ def test_addEvent(self):
+ self.assertFalse(self.registry.commentAdded)
+ comment = createObject('plone.Comment')
+ conversation = IConversation(self.document)
+ conversation.addComment(comment)
+ self.assertTrue(self.registry.commentAdded)
+
+ def test_removedEvent(self):
+ self.assertFalse(self.registry.commentRemoved)
+ comment = createObject('plone.Comment')
+ conversation = IConversation(self.document)
+ cid = conversation.addComment(comment)
+ del conversation[cid]
+ self.assertTrue(self.registry.commentRemoved)
+
+class RepliesEventsTest(unittest.TestCase):
+ """ Test custom replies events
+ """
+ layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING
+
+ def setUp(self):
+ self.portal = self.layer['portal']
+ self.request = self.layer['request']
+ self.registry = EventsRegistry
+
+ setRoles(self.portal, TEST_USER_ID, ['Manager'])
+ name = self.portal.invokeFactory(
+ id='doc1',
+ title='Document 1',
+ type_name='Document')
+
+ self.document = self.portal[name]
+
+ #
+ # Subscribers
+ #
+ configure = """
+
+
+
+
+
+
+
+ """
+ zcml.load_config("configure.zcml", Products.Five)
+ zcml.load_string(configure)
+
+ def test_addEvent(self):
+ self.assertFalse(self.registry.replyAdded)
+
+ conversation = IConversation(self.document)
+ replies = IReplies(conversation)
+
+ comment = createObject('plone.Comment')
+ comment.text = 'Comment text'
+ new_id = replies.addComment(comment)
+ comment = self.document.restrictedTraverse(
+ '++conversation++default/%s' % new_id)
+
+ re_comment = createObject('plone.Comment')
+ re_comment.text = 'Comment text'
+
+ replies = IReplies(comment)
+ new_re_id = replies.addComment(re_comment)
+
+ self.assertTrue(self.registry.replyAdded)
+
+ def test_removedEvent(self):
+ self.assertFalse(self.registry.replyRemoved)
+
+ conversation = IConversation(self.portal.doc1)
+ replies = IReplies(conversation)
+
+ comment = createObject('plone.Comment')
+ comment.text = 'Comment text'
+ new_id = replies.addComment(comment)
+ comment = self.portal.doc1.restrictedTraverse(
+ '++conversation++default/%s' % new_id)
+
+ re_comment = createObject('plone.Comment')
+ re_comment.text = 'Comment text'
+ replies = IReplies(comment)
+ new_re_id = replies.addComment(re_comment)
+
+ del replies[new_re_id]
+ self.assertTrue(self.registry.replyRemoved)
diff --git a/setup.py b/setup.py
index cdf21c7..a912d59 100644
--- a/setup.py
+++ b/setup.py
@@ -52,6 +52,9 @@ setup(name='plone.app.discussion',
extras_require={
'test': [
'plone.app.testing',
+ 'plone.stringinterp',
+ 'plone.contentrules',
+ 'plone.app.contentrules',
'plone.app.contenttypes[test]',
'plone.app.robotframework[ride,reload,debug]',
]