======================
 plone.app.discussion
======================

This is a functional test for the plone.app.discussion comments viewlet.

We use zope.testbrowser to simulate browser interaction in order to show how
the plone.app.discussion commenting works.


Setting up and loggin in
------------------------

First we have to set up some things and login.

    >>> app = layer['app']
    >>> from plone.testing.z2 import Browser
    >>> browser = Browser(app)
    >>> browser.handleErrors = False
    >>> browser.addHeader('Authorization', 'Basic admin:secret')
    >>> portal = layer['portal']
    >>> portal_url = 'http://nohost/plone'

By default, only HTTP error codes (e.g. 500 Server Side Error) are shown when an
error occurs on the server. To see more details, set handleErrors to False:

    >>> browser.handleErrors = False

We also keep another testbrowser handy for testing how tiles are rendered if
you're not logged in::

    >>> unprivileged_browser = Browser(app)

Make sure we have a test user from the layer and it uses fancy characters:

    >>> from Products.CMFCore.utils import getToolByName
    >>> mtool = getToolByName(portal, 'portal_membership', None)
    >>> jim_fullname = mtool.getMemberById('jim').getProperty('fullname')
    >>> jim_fullname
    'Jim Fult\xc3\xb8rn'

Enable commenting.

    >>> from zope.component import queryUtility
    >>> from plone.registry.interfaces import IRegistry
    >>> from plone.app.discussion.interfaces import IDiscussionSettings
    >>> registry = queryUtility(IRegistry)
    >>> settings = registry.forInterface(IDiscussionSettings)
    >>> settings.globally_enabled = True

    >>> import transaction
    >>> transaction.commit()

Create a public page with comments allowed.

    >>> browser.open(portal_url)
    >>> browser.getLink(id='document').click()
    >>> browser.getControl(name='title').value = "Doc1"
    >>> browser.getControl(name='allowDiscussion:boolean').value = True
    >>> browser.getControl(name='form.button.save').click()
    >>> urldoc1 = browser.url

Check that the form has been properly submitted

    >>> browser.url
    'http://nohost/plone/doc1'


Comment Viewlet
---------------

Check that the old comments viewlet does not show up

    >>> 'discussion_reply_form' in browser.contents
    False

Check that the comment form/viewlet shows up

    >>> 'formfield-form-widgets-in_reply_to' in browser.contents
    True

    >>> 'formfield-form-widgets-comment-text' in browser.contents
    True


Post a comment as admin
-----------------------

Login as admin.

    >>> from plone.app.testing import setRoles
    >>> from plone.app.testing import TEST_USER_NAME
    >>> setRoles(portal, 'manager', ['Manager'])

Post a comment as admin.

    >>> browser.getControl(name='form.widgets.text').value = "Comment from admin"
    >>> submit = browser.getControl(name='form.buttons.comment')
    >>> submit.click()

Check if comment has been added properly.

    >>> '<a href="http://nohost/plone/author/admin">admin</a>' in browser.contents
    True

    >>> browser.contents
    '...<a href="http://nohost/plone/author/admin">admin</a>...says:...'

    >>> "Comment from admin" in browser.contents
    True


Post a comment as user
----------------------

Login as user (without the 'Member' role).

    >>> browser.open(portal_url + '/logout')
    >>> browser.open(portal_url + '/login_form')
    >>> browser.getControl(name='__ac_name').value = 'johndoe'
    >>> browser.getControl(name='__ac_password').value = 'secret'
    >>> browser.getControl(name='submit').click()

Users without the 'Reply to item' permission will not see the comment form,
because they don't have the 'Reply to item' permission. By default, this
permission is only granted to the 'Member' role.

    >>> 'form.widgets.text' in browser.contents
    False

    >>> 'form.buttons.comment' in browser.contents
    False


Post a comment as member
------------------------

Login as user 'jim'.

    >>> browser.open(portal_url + '/logout')
    >>> browser.open(portal_url + '/login_form')
    >>> browser.getControl(name='__ac_name').value = 'jim'
    >>> browser.getControl(name='__ac_password').value = 'secret'
    >>> browser.getControl(name='submit').click()

Post a comment as user jim.

    >>> browser.open(urldoc1)
    >>> browser.getControl(name='form.widgets.text').value = "Comment from Jim"
    >>> submit = browser.getControl(name='form.buttons.comment')
    >>> submit.click()

Check if the comment has been added properly.

    >>> browser.contents
    '...<a href="http://nohost/plone/author/jim">Jim Fult\xc3\xb8rn</a>...says:...'

    >>> "Comment from Jim" in browser.contents
    True


