New feature: As a logged-in user, I can enable/disable email notification of additional comments on this content object.
svn path=/plone.app.discussion/trunk/; revision=40949
This commit is contained in:
parent
5fe339215b
commit
82afd3ef15
@ -4,6 +4,10 @@ Changelog
|
||||
1.0b11 (unreleased)
|
||||
-------------------
|
||||
|
||||
- New feature: As a logged-in user, I can enable/disable email notification of
|
||||
additional comments on this content object.
|
||||
[timo]
|
||||
|
||||
- Disable the plone.app.registry check on schema elements, so no error is
|
||||
raised on upgrades. This fixes https://dev.plone.org/plone/ticket/11195.
|
||||
[timo]
|
||||
|
@ -15,6 +15,7 @@ from zope.interface import alsoProvides
|
||||
|
||||
from z3c.form import form, field, button, interfaces
|
||||
from z3c.form.interfaces import IFormLayer
|
||||
from z3c.form.browser.checkbox import SingleCheckBoxFieldWidget
|
||||
|
||||
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
|
||||
from Products.CMFCore.utils import getToolByName
|
||||
@ -34,6 +35,7 @@ from plone.app.discussion.interfaces import ICaptcha
|
||||
from plone.app.discussion.browser.validator import CaptchaValidator
|
||||
|
||||
from plone.z3cform import z2
|
||||
from plone.z3cform.widget import SingleCheckBoxWidget
|
||||
from plone.z3cform.fieldsets import extensible
|
||||
|
||||
# starting from 0.6.0 version plone.z3cform has IWrappedForm interface
|
||||
@ -62,8 +64,8 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
|
||||
|
||||
def updateFields(self):
|
||||
super(CommentForm, self).updateFields()
|
||||
#self.fields['author_notification'].widgetFactory =
|
||||
# SingleCheckBoxFieldWidget
|
||||
self.fields['user_notification'].widgetFactory = \
|
||||
SingleCheckBoxFieldWidget
|
||||
|
||||
def updateWidgets(self):
|
||||
super(CommentForm, self).updateWidgets()
|
||||
@ -71,7 +73,7 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
|
||||
# Widgets
|
||||
self.widgets['in_reply_to'].mode = interfaces.HIDDEN_MODE
|
||||
self.widgets['text'].addClass("autoresize")
|
||||
#self.widgets['author_notification'].label = _(u"")
|
||||
self.widgets['user_notification'].label = _(u"")
|
||||
|
||||
# Anonymous / Logged-in
|
||||
portal_membership = getToolByName(self.context, 'portal_membership')
|
||||
@ -84,11 +86,12 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
|
||||
# integrators or later use.
|
||||
self.widgets['author_email'].mode = interfaces.HIDDEN_MODE
|
||||
|
||||
# XXX: Author notification code
|
||||
#registry = queryUtility(IRegistry)
|
||||
#settings = registry.forInterface(IDiscussionSettings, check=False)
|
||||
#if not settings.user_notification_enabled:
|
||||
# self.widgets['author_notification'].mode = interfaces.HIDDEN_MODE
|
||||
registry = queryUtility(IRegistry)
|
||||
settings = registry.forInterface(IDiscussionSettings, check=False)
|
||||
portal_membership = getToolByName(self.context, 'portal_membership')
|
||||
|
||||
if not settings.user_notification_enabled or portal_membership.isAnonymousUser():
|
||||
self.widgets['user_notification'].mode = interfaces.HIDDEN_MODE
|
||||
|
||||
def updateActions(self):
|
||||
super(CommentForm, self).updateActions()
|
||||
@ -109,7 +112,7 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
|
||||
text = u""
|
||||
author_name = u""
|
||||
author_email = u""
|
||||
#author_notification = None
|
||||
user_notification = None
|
||||
|
||||
# Captcha check for anonymous users (if Captcha is enabled and
|
||||
# anonymous commenting is allowed)
|
||||
@ -135,8 +138,8 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
|
||||
author_name = data['author_name']
|
||||
if 'author_email' in data:
|
||||
author_email = data['author_email']
|
||||
#if 'author_notification' in data:
|
||||
# author_notification = data['author_notification']
|
||||
if 'user_notification' in data:
|
||||
user_notification = data['user_notification']
|
||||
|
||||
# The add-comment view is called on the conversation object
|
||||
conversation = IConversation(self.__parent__)
|
||||
@ -163,7 +166,7 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
|
||||
comment.creator = author_name
|
||||
comment.author_name = author_name
|
||||
comment.author_email = author_email
|
||||
#comment.author_notification = author_notification
|
||||
comment.user_notification = user_notification
|
||||
comment.creation_date = comment.modification_date = datetime.utcnow()
|
||||
elif not portal_membership.isAnonymousUser():
|
||||
# Member
|
||||
@ -182,7 +185,7 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
|
||||
comment.author_username = username
|
||||
comment.author_name = fullname
|
||||
comment.author_email = email
|
||||
#comment.author_notification = comment.author_notification
|
||||
comment.user_notification = user_notification
|
||||
comment.creation_date = comment.modification_date = datetime.utcnow()
|
||||
else:
|
||||
raise Unauthorized, "Anonymous user tries to post a comment, but \
|
||||
@ -340,7 +343,7 @@ class CommentsViewlet(ViewletBase):
|
||||
def anonymous_discussion_allowed(self):
|
||||
# Check if anonymous comments are allowed in the registry
|
||||
registry = queryUtility(IRegistry)
|
||||
settings = registry.forInterface(IDiscussionSettings)
|
||||
settings = registry.forInterface(IDiscussionSettings, check=False)
|
||||
return settings.anonymous_comments
|
||||
|
||||
def show_commenter_image(self):
|
||||
|
@ -32,8 +32,8 @@ class DiscussionSettingsEditForm(controlpanel.RegistryEditForm):
|
||||
SingleCheckBoxFieldWidget
|
||||
self.fields['moderator_notification_enabled'].widgetFactory = \
|
||||
SingleCheckBoxFieldWidget
|
||||
#self.fields['user_notification_enabled'].widgetFactory = \
|
||||
# SingleCheckBoxFieldWidget
|
||||
self.fields['user_notification_enabled'].widgetFactory = \
|
||||
SingleCheckBoxFieldWidget
|
||||
|
||||
def updateWidgets(self):
|
||||
super(DiscussionSettingsEditForm, self).updateWidgets()
|
||||
@ -42,8 +42,8 @@ class DiscussionSettingsEditForm(controlpanel.RegistryEditForm):
|
||||
self.widgets['show_commenter_image'].label = _(u"Commenter Image")
|
||||
self.widgets['moderator_notification_enabled'].label = \
|
||||
_(u"Moderator Email Notification")
|
||||
#self.widgets['user_notification_enabled'].label = \
|
||||
# _(u"User Email Notification")
|
||||
self.widgets['user_notification_enabled'].label = \
|
||||
_(u"User Email Notification")
|
||||
|
||||
|
||||
class DiscussionSettingsControlPanel(controlpanel.ControlPanelFormWrapper):
|
||||
|
@ -49,7 +49,7 @@ COMMENT_TITLE = _(u"comment_title",
|
||||
default=u"${creator} on ${content}")
|
||||
|
||||
MAIL_NOTIFICATION_MESSAGE = _(u"mail_notification_message",
|
||||
default=u"A comment with the title '${title}' "
|
||||
default=u"A comment on '${title}' "
|
||||
"has been posted here: ${link}")
|
||||
|
||||
|
||||
@ -87,7 +87,7 @@ class Comment(CatalogAware, WorkflowAware, DynamicType, Traversable,
|
||||
author_name = None
|
||||
author_email = None
|
||||
|
||||
author_notification = None
|
||||
user_notification = None
|
||||
|
||||
# Note: we want to use zope.component.createObject() to instantiate
|
||||
# comments as far as possible. comment_id and __parent__ are set via
|
||||
@ -180,9 +180,7 @@ def notify_content_object_deleted(obj, event):
|
||||
for comment in conversation.getComments():
|
||||
del conversation[comment.id]
|
||||
|
||||
# XXX: This method is not enabled yet. Remove "pragma: no cover" as soon as the
|
||||
# commented out notify user code has been removed.
|
||||
def notify_user(obj, event): # pragma: no cover
|
||||
def notify_user(obj, event):
|
||||
"""Tell users when a comment has been added.
|
||||
|
||||
This method composes and sends emails to all users that have added a
|
||||
@ -209,17 +207,17 @@ def notify_user(obj, event): # pragma: no cover
|
||||
return
|
||||
|
||||
# Compose and send emails to all users that have add a comment to this
|
||||
# conversation and enabled author_notification.
|
||||
# conversation and enabled user_notification.
|
||||
conversation = aq_parent(obj)
|
||||
content_object = aq_parent(conversation)
|
||||
|
||||
for comment in conversation.getComments():
|
||||
if obj != comment and \
|
||||
comment.author_notification and comment.author_email:
|
||||
comment.user_notification and comment.author_email:
|
||||
subject = translate(_(u"A comment has been posted."),
|
||||
context=obj.REQUEST)
|
||||
message = translate(Message(MAIL_NOTIFICATION_MESSAGE,
|
||||
mapping={'title': obj.title,
|
||||
mapping={'title': content_object.title,
|
||||
'link': content_object.absolute_url()}),
|
||||
context=obj.REQUEST)
|
||||
mail_host.send(message, comment.author_email, sender, subject)
|
||||
@ -267,7 +265,7 @@ def notify_moderator(obj, event):
|
||||
#comment = conversation.getComments().next()
|
||||
subject = translate(_(u"A comment has been posted."), context=obj.REQUEST)
|
||||
message = translate(Message(MAIL_NOTIFICATION_MESSAGE,
|
||||
mapping={'title': obj.title,
|
||||
mapping={'title': content_object.title,
|
||||
'link': content_object.absolute_url()}),
|
||||
context=obj.REQUEST)
|
||||
|
||||
|
@ -71,9 +71,8 @@ class IDiscussionSettings(Interface):
|
||||
title=_(u"label_show_commenter_image",
|
||||
default=u"Show commenter image"),
|
||||
description=_(u"help_show_commenter_image",
|
||||
default=u"If selected, an image "
|
||||
"of the user is shown "
|
||||
"next to the comment."),
|
||||
default=u"If selected, an image of the user is shown next to "
|
||||
"the comment."),
|
||||
required=False,
|
||||
default=True,
|
||||
)
|
||||
@ -88,16 +87,14 @@ class IDiscussionSettings(Interface):
|
||||
default=False,
|
||||
)
|
||||
|
||||
#user_notification_enabled = schema.Bool(
|
||||
# title=_(u"label_user_notification_enabled",
|
||||
# default=u"Enable user email notification"),
|
||||
# description=_(u"help_user_notification_enabled",
|
||||
# default=u"If selected, users can "
|
||||
# "choose to be notified "
|
||||
# "of new comments by "
|
||||
# "email."),
|
||||
# required=False,
|
||||
# default=False)
|
||||
user_notification_enabled = schema.Bool(
|
||||
title=_(u"label_user_notification_enabled",
|
||||
default=u"Enable user email notification"),
|
||||
description=_(u"help_user_notification_enabled",
|
||||
default=u"If selected, users can choose to be notified "
|
||||
"of new comments by email."),
|
||||
required=False,
|
||||
default=False)
|
||||
|
||||
|
||||
class IConversation(IIterableMapping):
|
||||
@ -269,9 +266,9 @@ class IComment(Interface):
|
||||
text = schema.Text(title=_(u"label_comment",
|
||||
default=u"Comment"))
|
||||
|
||||
#author_notification = schema.Bool(title=_(u"Notify me of new comments via "
|
||||
# "email."),
|
||||
# required=False)
|
||||
user_notification = schema.Bool(title=_(u"Notify me of new comments via "
|
||||
"email."),
|
||||
required=False)
|
||||
|
||||
creator = schema.TextLine(title=_(u"Author name (for display)"))
|
||||
creation_date = schema.Date(title=_(u"Creation date"))
|
||||
|
@ -7,13 +7,11 @@
|
||||
|
||||
<configure zcml:condition="not-installed zope.app.container">
|
||||
|
||||
<!--
|
||||
<subscriber
|
||||
for="plone.app.discussion.interfaces.IComment
|
||||
zope.lifecycleevent.interfaces.IObjectAddedEvent"
|
||||
handler=".comment.notify_user"
|
||||
/>
|
||||
-->
|
||||
|
||||
<subscriber
|
||||
for="plone.app.discussion.interfaces.IComment
|
||||
@ -28,13 +26,11 @@
|
||||
|
||||
<configure zcml:condition="installed zope.app.container">
|
||||
|
||||
<!--
|
||||
<subscriber
|
||||
for="plone.app.discussion.interfaces.IComment
|
||||
zope.app.container.interfaces.IObjectAddedEvent"
|
||||
handler=".comment.notify_user"
|
||||
/>
|
||||
-->
|
||||
|
||||
<subscriber
|
||||
for="plone.app.discussion.interfaces.IComment
|
||||
|
@ -14,129 +14,129 @@ from Products.CMFPlone.tests.utils import MockMailHost
|
||||
from plone.registry.interfaces import IRegistry
|
||||
|
||||
from plone.app.discussion.interfaces import IConversation
|
||||
from plone.app.discussion.interfaces import IDiscussionSettings
|
||||
from plone.app.discussion.tests.layer import DiscussionLayer
|
||||
|
||||
|
||||
#class TestUserNotificationUnit(PloneTestCase):
|
||||
#
|
||||
# layer = DiscussionLayer
|
||||
#
|
||||
# def afterSetUp(self):
|
||||
# # Set up a mock mailhost
|
||||
# self.portal._original_MailHost = self.portal.MailHost
|
||||
# self.portal.MailHost = mailhost = MockMailHost('MailHost')
|
||||
# sm = getSiteManager(context=self.portal)
|
||||
# sm.unregisterUtility(provided=IMailHost)
|
||||
# sm.registerUtility(mailhost, provided=IMailHost)
|
||||
#
|
||||
# # We need to fake a valid mail setup
|
||||
# self.portal.email_from_address = "portal@plone.test"
|
||||
# self.mailhost = self.portal.MailHost
|
||||
#
|
||||
# # Enable user notification setting
|
||||
# registry = queryUtility(IRegistry)
|
||||
# settings = registry.forInterface(IDiscussionSettings)
|
||||
# registry['plone.app.discussion.interfaces.IDiscussionSettings.\
|
||||
# user_notification_enabled'] = True
|
||||
#
|
||||
# # Create test content
|
||||
# self.loginAsPortalOwner()
|
||||
# self.portal.invokeFactory('Document', 'doc1')
|
||||
# self.portal_discussion = self.portal.portal_discussion
|
||||
# self.conversation = IConversation(self.portal.doc1)
|
||||
#
|
||||
# def beforeTearDown(self):
|
||||
# self.portal.MailHost = self.portal._original_MailHost
|
||||
# sm = getSiteManager(context=self.portal)
|
||||
# sm.unregisterUtility(provided=IMailHost)
|
||||
# sm.registerUtility(aq_base(self.portal._original_MailHost),
|
||||
# provided=IMailHost)
|
||||
#
|
||||
# def test_notify_user(self):
|
||||
# # Add a comment with user notification enabled. Add another comment
|
||||
# # and make sure an email is send to the user of the first comment.
|
||||
# comment = createObject('plone.Comment')
|
||||
# comment.title = 'Comment 1'
|
||||
# comment.text = 'Comment text'
|
||||
# comment.author_notification = True
|
||||
# comment.author_email = "john@plone.test"
|
||||
# self.conversation.addComment(comment)
|
||||
#
|
||||
# comment = createObject('plone.Comment')
|
||||
# comment.title = 'Comment 2'
|
||||
# comment.text = 'Comment text'
|
||||
# self.conversation.addComment(comment)
|
||||
#
|
||||
# self.assertEquals(len(self.mailhost.messages), 1)
|
||||
# self.failUnless(self.mailhost.messages[0])
|
||||
# msg = self.mailhost.messages[0]
|
||||
# self.failUnless('To: john@plone.test' in msg)
|
||||
# self.failUnless('From: portal@plone.test' in msg)
|
||||
#
|
||||
# # We expect the headers to be properly header encoded (7-bit):
|
||||
# #>>> 'Subject: =?utf-8?q?Some_t=C3=A4st_subject=2E?=' in msg
|
||||
# #True
|
||||
class TestUserNotificationUnit(PloneTestCase):
|
||||
|
||||
layer = DiscussionLayer
|
||||
|
||||
def afterSetUp(self):
|
||||
# Set up a mock mailhost
|
||||
self.portal._original_MailHost = self.portal.MailHost
|
||||
self.portal.MailHost = mailhost = MockMailHost('MailHost')
|
||||
sm = getSiteManager(context=self.portal)
|
||||
sm.unregisterUtility(provided=IMailHost)
|
||||
sm.registerUtility(mailhost, provided=IMailHost)
|
||||
|
||||
# We need to fake a valid mail setup
|
||||
self.portal.email_from_address = "portal@plone.test"
|
||||
self.mailhost = self.portal.MailHost
|
||||
|
||||
# Enable user notification setting
|
||||
registry = queryUtility(IRegistry)
|
||||
settings = registry.forInterface(IDiscussionSettings)
|
||||
registry['plone.app.discussion.interfaces.IDiscussionSettings' +
|
||||
'.user_notification_enabled'] = True
|
||||
|
||||
# Create test content
|
||||
self.loginAsPortalOwner()
|
||||
self.portal.invokeFactory('Document', 'doc1')
|
||||
self.portal_discussion = self.portal.portal_discussion
|
||||
self.conversation = IConversation(self.portal.doc1)
|
||||
|
||||
def beforeTearDown(self):
|
||||
self.portal.MailHost = self.portal._original_MailHost
|
||||
sm = getSiteManager(context=self.portal)
|
||||
sm.unregisterUtility(provided=IMailHost)
|
||||
sm.registerUtility(aq_base(self.portal._original_MailHost),
|
||||
provided=IMailHost)
|
||||
|
||||
def test_notify_user(self):
|
||||
# Add a comment with user notification enabled. Add another comment
|
||||
# and make sure an email is send to the user of the first comment.
|
||||
comment = createObject('plone.Comment')
|
||||
comment.title = 'Comment 1'
|
||||
comment.text = 'Comment text'
|
||||
comment.user_notification = True
|
||||
comment.author_email = "john@plone.test"
|
||||
self.conversation.addComment(comment)
|
||||
|
||||
comment = createObject('plone.Comment')
|
||||
comment.title = 'Comment 2'
|
||||
comment.text = 'Comment text'
|
||||
self.conversation.addComment(comment)
|
||||
self.assertEquals(len(self.mailhost.messages), 1)
|
||||
self.failUnless(self.mailhost.messages[0])
|
||||
msg = self.mailhost.messages[0]
|
||||
self.failUnless('To: john@plone.test' in msg)
|
||||
self.failUnless('From: portal@plone.test' in msg)
|
||||
|
||||
# We expect the headers to be properly header encoded (7-bit):
|
||||
#>>> 'Subject: =?utf-8?q?Some_t=C3=A4st_subject=2E?=' in msg
|
||||
#True
|
||||
# # The output should be encoded in a reasonable manner
|
||||
# # (in this case quoted-printable):
|
||||
# #>>> msg
|
||||
# #'...Another t=C3=A4st message...You are receiving this mail \
|
||||
# #because T=C3=A4st user\ntest@plone.test...is sending feedback \
|
||||
# #about the site you administer at...
|
||||
#
|
||||
# def test_do_not_notify_user_when_notification_is_disabled(self):
|
||||
# # Disable user notification and make sure no email is send to the user.
|
||||
# registry = queryUtility(IRegistry)
|
||||
# settings = registry.forInterface(IDiscussionSettings)
|
||||
# registry['plone.app.discussion.interfaces.IDiscussionSettings.\
|
||||
# user_notification_enabled'] = False
|
||||
#
|
||||
# comment = createObject('plone.Comment')
|
||||
# comment.title = 'Comment 1'
|
||||
# comment.text = 'Comment text'
|
||||
# comment.author_notification = True
|
||||
# comment.author_email = "john@plone.test"
|
||||
# self.conversation.addComment(comment)
|
||||
#
|
||||
# comment = createObject('plone.Comment')
|
||||
# comment.title = 'Comment 2'
|
||||
# comment.text = 'Comment text'
|
||||
# self.conversation.addComment(comment)
|
||||
#
|
||||
# self.assertEquals(len(self.mailhost.messages), 0)
|
||||
#
|
||||
# def test_do_not_notify_user_when_email_address_is_given(self):
|
||||
# comment = createObject('plone.Comment')
|
||||
# comment.title = 'Comment 1'
|
||||
# comment.text = 'Comment text'
|
||||
# comment.author_notification = True
|
||||
# self.conversation.addComment(comment)
|
||||
#
|
||||
# comment = createObject('plone.Comment')
|
||||
# comment.title = 'Comment 2'
|
||||
# comment.text = 'Comment text'
|
||||
# self.conversation.addComment(comment)
|
||||
#
|
||||
# self.assertEquals(len(self.mailhost.messages), 0)
|
||||
#
|
||||
# def test_do_not_notify_user_when_no_sender_is_available(self):
|
||||
# # Set sender mail address to none and make sure no email is send to
|
||||
# # the moderator.
|
||||
# self.portal.email_from_address = None
|
||||
#
|
||||
# comment = createObject('plone.Comment')
|
||||
# comment.title = 'Comment 1'
|
||||
# comment.text = 'Comment text'
|
||||
# comment.author_notification = True
|
||||
# comment.author_email = "john@plone.test"
|
||||
# self.conversation.addComment(comment)
|
||||
#
|
||||
# comment = createObject('plone.Comment')
|
||||
# comment.title = 'Comment 2'
|
||||
# comment.text = 'Comment text'
|
||||
# self.conversation.addComment(comment)
|
||||
#
|
||||
# self.assertEquals(len(self.mailhost.messages), 0)
|
||||
# (in this case quoted-printable):
|
||||
#>>> msg
|
||||
#'...Another t=C3=A4st message...You are receiving this mail \
|
||||
#because T=C3=A4st user\ntest@plone.test...is sending feedback \
|
||||
#about the site you administer at...
|
||||
|
||||
def test_do_not_notify_user_when_notification_is_disabled(self):
|
||||
# Disable user notification and make sure no email is send to the user.
|
||||
registry = queryUtility(IRegistry)
|
||||
settings = registry.forInterface(IDiscussionSettings)
|
||||
registry['plone.app.discussion.interfaces.IDiscussionSettings.' +
|
||||
'user_notification_enabled'] = False
|
||||
|
||||
comment = createObject('plone.Comment')
|
||||
comment.title = 'Comment 1'
|
||||
comment.text = 'Comment text'
|
||||
comment.user_notification = True
|
||||
comment.author_email = "john@plone.test"
|
||||
self.conversation.addComment(comment)
|
||||
|
||||
comment = createObject('plone.Comment')
|
||||
comment.title = 'Comment 2'
|
||||
comment.text = 'Comment text'
|
||||
self.conversation.addComment(comment)
|
||||
|
||||
self.assertEquals(len(self.mailhost.messages), 0)
|
||||
|
||||
def test_do_not_notify_user_when_email_address_is_given(self):
|
||||
comment = createObject('plone.Comment')
|
||||
comment.title = 'Comment 1'
|
||||
comment.text = 'Comment text'
|
||||
comment.user_notification = True
|
||||
self.conversation.addComment(comment)
|
||||
|
||||
comment = createObject('plone.Comment')
|
||||
comment.title = 'Comment 2'
|
||||
comment.text = 'Comment text'
|
||||
self.conversation.addComment(comment)
|
||||
|
||||
self.assertEquals(len(self.mailhost.messages), 0)
|
||||
|
||||
def test_do_not_notify_user_when_no_sender_is_available(self):
|
||||
# Set sender mail address to none and make sure no email is send to
|
||||
# the moderator.
|
||||
self.portal.email_from_address = None
|
||||
|
||||
comment = createObject('plone.Comment')
|
||||
comment.title = 'Comment 1'
|
||||
comment.text = 'Comment text'
|
||||
comment.user_notification = True
|
||||
comment.author_email = "john@plone.test"
|
||||
self.conversation.addComment(comment)
|
||||
|
||||
comment = createObject('plone.Comment')
|
||||
comment.title = 'Comment 2'
|
||||
comment.text = 'Comment text'
|
||||
self.conversation.addComment(comment)
|
||||
|
||||
self.assertEquals(len(self.mailhost.messages), 0)
|
||||
|
||||
|
||||
class TestModeratorNotificationUnit(PloneTestCase):
|
||||
|
||||
|
@ -3,13 +3,13 @@ Products.PDBDebugMode = 1.1
|
||||
Products.PrintingMailHost = 0.7
|
||||
Sphinx-PyPI-upload = 0.2.1
|
||||
collective.recipe.omelette = 0.9
|
||||
collective.recipe.sphinxbuilder = 0.6.3.3
|
||||
collective.recipe.template = 1.8
|
||||
collective.xmltestreport = 1.0b3
|
||||
collective.z3cform.datetimewidget = 1.0.2
|
||||
coverage = 3.4
|
||||
hexagonit.recipe.download = 1.4.1
|
||||
interlude = 1.0
|
||||
ipython = 0.10
|
||||
ipython = 0.10.1
|
||||
logilab.pylintinstaller = 0.15.2
|
||||
mr.developer = 1.16
|
||||
plone.app.testing = 1.0a2
|
||||
@ -18,24 +18,23 @@ plone.supermodel = 1.0b5
|
||||
plone.testing = 1.0a2
|
||||
recaptcha-client = 1.0.5
|
||||
repoze.sphinx.autointerface = 0.4
|
||||
zc.recipe.cmmi = 1.3.2
|
||||
zest.releaser = 3.15
|
||||
zptlint = 0.2.3
|
||||
|
||||
#Required by:
|
||||
#collective.akismet 1.0a3
|
||||
#collective.akismet 1.0b2dev
|
||||
akismet = 0.2.0
|
||||
|
||||
#Required by:
|
||||
#plone.app.discussion 1.0b9dev
|
||||
#plone.app.discussion 1.0b11
|
||||
collective.autopermission = 1.0b1
|
||||
|
||||
#Required by:
|
||||
#plone.app.discussion 1.0b9dev
|
||||
#plone.app.discussion 1.0b11
|
||||
plone.app.registry = 1.0b2
|
||||
|
||||
#Required by:
|
||||
#plone.app.discussion 1.0b9dev
|
||||
#plone.app.discussion 1.0b11
|
||||
plone.registry = 1.0b2
|
||||
|
||||
#Required by:
|
||||
|
Loading…
Reference in New Issue
Block a user