def test_search_principal(self): root = SharingNode(name='root') request = self.layer.new_request() # Render sharing tile with search term with self.layer.authenticated('manager'): res = render_tile(root, request, 'sharing') self.assertFalse(res.find('Manager User') > -1) request.params['term'] = 'manager' with self.layer.authenticated('manager'): res = render_tile(root, request, 'sharing') self.assertTrue(res.find('Manager User') > -1) request.params['term'] = 'group1' with self.layer.authenticated('manager'): res = render_tile(root, request, 'sharing') self.assertTrue(res.find('Group 1') > -1) # Existing principal roles are not rendered if term found on request root.principal_roles['viewer'] = ['editor'] with self.layer.authenticated('manager'): res = render_tile(root, request, 'sharing') expected = ( '<input checked="checked" ' 'class="add_remove_role_for_principal" ' 'id="input-viewer" name="viewer" type="checkbox" value="editor" />' ) self.assertFalse(res.find(expected) > -1) # Existing principal roles are rendered if no term found del request.params['term'] with self.layer.authenticated('manager'): res = render_tile(root, request, 'sharing') self.assertTrue(res.find(expected) > -1)
def test_byline(self): # Byline renders ``model.metadata.creator``, ``model.metadata.created`` # and ``model.metadata.modified`` dt = datetime(2011, 3, 14) root = BaseNode() root.metadata.created = dt root.metadata.modified = dt root.metadata.creator = 'max' request = self.layer.new_request() # Unauthenticated res = render_tile(root, request, 'byline') self.assertEqual(res, u'') # Authenticated with self.layer.authenticated('max'): res = render_tile(root, request, 'byline') self.checkOutput(""" <p class="byline"> <span>Created by</span>: <strong>max</strong>, <span>on</span> <strong>14.03.2011 00:00</strong>. <span>Last modified</span>: <strong>14.03.2011 00:00</strong> </p> """, res)
def test_personaltools(self): root = BaseNode() request = self.layer.new_request() # Unauthorized res = render_tile(root, request, 'personaltools') self.assertFalse(res.find('id="personaltools"') != -1) # Authorized with self.layer.authenticated('max'): res = render_tile(root, request, 'personaltools') self.assertTrue(res.find('id="personaltools"') != -1) self.assertTrue(res.find('href="http://example.com/logout"') != -1) self.assertFalse(res.find('href="http://example.com/settings"') != -1) # No settings link if empty settings root['settings'] = BaseNode() with self.layer.authenticated('max'): res = render_tile(root, request, 'personaltools') self.assertFalse(res.find('href="http://example.com/settings"') != -1) # Settings link if settings container contains children root['settings']['mysettings'] = BaseNode() with self.layer.authenticated('max'): res = render_tile(root, request, 'personaltools') self.assertTrue(res.find('href="http://example.com/settings"') != -1)
def test_contextmenu(self): with self.layer.authenticated('manager'): parent = BaseNode('root') model = parent['model'] = SharingNode() model.properties.action_up = True model.properties.action_view = True model.properties.action_list = True model.properties.action_edit = True model.properties.action_delete = True # XXX: model.properties.action_delete_children = True request = self.layer.new_request() ActionContext(model, request, 'content') rendered = render_tile(model, request, 'contextmenu') self.assertTrue(rendered.find('toolbaraction-up') > -1) self.assertTrue(rendered.find('toolbaraction-view') > -1) self.assertTrue(rendered.find('toolbaraction-list') > -1) self.assertTrue(rendered.find('toolbaraction-edit') > -1) self.assertTrue(rendered.find('toolbaraction-delete') > -1) self.assertTrue(rendered.find('toolbaraction-share') > -1) model = CopySupportNode() ActionContext(model, request, 'listing') rendered = render_tile(model, request, 'contextmenu') self.assertTrue(rendered.find('toolbaraction-cut') > -1) self.assertTrue(rendered.find('toolbaraction-copy') > -1) self.assertTrue(rendered.find('toolbaraction-paste') > -1)
def test_edit_group(self): root = get_root() groups = root['groups'] group = groups['group_1'] self.assertEqual(group.attrs['groupname'], 'Group 1') request = self.layer.new_request() events_called = [] @classhandler.handler(GroupModifiedEvent) def on_user_created(event): events_called.append('GroupModifiedEvent') with self.layer.authenticated('manager'): res = render_tile(group, request, 'edit') expected = '<form action="http://example.com/groups/group_1/edit"' self.assertTrue(res.find(expected) > -1) request.params['groupform.groupname'] = 'Groupname Changed' request.params['groupform.principal_roles'] = [] request.params['action.groupform.save'] = '1' with self.layer.authenticated('manager'): res = render_tile(group, request, 'edit') self.assertEqual(res, '') self.assertEqual(group.attrs['groupname'], 'Groupname Changed') self.assertTrue('GroupModifiedEvent' in events_called)
def test_ProtectedContentTile(self): # A login form should be rendered instead of the content for anonymous # users. Class ``cone.app.browser.layout.ProtectedContentTile`` # provides this behavior class ProtectedModel(BaseNode): pass with self.layer.hook_tile_reg(): @tile(name='content', interface=ProtectedModel, permission='login') class ProtectedContent(ProtectedContentTile): def render(self): return '<div>Content</div>' model = ProtectedModel() request = self.layer.new_request() # Render protected tile. self.checkOutput(""" <form action="http://example.com/login" class="form-horizontal" enctype="multipart/form-data" id="form-loginform" method="post" novalidate="novalidate">... """, render_tile(model, request, 'content')) with self.layer.authenticated('max'): result = render_tile(model, request, 'content') self.assertTrue(result.find('<div>Content</div>') > -1)
def test_redirect(self): # Tile provides a redirect function which excepts either a string # containing the URL to redirect to or a HTTPFound instance. # This function sets request.environ['redirect'] with given value. It # is considered in ``render_template``, ``render_template_to_response`` # and ``render_to_response`` model = Model() request = self.layer.new_request() @tile(name='redirecttile') class RedirectTile(Tile): def render(self): self.redirect(HTTPFound(location='http://example.com')) self.assertEqual(render_tile(model, request, 'redirecttile'), u'') http_found = request.environ['redirect'] self.assertTrue(isinstance(http_found, HTTPFound)) del request.environ['redirect'] register_tile( name='redirecttiletwo', path='testdata/tile3.pt' ) self.assertEqual(render_tile(model, request, 'redirecttiletwo'), u'') self.assertEqual(request.environ['redirect'], 'http://example.com/foo') del request.environ['redirect']
def test_edit_user(self): root = get_root() users = root['users'] user = users['user_1'] self.assertEqual(user.attrs['fullname'], 'Max Mustermann') self.assertEqual(user.attrs['email'], '*****@*****.**') request = self.layer.new_request() events_called = [] @classhandler.handler(UserModifiedEvent) def on_user_modified(event): events_called.append('UserModifiedEvent') with self.layer.authenticated('manager'): res = render_tile(user, request, 'edit') expected = '<form action="http://example.com/users/user_1/edit"' self.assertTrue(res.find(expected) > -1) request.params['userform.password'] = '******' request.params['userform.fullname'] = 'Susi Musterfrau' request.params['userform.email'] = '*****@*****.**' request.params['userform.principal_roles'] = [] request.params['action.userform.save'] = '1' with self.layer.authenticated('manager'): res = render_tile(user, request, 'edit') self.assertEqual(res, '') self.assertEqual(user.attrs['fullname'], 'Susi Musterfrau') self.assertEqual(user.attrs['email'], '*****@*****.**') self.assertTrue('UserModifiedEvent' in events_called)
def render(self): if self.model.properties.default_child: model = self.model[self.model.properties.default_child] return render_tile(model, self.request, "content") if self.model.properties.default_content_tile: return render_tile(self.model, self.request, self.model.properties.default_content_tile) return render_template( "cone.app.browser:templates/default_root.pt", model=self.model, request=self.request, context=self )
def test_workflow_dropdown(self): request = self.layer.new_request() node = WorkflowNode() self.assertEqual(node.state, u'initial') with self.layer.authenticated('manager'): res = render_tile(node, request, 'wf_dropdown') self.checkOutput( """ ...<a href="#" class="state-initial dropdown-toggle" title="Change state" data-toggle="dropdown"> <span>State</span>: <span>initial</span> </a>... """, res) request.params['do_transition'] = 'initial_2_final' with self.layer.authenticated('manager'): res = render_tile(node, request, 'wf_dropdown') self.checkOutput( """ ...<li class="dropdown"> <span class="no-transitions state-final"> <span>State</span>: <span>final</span> </span> </li>... """, res) self.assertEqual(node.state, u'final') node = InexistentWorkflowNode() request = self.layer.new_request() with self.layer.authenticated('manager'): res = render_tile(node, request, 'wf_dropdown') self.assertEqual(res, u'\n\n \n\n\n') tsf = TranslationStringFactory('cone.app.tests') node = WorkflowNode() node.workflow_tsf = tsf with self.layer.authenticated('manager'): res = render_tile(node, request, 'wf_dropdown') self.checkOutput( """ ...<a href="#" class="state-initial dropdown-toggle" title="Change state" data-toggle="dropdown"> <span>State</span>: <span>initial</span> </a>... """, res)
def test_logout_tile(self): root = get_root() request = self.layer.new_request() with self.layer.authenticated('admin'): render_tile(root, request, 'logout') self.checkOutput(""" ResponseHeaders([('Set-Cookie', 'auth_tkt=; Max-Age=0; Path=/; expires=...'), ('Set-Cookie', 'auth_tkt=; Domain=example.com; Max-Age=0; Path=/; expires=...'), ('Set-Cookie', 'auth_tkt=; Domain=.example.com; Max-Age=0; Path=/; expires=...')]) """, str(request.response.headers))
def test_default_root_content(self): # Default root root = AppRoot() request = self.layer.new_request() with self.layer.authenticated('max'): res = render_tile(root, request, 'content') self.assertEqual(res, '<div>Default Root</div>') # Default child class DefaultChild(BaseNode): pass with self.layer.hook_tile_reg(): @tile(name='content', interface=DefaultChild, permission='view') class DefaultChildContentTile(Tile): def render(self): return '<div>Default Child Content</div>' root = AppRoot() root.factories['1'] = DefaultChild root.properties.default_child = '1' request = self.layer.new_request() with self.layer.authenticated('max'): res = render_tile(root, request, 'content') self.assertEqual(res, '<div>Default Child Content</div>') # Default content tile with self.layer.hook_tile_reg(): @tile(name='mycontent', interface=AppRoot, permission='view') class MyRootContentTile(Tile): def render(self): return '<div>My Root Content Tile</div>' root = AppRoot() root.properties.default_content_tile = 'mycontent' request = self.layer.new_request() with self.layer.authenticated('max'): res = render_tile(root, request, 'content') self.assertEqual(res, '<div>My Root Content Tile</div>') # Custom root content tile with self.layer.hook_tile_reg(): @tile(name='content', interface=AppRoot, permission='view') class RootContentTile(Tile): def render(self): return '<div>Root Content</div>' root = AppRoot() request = self.layer.new_request() with self.layer.authenticated('max'): res = render_tile(root, request, 'content') self.assertEqual(res, '<div>Root Content</div>')
def test_reference_pathbar(self): model = BaseNode() model['a'] = RefNode() model['a']['b'] = RefNode() model['z'] = RefNode() node = model['a']['b']['c'] = RefNode() request = self.layer.new_request() request.params['referencable'] = 'ref_node' request.params['selected'] = '' request.params['root'] = '/' # Case Unauthorized err = self.expectError(HTTPForbidden, render_tile, node, request, 'referencebrowser_pathbar') self.checkOutput( """ Unauthorized: tile <cone.app.browser.referencebrowser.ReferenceBrowserPathBar object at ...> failed permission check """, str(err)) # Case reference root is application root request = self.layer.new_request() request.params['referencable'] = 'ref_node' request.params['selected'] = '' request.params['root'] = '/' with self.layer.authenticated('max'): res = render_tile(node, request, 'referencebrowser_pathbar') self.assertTrue(res.find('"http://example.com/?') > -1) self.assertTrue(res.find('"http://example.com/a?') > -1) self.assertTrue(res.find('"http://example.com/a/b?') > -1) # Case reference root is in current sub tree request = self.layer.new_request() request.params['referencable'] = 'ref_node' request.params['selected'] = '' request.params['root'] = 'a' with self.layer.authenticated('max'): res = render_tile(node, request, 'referencebrowser_pathbar') self.assertFalse(res.find('"http://example.com/?') > -1) self.assertTrue(res.find('"http://example.com/a?') > -1) self.assertTrue(res.find('"http://example.com/a/b?') > -1) # Case reference root is in sibling sub tree request = self.layer.new_request() request.params['referencable'] = 'ref_node' request.params['selected'] = '' request.params['root'] = '/z' with self.layer.authenticated('max'): res = render_tile(node, request, 'referencebrowser_pathbar') self.assertFalse(res.find('"http://example.com/?') > -1) self.assertFalse(res.find('"http://example.com/a?') > -1) self.assertFalse(res.find('"http://example.com/a/b?') > -1) self.assertTrue(res.find('<strong>z</strong>') > -1)
def test_portrait(self): root = get_root() users = root['users'] user = users['user_1'] # Portrait related config properties settings = general_settings(users) self.assertEqual(settings.attrs.users_portrait, 'True') self.assertEqual(settings.attrs.users_portrait_attr, 'portrait') self.assertEqual(settings.attrs.users_portrait_accept, 'image/jpeg') self.assertEqual(settings.attrs.users_portrait_width, '50') self.assertEqual(settings.attrs.users_portrait_height, '50') # Portrait enabled, widget is rendered request = self.layer.new_request() with self.layer.authenticated('manager'): res = render_tile(user, request, 'editform') self.assertTrue(res.find('id="input-userform-portrait"') > -1) # No portrait, default portrait is shown expected = ('src="http://example.com/cone.ugm.static/images/' 'default_portrait.jpg?nocache=') self.assertTrue(res.find(expected) > -1) # Submit portrait dummy_jpg = dummy_file_data('dummy.jpg') portrait = { 'file': BytesIO(dummy_jpg), 'mimetype': 'image/jpeg', } request = user_portrait_request(self.layer, user, portrait) with self.layer.authenticated('manager'): res = render_tile(user, request, 'editform') # New portrait set on user expected = b'\xff\xd8\xff\xe0\x00\x10JFIF' self.assertTrue(user.attrs['portrait'].startswith(expected)) # Portrait present, link to user portrait is shown request = self.layer.new_request() with self.layer.authenticated('manager'): res = render_tile(user, request, 'editform') expected = 'src="http://example.com/users/user_1/portrait_image?nocache=' self.assertTrue(res.find(expected) > -1) # Portrait disabled, widget is skipped settings.attrs.users_portrait = u'False' settings() request = self.layer.new_request() with self.layer.authenticated('manager'): res = render_tile(user, request, 'editform') self.assertFalse(res.find('id="input-userform-portrait"') > -1)
def test_logout_tile(self): root = get_root() request = self.layer.new_request() with self.layer.authenticated('admin'): render_tile(root, request, 'logout') self.checkOutput( """ ResponseHeaders([('Set-Cookie', 'auth_tkt=; Max-Age=0; Path=/; expires=...'), ('Set-Cookie', 'auth_tkt=; Domain=example.com; Max-Age=0; Path=/; expires=...'), ('Set-Cookie', 'auth_tkt=; Domain=.example.com; Max-Age=0; Path=/; expires=...')]) """, str(request.response.headers))
def render(self): if self.model.properties.default_child: model = self.model[self.model.properties.default_child] return render_tile(model, self.request, 'content') if self.model.properties.default_content_tile: return render_tile(self.model, self.request, self.model.properties.default_content_tile) return render_template('cone.app.browser:templates/default_root.pt', model=self.model, request=self.request, context=self)
def test_workflow_dropdown(self): request = self.layer.new_request() node = WorkflowNode() self.assertEqual(node.state, u'initial') with self.layer.authenticated('manager'): res = render_tile(node, request, 'wf_dropdown') self.checkOutput(""" ...<a href="#" class="state-initial dropdown-toggle" title="Change state" data-toggle="dropdown"> <span>State</span>: <span>initial</span> </a>... """, res) request.params['do_transition'] = 'initial_2_final' with self.layer.authenticated('manager'): res = render_tile(node, request, 'wf_dropdown') self.checkOutput(""" ...<li class="dropdown"> <span>State</span>: <span class="state-final">final</span> </li>... """, res) self.assertEqual(node.state, u'final') node = InexistentWorkflowNode() request = self.layer.new_request() with self.layer.authenticated('manager'): res = render_tile(node, request, 'wf_dropdown') self.assertEqual(res, u'\n\n \n\n\n') tsf = TranslationStringFactory('cone.app.tests') node = WorkflowNode() node.workflow_tsf = tsf with self.layer.authenticated('manager'): res = render_tile(node, request, 'wf_dropdown') self.checkOutput(""" ...<a href="#" class="state-initial dropdown-toggle" title="Change state" data-toggle="dropdown"> <span>State</span>: <span>initial</span> </a>... """, res)
def test_add_user(self): users = root['users'] request = self.layer.new_request() request.params['factory'] = 'user' with self.layer.authenticated('viewer'): self.expectError( HTTPForbidden, render_tile, users, request, 'add' ) with self.layer.authenticated('manager'): res = render_tile(users, request, 'add') expected = '<form action="http://example.com/users/add"' self.assertTrue(res.find(expected) > -1) request.params['userform.id'] = '' request.params['userform.cn'] = 'cn99' request.params['userform.sn'] = 'sn99' request.params['userform.mail'] = '*****@*****.**' request.params['userform.userPassword'] = '******' request.params['userform.principal_roles'] = [] request.params['action.userform.save'] = '1' with self.layer.authenticated('manager'): res = render_tile(users, request, 'add') expected = '<div class="text-danger">No Id defined</div>' self.assertTrue(res.find(expected) > -1) request.params['userform.id'] = 'uid99' with self.layer.authenticated('manager'): res = render_tile(users, request, 'add') self.assertEqual(res, '') self.assertTrue(isinstance(request.environ['redirect'], HTTPFound)) self.assertEqual(sorted(users.keys()), [ 'admin', 'editor', 'localmanager_1', 'localmanager_2', 'manager', 'max', 'sepp', 'uid0', 'uid1', 'uid2', 'uid3', 'uid4', 'uid5', 'uid6', 'uid7', 'uid8', 'uid9', 'uid99', 'viewer' ]) user = users['uid99'] self.assertTrue(isinstance(user, User)) self.assertEqual(user.attrs['cn'], 'cn99') self.assertEqual(user.attrs['mail'], '*****@*****.**') self.assertEqual(user.attrs['rdn'], 'uid99') self.assertEqual(user.attrs['login'], 'uid99') self.assertEqual(user.attrs['sn'], 'sn99') self.assertTrue(user.attrs['userPassword'].startswith('{SSHA}'))
def render(self): default_child = self.model.properties.default_child if default_child: model = self.model[default_child] return render_tile(model, self.request, 'content') default_content_tile = self.model.properties.default_content_tile if default_content_tile: return render_tile(self.model, self.request, default_content_tile) return render_template( 'cone.app.browser:templates/default_root.pt', model=self.model, request=self.request, context=self)
def test_pathbar(self): root = BaseNode() root['1'] = BaseNode() request = self.layer.new_request() # Unauthorized res = render_tile(root, request, 'pathbar') self.assertFalse(res.find('pathbaritem') != -1) # Authorized with self.layer.authenticated('max'): res = render_tile(root['1'], request, 'pathbar') self.assertTrue(res.find('id="pathbar"') != -1) # Default child behavior of pathbar root = BaseNode() root['1'] = BaseNode() root['2'] = BaseNode() with self.layer.authenticated('max'): res = render_tile(root, request, 'pathbar') self.assertTrue(res.find('<strong>Home</strong>') > -1) with self.layer.authenticated('max'): res = render_tile(root['1'], request, 'pathbar') self.assertTrue(res.find('>Home</a>') > -1) self.assertTrue(res.find('<strong>1</strong>') > -1) with self.layer.authenticated('max'): res = render_tile(root['2'], request, 'pathbar') self.assertTrue(res.find('>Home</a>') > -1) self.assertTrue(res.find('<strong>2</strong>') > -1) root.properties.default_child = '1' with self.layer.authenticated('max'): res = render_tile(root['1'], request, 'pathbar') self.assertTrue(res.find('<strong>Home</strong>') > -1) self.assertFalse(res.find('<strong>1</strong>') > -1) with self.layer.authenticated('max'): res = render_tile(root['2'], request, 'pathbar') self.assertTrue(res.find('>Home</a>') > -1) self.assertTrue(res.find('<strong>2</strong>') > -1) root['1'].properties.default_child = '12' root['1']['11'] = BaseNode() root['1']['12'] = BaseNode() with self.layer.authenticated('max'): res = render_tile(root['1']['11'], request, 'pathbar') self.assertTrue(res.find('<strong>11</strong>') > -1) with self.layer.authenticated('max'): res = render_tile(root['1']['12'], request, 'pathbar') self.assertTrue(res.find('<strong>Home</strong>') > -1)
def test_portrait(self, users, groups): user = users['uid99'] # Portrait related config properties cfg = ugm_general(users) self.assertEqual(cfg.attrs.users_portrait, 'True') self.assertEqual(cfg.attrs.users_portrait_attr, 'jpegPhoto') self.assertEqual(cfg.attrs.users_portrait_accept, 'image/jpeg') self.assertEqual(cfg.attrs.users_portrait_width, '50') self.assertEqual(cfg.attrs.users_portrait_height, '50') # Portrait enabled, widget is rendered request = self.layer.new_request() with self.layer.authenticated('manager'): res = render_tile(user, request, 'editform') self.assertTrue(res.find('id="input-userform-portrait"') > -1) # No portrait, default portrait is shown expected = 'src="http://example.com/cone.ugm.static/images/default_portrait.jpg?nocache=' self.assertTrue(res.find(expected) > -1) # Submit portrait dummy_jpg = dummy_file_data('dummy.jpg') portrait = { 'file': BytesIO(dummy_jpg), 'mimetype': 'image/jpeg', } request = user_portrait_request(self.layer, user, portrait) with self.layer.authenticated('manager'): res = render_tile(user, request, 'editform') # New portrait set on user self.assertTrue(user.attrs['jpegPhoto'].startswith(b'\xff\xd8\xff\xe0\x00\x10JFIF')) # Portrait present, link to user portrait is shown request = self.layer.new_request() with self.layer.authenticated('manager'): res = render_tile(user, request, 'editform') expected = 'src="http://example.com/users/uid99/portrait_image?nocache=' self.assertTrue(res.find(expected) > -1) # Portrait disabled, widget is skipped cfg.attrs.users_portrait = u'False' cfg() request = self.layer.new_request() with self.layer.authenticated('manager'): res = render_tile(user, request, 'editform') self.assertFalse(res.find('id="input-userform-portrait"') > -1)
def test_settings_content_tile(self): root = get_root() settings = root['settings'] settings.factories.clear() register_plugin_config('foo', SomeSettings) register_plugin_config('bar', SomeSettings) register_plugin_config('baz', OtherSettings) request = self.layer.new_request() # Login and render 'content' tile on ``Settings`` node with self.layer.authenticated('manager'): res = render_tile(settings, request, 'content') self.assertTrue(res.find('foo</a>') > -1) self.assertTrue(res.find('bar</a>') > -1) self.assertTrue(res.find('baz</a>') > -1) # 'content' tile for ``SomeSettings`` with self.layer.hook_tile_reg(): @tile(name='content', interface=SomeSettings) class SomeSettingsTile(Tile): def render(self): return '<div>Settings Contents</div>' with self.layer.authenticated('manager'): res = render_tile(settings['foo'], request, 'content') self.assertEqual(res, '<div>Settings Contents</div>') # 'content' tile for ``OtherSettings`` which raises an exception at # render time with self.layer.hook_tile_reg(): @tile(name='content', interface=OtherSettings) class OtherSettingsTile(Tile): def render(self): msg = 'This tile can not be rendered for some reason' raise Exception(msg) with self.layer.authenticated('manager'): err = self.expectError( Exception, render_tile, settings['baz'], request, 'content' ) self.assertEqual( str(err), 'This tile can not be rendered for some reason' )
def test_YAMLForm(self): with self.layer.hook_tile_reg(): @tile(name='yamlsubscriptionform') @plumbing(YAMLForm) class YAMLSubscriptionForm(Form): action_resource = 'yamlsubscriptionform' form_template = 'cone.app.testing:dummy_form.yaml' model = BaseNode() model.__name__ = 'dummymodel' request = self.layer.new_request() with self.layer.authenticated('max'): rendered = render_tile(model, request, 'yamlsubscriptionform') expected = ( 'action="http://example.com/dummymodel/yamlsubscriptionform"' ) self.assertTrue(rendered.find(expected) > -1) # Instead of ``form_template`` attribute, ``form_template_path`` can be # used for backward compatibility with self.layer.hook_tile_reg(): @tile(name='yamlsubscriptionform2') class YAMLSubscriptionForm2(YAMLSubscriptionForm): action_resource = 'yamlsubscriptionform2' form_template = None form_template_path = 'cone.app.testing:dummy_form.yaml' with self.layer.authenticated('max'): rendered = render_tile(model, request, 'yamlsubscriptionform2') expected = ( 'action="http://example.com/dummymodel/yamlsubscriptionform2"' ) self.assertTrue(rendered.find(expected) > -1) # form flavor add renders form action URL on parent root = BaseNode(name='root') model = root['child'] = BaseNode() YAMLSubscriptionForm.form_flavor = 'add' with self.layer.authenticated('max'): rendered = render_tile(model, request, 'yamlsubscriptionform') expected = ( 'action="http://example.com/root/yamlsubscriptionform"' ) self.assertTrue(rendered.find(expected) > -1)
def test_override_tile(self): model = Model() request = self.layer.new_request() # Override tile register_tile(name='tileone', path='testdata/tile1_override.pt') self.assertEqual( render_tile(model, request, 'tileone'), u'<span>Tile One Override</span>' ) # Reset overwritten tile self.layer.logger.clear() register_tile(name='tileone', path='testdata/tile1.pt') self.checkOutput(""" Unregister secured view for '<InterfaceClass zope.interface.Interface>' with name 'tileone' """, self.layer.logger.messages[0]) self.checkOutput(""" Unregister tile for '<InterfaceClass zope.interface.Interface>' with name 'tileone' """, self.layer.logger.messages[1]) self.layer.logger.clear()
def render_ajax_form(model, request, name): """Render ajax form. """ try: result = render_tile(model, request, name) selector = request.environ.get('cone.app.form.selector', '#content') mode = request.environ.get('cone.app.form.mode', 'inner') continuation = request.environ.get('cone.app.continuation') form_continue = AjaxFormContinue(result, continuation) rendered_form = form_continue.form rendered = ajax_form_template % { 'form': rendered_form, 'selector': selector, 'mode': mode, 'next': form_continue.next } request.response.body = safe_encode(rendered) return request.response except Exception: result = '<div>Form rendering error</div>' selector = request.environ.get('cone.app.form.selector', '#content') mode = request.environ.get('cone.app.form.mode', 'inner') tb = format_traceback() continuation = AjaxMessage(tb, 'error', None) form_continue = AjaxFormContinue(result, [continuation]) rendered = ajax_form_template % { 'form': form_continue.form.replace(u'\n', u' '), # XXX: replace? 'selector': selector, 'mode': mode, 'next': form_continue.next } return Response(rendered)
def test_content_tile(self): request = self.layer.new_request() # Unauthenticated content tile renders login form expected = '<form action="http://example.com/login"' res = render_tile(root, request, 'content') self.assertTrue(res.find(expected) > -1)
def test_authenticated(self): model = self.create_dummy_model() request = self.layer.new_request() # Rendering fails unauthorized, 'list' permission is required rule = request.has_permission('list', model) self.assertTrue(isinstance(rule, ACLDenied)) err = self.expectError(HTTPForbidden, render_tile, model, request, 'contents') self.checkOutput( """ Unauthorized: tile <cone.app.browser.contents.ContentsTile object at ...> failed permission check """, str(err)) # Render authenticated with self.layer.authenticated('manager'): request.params['sort'] = 'modified' request.params['b_page'] = '1' rendered = render_tile(model, request, 'contents') expected = ('<a href="http://example.com/?b_page=1&' 'order=desc&size=15&sort=title"') self.assertTrue(rendered.find(expected) != -1)
def render_ajax_form(model, request, name): """Render ajax form. """ try: result = render_tile(model, request, name) selector = request.environ.get("cone.app.form.selector", "#content") mode = request.environ.get("cone.app.form.mode", "inner") continuation = request.environ.get("cone.app.continuation") form_continue = AjaxFormContinue(result, continuation) rendered_form = form_continue.form rendered = ajax_form_template % { "form": rendered_form, "selector": selector, "mode": mode, "next": form_continue.next, } return Response(rendered) except Exception: result = "<div>Form rendering error</div>" selector = request.environ.get("cone.app.form.selector", "#content") mode = request.environ.get("cone.app.form.mode", "inner") tb = format_traceback() continuation = AjaxMessage(tb, "error", None) form_continue = AjaxFormContinue(result, [continuation]) rendered = ajax_form_template % { "form": form_continue.form.replace(u"\n", u" "), # XXX: replace? "selector": selector, "mode": mode, "next": form_continue.next, } return Response(rendered)
def ajax_tile(model, request): """bdajax ``ajaxaction`` implementation for cone. * Renders tile with name ``bdajax.action``. * Uses definitions from ``request.environ['cone.app.continuation']`` for continuation definitions. """ try: name = request.params["bdajax.action"] ActionContext(model, request, name) rendered = render_tile(model, request, name) continuation = request.environ.get("cone.app.continuation") if continuation: continuation = AjaxContinue(continuation).definitions else: continuation = False return { "mode": request.params.get("bdajax.mode"), "selector": request.params.get("bdajax.selector"), "payload": rendered, "continuation": continuation, } except Exception: logging.exception("Error within ajax tile") tb = format_traceback() continuation = AjaxContinue([AjaxMessage(tb, "error", None)]).definitions return {"mode": "NONE", "selector": "NONE", "payload": "", "continuation": continuation}
def test_authenticated(self): model = self.create_dummy_model() request = self.layer.new_request() # Rendering fails unauthorized, 'list' permission is required rule = request.has_permission('list', model) self.assertTrue(isinstance(rule, ACLDenied)) err = self.expectError( HTTPForbidden, render_tile, model, request, 'contents' ) self.checkOutput(""" Unauthorized: tile <cone.app.browser.contents.ContentsTile object at ...> failed permission check """, str(err)) # Render authenticated with self.layer.authenticated('manager'): request.params['sort'] = 'modified' request.params['b_page'] = '1' rendered = render_tile(model, request, 'contents') expected = ( '<a href="http://example.com/?b_page=1&' 'order=desc&size=15&sort=title"' ) self.assertTrue(rendered.find(expected) != -1)
def test_allcolumnlisting_tile(self): groups = root['groups'] group = groups['group5'] request = self.layer.new_request() self.expectError( HTTPForbidden, render_tile, group, request, 'allcolumnlisting' ) with self.layer.authenticated('manager'): res = render_tile(group, request, 'allcolumnlisting') expected = ( '<li class="list-group-item "\n ' 'ajax:target="http://example.com/users/uid1">' ) self.assertTrue(res.find(expected) > -1) expected = ( '<li class="list-group-item "\n ' 'ajax:target="http://example.com/users/uid6">' ) self.assertTrue(res.find(expected) > -1)
def test_content_view_tile(self): class Model(BaseNode): pass with self.layer.hook_tile_reg(): @content_view_tile( name='model_tile', interface=Model, permission='view') class ModelContentTile(Tile): def render(self): return '<div>Model Content</div>' model = Model() request = self.layer.new_request() with self.layer.authenticated('manager'): res = render_tile(model, request, 'model_tile') self.assertEqual(res, '<div>Model Content</div>') from cone.app.tests.test_browser_content import model_tile_content_view self.assertEqual(model_tile_content_view.__doc__, ( 'Dynamically created by ' 'cone.app.browser.content.content_view_tile' )) with self.layer.authenticated('manager'): res = model_tile_content_view(model, request) self.assertTrue(res.body.startswith(b'<!DOCTYPE html>') > -1) self.assertTrue(res.body.find(b'<div>Model Content</div>') > -1)
def test_inherited_principal_roles(self): root = SharingNode(name='root') root.principal_roles['viewer'] = ['editor'] child = root['child'] = SharingNode() child.role_inheritance = True child.principal_roles['viewer'] = ['admin'] request = self.layer.new_request() with self.layer.authenticated('manager'): res = render_tile(child, request, 'sharing') expected = ( '<input checked="checked" ' 'class="add_remove_role_for_principal" disabled="disabled" ' 'id="input-viewer" name="viewer" type="checkbox" value="editor" />' ) self.assertTrue(res.find(expected) > -1) expected = ( '<input checked="checked" ' 'class="add_remove_role_for_principal" id="input-viewer" ' 'name="viewer" type="checkbox" value="admin" />' ) self.assertTrue(res.find(expected) > -1) expected = ( '<input class="add_remove_role_for_principal" ' 'id="input-viewer" name="viewer" type="checkbox" ' 'value="manager" />' ) self.assertTrue(res.find(expected) > -1)
def test_inexistent_tile(self): model = Model() request = self.layer.new_request() self.layer.logger.clear() # By default, render error message if tile ComponentLookupError self.checkOutput(""" Tile with name 'inexistent' not found:<br /><pre>((<cone.tile.tests.Model ... at ...>, <pyramid.testing.DummyRequest object at ...>), <InterfaceClass cone.tile._api.ITile>, ...inexistent...)</pre> """, render_tile(model, request, 'inexistent')) self.checkOutput(""" Error in rendering_tile: ((<cone.tile.tests.Model ... at ...>, <pyramid.testing.DummyRequest object at ...>), <InterfaceClass cone.tile._api.ITile>, 'inexistent') """, self.layer.logger.messages[0]) self.layer.logger.clear() # To change the above behavior, the ``catch_errors`` argument can be # changed to ``False``, thus preventing error swallowing self.expectError( ComponentLookupError, render_tile, model, request, 'inexistent', catch_errors=False )
def test_referencebrowser(self): model = BaseNode() model['a'] = RefNode() request = self.layer.new_request() request.params['referencable'] = 'ref_node' request.params['selected'] = '' request.params['root'] = '/' # Case unauthorized err = self.expectError(HTTPForbidden, render_tile, model, request, 'referencebrowser') self.checkOutput( """ Unauthorized: tile <cone.app.browser.referencebrowser.ReferenceBrowser object at ...> failed permission check """, str(err)) # Case authorized with self.layer.authenticated('max'): res = render_tile(model, request, 'referencebrowser') self.assertTrue(res.find('<div class="referencebrowser">') > -1) self.assertTrue(res.find('<div id="referencebrowser_pathbar"') > -1) self.assertTrue(res.find('<div id="referencebrowser"') > -1)
def test_forbidden(self): # Forbidden tile root = get_root() model = root['model'] = BaseNode() request = self.layer.new_request() self.checkOutput(""" \n\n <div>\n <h1>Unauthorized</h1>\n <p>You are not allowed to access this resource.</p>\n </div>\n\n\n """, render_tile(model, request, 'unauthorized')) del root['model'] # Forbidden view root = get_root() model = root['model'] = BaseNode() request = self.layer.new_request() request.context = model res = forbidden_view(request).text self.assertTrue(res.find('id="input-loginform-login"') > -1) with self.layer.authenticated('admin'): request = self.layer.new_request() request.context = model res = forbidden_view(request).text self.assertTrue(res.find('<h1>Unauthorized</h1>') > -1) del root['model']
def ajax_tile(model, request): """bdajax ``ajaxaction`` implementation for cone. * Renders tile with name ``bdajax.action``. * Uses definitions from ``request.environ['cone.app.continuation']`` for continuation definitions. """ try: name = request.params.get('bdajax.action') rendered = render_tile(model, request, name) continuation = request.environ.get('cone.app.continuation') if continuation: continuation = AjaxContinue(continuation).definitions else: continuation = False return { 'mode': request.params.get('bdajax.mode'), 'selector': request.params.get('bdajax.selector'), 'payload': rendered, 'continuation': continuation, } except Exception: logging.exception('Error within ajax tile') tb = format_traceback() continuation = AjaxContinue( [AjaxMessage(tb, 'error', None)]).definitions return { 'mode': 'NONE', 'selector': 'NONE', 'payload': '', 'continuation': continuation, }
def test_not_found(self): # Not Found tile root = get_root() model = root['model'] = BaseNode() request = self.layer.new_request() self.checkOutput(""" \n\n <div>\n <h1>Not Found</h1>\n <p>The requested resource cannot be found.</p>\n </div>\n\n\n """, render_tile(model, request, 'not_found')) del root['model'] # Not Found view root = get_root() model = root['model'] = BaseNode() request = self.layer.new_request() request.context = model res = not_found_view(request).text self.assertTrue(res.find('<h1>Not Found</h1>') > -1) with self.layer.authenticated('admin'): request = self.layer.new_request() request.context = model res = not_found_view(request).text self.assertTrue(res.find('<h1>Not Found</h1>') > -1) del root['model']
def test_bc_batch_tile(self): # Test B/C batch vocab rendering:: with self.layer.hook_tile_reg(): @tile('bc_testbatch') class BCTestBatch(Batch): @property def vocab(self): ret = list() path = node_path(self.model) current = self.request.params.get('b_page', '0') for i in range(10): query = make_query(b_page=str(i)) url = make_url(self.request, path=path, query=query) ret.append({ 'page': '%i' % i, 'current': current == str(i), 'visible': True, 'url': url }) return ret with self.layer.authenticated('max'): model = BaseNode() request = self.layer.new_request() res = render_tile(model, request, 'bc_testbatch') expected = 'href="http://example.com/?b_page=1"' self.assertTrue(res.find(expected) > -1) expected = 'ajax:target="http://example.com/?b_page=1"' self.assertTrue(res.find(expected) > -1) expected = 'href="http://example.com/?b_page=2"' self.assertTrue(res.find(expected) > -1) expected = 'ajax:target="http://example.com/?b_page=2"' self.assertTrue(res.find(expected) > -1)
def test_inherited_principal_roles(self): root = SharingNode(name='root') root.principal_roles['viewer'] = ['editor'] child = root['child'] = SharingNode() child.role_inheritance = True child.principal_roles['viewer'] = ['admin'] request = self.layer.new_request() with self.layer.authenticated('manager'): res = render_tile(child, request, 'sharing') expected = ( '<input checked="checked" ' 'class="add_remove_role_for_principal" disabled="disabled" ' 'id="input-viewer" name="viewer" type="checkbox" value="editor" />' ) self.assertTrue(res.find(expected) > -1) expected = ('<input checked="checked" ' 'class="add_remove_role_for_principal" id="input-viewer" ' 'name="viewer" type="checkbox" value="admin" />') self.assertTrue(res.find(expected) > -1) expected = ('<input class="add_remove_role_for_principal" ' 'id="input-viewer" name="viewer" type="checkbox" ' 'value="manager" />') self.assertTrue(res.find(expected) > -1)
def test_add_user(self): root = get_root() users = root['users'] request = self.layer.new_request() request.params['factory'] = 'user' events_called = [] @classhandler.handler(UserCreatedEvent) def on_user_created(event): events_called.append('UserCreatedEvent') with self.layer.authenticated('viewer'): self.expectError(HTTPForbidden, render_tile, users, request, 'add') with self.layer.authenticated('manager'): res = render_tile(users, request, 'add') expected = '<form action="http://example.com/users/add"' self.assertTrue(res.find(expected) > -1) request.params['userform.id'] = '' request.params['userform.password'] = '******' request.params['userform.fullname'] = 'Max Mustermann' request.params['userform.email'] = '*****@*****.**' request.params['userform.principal_roles'] = [] request.params['action.userform.save'] = '1' with self.layer.authenticated('manager'): res = render_tile(users, request, 'add') expected = '<div class="text-danger">No User ID defined</div>' self.assertTrue(res.find(expected) > -1) request.params['userform.id'] = 'user_1' with self.layer.authenticated('manager'): res = render_tile(users, request, 'add') self.assertEqual(res, '') self.assertTrue(isinstance(request.environ['redirect'], HTTPFound)) self.assertEqual(sorted(users.keys()), ['manager', 'user_1']) user = users['user_1'] self.assertTrue(isinstance(user, User)) self.assertTrue(bool(user.attrs['password'])) self.assertEqual(user.attrs['fullname'], 'Max Mustermann') self.assertEqual(user.attrs['email'], '*****@*****.**') self.assertTrue('UserCreatedEvent' in events_called)
def test_content_tile(self): users = root['users'] request = self.layer.new_request() # Unauthenticated content tile renders login form expected = '<form action="http://example.com/users/login"' res = render_tile(users, request, 'content') self.assertTrue(res.find(expected) > -1)
def test_edit_group(self, users, groups): group = groups['group99'] request = self.layer.new_request() with self.layer.authenticated('manager'): res = render_tile(group, request, 'edit') expected = '<form action="http://example.com/groups/group99/edit"' self.assertTrue(res.find(expected) > -1)
def test_deleting(self): class CallableNode(BaseNode): def __call__(self): pass node = CallableNode() node['child'] = CallableNode() self.checkOutput(""" <class '...CallableNode'>: None <class '...CallableNode'>: child """, node.treerepr()) del node['child'] self.checkOutput(""" <class '...CallableNode'>: None """, node.treerepr()) node['child'] = CallableNode() with self.layer.authenticated('manager'): request = self.layer.new_request() self.assertEqual(render_tile(node['child'], request, 'delete'), u'') self.assertEqual( request.environ['cone.app.continuation'][0].payload, u'Object "child" not deletable' ) node['child'].properties.action_delete = True with self.layer.authenticated('manager'): request = self.layer.new_request() self.assertEqual(render_tile(node['child'], request, 'delete'), u'') self.assertTrue(isinstance( request.environ['cone.app.continuation'][0], AjaxEvent )) self.assertTrue(isinstance( request.environ['cone.app.continuation'][1], AjaxMessage )) self.checkOutput(""" <class '...CallableNode'>: None """, node.treerepr())
def render(self): nodeinfo = self.info if not nodeinfo: return _('unknown_factory', default='Unknown factory') factory = nodeinfo.factory if not factory: factory = default_addmodel_factory addmodel = factory(self.model, nodeinfo) return render_tile(addmodel, self.request, self.form_tile_name)
def settings_tab_content(model, request): """Used by jquerytools tabs plugin to get settings section content. """ try: rendered = render_tile(model, request, 'content') except Exception, e: localizer = get_localizer(request) error = localizer.translate(_('error', default='Error')) rendered = '<div>%s: %s</div>' % (error, format_traceback())
def test_content_tile(self): root = get_root() groups = root['groups'] group = groups['group_1'] request = self.layer.new_request() # Unauthenticated content tile renders login form expected = '<form action="http://example.com/groups/group_1/login"' res = render_tile(group, request, 'content') self.assertTrue(res.find(expected) > -1)
def test_rightcolumn_tile(self): request = self.layer.new_request() self.expectError(HTTPForbidden, render_tile, root, request, 'rightcolumn') with self.layer.authenticated('editor'): res = render_tile(root, request, 'rightcolumn') expected = '<div class="column right_column col-md-6">' self.assertTrue(res.find(expected) > -1)
def test_add_group(self): root = get_root() groups = root['groups'] request = self.layer.new_request() request.params['factory'] = 'group' events_called = [] @classhandler.handler(GroupCreatedEvent) def on_group_created(event): events_called.append('GroupCreatedEvent') with self.layer.authenticated('viewer'): self.expectError(HTTPForbidden, render_tile, groups, request, 'add') with self.layer.authenticated('manager'): res = render_tile(groups, request, 'add') expected = '<form action="http://example.com/groups/add"' self.assertTrue(res.find(expected) > -1) request.params['groupform.id'] = '' request.params['groupform.groupname'] = 'Group 1' request.params['groupform.principal_roles'] = [] request.params['action.groupform.save'] = '1' with self.layer.authenticated('manager'): res = render_tile(groups, request, 'add') expected = '<div class="text-danger">No Group ID defined</div>' self.assertTrue(res.find(expected) > -1) request.params['groupform.id'] = 'group_1' with self.layer.authenticated('manager'): res = render_tile(groups, request, 'add') self.assertEqual(res, '') self.assertTrue(isinstance(request.environ['redirect'], HTTPFound)) self.assertEqual(sorted(groups.keys()), ['group_1']) group = groups['group_1'] self.assertTrue(isinstance(group, Group)) self.assertEqual(group.attrs['groupname'], 'Group 1') self.assertTrue('GroupCreatedEvent' in events_called)