Post a comment as anonymous user
--------------------------------

Login and post comment as Anonymous

    >>> unprivileged_browser.open(urldoc1)

    >>> 'Log in to add comments' in unprivileged_browser.contents
    True

Enable anonymous comment

    >>> browser.open(portal_url + '/logout')
    >>> browser.open(portal_url + '/login_form')
    >>> browser.getControl(name='__ac_name').value = 'admin'
    >>> browser.getControl(name='__ac_password').value = 'secret'
    >>> browser.getControl(name='submit').click()
    >>> browser.open(portal_url+'/@@discussion-settings')
    >>> browser.getControl(name='form.widgets.anonymous_comments:list').value = [True]
    >>> browser.getControl(name='form.buttons.save').click()
    >>> browser.open(portal_url + '/logout')

Now we can post an anonymous comment.

    >>> unprivileged_browser.open(urldoc1)
    >>> unprivileged_browser.getControl(name='form.widgets.text').value = "This is an anonymous comment"
    >>> unprivileged_browser.getControl(name='form.buttons.comment').click()

    >>> '<span>Anonymous</span>' in unprivileged_browser.contents
    True

    >>> 'says' in unprivileged_browser.contents
    True

    >>> 'This is an anonymous comment' in unprivileged_browser.contents
    True

Make sure special characters work as well.

    >>> unprivileged_browser.open(urldoc1)
    >>> tarek_fullname = "Tarek Ziadé"
    >>> unprivileged_browser.getControl(name='form.widgets.author_name').value = tarek_fullname
    >>> unprivileged_browser.getControl(name='form.widgets.text').value = "This is an äüö comment"
    >>> unprivileged_browser.getControl(name='form.buttons.comment').click()

    >>> tarek_fullname in unprivileged_browser.contents
    True

    >>> 'says' in unprivileged_browser.contents
    True

    >>> 'This is an äüö comment' in unprivileged_browser.contents
    True

Reply to an existing comment
----------------------------

Check that there is no existing direct reply to a comment.

    >>> 'replyTreeLevel1' in browser.contents
    False

Find a comment id to reply to.

    >>> browser.open(urldoc1)
    >>> import re
    >>> comment_div = re.findall('<div.*?.class="comment.*?>', browser.contents)[0]
    >>> id = re.findall('"([^"]*)"', comment_div)[1]

Post a reply to an existing comment.

    >>> browser.getControl(name='form.widgets.in_reply_to').value = id
    >>> browser.getControl(name='form.widgets.text').value = "Reply comment"
    >>> browser.getControl(name='form.buttons.comment').click()

Check that the reply has been posted properly.

    >>> 'Reply comment' in browser.contents
    True

    >>> 'replyTreeLevel1' in browser.contents
    True


Edit an existing comment
------------------------

Log in as admin

    >>> browser.getLink('Log out').click()
    >>> browser.open(portal_url + '/login_form')
    >>> browser.getControl('Login Name').value = 'admin'
    >>> browser.getControl('Password').value = 'secret'
    >>> browser.getControl('Log in').click()

Use the Plone control panel to enable comment editing.

    >>> browser.open(portal_url + '/plone_control_panel')
    >>> browser.getLink('Discussion').click()
    >>> browser.getControl('Enable editing of comments').selected = True
    >>> browser.getControl(name='form.buttons.save').click()

Extract the edit comment url from the first "edit comment" button

    >>> browser.open(urldoc1)
    >>> form = browser.getForm(name='edit', index=0)
    >>> '@@edit-comment' in form.action
    True

Open the edit comment view

    >>> browser.open(form.action)
    >>> ctrl = browser.getControl('Comment')
    >>> ctrl.value
    'Comment from admin'

Change and save the comment

    >>> ctrl.value = 'Comment from admin / was edited'
    >>> browser.getControl('Edit comment').click()

This used to trigger permissions problems in some portlet configurations.
Check it ain't so.

    >>> 'require_login' in browser.url
    False
    >>> browser.url.startswith('http://nohost/plone/doc1')
    True
    >>> 'Comment from admin / was edited' in browser.contents
    True

Opening the edit comment view, then cancel, does nothing.

    >>> form = browser.getForm(name='edit', index=0)
    >>> '@@edit-comment' in form.action
    True
    >>> browser.open(form.action)
    >>> browser.getControl('Cancel').click()
    >>> browser.url.startswith('http://nohost/plone/doc1')
    True


Anon cannot edit comments.

    >>> unprivileged_browser.open(urldoc1)
    >>> '@@edit-comments' in browser.contents
    False

But Anon can see the edited comment.

    >>> 'Comment from admin / was edited' in unprivileged_browser.contents
    True



