Test coverage for vnccollab.theme.portlets.etherpads_list

vnccollab/      covered 69% (1245 of 4098 uncovered)
    theme/      covered 69% (1245 of 4098 uncovered)
        portlets/      covered 68% (353 of 1108 uncovered)
            etherpads_list.py      covered 48% (76 of 148 uncovered)

    1: import logging
    1: from BeautifulSoup import BeautifulSoup
       
    1: from zope.formlib import form
    1: from zope.interface import implements
    1: from zope import schema
    1: from zope.testbrowser.browser import Browser
       
    1: from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile
    1: from Products.CMFCore.utils import getToolByName
    1: from Products.CMFPlone.utils import safe_unicode
       
    1: from plone.memoize.instance import memoize
    1: from plone.portlets.interfaces import IPortletDataProvider
    1: from plone.app.portlets.portlets import base
       
    1: from vnccollab.theme import messageFactory as _
    1: from vnccollab.common.portlets import deferred
    1: from vnccollab.theme.portlets.zimbra_mail import logException
       
    1: logger = logging.getLogger('vnccollab.theme.EtherpadListsPortlet')
       
       
    2: class IEtherpadsListPortlet(IPortletDataProvider):
       
    1:     header = schema.TextLine(
    1:         title=_(u"Header"),
    1:         description=_(u"Header of the portlet."),
    1:         required=True,
    1:         default=u'Your Pads')
       
    1:     url = schema.URI(
    1:         title=_(u"Etherpad Root URL"),
    1:         description=_(u"Root url to your Etherpad service. If not set here, "
                   "then user settings will be checked for etherpad root url "
                   " service."),
    1:         required=False,
    1:         default='https://vitaliy.etherpad.zdemo.vnc.biz')
       
    1:     count = schema.Int(
    1:        title=_(u"Number of pads to display"),
    1:        description=u'',
    1:        required=True,
    1:        default=10)
       
    1:     username = schema.ASCIILine(
    1:         title=_(u"Username"),
    1:         description=_(u"If not set, etherpad_username property of "
                   "authenticated user will be used."),
    1:         required=False,
    1:         default='')
       
    1:     password = schema.Password(
    1:         title=_(u"Password"),
    1:         description=_(u"If not set, etherpad_password property of authenticated"
                   " user will be used."),
    1:         required=False,
    1:         default=u'')
       
       
    2: class Assignment(base.Assignment):
    1:     implements(IEtherpadsListPortlet)
       
    1:     header = u'Your Pads'
    1:     url = 'https://vitaliy.etherpad.zdemo.vnc.biz'
    1:     count = 10
    1:     username = ''
    1:     password = u''
       
    1:     @property
           def title(self):
               """Return portlet header"""
>>>>>> return self.header
1: def __init__(self, header=u'Your Pads', 1: url='https://vitaliy.etherpad.zdemo.vnc.biz', 1: count=10, username='', password=u''):
>>>>>> self.header = header
>>>>>> self.url = url
>>>>>> self.count = count
>>>>>> self.username = username
>>>>>> self.password = password
2: class Renderer(deferred.DeferredRenderer): 1: render = ZopeTwoPageTemplateFile('templates/etherpads_list.pt') 1: def refresh(self):
>>>>>> self.pads = self.getPads()
1: @memoize def getPads(self):
>>>>>> pads = []
>>>>>> username, password, url = self.getUserData()
>>>>>> if not (username and password and url):
>>>>>> return ()
# try to request etherpad for page with table of pads
>>>>>> try:
>>>>>> content = self._getPadsPage()
>>>>>> except:
>>>>>> logException(_(u"Error during fetching pads from %s" % url),
>>>>>> context=self.context, logger=logger)
>>>>>> return ()
# try to parse html page into pads
>>>>>> try:
>>>>>> pads = self._parsePadsPage(content, self.trail_url(url),
>>>>>> self.data.count)
>>>>>> except:
>>>>>> logException(_(u"Error during parsing pads page from %s" % url),
>>>>>> context=self.context, logger=logger)
>>>>>> return ()
>>>>>> return tuple(pads)
1: def _parsePadsPage(self, content, base_url, limit):
>>>>>> pads = []
>>>>>> soup = BeautifulSoup(content)
# go over pads table rows, skipping first header row
>>>>>> counter = 0
>>>>>> for row in soup.find('table', id='padtable').findAll('tr')[1:]:
>>>>>> if limit and limit <= counter:
>>>>>> break
# get row cells
>>>>>> ctitle, cdate, ceditors = row.findAll('td')[:3]
>>>>>> if not (ctitle and cdate and ceditors):
>>>>>> continue
# prepare pad url
>>>>>> link = ctitle.find('a')
>>>>>> if not link:
>>>>>> continue
>>>>>> url = '%s%s' % (base_url, link.get('href'))
>>>>>> if not url:
>>>>>> continue
# prepare editors
>>>>>> editors = []
>>>>>> for editor in ceditors.findAll('a'):
>>>>>> editors.append({
>>>>>> 'name': editor.text,
>>>>>> 'url': '%s%s' % (base_url, editor.get('href'))
})
>>>>>> pads.append({
>>>>>> 'url': url,
>>>>>> 'title': link.text,
>>>>>> 'date': cdate.text,
>>>>>> 'editors': tuple(editors)
})
>>>>>> counter += 1
>>>>>> return pads
1: def _getPadsPage(self):
>>>>>> username, password, url = self.getUserData()
# login
>>>>>> browser = Browser()
>>>>>> browser.open('%s/ep/account/sign-in' % self.trail_url(url))
>>>>>> browser.getControl(name='email').value = username
>>>>>> browser.getControl(name='password').value = password
>>>>>> browser.getForm(id='signin-form').submit()
# open pads table page
>>>>>> browser.getLink('Pads').click()
>>>>>> return safe_unicode(browser.contents)
1: @memoize def root_url(self): """Return url w/o trailing slash prepared either from portlet or user settings. Used in template. """
>>>>>> return self.trail_url(self.getUserData()[2])
1: def trail_url(self, url=None): """Remove trailing slash from url."""
>>>>>> if url and url.endswith('/'):
>>>>>> return url[:-1]
>>>>>> return url
1: @memoize def getUserData(self): """Returns username, password and root etherpad url for user. Returns tuple of: (username, password, root etherpad url) """
>>>>>> mtool = getToolByName(self.context, 'portal_membership')
>>>>>> member = mtool.getAuthenticatedMember()
>>>>>> username, password, url = self.data.username, self.data.password, \
>>>>>> self.data.url
# take username and password from authenticated user Etherpad creds
>>>>>> if not (username and password):
>>>>>> username, password = member.getProperty('etherpad_username', ''), \
>>>>>> member.getProperty('etherpad_password', '')
# if not set globally, take url from user settings
>>>>>> if not url:
>>>>>> url = member.getProperty('etherpad_url', '')
# password could contain non-ascii chars, ensure it's properly encoded
>>>>>> return username, safe_unicode(password).encode('utf-8'), url
1: @property def title(self): """return title of feed for portlet"""
>>>>>> return self.data.header
2: class AddForm(base.AddForm): 1: form_fields = form.Fields(IEtherpadsListPortlet) 1: label = _(u"Add Etherpad Lists portlet") 1: description = _(u"A portlet displaying list of Etherpad pads.") 1: def create(self, data):
>>>>>> return Assignment(**data)
2: class EditForm(base.EditForm): 1: form_fields = form.Fields(IEtherpadsListPortlet) 1: label = _(u"Edit Etherpad Lists portlet") 1: description = _(u"A portlet displaying list of Etherpad pads.")