UNPKG

openrosa-xpath-evaluator

Version:

Wrapper for browsers' XPath evaluator with added support for OpenRosa extensions.

272 lines (239 loc) 9.18 kB
const { initDoc, filterAttributes, snapshotToArray, assertNodes, assertUnorderedNodes, } = require('../helpers'); describe('Union operator', () => { let doc; beforeEach(() => { doc = initDoc(` <div id="UnionOperatorTestCase"> <div id="eee10"> <div id="eee20"> <div> <div id="eee25"></div> </div> </div> <div id="eee30"> <div id="eee35"></div> <div id="eee40" class="sss"></div> </div> </div> <div id="eee50"></div> <div id="nss10"> <div id="nss20"> <div id="nss25" xmlns:asdf="http://asdf.com/" align="right"></div> <div xmlns:asdf="http://asdf.com/" id="nss30"></div> </div> <div id="nss40" xmlns:asdf="sss" xmlns:asdf2="sdfsdf"></div> </div> </div>`); }); it('combines two elements', () => { assertNodes("id('eee10') | id('eee20')", doc, [ doc.getElementById('eee10'), doc.getElementById('eee20'), ]); }); describe('without spaces around the operator', () => { it('should work with a simple nodeset before the operator', () => { assertNodes("/div/div/div/div/div|id('eee20')", doc, [ // these are in document order, not the order they are listed in the expression // TODO check if this is to spec doc.getElementById('eee20'), doc.getElementById('eee25'), ]); }); it('should work with a predicated nodeset before the operator 0', () => { assertNodes("/*[1]/*[1]|id('eee20')", doc, [ doc.getElementById('eee10'), doc.getElementById('eee20'), ]); }); it('should work with a predicated nodeset before the operator 1', () => { assertNodes("/div/div[1]|id('eee20')", doc, [ doc.getElementById('eee10'), doc.getElementById('eee20'), ]); }); it('should work with a predicated nodeset before the operator 2', () => { assertNodes("/div[1]/div[1]|id('eee20')", doc, [ doc.getElementById('eee10'), doc.getElementById('eee20'), ]); }); it('should work with a predicated nodeset before the operator 3', () => { assertNodes("/div[1]/div[1]|id('eee20')", doc, [ doc.getElementById('eee10'), doc.getElementById('eee20'), ]); }); it('should work with a function call before the operator', () => { assertNodes("id('eee10')|id('eee20')", doc, [ doc.getElementById('eee10'), doc.getElementById('eee20'), ]); }); }); it('combines many elements', () => { assertNodes( "id('eee40') | id('eee20') | id('eee25') | id('eee10') | id('eee30') | id('eee50')", doc, [ doc.getElementById('eee10'), doc.getElementById('eee20'), doc.getElementById('eee25'), doc.getElementById('eee30'), doc.getElementById('eee40'), doc.getElementById('eee50'), ] ); }); describe('general tests', () => { // TODO these were created while debugging UNION, but should be somewhere else it('combines elements and attributes', () => { assertNodes("id('eee40')/attribute::*[1] | id('eee30')", doc, [ doc.getElementById('eee30'), filterAttributes(doc.getElementById('eee40').attributes)[0], ]); }); it('returns indexed attributes', () => { assertNodes("id('eee40')/attribute::*[1]", doc, [ filterAttributes(doc.getElementById('eee40').attributes)[0], ]); }); it('returns all attributes', () => { assertNodes( "id('eee40')/attribute::*", doc, filterAttributes(doc.getElementById('eee40').attributes) ); }); it('returns root node', () => { assertNodes('/div', doc, [ doc.getElementById('UnionOperatorTestCase'), ]); }); it('returns doc node', () => { assertNodes('/', doc, [doc]); }); }); it('combines elements and attributes', () => { assertNodes("id('eee40')/attribute::*[1] | id('eee30')", doc, [ doc.getElementById('eee30'), filterAttributes(doc.getElementById('eee40').attributes)[0], ]); }); it('combines elements and attributes if they refer to the same element', () => { assertNodes("id('eee40')/attribute::*[1] | id('eee40')", doc, [ doc.getElementById('eee40'), filterAttributes(doc.getElementById('eee40').attributes)[0], ]); }); it('combines elements and attributs if they refer to different trees', () => { assertNodes("id('eee40')/attribute::*[1] | id('eee20')", doc, [ doc.getElementById('eee20'), filterAttributes(doc.getElementById('eee40').attributes)[0], ]); }); it('combines elements and attributes if the attribute is on a parent element in the same tree', () => { assertNodes("id('eee40') | id('eee30')/attribute::*[1]", doc, [ filterAttributes(doc.getElementById('eee30').attributes)[0], doc.getElementById('eee40'), ]); }); it('combines elements and attributes if both are (on) elements under the same parent', () => { assertNodes("id('eee40') | id('eee35')/attribute::*[1]", doc, [ filterAttributes(doc.getElementById('eee35').attributes)[0], doc.getElementById('eee40'), ]); }); it('combines attributes that live on different elements', () => { assertNodes( "id('eee35')/attribute::*[1] | id('eee40')/attribute::*[1]", doc, [ filterAttributes(doc.getElementById('eee35').attributes)[0], filterAttributes(doc.getElementById('eee40').attributes)[0], ] ); }); it('combines attributes that live on descendent elements', () => { assertNodes( "id('eee30')/attribute::*[1] | id('eee40')/attribute::*[1]", doc, [ filterAttributes(doc.getElementById('eee30').attributes)[0], filterAttributes(doc.getElementById('eee40').attributes)[0], ] ); }); it('combines attributes that live on descendent element (reversed)', () => { assertNodes( "id('eee40')/attribute::*[1] | id('eee30')/attribute::*[1]", doc, [ filterAttributes(doc.getElementById('eee30').attributes)[0], filterAttributes(doc.getElementById('eee40').attributes)[0], ] ); }); it('combines different attributes on the same element', () => { // TODO Is node order important? chrome vs firefox have different order. assertUnorderedNodes( "id('eee40')/attribute::*[2] | id('eee40')/attribute::*[1]", doc, filterAttributes(doc.getElementById('eee40').attributes) ); // firefox // expected // [class="sss", id="eee40"] // chrome // [class="sss", id="eee40"] // firefox -- returns attributes in the order they are found // [id="eee40", class="sss"] }); it('combines a namespace and attribute on the same element', () => { const result = doc.xEval( "id('nss25')/namespace::*", doc, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE ); assertNodes( "id('nss25')/namespace::* | id('nss25')/attribute::*", doc, snapshotToArray(result).concat( filterAttributes(doc.getElementById('nss25').attributes) ) ); }); it('combines two namespaces on the same element', () => { const result = doc.xEval( "id('nss40')/namespace::*", doc, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE ); assertNodes( "id('nss40')/namespace::* | id('nss40')/namespace::*", doc, snapshotToArray(result) ); }); it('combines a namespace and attribute', () => { const result = doc.xEval( "id('nss40')/namespace::*", doc, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE ); // chrome vs firefox have different order. assertUnorderedNodes( "id('nss40')/namespace::* | id('nss25')/attribute::* | id('nss25')", doc, [doc.getElementById('nss25')] .concat( filterAttributes(doc.getElementById('nss25').attributes) ) .concat(snapshotToArray(result)) ); }); });