def test_conversations_method(self): self.topic.invokeFactory( 'conversation', id='conv1', title='Conversation 1' ) conversation = IConversation(self.topic.conv1) comment1 = createObject('plone.Comment') comment1.creation_date = datetime.utcnow() comment1.author_name = u'John Doe' conversation.addComment(comment1) comment2 = createObject('plone.Comment') comment2.creation_date = datetime.utcnow() comment2.author_name = u'Jane Doe' conversation.addComment(comment2) from collective.ploneboard.browser.topic import TopicView view = TopicView(self.topic, self.request) conversations = view.conversations() self.assertEqual(len(conversations), 1) self.assertEqual( conversations, [ { 'title': u'Conversation 1', 'url': 'http://nohost/plone/board/topic1/conv1', 'total_comments': 2, 'last_commenter': u'Jane Doe', 'last_comment_date': comment2.creation_date, } ] )
def test_get_commenter_portrait(self): # Add a user with a member image self.membershipTool.addMember('jim', 'Jim', ['Member'], []) self.memberdata._setPortrait(Image( id='jim', file=dummy.File(), title='' ), 'jim') self.assertEqual( self.memberdata._getPortrait('jim').getId(), 'jim' ) self.assertEqual( self.memberdata._getPortrait('jim').meta_type, 'Image' ) # Add a conversation with a comment conversation = IConversation(self.portal.doc1) comment = createObject('plone.Comment') comment.text = 'Comment text' comment.Creator = 'Jim' comment.author_username = '******' conversation.addComment(comment) # Call get_commenter_portrait method of the viewlet self.viewlet.update() portrait_url = self.viewlet.get_commenter_portrait('jim') # Check if the correct member image URL is returned self.assertEqual( portrait_url, 'http://nohost/plone/portal_memberdata/portraits/jim' )
def write_comments(self): comments = self._data['comments'] for cid, name, email, url, date, text, _ in comments: posts = self._posts try: post = posts[cid] except KeyError: continue conversation = IConversation(post) date = DateTime(date).asdatetime() comment = createObject('plone.Comment') comment.text = fix_text(text) comment.author_name = comment.creator = name comment.author_email = email comment.creation_date = comment.modification_date = date conversation.addComment(comment) transaction.commit() print("Wrote comment by %s" % comment.creator)
def test_traversal(self): # Create a nested structure of comment replies and check the traversal # make sure comments are traversable, have an id, absolute_url and # physical path conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') comment1.text = 'Comment text' conversation.addComment(comment1) comment = createObject('plone.Comment') comment.text = 'Comment text' new_id = conversation.addComment(comment) comment = self.portal.doc1.restrictedTraverse( '++conversation++default/%s' % new_id) # Add a reply to the CommentReplies adapter of the first comment re_comment = createObject('plone.Comment') re_comment.text = 'Comment text' replies = IReplies(comment) new_re_id = replies.addComment(re_comment) re_comment = self.portal.doc1.restrictedTraverse( '++conversation++default/%s' % new_re_id) # Add a reply to the reply re_re_comment = createObject('plone.Comment') re_re_comment.text = 'Comment text' replies = IReplies(re_comment) new_re_re_id = replies.addComment(re_re_comment) re_re_comment = self.portal.doc1.restrictedTraverse( '++conversation++default/%s' % new_re_re_id) # Add a reply to the replies reply re_re_re_comment = createObject('plone.Comment') re_re_re_comment.text = 'Comment text' replies = IReplies(re_re_comment) new_re_re_re_id = replies.addComment(re_re_re_comment) re_re_re_comment = self.portal.doc1.restrictedTraverse( '++conversation++default/%s' % new_re_re_re_id) self.assertEqual(('', 'plone', 'doc1', '++conversation++default', str(new_id)), comment.getPhysicalPath()) self.assertEqual('http://nohost/plone/doc1/++conversation++default/' + str(new_id), comment.absolute_url()) self.assertEqual(('', 'plone', 'doc1', '++conversation++default', str(new_re_id)), re_comment.getPhysicalPath()) self.assertEqual('http://nohost/plone/doc1/++conversation++default/' + str(new_re_id), re_comment.absolute_url()) self.assertEqual(('', 'plone', 'doc1', '++conversation++default', str(new_re_re_id)), re_re_comment.getPhysicalPath()) self.assertEqual('http://nohost/plone/doc1/++conversation++default/' + str(new_re_re_id), re_re_comment.absolute_url()) self.assertEqual(('', 'plone', 'doc1', '++conversation++default', str(new_re_re_re_id)), re_re_re_comment.getPhysicalPath()) self.assertEqual('http://nohost/plone/doc1/++conversation++default/' + str(new_re_re_re_id), re_re_re_comment.absolute_url())
def write_comments(self): comments = self._data['comments'] for com in comments: cid = com['cid'] posts = self._posts try: post = posts[cid] except KeyError: continue conversation = IConversation(post) date = DateTime(com['date']).asdatetime() comment = createObject('plone.Comment') comment.text = fix_text(com['text']) comment.author_name = comment.creator = com['name'] comment.author_email = com['email'] comment.creation_date = comment.modification_date = date conversation.addComment(comment) transaction.commit() print("Wrote comment by %s" % comment.creator)
def test_comment_uid_differs_from_content_uid(self): conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') conversation.addComment(comment1) comment_brain = self.catalog.searchResults( portal_type = 'Discussion Item')[0] self.assertNotEqual(self.document_brain.UID, comment_brain.UID)
def test_has_replies(self): self.assertEqual(self.viewlet.has_replies(), False) comment = createObject('plone.Comment') comment.text = 'Comment text' conversation = IConversation(self.portal.doc1) conversation.addComment(comment) self.assertEqual(self.viewlet.has_replies(), True)
def test_uid(self): conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') conversation.addComment(comment1) comment_brain = self.catalog.searchResults( portal_type = 'Discussion Item')[0] self.assertTrue(comment_brain.UID)
def test_get_commenter_portrait_without_userimage(self): # Create a user without a user image self.membershipTool.addMember('jim', 'Jim', ['Member'], []) # Add a conversation with a comment conversation = IConversation(self.portal.doc1) comment = createObject('plone.Comment') comment.text = 'Comment text' comment.Creator = 'Jim' comment.author_username = '******' conversation.addComment(comment) # Call get_commenter_portrait method of the viewlet self.viewlet.update() portrait_url = self.viewlet.get_commenter_portrait('jim') # Check if the correct default member image URL is returned. # Note that Products.PlonePAS 4.0.5 and later have .png and # earlier versions have .gif. self.assertTrue( portrait_url in ( 'http://nohost/plone/defaultUser.png', 'http://nohost/plone/defaultUser.gif' ) )
def setUp(self): self.app = self.layer["app"] self.portal = self.layer["portal"] self.request = self.layer["request"] setRoles(self.portal, TEST_USER_ID, ["Manager"]) typetool = self.portal.portal_types typetool.constructContent("Document", self.portal, "doc1") self.wf = getToolByName(self.portal, "portal_workflow", None) self.context = self.portal self.portal.portal_workflow.setChainForPortalTypes(("Discussion Item",), "comment_review_workflow") self.wf_tool = self.portal.portal_workflow # Add a conversation with three comments conversation = IConversation(self.portal.doc1) comment1 = createObject("plone.Comment") comment1.title = "Comment 1" comment1.text = "Comment text" comment1.Creator = "Jim" new_id_1 = conversation.addComment(comment1) self.comment1 = self.portal.doc1.restrictedTraverse("++conversation++default/%s" % new_id_1) comment2 = createObject("plone.Comment") comment2.title = "Comment 2" comment2.text = "Comment text" comment2.Creator = "Joe" new_id_2 = conversation.addComment(comment2) self.comment2 = self.portal.doc1.restrictedTraverse("++conversation++default/%s" % new_id_2) comment3 = createObject("plone.Comment") comment3.title = "Comment 3" comment3.text = "Comment text" comment3.Creator = "Emma" new_id_3 = conversation.addComment(comment3) self.comment3 = self.portal.doc1.restrictedTraverse("++conversation++default/%s" % new_id_3) self.conversation = conversation
def setUp(self): self.portal = self.layer['portal'] setRoles(self.portal, TEST_USER_ID, ['Manager']) workflow = self.portal.portal_workflow workflow.doActionFor(self.portal.doc1, 'publish') # Create a conversation. conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') comment1.text = 'Comment Text' comment1.creator = 'jim' comment1.author_username = '******' comment1.creation_date = datetime(2006, 9, 17, 14, 18, 12) comment1.modification_date = datetime(2006, 9, 17, 14, 18, 12) self.new_id1 = conversation.addComment(comment1) comment2 = createObject('plone.Comment') comment2.text = 'Comment Text' comment2.creator = 'emma' comment2.author_username = '******' comment2.creation_date = datetime(2007, 12, 13, 4, 18, 12) comment2.modification_date = datetime(2007, 12, 13, 4, 18, 12) self.new_id2 = conversation.addComment(comment2) comment3 = createObject('plone.Comment') comment3.text = 'Comment Text' comment3.creator = 'lukas' comment3.author_username = '******' comment3.creation_date = datetime(2009, 4, 12, 11, 12, 12) comment3.modification_date = datetime(2009, 4, 12, 11, 12, 12) self.new_id3 = conversation.addComment(comment3) self.conversation = conversation
def setUp(self): self.portal = self.layer['portal'] setRoles(self.portal, TEST_USER_ID, ['Manager']) # Create a conversation. conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') comment1.text = 'Comment Text' comment1.creator = "jim" comment1.author_username = "******" comment1.creation_date = datetime(2006, 9, 17, 14, 18, 12) comment1.modification_date = datetime(2006, 9, 17, 14, 18, 12) self.new_id1 = conversation.addComment(comment1) comment2 = createObject('plone.Comment') comment2.text = 'Comment Text' comment2.creator = "emma" comment2.author_username = "******" comment2.creation_date = datetime(2007, 12, 13, 4, 18, 12) comment2.modification_date = datetime(2007, 12, 13, 4, 18, 12) self.new_id2 = conversation.addComment(comment2) comment3 = createObject('plone.Comment') comment3.text = 'Comment Text' comment3.creator = "lukas" comment3.author_username = "******" comment3.creation_date = datetime(2009, 4, 12, 11, 12, 12) comment3.modification_date = datetime(2009, 4, 12, 11, 12, 12) self.new_id3 = conversation.addComment(comment3) self.conversation = conversation
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': '*****@*****.**' }) 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 = "******" comment.author_name = "Jim" comment.author_email = "*****@*****.**" conversation = IConversation(self.document) conversation.addComment(comment)
def test_like_discussion_item(self): # test discussion-item conversation = IConversation(self.doc1) comment1 = createObject("plone.Comment") conversation.addComment(comment1) comment = [i for i in conversation.getComments()][0] comment_id = IUUID(comment) self.request.form["like_button"] = "like" view = api.content.get_view("toggle_like", self.portal, self.request) view = view.publishTraverse(self.request, comment_id) # Toggle like for comment output = view() self.assertIn("(1)", output) self.assertIn("Unlike", output) user_likes = self.util.get_items_for_user(self.user_id) self.assertTrue(self.util.is_item_liked_by_user(self.user_id, comment_id)) self.assertEqual(len(user_likes), 1) # Toggle like for comment output = view() user_likes = self.util.get_items_for_user(self.user_id) self.assertEqual(len(user_likes), 0) self.assertIn("(0)", output) self.assertIn("Like", output)
def _add_comment(self, text='lilala'): comment = createObject('plone.Comment') comment.text = text comment.author_username = '******' comment.author_name = 'Jim' comment.author_email = '*****@*****.**' conversation = IConversation(self.document) conversation.addComment(comment)
def __iter__(self): for item in self.previous: pathkey = self.pathkey(*item.keys())[0] typekey = self.comment_type_key(*item.keys())[0] # item doesn't exist or the type of comment cannot be # created if not pathkey or not typekey: # TODO: log a note yield item continue comment_type = item[typekey] if comment_type == "plone.app.discussion" and not PAD_INSTALLED: # TODO: log a note yield item continue path = item[pathkey] obj = self.context.unrestrictedTraverse(path.lstrip('/'), None) # path doesn't exist if obj is None: yield item continue # TODO: check to see if the object supports commenting... title = item.get('title', '') text = item.get('text', '') creator = item.get('author_name', '') creation_date = item.get('published', '') modification_date = item.get('updated', '') mime_type = item.get('mime_type', 'text/x-html-safe') if comment_type == "plone.app.discussion": conversation = IConversation(obj) # create a reply object comment = CommentFactory() comment.title = title comment.text = text comment.creator = creator comment.author_name = creator comment.author_username = creator comment.mime_type = mime_type # TODO: strptime is is python2.5+, need python2.4 solution if not isinstance(creation_date, datetime): creation_date = datetime.strptime( creation_date, self.date_format) comment.creation_date = creation_date if not isinstance(modification_date, datetime): modification_date = datetime.strptime( modification_date, self.date_format) comment.modification_date = modification_date conversation.addComment(comment) # TODO: fire events if comment_type == "plone": # TODO: create default plone content pass yield item
def test_getText_invalid_transformation_raises_error(self): conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') comment1.mime_type = 'text/x-html-safe' comment1.text = 'para' conversation.addComment(comment1) self.assertEqual( comment1.getText(targetMimetype='text/html'), 'para')
def test_uid_is_unique(self): conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') conversation.addComment(comment1) comment2 = createObject('plone.Comment') conversation.addComment(comment2) brains = self.catalog.searchResults( portal_type = 'Discussion Item') self.assertNotEqual(brains[0].UID, brains[1].UID)
def test_title_special_characters(self): self.portal.invokeFactory(id='doc_sp_chars', title=u'Document äüö', type_name='Document') conversation = IConversation(self.portal.doc_sp_chars) comment1 = createObject('plone.Comment') comment1.creator = u"Tarek Ziadé" conversation.addComment(comment1) self.assertEqual(u"Tarek Ziadé on Document äüö", comment1.Title())
def test_getText_invalid_transformation_raises_error(self): conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') comment1.mime_type = 'text/x-html-safe' comment1.text = 'para' conversation.addComment(comment1) self.assertEqual( comment1.getText(targetMimetype='text/html'), 'para')
def test_uid_is_unique(self): conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') conversation.addComment(comment1) comment2 = createObject('plone.Comment') conversation.addComment(comment2) brains = self.catalog.searchResults( portal_type='Discussion Item' ) self.assertNotEqual(brains[0].UID, brains[1].UID)
def test_private_comment(self): conversation = IConversation(self.portal.doc1) comment = createObject('plone.Comment') comment.author_username = "******" conversation.addComment(comment) comment.manage_permission("View", roles=tuple()) self.assertEquals(0, conversation.total_comments) self.assertEquals(None, conversation.last_comment_date) self.assertEquals(["nobody"], list(conversation.commentators)) self.assertEquals([], list(conversation.public_commentators))
def test_title_special_characters(self): self.portal.invokeFactory( id='doc_sp_chars', title=u'Document äüö', type_name='Document', ) conversation = IConversation(self.portal.doc_sp_chars) comment1 = createObject('plone.Comment') comment1.author_name = u'Tarek Ziadé' conversation.addComment(comment1) self.assertEqual(u'Tarek Ziadé on Document äüö', comment1.Title())
def test_title_special_characters_utf8(self): self.portal.invokeFactory( id='doc_sp_chars_utf8', title='Document ëïû', type_name='Document', ) conversation = IConversation(self.portal.doc_sp_chars_utf8) comment1 = createObject('plone.Comment') comment1.author_name = 'Hüüb Bôûmä' conversation.addComment(comment1) self.assertEqual(u'Hüüb Bôûmä on Document ëïû', comment1.Title())
def test_private_comment(self): conversation = IConversation(self.portal.doc1) comment = createObject('plone.Comment') comment.author_username = "******" conversation.addComment(comment) comment.manage_permission("View", roles=tuple()) self.assertEqual(0, conversation.total_comments()) self.assertEqual(None, conversation.last_comment_date) self.assertEqual(["nobody"], list(conversation.commentators)) self.assertEqual([], list(conversation.public_commentators))
def test_dict_operations(self): # test dict operations and acquisition wrapping # Create a conversation. In this case we doesn't assign it to an # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) # Add a comment. Note: in real life, we always create comments via the # factory to allow different factories to be swapped in comment1 = createObject('plone.Comment') comment1.text = 'Comment text' new_id1 = conversation.addComment(comment1) comment2 = createObject('plone.Comment') comment2.text = 'Comment text' new_id2 = conversation.addComment(comment2) # check if get returns a comment object, and None if the key # can not be found self.assertTrue(IComment.providedBy(conversation.get(new_id1))) self.assertTrue(IComment.providedBy(conversation.get(new_id2))) self.assertEqual(conversation.get(123), None) # check if keys return the ids of all comments self.assertEqual(len(conversation.keys()), 2) self.assertTrue(new_id1 in conversation.keys()) self.assertTrue(new_id2 in conversation.keys()) self.assertFalse(123 in conversation.keys()) # check if items returns (key, comment object) pairs self.assertEqual(len(conversation.items()), 2) self.assertTrue((new_id1, comment1) in conversation.items()) self.assertTrue((new_id2, comment2) in conversation.items()) # check if values returns the two comment objects self.assertEqual(len(conversation.values()), 2) self.assertTrue(comment1 in conversation.values()) self.assertTrue(comment2 in conversation.values()) # check if comment ids are in iterkeys self.assertTrue(new_id1 in conversation.iterkeys()) self.assertTrue(new_id2 in conversation.iterkeys()) self.assertFalse(123 in conversation.iterkeys()) # check if comment objects are in itervalues self.assertTrue(comment1 in conversation.itervalues()) self.assertTrue(comment2 in conversation.itervalues()) # check if iteritems returns (key, comment object) pairs self.assertTrue((new_id1, comment1) in conversation.iteritems()) self.assertTrue((new_id2, comment2) in conversation.iteritems())
def test_dict_operations(self): # test dict operations and acquisition wrapping # Create a conversation. In this case we doesn't assign it to an # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) # Add a comment. Note: in real life, we always create comments via the # factory to allow different factories to be swapped in comment1 = createObject('plone.Comment') comment1.text = 'Comment text' new_id1 = conversation.addComment(comment1) comment2 = createObject('plone.Comment') comment2.text = 'Comment text' new_id2 = conversation.addComment(comment2) # check if get returns a comment object, and None if the key # can not be found self.assertTrue(IComment.providedBy(conversation.get(new_id1))) self.assertTrue(IComment.providedBy(conversation.get(new_id2))) self.assertEqual(conversation.get(123), None) # check if keys return the ids of all comments self.assertEqual(len(conversation.keys()), 2) self.assertTrue(new_id1 in conversation.keys()) self.assertTrue(new_id2 in conversation.keys()) self.assertFalse(123 in conversation.keys()) # check if items returns (key, comment object) pairs self.assertEqual(len(conversation.items()), 2) self.assertTrue((new_id1, comment1) in conversation.items()) self.assertTrue((new_id2, comment2) in conversation.items()) # check if values returns the two comment objects self.assertEqual(len(conversation.values()), 2) self.assertTrue(comment1 in conversation.values()) self.assertTrue(comment2 in conversation.values()) # check if comment ids are in iterkeys self.assertTrue(new_id1 in conversation.iterkeys()) self.assertTrue(new_id2 in conversation.iterkeys()) self.assertFalse(123 in conversation.iterkeys()) # check if comment objects are in itervalues self.assertTrue(comment1 in conversation.itervalues()) self.assertTrue(comment2 in conversation.itervalues()) # check if iteritems returns (key, comment object) pairs self.assertTrue((new_id1, comment1) in conversation.iteritems()) self.assertTrue((new_id2, comment2) in conversation.iteritems())
def test_title_special_characters_utf8(self): self.portal.invokeFactory( id='doc_sp_chars_utf8', title='Document ëïû', type_name='Document' ) conversation = IConversation(self.portal.doc_sp_chars_utf8) comment1 = createObject('plone.Comment') comment1.author_name = 'Hüüb Bôûmä' conversation.addComment(comment1) self.assertEqual(u'Hüüb Bôûmä on Document ëïû', comment1.Title())
def test_discussion_indexes_updated(self): # Allow discussion registry = queryUtility(IRegistry) discussion_settings = registry.forInterface(IDiscussionSettings) discussion_settings.globally_enabled = True self.document.allow_discussion = True conversation = IConversation(self.document) comment = createObject("plone.Comment") comment.text = "Comment text" conversation.addComment(comment) self._action_delete([u"Fr\\xfchst\\xfcck"]) self.assertFalse(u"Fr\\xfchst\\xfcck" in self.pkm.getKeywords())
def test_last_comment_date(self): # add and remove some comments and check if last_comment_date # is properly updated # Create a conversation. In this case we doesn't assign it to an # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) # Add a three comments that are at least one day old # Note: in real life, we always create # comments via the factory to allow different factories to be # swapped in comment1 = createObject('plone.Comment') comment1.text = 'Comment text' comment1.creation_date = datetime.utcnow() - timedelta(4) conversation.addComment(comment1) comment2 = createObject('plone.Comment') comment2.text = 'Comment text' comment2.creation_date = datetime.utcnow() - timedelta(2) new_comment2_id = conversation.addComment(comment2) comment3 = createObject('plone.Comment') comment3.text = 'Comment text' comment3.creation_date = datetime.utcnow() - timedelta(1) new_comment3_id = conversation.addComment(comment3) # check if the latest comment is exactly one day old self.assertTrue(conversation.last_comment_date < datetime.utcnow() - timedelta(hours=23, minutes=59, seconds=59)) self.assertTrue(conversation.last_comment_date > datetime.utcnow() - timedelta(days=1, seconds=1)) # remove the latest comment del conversation[new_comment3_id] # check if the latest comment has been updated # the latest comment should be exactly two days old self.assertTrue(conversation.last_comment_date < datetime.utcnow() - timedelta(days=1, hours=23, minutes=59, seconds=59)) self.assertTrue(conversation.last_comment_date > datetime.utcnow() - timedelta(days=2, seconds=1)) # remove the latest comment again del conversation[new_comment2_id] # check if the latest comment has been updated # the latest comment should be exactly four days old self.assertTrue(conversation.last_comment_date < datetime.utcnow() - timedelta(days=3, hours=23, minutes=59, seconds=59)) self.assertTrue(conversation.last_comment_date > datetime.utcnow() - timedelta(days=4, seconds=2))
def test_last_comment_date(self): # add and remove some comments and check if last_comment_date # is properly updated # Create a conversation. In this case we doesn't assign it to an # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) # Add a three comments that are at least one day old # Note: in real life, we always create # comments via the factory to allow different factories to be # swapped in comment1 = createObject('plone.Comment') comment1.text = 'Comment text' comment1.creation_date = datetime.utcnow() - timedelta(4) conversation.addComment(comment1) comment2 = createObject('plone.Comment') comment2.text = 'Comment text' comment2.creation_date = datetime.utcnow() - timedelta(2) new_comment2_id = conversation.addComment(comment2) comment3 = createObject('plone.Comment') comment3.text = 'Comment text' comment3.creation_date = datetime.utcnow() - timedelta(1) new_comment3_id = conversation.addComment(comment3) # check if the latest comment is exactly one day old self.assertTrue(conversation.last_comment_date < datetime.utcnow() - timedelta(hours=23, minutes=59, seconds=59)) self.assertTrue(conversation.last_comment_date > datetime.utcnow() - timedelta(days=1, seconds=1)) # remove the latest comment del conversation[new_comment3_id] # check if the latest comment has been updated # the latest comment should be exactly two days old self.assertTrue(conversation.last_comment_date < datetime.utcnow() - timedelta(days=1, hours=23, minutes=59, seconds=59)) self.assertTrue(conversation.last_comment_date > datetime.utcnow() - timedelta(days=2, seconds=1)) # remove the latest comment again del conversation[new_comment2_id] # check if the latest comment has been updated # the latest comment should be exactly four days old self.assertTrue(conversation.last_comment_date < datetime.utcnow() - timedelta(days=3, hours=23, minutes=59, seconds=59)) self.assertTrue(conversation.last_comment_date > datetime.utcnow() - timedelta(days=4, seconds=2))
def test_discussion_indexes_updated(self): # Allow discussion registry = queryUtility(IRegistry) discussion_settings = registry.forInterface(IDiscussionSettings) discussion_settings.globally_enabled = True self.document.allow_discussion = True conversation = IConversation(self.document) comment = createObject("plone.Comment") comment.text = "Comment text" conversation.addComment(comment) self._action_delete(["Fr\\xfchst\\xfcck"]) self.assertNotIn("Fr\\xfchst\\xfcck", self.document.subject) self.assertNotIn("Fr\\xfchst\\xfcck", self.pkm.getKeywords())
def test_get_replies(self): self.assertFalse(self.viewlet.get_replies()) comment = createObject('plone.Comment') comment.text = 'Comment text' conversation = IConversation(self.portal.doc1) conversation.addComment(comment) conversation.addComment(comment) replies = self.viewlet.get_replies() self.assertEqual(len(tuple(replies)), 2) replies = self.viewlet.get_replies() replies.next() replies.next() self.assertRaises(StopIteration, replies.next)
def test_get_replies(self): self.assertFalse(self.viewlet.get_replies()) comment = createObject('plone.Comment') comment.text = 'Comment text' conversation = IConversation(self.portal.doc1) conversation.addComment(comment) conversation.addComment(comment) replies = self.viewlet.get_replies() self.assertEqual(len(tuple(replies)), 2) replies = self.viewlet.get_replies() replies.next() replies.next() self.assertRaises(StopIteration, replies.next)
def test_discussion_indexes_updated(self): # Allow discussion registry = queryUtility(IRegistry) discussion_settings = registry.forInterface(IDiscussionSettings) discussion_settings.globally_enabled = True self.document.allow_discussion = True conversation = IConversation(self.document) comment = createObject('plone.Comment') comment.text = 'Comment text' conversation.addComment(comment) self._action_delete([ u'Fr\\xfchst\\xfcck', ]) self.assertFalse(u'Fr\\xfchst\\xfcck' in self.pkm.getKeywords())
def test_delete_comment_when_content_object_is_deleted(self): # Make sure all comments of a content object are deleted when the # object itself is deleted. conversation = IConversation(self.portal.doc1) comment = createObject('plone.Comment') comment.text = 'Comment text' conversation.addComment(comment) # Delete the content object self.portal.manage_delObjects(['doc1']) # Make sure the comment has been deleted as well self.assertEqual(len(list(conversation.getComments())), 0) self.assertEqual(len(tuple(conversation.getThreads())), 0) self.assertEqual(conversation.total_comments, 0)
def test_delete_comment_when_content_object_is_deleted(self): # Make sure all comments of a content object are deleted when the # object itself is deleted. conversation = IConversation(self.portal.doc1) comment = createObject('plone.Comment') comment.text = 'Comment text' conversation.addComment(comment) # Delete the content object self.portal.manage_delObjects(['doc1']) # Make sure the comment has been deleted as well self.assertEqual(len(list(conversation.getComments())), 0) self.assertEqual(len(tuple(conversation.getThreads())), 0) self.assertEqual(conversation.total_comments, 0)
def setUp(self): self.portal = self.layer["portal"] setRoles(self.portal, TEST_USER_ID, ["Manager"]) self.portal.invokeFactory(id="doc1", Title="Document 1", type_name="Document") self.catalog = getToolByName(self.portal, "portal_catalog") conversation = IConversation(self.portal.doc1) comment1 = createObject("plone.Comment") comment1.title = "Comment 1" comment1.text = "Comment text" comment1.creator = "Jim" comment1.author_username = "******" comment1.creation_date = datetime(2006, 9, 17, 14, 18, 12) comment1.modification_date = datetime(2006, 9, 17, 14, 18, 12) new_comment1_id = conversation.addComment(comment1) self.comment_id = new_comment1_id brains = self.catalog.searchResults( dict(path={"query": "/".join(self.portal.doc1.getPhysicalPath())}, portal_type="Document") ) self.conversation = conversation self.brains = brains self.doc1_brain = brains[0] self.comment1 = comment1 self.new_comment1_id = new_comment1_id
def setUp(self): self.portal = self.layer['portal'] setRoles(self.portal, TEST_USER_ID, ['Manager']) self.portal.invokeFactory('Folder', 'test-folder') self.folder = self.portal['test-folder'] # Allow discussion on the Document content type self.portal.portal_types['Document'].allow_discussion = True # Set workflow for Discussion item to review workflow self.portal.portal_workflow.setChainForPortalTypes( ('Discussion Item',), ('comment_review_workflow',)) # Create a Document self.portal.invokeFactory('Document', 'doc1') self.portal_discussion = self.portal.portal_discussion # Create a conversation for this Document conversation = IConversation(self.portal.doc1) # Add a comment. comment = createObject('plone.Comment') comment.text = 'Comment text' comment_id = conversation.addComment(comment) comment = self.portal.doc1.restrictedTraverse( '++conversation++default/%s' % comment_id) self.conversation = conversation self.comment_id = comment_id self.comment = comment setRoles(self.portal, TEST_USER_ID, ['Reviewer']) alsoProvides(self.portal.REQUEST, IDiscussionLayer)
def setUp(self): self.portal = self.layer['portal'] setRoles(self.portal, TEST_USER_ID, ['Manager']) self.portal.invokeFactory('Folder', 'test-folder') self.folder = self.portal['test-folder'] self.catalog = self.portal.portal_catalog self.workflow = self.portal.portal_workflow self.workflow.setChainForPortalTypes(['Document'], 'one_state_workflow') self.folder.invokeFactory('Document', 'doc1') self.doc = self.folder.doc1 # Add a comment conversation = IConversation(self.folder.doc1) comment = createObject('plone.Comment') comment.text = 'Comment text' cid = conversation.addComment(comment) self.comment = self.folder.doc1.restrictedTraverse(\ '++conversation++default/%s' % cid) self.portal.acl_users._doAddUser('member', 'secret', ['Member'], []) self.portal.acl_users._doAddUser('reviewer', 'secret', ['Reviewer'], []) self.portal.acl_users._doAddUser('manager', 'secret', ['Manager'], []) self.portal.acl_users._doAddUser('editor' , ' secret', ['Editor'],[]) self.portal.acl_users._doAddUser('reader', 'secret', ['Reader'], [])
def handleComment(self, action): context = aq_inner(self.context) # Check if conversation is enabled on this content object if not self.__parent__.restrictedTraverse( '@@conversation_view').enabled(): raise Unauthorized( 'Discussion is not enabled for this content object.') # Validation form data, errors = self.extractData() if errors: return # Validate Captcha registry = queryUtility(IRegistry) settings = registry.forInterface(IDiscussionSettings, check=False) portal_membership = getToolByName(self.context, 'portal_membership') captcha_enabled = settings.captcha != 'disabled' anonymous_comments = settings.anonymous_comments anon = portal_membership.isAnonymousUser() if captcha_enabled and anonymous_comments and anon: if 'captcha' not in data: data['captcha'] = u'' captcha = CaptchaValidator(self.context, self.request, None, ICaptcha['captcha'], None) captcha.validate(data['captcha']) # Create comment comment = self.create_comment(data) # Add comment to conversation conversation = IConversation(self.__parent__) if data['in_reply_to']: # Add a reply to an existing comment conversation_to_reply_to = conversation.get(data['in_reply_to']) replies = IReplies(conversation_to_reply_to) comment_id = replies.addComment(comment) else: # Add a comment to the conversation comment_id = conversation.addComment(comment) # Redirect after form submit: # If a user posts a comment and moderation is enabled, a message is # shown to the user that his/her comment awaits moderation. If the user # has 'review comments' permission, he/she is redirected directly # to the comment. can_review = getSecurityManager().checkPermission( 'Review comments', context) workflowTool = getToolByName(context, 'portal_workflow') comment_review_state = workflowTool.getInfoFor(comment, 'review_state', None) if comment_review_state == 'pending' and not can_review: # Show info message when comment moderation is enabled IStatusMessage(self.context.REQUEST).addStatusMessage( _('Your comment awaits moderator approval.'), type='info') self.request.response.redirect(self.action) else: # Redirect to comment (inside a content object page) self.request.response.redirect(self.action + '#' + str(comment_id))
def test_add_comment(self): # Create a conversation. In this case we doesn't assign it to an # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) # Add a comment. Note: in real life, we always create comments via the # factory to allow different factories to be swapped in comment = createObject('plone.Comment') comment.text = 'Comment text' new_id = conversation.addComment(comment) # Check that the conversation methods return the correct data self.assertTrue(isinstance(comment.comment_id, int)) self.assertTrue(IComment.providedBy(conversation[new_id])) self.assertEqual( aq_base(conversation[new_id].__parent__), aq_base(conversation), ) self.assertEqual(new_id, comment.comment_id) self.assertEqual(len(list(conversation.getComments())), 1) self.assertEqual(len(tuple(conversation.getThreads())), 1) self.assertEqual(conversation.total_comments(), 1) self.assertTrue( conversation.last_comment_date - datetime.utcnow() < timedelta(seconds=1), )
def test_view(self): # make sure that the comment view is there and redirects to the right # URL # Create a conversation. In this case we doesn't assign it to an # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) # Create a comment comment1 = createObject('plone.Comment') comment1.text = 'Comment text' # Add comment to the conversation new_comment1_id = conversation.addComment(comment1) comment = self.portal.doc1.restrictedTraverse( '++conversation++default/{0}'.format(new_comment1_id), ) # make sure the view is there self.assertTrue( getMultiAdapter( (comment, self.request), name='view', ), ) # make sure the HTTP redirect (status code 302) works when a comment # is called directly view = View(comment, self.request) View.__call__(view) self.assertEqual(self.request.response.status, 302)
def test_get_replies_with_workflow_actions(self): self.assertFalse(self.viewlet.get_replies(workflow_actions=True)) comment = createObject('plone.Comment') comment.text = 'Comment text' conversation = IConversation(self.portal.doc1) c1 = conversation.addComment(comment) self.assertEqual( len(tuple(self.viewlet.get_replies(workflow_actions=True))), 1 ) # Enable moderation workflow self.workflowTool.setChainForPortalTypes( ('Discussion Item',), ('comment_review_workflow,') ) # Check if workflow actions are available reply = self.viewlet.get_replies(workflow_actions=True).next() self.assertTrue('actions' in reply) self.assertEqual( reply['actions'][0]['id'], 'publish' ) self.assertEqual( reply['actions'][0]['url'], 'http://nohost/plone/doc1/++conversation++default/%s' % int(c1) + '/content_status_modify?workflow_action=publish' )
def setUp(self): self.portal = self.layer['portal'] setRoles(self.portal, TEST_USER_ID, ['Manager']) self.portal.invokeFactory(id='doc1', title='Document 1', type_name='Document') self.catalog = getToolByName(self.portal, 'portal_catalog') conversation = IConversation(self.portal.doc1) self.conversation = conversation comment1 = createObject('plone.Comment') comment1.text = 'Comment text' comment1.creator = 'jim' comment1.author_name = 'Jim' new_comment1_id = conversation.addComment(comment1) self.comment_id = new_comment1_id # Comment brain self.comment = self.portal.doc1.restrictedTraverse( '++conversation++default/%s' % new_comment1_id) brains = self.catalog.searchResults(dict( path={ 'query': '/'.join(self.comment.getPhysicalPath()) } )) self.comment_brain = brains[0]
def test_delete_comment(self): # Create a conversation. In this case we doesn't assign it to an # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) # Add a comment. Note: in real life, we always create comments via the # factory to allow different factories to be swapped in comment = createObject('plone.Comment') comment.text = 'Comment text' new_id = conversation.addComment(comment) # make sure the comment has been added self.assertEqual(len(list(conversation.getComments())), 1) self.assertEqual(len(tuple(conversation.getThreads())), 1) self.assertEqual(conversation.total_comments, 1) # delete the comment we just created del conversation[new_id] # make sure there is no comment left in the conversation self.assertEqual(len(list(conversation.getComments())), 0) self.assertEqual(len(tuple(conversation.getThreads())), 0) self.assertEqual(conversation.total_comments, 0)
def test_traversal(self): # make sure comments are traversable, have an id, absolute_url and # physical path conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') comment1.text = 'Comment text' new_comment1_id = conversation.addComment(comment1) comment = self.portal.doc1.restrictedTraverse( '++conversation++default/{0}'.format(new_comment1_id), ) self.assertTrue(IComment.providedBy(comment)) self.assertEqual( ( '', 'plone', 'doc1', '++conversation++default', str(new_comment1_id), ), comment.getPhysicalPath(), ) self.assertEqual( 'http://nohost/plone/doc1/++conversation++default/' + str(new_comment1_id), comment.absolute_url(), )
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)
def test_workflow(self): """Basic test for the 'comment_review_workflow' """ self.portal.portal_workflow.setChainForPortalTypes( ('Discussion Item', ), ('comment_review_workflow,'), ) conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') new_comment1_id = conversation.addComment(comment1) comment = conversation[new_comment1_id] # Make sure comments use the 'comment_review_workflow' chain = self.portal.portal_workflow.getChainFor(comment) self.assertEqual(('comment_review_workflow', ), chain) # Ensure the initial state was entered and recorded self.assertEqual( 1, len(comment.workflow_history['comment_review_workflow']), ) self.assertEqual( None, comment.workflow_history['comment_review_workflow'][0]['action'], ) self.assertEqual( 'pending', self.portal.portal_workflow.getInfoFor(comment, 'review_state'), )
def setUp(self): self.portal = self.layer['portal'] setRoles(self.portal, TEST_USER_ID, ['Manager']) self.portal.invokeFactory(id='doc1', title='Document 1', type_name='Document') # Create a conversation. In this case we doesn't assign it to an # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) # Add a comment. Note: in real life, we always create comments via the # factory to allow different factories to be swapped in comment = createObject('plone.Comment') comment.text = 'Lorem ipsum dolor sit amet.' comment.creator = "jim" comment.author_name = "Jim" comment.creation_date = datetime(2006, 9, 17, 14, 18, 12) comment.modification_date = datetime(2008, 3, 12, 7, 32, 52) self.comment_id = conversation.addComment(comment) self.comment = comment.__of__(conversation) self.conversation = conversation
def setUp(self): self.portal = self.layer['portal'] setRoles(self.portal, TEST_USER_ID, ['Manager']) self.portal.invokeFactory(id='doc1', Title='Document 1', type_name='Document') self.catalog = getToolByName(self.portal, 'portal_catalog') conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') comment1.title = 'Comment 1' comment1.text = 'Comment text' comment1.creator = 'Jim' comment1.author_username = '******' comment1.creation_date = datetime(2006, 9, 17, 14, 18, 12) comment1.modification_date = datetime(2006, 9, 17, 14, 18, 12) new_comment1_id = conversation.addComment(comment1) self.comment_id = new_comment1_id brains = self.catalog.searchResults( dict(path={'query': '/'.join(self.portal.doc1.getPhysicalPath())}, portal_type="Document")) self.conversation = conversation self.brains = brains self.doc1_brain = brains[0] self.comment1 = comment1 self.new_comment1_id = new_comment1_id
def __iter__(self): for item in self.previous: keys = item.keys() typekey = self.typekey(*keys)[0] if item[typekey] != 'plone.Comment': # not a comment yield item; continue pathkey = self.pathkey(*item.keys())[0] if not pathkey: # not enough info yield item; continue path = item[pathkey] ob = self.context.unrestrictedTraverse(path.lstrip('/'), None) if ob is None: yield item; continue # object not found # XXX make sure comment doesn't exist already? conversation = IConversation(ob) comment = createObject('plone.Comment') comment.text = item['text'] comment.author_name = item['author_name'] comment.author_email = item['author_email'] comment.creation_date = DateTime(item['created']).asdatetime() comment.modification_date = comment.creation_date in_reply_to = item.get('_in_reply_to', 0) if in_reply_to: comment.in_reply_to = self.comment_map[in_reply_to] id = conversation.addComment(comment) self.comment_map[item['_comment_id']] = id yield item
def setUp(self): self.portal = self.layer['portal'] setRoles(self.portal, TEST_USER_ID, ['Manager']) self.portal.invokeFactory(id='doc1', title='Document 1', type_name='Document') # Create a conversation. In this case we doesn't assign it to an # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) # Add a comment. Note: in real life, we always create comments via the # factory to allow different factories to be swapped in comment = createObject('plone.Comment') comment.text = 'Lorem ipsum dolor sit amet.' comment.creator = "jim" comment.author_name = "Jim" comment.creation_date = datetime(2006, 9, 17, 14, 18, 12) comment.modification_date = datetime(2008, 3, 12, 7, 32, 52) self.comment_id = conversation.addComment(comment) self.comment = comment.__of__(conversation) self.conversation = conversation
def test_get_replies_with_workflow_actions(self): self.assertFalse(self.viewlet.get_replies(workflow_actions=True)) comment = createObject('plone.Comment') comment.text = 'Comment text' conversation = IConversation(self.portal.doc1) c1 = conversation.addComment(comment) self.assertEqual( len(tuple(self.viewlet.get_replies(workflow_actions=True))), 1 ) # Enable moderation workflow self.workflowTool.setChainForPortalTypes( ('Discussion Item',), ('comment_review_workflow,') ) # Check if workflow actions are available reply = self.viewlet.get_replies(workflow_actions=True).next() self.assertTrue('actions' in reply) self.assertEqual( reply['actions'][0]['id'], 'publish' ) self.assertEqual( reply['actions'][0]['url'], 'http://nohost/plone/doc1/++conversation++default/%s' % int(c1) + '/content_status_modify?workflow_action=publish' )
def test_move_upper_level_folder(self): # create a folder with a nested structure self.portal.invokeFactory( id='sourcefolder', title='Source Folder', type_name='Folder', ) self.portal.sourcefolder.invokeFactory( id='moveme', title='Move Me', type_name='Folder', ) self.portal.sourcefolder.moveme.invokeFactory( id='mydocument', title='My Document', type_name='Folder', ) self.portal.invokeFactory( id='targetfolder', title='Target Folder', type_name='Folder', ) # create comment on my-document conversation = IConversation( self.portal.sourcefolder.moveme.mydocument, ) comment = createObject('plone.Comment') comment_id = conversation.addComment(comment) # We need to commit here so that _p_jar isn't None and move will work transaction.savepoint(optimistic=True) # Move moveme from folder1 to folder2 cp = self.portal.sourcefolder.manage_cutObjects(ids=('moveme',)) self.portal.targetfolder.manage_pasteObjects(cp) # Make sure no old comment brains are left brains = self.catalog.searchResults( dict( portal_type='Discussion Item', path={'query': '/plone/sourcefolder/moveme'}, ), ) self.assertEqual(len(brains), 0) # make sure comments are correctly index on the target brains = self.catalog.searchResults( dict( portal_type='Discussion Item', path={'query': '/plone/targetfolder/moveme'}, ), ) self.assertEqual(len(brains), 1) self.assertEqual( brains[0].getPath(), '/plone/targetfolder/moveme/mydocument/++conversation++default/' + str(comment_id), )
def test_tool_indexing(self): # Create a conversation. In this case we doesn't assign it to an # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) # Add a comment. comment = createObject('plone.Comment') comment.creator = 'Jim' comment.text = 'Comment text' conversation.addComment(comment) # Check that the comment got indexed in the tool: tool = queryUtility(ICommentingTool) comment = list(tool.searchResults()) self.assertTrue( len(comment) == 1, "There is only one comment, but we got" " %s results in the search" % len(comment)) self.assertEqual(comment[0].Title, 'Jim on Document 1')
def test_delete_recursive(self): # Create a conversation. In this case we doesn't assign it to an # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) IReplies(conversation) # Create a nested comment structure: # # Conversation # +- Comment 1 # +- Comment 1_1 # | +- Comment 1_1_1 # +- Comment 1_2 # +- Comment 2 # +- Comment 2_1 # Create all comments comment1 = createObject('plone.Comment') comment1.text = 'Comment text' comment1_1 = createObject('plone.Comment') comment1_1.text = 'Comment text' comment1_1_1 = createObject('plone.Comment') comment1_1_1.text = 'Comment text' comment1_2 = createObject('plone.Comment') comment1_2.text = 'Comment text' comment2 = createObject('plone.Comment') comment2.text = 'Comment text' comment2_1 = createObject('plone.Comment') comment2_1.text = 'Comment text' # Create the nested comment structure new_id_1 = conversation.addComment(comment1) new_id_2 = conversation.addComment(comment2) comment1_1.in_reply_to = new_id_1 new_id_1_1 = conversation.addComment(comment1_1) comment1_1_1.in_reply_to = new_id_1_1 conversation.addComment(comment1_1_1) comment1_2.in_reply_to = new_id_1 conversation.addComment(comment1_2) comment2_1.in_reply_to = new_id_2 new_id_2_1 = conversation.addComment(comment2_1) del conversation[new_id_1] self.assertEqual( [{'comment': comment2, 'depth': 0, 'id': new_id_2}, {'comment': comment2_1, 'depth': 1, 'id': new_id_2_1}, ], list(conversation.getThreads()))
def testDiscussionReply(self): from zope.component import createObject, queryUtility from plone.registry.interfaces import IRegistry from plone.app.discussion.interfaces import IDiscussionSettings from plone.app.discussion.interfaces import IConversation self.folder.invokeFactory('Document', id='doc', title="Document") # Enable discussion registry = queryUtility(IRegistry) settings = registry.forInterface(IDiscussionSettings) settings.globally_enabled = True # Create the conversation object conversation = IConversation(self.folder.doc) # Add a comment comment = createObject('plone.Comment') comment.text = 'Comment text' conversation.addComment(comment) # Test the comment self.assertEqual(len(list(conversation.getComments())), 1) reply = conversation.getComments().next() self.assertEqual(reply.Title(), u'Anonymous on Document') self.assertEqual(reply.text, 'Comment text')
def test_move_comments_when_content_object_is_moved(self): # Create two folders and a content object with a comment self.portal.invokeFactory( id='folder1', title='Folder 1', type_name='Folder', ) self.portal.invokeFactory( id='folder2', title='Folder 2', type_name='Folder', ) self.portal.folder1.invokeFactory( id='moveme', title='Move Me', type_name='Document', ) conversation = IConversation(self.portal.folder1.moveme) comment = createObject('plone.Comment') comment_id = conversation.addComment(comment) # We need to commit here so that _p_jar isn't None and move will work transaction.savepoint(optimistic=True) # Move moveme from folder1 to folder2 cp = self.portal.folder1.manage_cutObjects(ids=('moveme',)) self.portal.folder2.manage_pasteObjects(cp) # Make sure no old comment brains are brains = self.catalog.searchResults( dict( portal_type='Discussion Item', path={ 'query': '/'.join(self.portal.folder1.getPhysicalPath()), }, ), ) self.assertEqual(len(brains), 0) brains = self.catalog.searchResults( dict( portal_type='Discussion Item', path={ 'query': '/'.join(self.portal.folder2.getPhysicalPath()), }, ), ) self.assertEqual(len(brains), 1) self.assertEqual( brains[0].getPath(), '/plone/folder2/moveme/++conversation++default/' + str(comment_id), )
def setUp(self): self.portal = self.layer['portal'] setRoles(self.portal, TEST_USER_ID, ['Manager']) interface.alsoProvides( self.portal.REQUEST, interfaces.IDiscussionLayer) self.portal.invokeFactory('Document', 'doc1') self.portal.invokeFactory('Document', 'doc2') self.portal_discussion = getToolByName( self.portal, 'portal_discussion', None, ) # Allow discussion registry = queryUtility(IRegistry) settings = registry.forInterface(IDiscussionSettings) settings.globally_enabled = True conversation = IConversation(self.portal.doc1) comment = createObject('plone.Comment') comment.text = 'Comment text' conversation.addComment(comment)