UNPKG

openrosa-xpath-evaluator

Version:

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

386 lines (356 loc) 14.9 kB
const { initDoc, nsResolver, assertMatch, assertFalse, assertString, assertBoolean, assertStringValue, assertNumberRounded, } = require('../helpers'); describe('#date()', () => { describe('invalid dates', () => { [ // TODO "date('1983-09-31')", 'date("not a date")', 'date("opv3")', // TODO 'date("opv_3")' once https://bugzilla.mozilla.org/show_bug.cgi?id=1881930 is addressed 'date(true())', // TODO "date(convertible())" ].forEach((expr) => { it(`should convert ${expr} to false`, () => { assertFalse(expr); // do the same tests for the alias date-time() expr = expr.replace('date(', 'date-time('); assertFalse(expr); }); }); }); describe('valid date string', () => { describe('should be left alone', () => { [ ['date("1970-01-01")', '1970-01-01'], ['date("2018-01-01")', '2018-01-01'], ['"2018-01-01"', '2018-01-01'], ].forEach(([expr, expected]) => { it(`should convert ${expr} to ${expected}`, () => { assertStringValue(expr, expected); }); }); }); describe('dates as number', () => { it('example 1', () => { assertNumberRounded('"2018-01-01" + 1', 17533.29167, 100000); }); it('example 2', () => { assertNumberRounded( 'date("1970-01-01T00:00:00.000+00:00")', 0, 100000 ); }); it('example 3', () => { assertNumberRounded('date(0)', 0, 100000); }); describe('with explicit number() call', () => { it('example 1', () => { assertNumberRounded( 'number("2018-01-01" + 1)', 17533.29167, 100000 ); }); }); }); describe('dates as string', () => { it('example 1', () => { assertStringValue('"2018-01-01"', '2018-01-01'); }); it('example 2', () => { assertStringValue('date("2018-01-01")', '2018-01-01'); }); it('example 3', () => { assertStringValue('date("2018-01-01" + 1)', '2018-01-02'); }); it('example 4', () => { assertStringValue('"2021-11-30" + 1', '18962.291666666668'); // correctness of decimals tbd later }); it('example 5', () => { assertStringValue('"2021-11-30" - "2021-11-29"', '1'); }); it('example 6', () => { assertStringValue( 'date(decimal-date-time("2003-10-20T08:00:00.000-07:00"))', '2003-10-20T08:00:00.000-07:00' ); }); ['today()', 'date(today() + 10)', 'date(10 + today())'].forEach( (expr) => { it(`should convert ${expr} to a date string`, () => { assertMatch(expr, /([0-9]{4}-[0-9]{2}-[0-9]{2})$/); }); } ); describe('with explicit string() call', () => { it('example 1', () => { assertStringValue('string("2018-01-01")', '2018-01-01'); }); it('example 2', () => { assertStringValue( 'string(date("2018-01-01"))', '2018-01-01' ); }); it('example 3', () => { assertStringValue( 'string(date("2018-01-01" + 1))', '2018-01-02' ); }); [ 'string(today())', 'string(date(today() + 10))', 'string(date(10 + today()))', ].forEach((expr) => { it(`should convert ${expr} to a date string`, () => { assertMatch(expr, /([0-9]{4}-[0-9]{2}-[0-9]{2})$/); }); }); }); }); }); describe('date string with single-digit day or month values', () => { it('should insert zeroes', () => { assertStringValue('date("1970-1-2")', '1970-01-02'); }); }); describe('number', () => { [ ['date(0)', '1969-12-31T17:00:00.000-07:00'], ['date(1)', '1970-01-01T17:00:00.000-07:00'], ['date(1.5)', '1970-01-02T05:00:00.000-07:00'], ['date(-1)', '1969-12-30T17:00:00.000-07:00'], ].forEach(([expr, expected]) => { it(`${expr} should be converted to ${expected}`, () => { assertString(expr, expected); }); }); }); describe('invalid date', () => { ["'nonsense'", "number('invalid')"].forEach((expr) => { it(`should not parse ${expr}, but instead should return "Invalid Date"`, () => { assertString(`date(${expr})`, 'Invalid Date'); }); }); it('should not parse an empty string, but instead should return an empty string', () => { assertString("date('')", ''); }); }); describe('comparisons', () => { [ ['date("2001-12-26") > date("2001-12-25")', true], ['date("2001-12-26") < date("2001-12-25")', false], ['date("1969-07-20") < date("1969-07-21")', true], ['date("1969-07-20") > date("1969-07-21")', false], ['date("2004-05-01") = date("2004-05-01")', true], ['date("2004-05-01") != date("2004-05-01")', false], ['"string" != date("1999-09-09")', true], ['"string" = date("1999-09-09")', false], ['date(0) = date("1970-01-01T00:00:00.000Z")', true], ['date(0) != date("1970-01-01T00:00:00.000Z")', false], ['date(1) = date("1970-01-02T00:00:00.000Z")', true], ['date(1) != date("1970-01-02T00:00:00.000Z")', false], ['date(-1) = date("1969-12-31T00:00:00.000Z")', true], ['date(-1) != date("1969-12-31T00:00:00.000Z")', false], ['date(14127) = date("2008-09-05T00:00:00.000Z")', true], ['date(14127) != date("2008-09-05T00:00:00.000Z")', false], ['date(-10252) = date("1941-12-07T00:00:00.000Z")', true], ['date(-10252) != date("1941-12-07T00:00:00.000Z")', false], ['date("2012-01-01") < today()', true], ['date("2012-01-01") > today()', false], ['date("2100-01-02") > today()', true], ['date("2100-01-02") < today()', false], ['date("2100-01-02") > 1', true], ['date("1970-01-02") < 3', true], ].forEach(([expr, expected]) => { it(`should evaluate '${expr}' to: ${expected}`, () => { assertBoolean(expr, expected); }); }); }); describe('math', () => { [ ['date("2001-12-26") + 5', '11687.291666666666'], ['date("2001-12-26") - 5', '11677.291666666666'], ['5 + date("2001-12-26")', '11687.291666666666'], ['-5 + date("2001-12-26")', '11677.291666666666'], ['3 + date("2001-12-26") + 5', '11690.291666666666'], ['3 + date("2001-12-26") - 5', '11680.291666666666'], ].forEach(([expr, expected]) => { it(`should evaluate '${expr}' to: ${expected}`, () => { assertString(expr, expected); }); }); }); it('should convert now() to a date string with time component', () => { assertMatch( 'now()', /([0-9]{4}-[0-9]{2}-[0-9]{2})([T]|[\s])([0-9]){2}:([0-9]){2}([0-9:.]*)(\+|-)([0-9]{2}):([0-9]{2})$/ ); }); describe('converts dates to numbers', () => { [ ["number(date('1970-01-01'))", 0.29], ["number(date('1970-01-02'))", 1.29], ["number(date('1969-12-31'))", -0.71], ["number(date('2008-09-05'))", 14127.29], ["number(date('1941-12-07'))", -10251.71], ["number('2008-09-05')", 14127.29], ['number(1 div 1000000000 )', 0], ].forEach(([expr, expected]) => { it(`should convert ${expr} to ${expected}`, () => { assertNumberRounded(expr, expected, 100); }); }); }); describe('for nodes (where the date datatype is guessed)', () => { let doc; before(() => { doc = initDoc( ` <div id="FunctionDate"> <div id="FunctionDateCase1">2012-07-23</div> <div id="FunctionDateCase2">2012-08-20T00:00:00.00+00:00</div> <div id="FunctionDateCase3">2012-08-08T00:00:00+00:00</div> <div id="FunctionDateCase4">2012-06-23</div> <div id="FunctionDateCase5">2012-08-08T06:07:08.123-07:00</div> </div>`, nsResolver ); }); [ ['.', 'FunctionDateCase1', 15544.29], ['.', 'FunctionDateCase2', 15572], ].forEach(([expr, id, expected]) => { it(`should convert ${expr} on ${id} to ${expected}`, () => { assertNumberRounded( expr, expected, 100, doc.getElementById(id) ); }); }); }); describe('datetype comparisons', () => { [ ["date('2001-12-26') > date('2001-12-25')", true], ["date('1969-07-20') < date('1969-07-21')", true], ["date('2004-05-01') = date('2004-05-01')", true], ["true() != date('1999-09-09T00:00:00.000+00:00')", false], ["date(0) = date('1970-01-01T00:00:00.000+00:00')", true], ["date(1) = date('1970-01-02T00:00:00.000+00:00')", true], ["date(-1) = date('1969-12-31T00:00:00.000+00:00')", true], ["date(14127) = date('2008-09-05T00:00:00.000+00:00')", true], ["date(-10252) = date('1941-12-07T00:00:00.000+00:00')", true], ["date(date('1989-11-09')) = date('1989-11-09')", true], ["date('2012-01-01') < today()", true], ["date('2100-01-02') > today()", true], ["date('2012-01-01') < now()", true], ["date('2100-01-02') > now()", true], // ["now() > today()", true], ['"2018-06-25" = "2018-06-25T00:00:00.000-07:00"', true], ['"2018-06-25" < "2018-06-25T00:00:00.000-07:00"', false], ['"2018-06-25" < "2018-06-25T00:00:00.001-07:00"', true], ].forEach(([expr, expected]) => { it(`should convert ${expr} to ${expected}`, () => { assertBoolean(expr, expected); // do the same tests for the alias date-time() expr = expr.replace('date(', 'date-time('); assertBoolean(expr, expected); }); }); }); describe('datestring comparisons (date detection)', () => { let doc; before(() => { doc = initDoc(` <div id="FunctionDate"> <div id="FunctionDateCase1">2012-07-23</div> <div id="FunctionDateCase2">2012-08-20T00:00:00.00+00:00</div> <div id="FunctionDateCase3">2012-08-08T00:00:00+00:00</div> <div id="FunctionDateCase4">2012-06-23</div> <div id="FunctionDateCase5">2012-08-08T06:07:08.123-07:00</div> </div>`); }); [ [true, 'FunctionDateCase1', ". < date('2012-07-24')"], // returns false if strings are compared but true if dates are compared [ true, 'FunctionDateCase1', "../node()[@id='FunctionDateCase2'] > ../node()[@id='FunctionDateCase3']", ], ].forEach(([expected, id, expr]) => { it(`should convert ${expr} to ${expected}`, () => { const node = doc.getElementById(id); assertBoolean(node, null, expr, expected); expr = expr.replace('date(', 'date-time('); assertBoolean(node, null, expr, expected); }); }); }); describe('date calculations', () => { let doc; beforeEach(() => { doc = initDoc( ` <!DOCTYPE html> <html xml:lang="en-us" xmlns="http://www.w3.org/1999/xhtml" xmlns:ev="http://some-namespace.com/nss"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>xpath-test</title> </head> <body> <div id="FunctionDate"> <div id="FunctionDateCase1">2012-07-23</div> <div id="FunctionDateCase4">2012-06-23</div> </div> </body> </html>`, nsResolver ); }); [ [true, doc, "today() > ('2012-01-01' + 10)"], [true, doc, "10 + date('2012-07-24') = date('2012-08-03')"], [true, 'FunctionDateCase1', ". = date('2012-07-24') - 1"], [true, 'FunctionDateCase1', ". > date('2012-07-24') - 2"], [true, 'FunctionDateCase1', ". < date('2012-07-25') - 1"], [ true, 'FunctionDateCase1', ". = 30 + /xhtml:html/xhtml:body/xhtml:div[@id='FunctionDate']/xhtml:div[@id='FunctionDateCase4']", ], [true, doc, "10 + '2012-07-24' = '2012-08-03'"], ].forEach(([expected, node, expr]) => { it(`should convert ${expr} to ${expected}`, () => { if (node !== doc) node = doc.getElementById(node); assertBoolean(node, null, expr, expected); // do the same tests for the alias date-time() expr = expr.replace('date(', 'date-time('); assertBoolean(node, null, expr, expected); }); }); [['10 + date("2012-07-24")', doc, 15555.29]].forEach( ([expr, node, expected]) => { it(`should convert ${expr} to ${expected}`, () => { assertNumberRounded(expr, expected, 100, node); // do the same tests for the alias date-time() expr = expr.replace('date(', 'date-time('); assertNumberRounded(expr, expected, 100, node); }); } ); }); });