diff --git a/openerp/addons/base/ir/ir_ui_view.py b/openerp/addons/base/ir/ir_ui_view.py index 219cc991d2a..dd5da97729d 100644 --- a/openerp/addons/base/ir/ir_ui_view.py +++ b/openerp/addons/base/ir/ir_ui_view.py @@ -86,6 +86,16 @@ class view_custom(osv.osv): if not cr.fetchone(): cr.execute('CREATE INDEX ir_ui_view_custom_user_id_ref_id ON ir_ui_view_custom (user_id, ref_id)') +def _hasclass(context, *cls): + """ Checks if the context node has all the classes passed as arguments + """ + node_classes = set(context.context_node.attrib.get('class', '').split()) + + return node_classes.issuperset(cls) + +xpath_utils = etree.FunctionNamespace(None) +xpath_utils['hasclass'] = _hasclass + class view(osv.osv): _name = 'ir.ui.view' diff --git a/openerp/addons/base/tests/test_views.py b/openerp/addons/base/tests/test_views.py index f0967836726..feb22eb2be9 100644 --- a/openerp/addons/base/tests/test_views.py +++ b/openerp/addons/base/tests/test_views.py @@ -804,3 +804,26 @@ class test_views(ViewCase): E.button(name="action_next", type="object", string="New button")), string="Replacement title", version="7.0" )) + +class TestXPathExtentions(common.BaseCase): + def test_hasclass(self): + tree = E.node( + E.node({'class': 'foo bar baz'}), + E.node({'class': 'foo bar'}), + {'class': "foo"}) + + self.assertEqual( + len(tree.xpath('//node[hasclass("foo")]')), + 3) + self.assertEqual( + len(tree.xpath('//node[hasclass("bar")]')), + 2) + self.assertEqual( + len(tree.xpath('//node[hasclass("baz")]')), + 1) + self.assertEqual( + len(tree.xpath('//node[hasclass("foo")][not(hasclass("bar"))]')), + 1) + self.assertEqual( + len(tree.xpath('//node[hasclass("foo", "baz")]')), + 1)