Post a comment with comment review workflow enabled
---------------------------------------------------

Create a new public page with comments allowed.

    >>> browser.open(portal_url)
    >>> browser.getLink(id='document').click()
    >>> browser.getControl(name='title').value = "Doc2"
    >>> browser.getControl(name='allowDiscussion:boolean').value = True
    >>> browser.getControl(name='form.button.save').click()
    >>> urldoc2 = browser.url

Check that the form has been properly submitted

    >>> browser.url
    'http://nohost/plone/doc2'

Enable the 'comment review workflow' for comments.

    >>> portal.portal_workflow.setChainForPortalTypes(('Discussion Item',), ('comment_review_workflow'),)
    >>> portal.portal_workflow.getChainForPortalType('Discussion Item')
    ('comment_review_workflow',)

We need to commit the transaction, otherwise setting the workflow will not work.

    >>> import transaction
    >>> transaction.commit()

Post comment as anonymous user.

    >>> unprivileged_browser.open(urldoc2)
    >>> unprivileged_browser.getControl(name='form.widgets.text').value = "Comment review workflow comment"
    >>> unprivileged_browser.getControl(name='form.buttons.comment').click()

Make sure the comment has not been published.

    >>> 'Comment review workflow comment' not in unprivileged_browser.contents
    True

Make sure the user gets a notification that the comment awaits moderator
approval.

    >>> 'Your comment awaits moderator approval' in unprivileged_browser.contents
    True

Login as manager.

    >>> browser.open(portal_url + '/logout')
    >>> browser.open(portal_url + '/login_form')
    >>> browser.getControl(name='__ac_name').value = 'admin'
    >>> browser.getControl(name='__ac_password').value = 'secret'
    >>> browser.getControl(name='submit').click()

Make sure the Manager can publish.

    >>> browser.open(urldoc2)
    >>> 'name="form.button.PublishComment"' in browser.contents
    True
    
Manager (with moderate permission) publishes the comment.
    
    >>> browser.getControl(name='form.button.PublishComment').click()

Make sure there are no left over comments to publish.

    >>> 'name="form.button.PublishComment"' in browser.contents
    False    

Make sure Anonymous user sees published comment.

    >>> unprivileged_browser.open(urldoc2)
    >>> 'Comment review workflow comment' in unprivileged_browser.contents
    True

Post a comment with comment review workflow enabled (with email)
----------------------------------------------------------------

Enable anonymous comment and email field

    >>> browser.open(portal_url+'/@@discussion-settings')
    >>> browser.getControl(name='form.widgets.anonymous_email_enabled:list').value = [True]
    >>> browser.getControl(name='form.widgets.anonymous_comments:list').value = [True]
    >>> browser.getControl(name='form.buttons.save').click()
    >>> browser.open(portal_url + '/logout')

Post comment as anonymous user.

    >>> unprivileged_browser.open(urldoc2)
    >>> unprivileged_browser.getControl(name='form.widgets.author_name').value = "Godefroid"
    >>> unprivileged_browser.getControl(name='form.widgets.author_email').value = "gotcha@bubblenet.be"
    >>> unprivileged_browser.getControl(name='form.widgets.text').value = "With email"
    >>> unprivileged_browser.getControl(name='form.buttons.comment').click()

Make sure the comment has not been published.

    >>> 'With email' not in unprivileged_browser.contents
    True

Make sure the user gets a notification that the comment awaits moderator
approval.

    >>> 'Your comment awaits moderator approval' in unprivileged_browser.contents
    True

Make sure comment is not yet published.

    >>> 'With email' in unprivileged_browser.contents
    False

Make sure email is displayed for Manager.

    >>> browser.open(urldoc2)

    >>> "Godefroid" in browser.contents
    True

    >>> '(<a href="mailto:gotcha@bubblenet.be">gotcha@bubblenet.be</a>)' in browser.contents
    True

    >>> 'says' in browser.contents
    True
    
Manager (with moderate permission) publishes the comment.

    >>> browser.getControl(name='form.button.PublishComment').click()

Make sure email is still displayed for Manager.
    
    >>> "Godefroid" in browser.contents
    True

    >>> '(<a href="mailto:gotcha@bubblenet.be">gotcha@bubblenet.be</a>)' in browser.contents
    True

    >>> 'says' in browser.contents
    True

Make sure comment is published but email is not displayed for anonymous.
    
    >>> unprivileged_browser.open(urldoc2)

    >>> 'With email' in unprivileged_browser.contents
    True

    >>> "Godefroid" in unprivileged_browser.contents
    True

    >>> '(<a href="mailto:gotcha@bubblenet.be">gotcha@bubblenet.be</a>)' in unprivileged_browser.contents
    False 

    >>> 'says' in unprivileged_browser.contents
    True


