def test_ActionAdd(self): info = NodeInfo() info.title = 'Addable' info.addables = ['addable'] register_node_info('addable', info) action = ActionAdd() addmodel = BaseNode() request = self.layer.new_request() ActionContext(addmodel, request, 'listing') self.assertEqual(action(addmodel, request), u'') with self.layer.authenticated('viewer'): rule = request.has_permission('add', addmodel) self.assertTrue(isinstance(rule, ACLDenied)) self.assertEqual(action(addmodel, request), u'') with self.layer.authenticated('editor'): rule = request.has_permission('add', addmodel) self.assertTrue(isinstance(rule, ACLAllowed)) self.assertEqual(action(addmodel, request), u'') addmodel.node_info_name = 'addable' self.assertTrue(addmodel.nodeinfo is info) rendered = action(addmodel, request) self.checkOutput( """ ...<li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> <span>Add</span> <span class="caret"></span> </a> <ul class="dropdown-menu" role="addmenu"> <li> <a href="http://example.com/add?factory=addable" ajax:bind="click" ajax:target="http://example.com/?factory=addable" ajax:action="add:#content:inner" ajax:path="href"> <span class="glyphicon glyphicon-asterisk"></span> Addable </a> </li> </ul> </li>... """, rendered)
def test_NodeInfo(self): # The ``INodeInfo`` providing object holds information about the # application node nodeinfo = NodeInfo() nodeinfo.node = BaseNode nodeinfo.addables = ['basenode'] nodeinfo.title = 'Base Node' nodeinfo.description = 'Base Node Description' nodeinfo.factory = None nodeinfo.icon = 'base-node-icon' # check interface self.assertTrue(INodeInfo.providedBy(nodeinfo)) # check superclass self.assertTrue(isinstance(nodeinfo, Properties)) # Register node info register_node_info('basenode', nodeinfo) # Lookup Node info nodeinfo = get_node_info('basenode') self.assertTrue(nodeinfo.node is BaseNode) self.assertEqual(nodeinfo.addables, ['basenode']) self.assertEqual(nodeinfo.title, 'Base Node') self.assertEqual(nodeinfo.description, 'Base Node Description') self.assertEqual(nodeinfo.factory, None) self.assertEqual(nodeinfo.icon, 'base-node-icon') # ``__getattr__``. No AttributeError is raised if attribute missing self.assertTrue(nodeinfo.inexistent is None) # ``__getitem__`` self.assertEqual(nodeinfo['addables'], ['basenode']) # ``__contains__`` self.assertTrue('node' in nodeinfo) # ``get`` self.assertTrue(nodeinfo.get('node') is BaseNode)
def test_add_items_dropdown(self): @node_info( name='mynode', addables=['mynode']) class MyNode(BaseNode): pass # Dummy model root = MyNode() root['somechild'] = MyNode() # child.attrs.title = 'My Node' # Dropdown menu containing links to the addforms of allowed child nodes with self.layer.authenticated('manager'): request = self.layer.new_request() rendered = render_tile(root['somechild'], request, 'add_dropdown') # Non JS link to add form expected = 'href="http://example.com/somechild/add?factory=mynode"' self.assertTrue(rendered.find(expected) != -1) # Ajax target for add form expected = 'ajax:target="http://example.com/somechild?factory=mynode"' self.assertTrue(rendered.find(expected) != -1) # Ajax action rule for add form expected = 'ajax:action="add:#content:inner"' self.assertTrue(rendered.find(expected) != -1) # Allow another node type as child nodeinfo = NodeInfo() register_node_info('anothernode', nodeinfo) get_node_info('mynode').addables = ['mynode', 'anothernode'] with self.layer.authenticated('manager'): request = self.layer.new_request() rendered = render_tile(root['somechild'], request, 'add_dropdown') # Non JS links to add form expected = 'href="http://example.com/somechild/add?factory=mynode"' self.assertTrue(rendered.find(expected) != -1) expected = 'href="http://example.com/somechild/add?factory=anothernode"' self.assertTrue(rendered.find(expected) != -1) # Ajax targets for add form expected = 'ajax:target="http://example.com/somechild?factory=mynode"' self.assertTrue(rendered.find(expected) != -1) expected = 'ajax:target="http://example.com/somechild?factory=anothernode"' self.assertTrue(rendered.find(expected) != -1) # Test node without addables, results in empty listing. # XXX: hide entire widget if no items @node_info(name='nochildaddingnode') class NoChildAddingNode(BaseNode): pass with self.layer.authenticated('manager'): request = self.layer.new_request() rendered = render_tile(NoChildAddingNode(), request, 'add_dropdown') self.checkOutput(""" ...<li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> <span>Add</span> <span class="caret"></span> </a> <ul class="dropdown-menu" role="addmenu"> </ul> </li>... """, rendered) # Test node with invalid addable, results in empty listing # XXX: hide entire widget if no items @node_info( name='invalidchildnodeinfo', addables=['invalid']) class InvalidChildNodeInfoNode(BaseNode): pass with self.layer.authenticated('manager'): request = self.layer.new_request() rendered = render_tile( InvalidChildNodeInfoNode(), request, 'add_dropdown' ) self.checkOutput(""" ...<li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> <span>Add</span> <span class="caret"></span> </a> <ul class="dropdown-menu" role="addmenu"> </ul> </li>... """, rendered)
@property def properties(self): props = Properties() props.in_navtree = True props.action_list = True props.action_add = True return props @property def metadata(self): md = BaseMetadata() md.title = 'c3s App' return md info = NodeInfo() info.title = 'C3SApp' info.description = 'This is a c3s app' info.addables = ['band'] #info.icon = 'url/to/icon' info.node = C3SApp registerNodeInfo('c3sapp', info) class Band(BaseNode): __metaclass__ = plumber __plumbing__ = UUIDAttributeAware node_info_name = 'band' @property