openrosa-xpath-evaluator
Advanced tools
Comparing version 2.0.0-beta.7 to 2.0.0-beta.8
{ | ||
"name": "openrosa-xpath-evaluator", | ||
"version": "2.0.0-beta.7", | ||
"version": "2.0.0-beta.8", | ||
"description": "Wrapper for browsers' XPath evaluator with added support for OpenRosa extensions.", | ||
@@ -5,0 +5,0 @@ "main": "src/XPathJS.js", |
@@ -56,7 +56,2 @@ var config = require('./config'); | ||
// returns promise | ||
if(r.v && typeof r.v.then === 'function' && rt === XPathResult.STRING_TYPE) { | ||
return {resultType: XPathResult.STRING_TYPE, stringValue: r.v}; | ||
} | ||
if((r.t === 'arr' && rt === XPathResult.NUMBER_TYPE && DATE_STRING.test(r.v[0])) || | ||
@@ -158,3 +153,6 @@ (r.t === 'str' && rt === XPathResult.NUMBER_TYPE && DATE_STRING.test(r.v))) { | ||
if(isNativeFunction(input) && input.indexOf('[selected(') < 0) { | ||
if(isNativeFunction(input) && | ||
input.indexOf('[selected(') < 0 && | ||
!(input.startsWith('/') && input.indexOf(' ')>0) && | ||
input !== '/') { | ||
var args = inputArgs(input); | ||
@@ -191,3 +189,3 @@ if(args.length && args[0].length && !isNaN(args[0])) { throw INVALID_ARGS; } | ||
if(rT === XPathResult.STRING_TYPE && res.resultType === XPathResult.NUMBER_TYPE) { | ||
return { resultType: rT, stringValue: res.numberValue.toString() }; | ||
return { resultType: rT, numberValue: res.numberValue, stringValue: res.numberValue.toString() }; | ||
} | ||
@@ -235,3 +233,3 @@ if(rT === XPathResult.STRING_TYPE && res.resultType >= 4) { | ||
var wrappedResult = wrapped(input, cN); | ||
var wrappedResult = wrapped(input, cN, nR, rT); | ||
// Native count always returns Number even when result type is asking | ||
@@ -255,3 +253,3 @@ // for a string. | ||
input = input.replace(/'(\d)'/g, '$1'); | ||
input = "boolean-from-string("+input+")"; | ||
input = `boolean-from-string(${input})`; | ||
} | ||
@@ -315,3 +313,3 @@ | ||
stack.length === 1 && !/^[a-z]*[(|[]{1}/.test(cur.v))) { | ||
evaluated = toNodes(wrapped(expr, cN, returnType)); | ||
evaluated = toNodes(wrapped(expr, cN, nR, returnType)); | ||
} else { | ||
@@ -321,3 +319,3 @@ if(expr.startsWith('$')) { | ||
} else { | ||
evaluated = toInternalResult(wrapped(expr, cN, returnType)); | ||
evaluated = toInternalResult(wrapped(expr, cN, nR, returnType)); | ||
} | ||
@@ -324,0 +322,0 @@ } |
@@ -62,5 +62,7 @@ require('./date-extensions'); | ||
if(config.includeLocalTimeForDatesWithoutTime) { | ||
it += 'T00:00:00.000' + (new Date(it)).getTimezoneOffsetAsTime(); | ||
var time = `${_zeroPad(temp[0])}-${_zeroPad(temp[1])}-${_zeroPad(temp[2])}`+ | ||
'T00:00:00.000' + (new Date(it)).getTimezoneOffsetAsTime(); | ||
return new Date(time); | ||
} | ||
return new Date(it); | ||
return new Date(temp[0], temp[1]-1, temp[2]); | ||
} | ||
@@ -184,3 +186,3 @@ } | ||
'boolean-from-string': function(r) { | ||
if(r.t === 'num' && r.v > 0) { | ||
if(r.t === 'num' && r.v > 0 && !r.decimal) { | ||
return XPR.boolean(true); | ||
@@ -406,3 +408,3 @@ } | ||
pow: function(x, y) { return XPR.number(Math.pow(_float(x), _float(y))); }, | ||
random: function() { return XPR.number(Math.random().toFixed(15)); }, | ||
random: function() { return XPR.number(parseFloat(Math.random().toFixed(15))); }, | ||
randomize: function(r) { | ||
@@ -488,8 +490,8 @@ if(arguments.length === 1) throw TOO_FEW_ARGS;//only rT passed | ||
// value or weight might be a nodeset | ||
values = v.t === 'arr' ? v.v : [v.v]; | ||
weights = w.t === 'arr' ? w.v : [w.v]; | ||
values = values.concat(v.t === 'arr' ? v.v : [v.v]); | ||
weights = weights.concat( w.t === 'arr' ? w.v : [w.v]); | ||
} | ||
} | ||
for(i=0; i < values.length; i++) { | ||
if(values[i].length) { | ||
if(values[i]) { | ||
var weight = weights[i]; | ||
@@ -496,0 +498,0 @@ weightedTrues += isNaN(weight) ? 0 : parseFloat(weight); |
@@ -42,4 +42,4 @@ var DATE_STRING = /^\d\d\d\d-\d{1,2}-\d{1,2}(?:T\d\d:\d\d:\d\d\.?\d?\d?(?:Z|[+-]\d\d:\d\d)|.*)?$/; | ||
var isValidDate = function (y, m, d) { | ||
m = parseInt(m, 10) - 1; | ||
return m >= 0 && m < 12 && d > 0 && d <= daysInMonth(m, y); | ||
m = parseInt(m, 10) - 1; | ||
return m >= 0 && m < 12 && d > 0 && d <= daysInMonth(m, y); | ||
}; | ||
@@ -46,0 +46,0 @@ |
@@ -7,4 +7,4 @@ var {DATE_STRING, dateToDays} = require('./date'); | ||
var NATIVE_FUNS = /^id\(|^\([a-zA-Z]|lang\(|local-name|namespace-uri|last\(|name\(|child::|parent::|descendant::|descendant-or-self::|ancestor::|ancestor-or-self::sibling|following::|following-sibling::|preceding-sibling::|preceding::|attribute::|^\/.*$/; | ||
var NATIVE_FUNS = /^id\(|^\([1-9]|^\([a-zA-Z]|lang\(|local-name|namespace-uri|last\(|name\(|child::|parent::|descendant::|descendant-or-self::|ancestor::|ancestor-or-self::sibling|following::|following-sibling::|preceding-sibling::|preceding::|attribute::|^\/.*$/; | ||
function isNativeFunction(input) { | ||
@@ -11,0 +11,0 @@ return NATIVE_FUNS.test(input); |
@@ -17,3 +17,4 @@ | ||
'xhtml' : 'http://www.w3.org/1999/xhtml', | ||
'mathml': 'http://www.w3.org/1998/Math/MathML' | ||
'mathml': 'http://www.w3.org/1998/Math/MathML', | ||
'jr': 'http://openrosa.org/javarosa' | ||
}; | ||
@@ -29,5 +30,6 @@ return ns[prefix] || null; | ||
evaluator = new ExtendedXPathEvaluator( | ||
(v, xnode) => { | ||
(v, xnode, xnsr, xrt) => { | ||
if(!rt || rt<7 || v.startsWith('//')) rt = null; //TODO ??? | ||
const result = doc.evaluate.call(doc, v, xnode || node || doc, nsr, rt || XPathResult.ANY_TYPE, null); | ||
xrt = xrt || rt || XPathResult.ANY_TYPE; | ||
const result = doc.evaluate.call(doc, v, xnode || node || doc, xnsr || nsr, xrt, null); | ||
// console.log(`${v} => ${result.resultType}`); | ||
@@ -34,0 +36,0 @@ return result; |
@@ -1,2 +0,3 @@ | ||
const { initDoc, filterAttributes, assert } = require('../../helpers'); | ||
const { initDoc, nsResolver, filterAttributes, assert } = require('../../helpers'); | ||
const { toNodes } = require('../../../src/utils/result'); | ||
@@ -67,1 +68,46 @@ describe('XPath expression evaluation', () => { | ||
}); | ||
describe('XPath expression evaluation3', () => { | ||
const doc = initDoc(`<model> | ||
<instance> | ||
<nested_repeats id="nested_repeats"> | ||
<formhub><uuid/></formhub> | ||
<kids> | ||
<has_kids>1</has_kids> | ||
</kids> | ||
</nested_repeats> | ||
</instance> | ||
</model>`); | ||
it('works with expected return type', () => { | ||
let expr = `/model/instance[1]/nested_repeats/kids/has_kids='1'`; | ||
let res = doc.xEval(expr, doc, 3); | ||
assert.equal(res.resultType, 3); | ||
assert.equal(res.booleanValue, true); | ||
expr = `/model/instance[1]/nested_repeats/kids/has_kids='2'`; | ||
res = doc.xEval(expr, doc, 3); | ||
assert.equal(res.resultType, 3); | ||
assert.equal(res.booleanValue, false); | ||
}); | ||
}); | ||
describe('XPath expression evaluation4', () => { | ||
const doc = initDoc(`<thedata id="thedata"> | ||
<nodeA/> | ||
<nodeB>b</nodeB> | ||
</thedata>`); | ||
[ | ||
['/thedata/nodeA', true], | ||
['/thedata/nodeB', true], | ||
['/thedata/nodeC', false], | ||
].forEach(([expr, expected]) => { | ||
it('returns correct result type', () => { | ||
const res = doc.xEval(expr, doc, 3); | ||
assert.equal(res.resultType, 3); | ||
assert.equal(res.booleanValue, expected); | ||
}); | ||
}) | ||
}); |
@@ -1,2 +0,2 @@ | ||
const { initDoc, assert, assertNumber, assertNumberValue } = require('../../helpers'); | ||
const { initDoc, assert, assertNumber, assertNumberValue, assertBoolean } = require('../../helpers'); | ||
@@ -239,8 +239,14 @@ describe('number operators', () => { | ||
["4-3*4+5-1", -4], | ||
// ["(4-3)*4+5-1", 8], | ||
["(4-3)*4+5-1", 8], | ||
["8 div 2 + 4", 8] | ||
].forEach(t => { | ||
assertNumber(t[0], t[1]); | ||
].forEach(([expr, expected]) => { | ||
assertNumber(expr, expected); | ||
}); | ||
}); | ||
it('works with different return type', () => { | ||
assertBoolean('1 + 1', true); | ||
assertBoolean('0 + 1', true); | ||
assertBoolean('0 + 0', false); | ||
}) | ||
}); |
@@ -60,3 +60,3 @@ const { initDoc, assert, assertThrow, assertTrue, nsResolver, | ||
['42', 'AFCBDE'], | ||
// [-42, 'EDAFBC'], | ||
[-42, 'EDAFBC'], | ||
[1, 'BFEACD'], | ||
@@ -66,3 +66,3 @@ [11111111, 'ACDBFE'], | ||
['floor(1.1)', 'BFEACD'], | ||
// ['//xhtml:div[@id="testFunctionNodeset2"]/xhtml:p', 'BFEACD'] | ||
['//xhtml:div[@id="testFunctionNodeset2"]/xhtml:p', 'BFEACD'] | ||
].forEach(([seed, expected]) => { | ||
@@ -87,1 +87,54 @@ it(`with a seed: ${seed}`, () => { | ||
}); | ||
describe('randomize()', () => { | ||
const doc = initDoc(` | ||
<model> | ||
<instance> | ||
<rank id="rank"> | ||
<s1/> | ||
<r1/> | ||
<r2/> | ||
<r3>foddertree beans cacao coffee foddergrass banana</r3> | ||
<r4/> | ||
<meta> | ||
<instanceID/> | ||
</meta> | ||
</rank> | ||
</instance> | ||
<instance id="crop_list"> | ||
<root> | ||
<item> | ||
<label>Banana</label> | ||
<name>banana</name> | ||
</item> | ||
<item> | ||
<label>Beans</label> | ||
<name>beans</name> | ||
</item> | ||
<item> | ||
<label>Cacao</label> | ||
<name>cacao</name> | ||
</item> | ||
<item> | ||
<label>Coffee</label> | ||
<name>coffee</name> | ||
</item> | ||
<item> | ||
<label>Fodder Grass</label> | ||
<name>foddergrass</name> | ||
</item> | ||
<item> | ||
<label>Fodder Tree</label> | ||
<name>foddertree</name> | ||
</item> | ||
</root> | ||
</instance> | ||
</model>`); | ||
it('randomizes nodes', () => { | ||
const expr = 'randomize(/model/instance[@id="crop_list"]/root/item)'; | ||
const res = doc.xEval(expr, doc, 7); | ||
assert.equal(res.resultType, 7) | ||
assert.equal(res.snapshotLength, 6) | ||
}); | ||
}); |
@@ -45,1 +45,26 @@ const { assertTrue, assertFalse, initDoc } = require('../../helpers'); | ||
}); | ||
describe('#weighted-checklist()', () => { | ||
const doc = initDoc(` | ||
<thedata id="thedata"> | ||
<somenodes> | ||
<A>one</A> | ||
<B>one</B> | ||
<C>one</C> | ||
</somenodes> | ||
<someweights> | ||
<w1>1</w1> | ||
<w2>3</w2> | ||
<w.3>5</w.3> | ||
</someweights> | ||
</thedata>`); | ||
it('with more nodes', () => { | ||
let expr = 'weighted-checklist(9, 9, /thedata/somenodes/*, /thedata/someweights/*)'; | ||
assertTrue(doc, null, expr); | ||
expr = 'weighted-checklist(8, 8, /thedata/somenodes/*, /thedata/someweights/*)'; | ||
assertFalse(doc, null, expr); | ||
expr = 'weighted-checklist(10, 10, /thedata/somenodes/*, /thedata/someweights/*)'; | ||
assertFalse(doc, null, expr); | ||
}); | ||
}); |
346174
8353