Edit the content object after a comment has been posted
-------------------------------------------------------

Make sure we still can edit the content object after a comment has been posted.
This is a regression test for http://dev.plone.org/plone/ticket/11157
(TypeError: Can't pickle objects in acquisition wrappers).

Login as admin.

    >>> browser.open(portal_url + '/logout')
    >>> browser.open(portal_url + '/login_form')
    >>> browser.getControl(name='__ac_name').value = 'admin'
    >>> browser.getControl(name='__ac_password').value = 'secret'
    >>> browser.getControl(name='submit').click()

Edit the content object.

    >>> browser.open(urldoc1 + "/edit")
    >>> browser.getControl(name='text').value = "Lorem ipsum"
    >>> browser.getControl(name='form.button.save').click()

Make sure the edit was successful.

    >>> 'Lorem ipsum' in browser.contents
    True


List comments in a collection
-----------------------------

Create a collection.

    >>> from plone.app.testing import setRoles
    >>> from plone.app.testing import TEST_USER_NAME
    >>> setRoles(portal, 'manager', ['Manager'])
    >>> browser.open(portal.absolute_url())
    >>> from plone.app.discussion.testing import COLLECTION_TYPE
    >>> browser.getLink(url='createObject?type_name=' + COLLECTION_TYPE).click()
    >>> browser.getControl('Title', index=0
    ...                    ).value = 'Foo Comment Collection'
    >>> browser.getControl('Save').click()
    >>> print browser.contents
    <...Changes saved...
    >>> topic_url = browser.url

Set the collection criteria.

    >>> browser.open(topic_url + "/edit")

    >>> if COLLECTION_TYPE == "Collection":
    ...     browser.getControl(name="addindex").value = ['portal_type']
    ...     browser.getControl(name="form.button.addcriteria").click()
    ...     browser.getControl(name="addoperator").value = ['plone.app.querystring.operation.selection.is']
    ...     browser.getControl(name="form.button.addcriteria").click()
    ...     browser.getControl(name="query.v:records:list").value = ["Discussion Item"]
    ...     browser.getControl(name="form.button.save").click()
    ... else:
    ...     browser.getLink('Criteria').click()
    ...     browser.getControl('Item Type', index=0).selected = True
    ...     browser.getControl('Select content types').selected = True
    ...     browser.getControl('Add criteria').click()
    ...     browser.getControl('Comment').selected = True
    ...     browser.getControl('Save', index=0).click()
    >>> print browser.contents
    <...Changes saved...

View the collection listing.

    >>> browser.getLink('View').click()
    >>> browser.getLink('admin on Doc1', index=0)
    <Link text='admin on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
    >>> browser.getLink('admin on Doc1', index=1)
    <Link text='admin on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
    >>> browser.getLink('Anonymous on Doc1', index=0)
    <Link text='Anonymous on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
    >>> browser.getLink('Anonymous on Doc2', index=0)
    <Link text='Anonymous on Doc2' url='http://nohost/plone/doc2/++conversation++default/...'>
    >>> browser.getLink(tarek_fullname + ' on Doc1')
    <Link text='Tarek Ziad\xc3\xa9 on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
    >>> browser.getLink(jim_fullname + ' on Doc1')
    <Link text='Jim Fult\xc3\xb8rn on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>

Comments are unindexed when the content is deleted
--------------------------------------------------

Delete the commented content.

    >>> browser.open(urldoc1)
    >>> browser.getLink('Delete').click()
    >>> browser.getControl('Delete').click()
    >>> print browser.contents
    <...Doc1 has been deleted...

The comments are no longer in the catalog.

    >>> browser.open(topic_url)
    >>> browser.getLink('admin on Doc1', index=0)
    Traceback (most recent call last):
    LinkNotFoundError
    >>> browser.getLink('admin on Doc1', index=1)
    Traceback (most recent call last):
    LinkNotFoundError
    >>> browser.getLink('Anonymous on Doc1', index=0)
    Traceback (most recent call last):
    LinkNotFoundError
    >>> browser.getLink('Anonymous on Doc1', index=1)
    Traceback (most recent call last):
    LinkNotFoundError
    >>> browser.getLink(tarek_fullname + ' on Doc1')
    Traceback (most recent call last):
    LinkNotFoundError
    >>> browser.getLink(jim_fullname + ' on Doc1')
    Traceback (most recent call last):
    LinkNotFoundError
