Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

plone.app.testing can't call BrowserView

I've added a couple of BrowserViews through paster, now I'm trying to run them from plone.app.testing, because I like repeatable and consistent tests. Calling the view manually from the browser works without any problems.

I've tried both importing and initializing views manually, as well as calling the class from restricted traverse. In both cases an object gets initialized just fine but when I try to trigger rendering either calling the instance as a function or using __call__() method, I get the following error:

*** KeyError: 'global_cache_settings

I looked at the example in README.rst in plone.app.testing it doesn't seem to mention the problem, quick googling didn't yield any results either. It could be one of the site customization, however when greping the source, I found 'global_cache_settings' mentioned in Products.CMFPlone, so it's probably a plone thing:

eggs/Products.CMFPlone-4.1.4-py2.6.egg/Products/CMFPlone/skins/plone_templates/main_template.pt
28:  <metal:cache use-macro="context/global_cache_settings/macros/cacheheaders">
29:    Get the global cache headers located in global_cache_settings.

eggs/plone.app.layout-2.1.13-py2.6.egg/plone/app/layout/presentation/presentation.pt
11:    <metal:cache use-macro="here/global_cache_settings/macros/cacheheaders">
12:        Get the global cache headers located in global_cache_settings.

eggs/plonetheme.sunburst-1.1.6-py2.6.egg/plonetheme/sunburst/skins/sunburst_templates/main_template.pt
20:    <metal:cache use-macro="context/global_cache_settings/macros/cacheheaders">
21:    Get the global cache headers located in global_cache_settings.

Here's relevant class declarations:

from zope.interface import implements, Interface

from Products.Five import BrowserView
from Products.CMFCore.utils import getToolByName
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from Products.MyProduct import MyProductMessageFactory as _

class IPromoBoardHome(Interface):
    """
    PromoBoardHome view interface
    """
    def __init__(self, context, request):
        pass
    def __call__(self):
        pass
    def test():
        """ test method"""


class PromoBoardHome(BrowserView):
    """
    PromoBoardHome browser view
    """
    implements(IPromoBoardHome)

    def __init__(self, context, request):
        self.context = context
        self.request = request
    def __call__(self):
        return ViewPageTemplateFile('pt/promoboardhome.pt')(self)
    @property
    def portal_catalog(self):
        return getToolByName(self.context, 'portal_catalog')

    @property
    def portal(self):
        return getToolByName(self.context, 'portal_url').getPortalObject()


    def test(self):
        """
        test method
        """
        dummy = _(u'a dummy string')

        return {'dummy': dummy}

Template:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
    lang="en"
    metal:use-macro="here/main_template/macros/master"
    i18n:domain="Products.MyProduct">
<body>
    <div metal:fill-slot="main">
        <tal:main-macro metal:define-macro="main"
                        tal:define="testview view/test">

            <span tal:content="testview/dummy">test</span>

        </tal:main-macro>
    </div>
</body>
</html>

configure.zcml declaration:

<browser:page
    for="*"
    name="promoboardhome"
    class=".promoboardhome.PromoBoardHome"
    allowed_interface=".promoboardhome.IPromoBoardHome"
    permission="zope2.View"
/>

test file:

import unittest2 as unittest
from . import PROD_INTEGRATION_TESTING

from plone.app.testing import setRoles, TEST_USER_ID

from Products.CMFCore.utils import getToolByName
from Products.MyProduct.browser.promoboardhome import PromoBoardHome

class TestPromoBoardHome(unittest.TestCase):
    layer = PROD_INTEGRATION_TESTING
    def setUp(self):
        self.portal = self.layer['portal']
    def test_call(self):
        pbh = self.portal.restrictedTraverse('@@promoboardhome')
        try:
            pbh()
        except KeyError:
            print "that didn't work!"
            import pdb; pdb.set_trace()

Am I doing something wrong here?

like image 471
Alex Volkov Avatar asked Nov 11 '12 04:11

Alex Volkov


2 Answers

Browser views are nothing but named multi adapters; to test them you have call them on the right context and to manually set up the request to provide the interface declared for the view; in you case is probably something like this:

from zope.interface import alsoProvides
from Products.MyProduct.browser.promoboardhome import IPromoBoardHome

class TestPromoBoardHome(unittest.TestCase):

    layer = PROD_INTEGRATION_TESTING

    def setUp(self):
        self.portal = self.layer['portal']
        self.request = self.layer['request']
        alsoProvides(self.request, IPromoBoardHome)

I have a bunch of browser views tests on packages like collective.nitf.

Happy testing!

like image 64
hvelarde Avatar answered Nov 15 '22 14:11

hvelarde


You probably want to test the views with testbrowser instead:

from plone.testing import z2
browser = z2.Browser(self.layer['app'])
browser.open(self.layer['portal'].absolute_url() + '/@@promoboardhome')

Or similar.

like image 20
Lennart Regebro Avatar answered Nov 15 '22 12:11

Lennart Regebro