fontoxpath
Version:
A minimalistic XPath 3.1 engine in JavaScript
238 lines (210 loc) • 13.2 kB
JavaScript
import * as slimdom from 'slimdom';
import {
evaluateXPathToBoolean
} from 'fontoxpath';
import evaluateXPathToAsyncSingleton from 'test-helpers/evaluateXPathToAsyncSingleton';
let documentNode;
beforeEach(() => {
documentNode = new slimdom.Document();
});
describe('castable as', () => {
it('accepts empty sequences',
() => chai.assert.isTrue(evaluateXPathToBoolean('() castable as xs:boolean?', documentNode)));
it('does not accept empty sequences',
() => chai.assert.isFalse(evaluateXPathToBoolean('() castable as xs:boolean', documentNode)), 'XPST0004');
it('does not accept sequences of length > 1',
() => chai.assert.isFalse(evaluateXPathToBoolean('("a", "b") castable as xs:boolean', documentNode)), 'XPST0004');
it('accepts async params', async () => {
chai.assert.isTrue(await evaluateXPathToAsyncSingleton('("a" => fontoxpath:sleep()) castable as xs:string', documentNode));
});
describe('as xs:boolean', () => {
it('casts "true" to true',
() => chai.assert.isTrue(evaluateXPathToBoolean('"true" castable as xs:boolean', documentNode)));
it('casts "false" to false',
() => chai.assert.isTrue(evaluateXPathToBoolean('"false" castable as xs:boolean', documentNode)));
it('casts "1" to true',
() => chai.assert.isTrue(evaluateXPathToBoolean('"1" castable as xs:boolean', documentNode)));
it('casts "0" to false',
() => chai.assert.isTrue(evaluateXPathToBoolean('"0" castable as xs:boolean', documentNode)));
it('casts xs:untypedAtomic to false',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:untypedAtomic("0") castable as xs:boolean', documentNode)));
it('throws when given an invalid value',
() => chai.assert.isFalse(evaluateXPathToBoolean('"wat" castable as xs:boolean', documentNode)), 'FORG0001');
it('can cast integers to booleans: true',
() => chai.assert.isTrue(evaluateXPathToBoolean('25 castable as xs:boolean', documentNode)));
it('can cast integers to booleans: false',
() => chai.assert.isTrue(evaluateXPathToBoolean('0 castable as xs:boolean', documentNode)));
});
describe('as xs:integer', () => {
it('can cast booleans to integers: false',
() => chai.assert.isTrue(evaluateXPathToBoolean('false() castable as xs:integer', documentNode)));
it('can cast booleans to integers: true',
() => chai.assert.isTrue(evaluateXPathToBoolean('true() castable as xs:integer', documentNode)));
it('can cast strings to integers: "123"',
() => chai.assert.isTrue(evaluateXPathToBoolean('"123" castable as xs:integer', documentNode)));
it('can cast decimals to integers: 123.2',
() => chai.assert.isTrue(evaluateXPathToBoolean('123.2 castable as xs:integer', documentNode)));
});
describe('as xs:decimal', () => {
it('can cast booleans to decimals: false',
() => chai.assert.isTrue(evaluateXPathToBoolean('false() castable as xs:decimal', documentNode)));
it('can cast booleans to decimals: true',
() => chai.assert.isTrue(evaluateXPathToBoolean('true() castable as xs:decimal', documentNode)));
it('can cast strings to decimals: "123"',
() => chai.assert.isTrue(evaluateXPathToBoolean('"123" castable as xs:decimal', documentNode)));
it('can cast untypedAtomic to decimals: "123"',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:untypedAtomic("123") castable as xs:decimal', documentNode)));
it('fails casting non-numeric untypedAtomic to decimals: "Not a number at ALL"',
() => chai.assert.isFalse(evaluateXPathToBoolean('xs:untypedAtomic("Not a number at all") castable as xs:decimal', documentNode)), 'XPTY0004');
it('can cast floats to decimals: 123.2',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:float("123.2") castable as xs:decimal', documentNode)));
it('can cast integers to decimals: 123.2',
() => chai.assert.isTrue(evaluateXPathToBoolean('123 castable as xs:decimal', documentNode)));
it('fails casting NaN to decimals',
() => chai.assert.isFalse(evaluateXPathToBoolean('xs:float("NaN") castable as xs:decimal', documentNode)), 'FOCA0002');
});
describe('as xs:float', () => {
it('can cast booleans to floats: false',
() => chai.assert.isTrue(evaluateXPathToBoolean('false() castable as xs:float', documentNode)));
it('can cast booleans to floats: true',
() => chai.assert.isTrue(evaluateXPathToBoolean('true() castable as xs:float', documentNode)));
it('can cast strings to floats: "123"',
() => chai.assert.isTrue(evaluateXPathToBoolean('"123" castable as xs:float', documentNode)));
it('can cast strings to floats: "INF"',
() => chai.assert.isTrue(evaluateXPathToBoolean('"INF" castable as xs:float', documentNode)));
it('can cast strings to floats: "-INF"',
() => chai.assert.isTrue(evaluateXPathToBoolean('"-INF" castable as xs:float', documentNode)));
it('can cast strings to floats: "NaN"',
() => chai.assert.isTrue(evaluateXPathToBoolean('"NaN" castable as xs:float', documentNode)));
it('can cast strings to floats: "1E100"',
() => chai.assert.isTrue(evaluateXPathToBoolean('"1E3" castable as xs:float', documentNode)));
});
describe('as xs:double', () => {
it('can cast booleans to doubles: false',
() => chai.assert.isTrue(evaluateXPathToBoolean('false() castable as xs:double', documentNode)));
it('can cast booleans to doubles: true',
() => chai.assert.isTrue(evaluateXPathToBoolean('true() castable as xs:double', documentNode)));
it('can cast strings to doubles: "123"',
() => chai.assert.isTrue(evaluateXPathToBoolean('"123" castable as xs:double', documentNode)));
it('can cast strings to doubles: "INF"',
() => chai.assert.isTrue(evaluateXPathToBoolean('"INF" castable as xs:double', documentNode)));
it('can cast strings to doubles: "-INF"',
() => chai.assert.isTrue(evaluateXPathToBoolean('"-INF" castable as xs:double', documentNode)));
it('can cast strings to doubles: "NaN"',
() => chai.assert.isTrue(evaluateXPathToBoolean('"NaN" castable as xs:double', documentNode)));
it('can cast strings to doubles: "1E100"',
() => chai.assert.isTrue(evaluateXPathToBoolean('"1E3" castable as xs:double', documentNode)));
});
describe('as xs:string', () => {
describe('from xs:float', () => {
it('can cast floats to strings: 1E100',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:float("1E100") castable as xs:string', documentNode)));
it('can cast floats to strings: 1E100',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:float("1E100") castable as xs:string', documentNode)));
it('can cast floats to strings: 0',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:float("0") castable as xs:string', documentNode)));
it('can cast floats to strings: -0',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:float("-0") castable as xs:string', documentNode)));
it('can cast floats to strings: INF',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:float("INF") castable as xs:string', documentNode)));
it('can cast floats to strings: -INF',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:float("-INF") castable as xs:string', documentNode)));
it('can cast floats to strings: +INF',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:float("+INF") castable as xs:string', documentNode)));
});
describe('from xs:double', () => {
it('can cast doubles to strings: 1E100',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:double("1E100") castable as xs:string', documentNode)));
it('can cast doubles to strings: 1E100',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:double("1E100") castable as xs:string', documentNode)));
it('can cast doubles to strings: 0',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:double("0") castable as xs:string', documentNode)));
it('can cast doubles to strings: -0',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:double("-0") castable as xs:string', documentNode)));
it('can cast doubles to strings: INF',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:double("INF") castable as xs:string', documentNode)));
it('can cast doubles to strings: -INF',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:double("-INF") castable as xs:string', documentNode)));
it('can cast doubles to strings: +INF',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:double("+INF") castable as xs:string', documentNode)));
});
it('can cast integers to strings: 100',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:integer("100") castable as xs:string', documentNode)));
it('can cast integers to strings: -100',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:integer("-100") castable as xs:string', documentNode)));
});
describe('as xs:untypedAtomic', () => {
it('can cast strings to untypedAtomics',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:untypedAtomic("1E100") castable as xs:untypedAtomic', documentNode)));
});
describe('as xs:anyURI', () => {
it('can cast strings to anyURI',
() => chai.assert.isTrue(evaluateXPathToBoolean('"a string" castable as xs:anyURI', documentNode)));
});
describe('as xs:hexBinary', () => {
it('can cast the empty string to hexBinary',
() => chai.assert.isTrue(evaluateXPathToBoolean('"" castable as xs:hexBinary', documentNode)));
it('fails to cast invalid strings to hexBinary',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:untypedAtomic("0100101010") castable as xs:hexBinary', documentNode)));
});
describe('as xs:base64Binary', () => {
it('can cast the empty string to base64Binary',
() => chai.assert.isTrue(evaluateXPathToBoolean('xs:base64Binary("") castable as xs:base64Binary', documentNode)));
});
describe('as xs:date', () => {
it.skip('can cast a string to date: upper bounds. This will not work because JavaScript Dates do not allow setting the year that far back',
() => chai.assert.isTrue(evaluateXPathToBoolean('"25252734927766555-06-07+02:00" castable as xs:date', documentNode)));
it.skip('can cast a string to date: lower bounds. This will not work because JavaScript Dates do not allow setting the year that far back',
() => chai.assert.isTrue(evaluateXPathToBoolean('"-25252734927766555-06-07+02:00" castable as xs:date', documentNode)));
});
describe('as xs:gMonthDay', () => {
it('can cast a string to gMonthDay: lower bounds',
() => chai.assert.isTrue(evaluateXPathToBoolean('"--01-01Z" castable as xs:gMonthDay', documentNode)));
it('can cast a string to gMonthDay: upper bounds',
() => chai.assert.isTrue(evaluateXPathToBoolean('"--12-31Z" castable as xs:gMonthDay', documentNode)));
});
describe('as xs:long', () => {
it('can cast strings to xs:long: max bounds. This will not work because of JavaScript numbers not having the same ranges',
() => chai.assert.isFalse(evaluateXPathToBoolean('"9223372036854775808" castable as xs:long', documentNode), 9223372036854775808), 'FOAR0002');
it('can cast strings to xs:long: middle bounds',
() => chai.assert.isTrue(evaluateXPathToBoolean('"922337203685458" castable as xs:long', documentNode), 922337203685458));
});
describe('as xs:int', () => {
it('can cast strings to xs:int',
() => chai.assert.isTrue(evaluateXPathToBoolean('"1234" castable as xs:int', documentNode), 1234));
it('xs:int can not be written in hexadecimal',
() => chai.assert.isFalse(evaluateXPathToBoolean('"0x1234" castable as xs:int', documentNode)));
it('xs:int can not be written with fractions',
() => chai.assert.isFalse(evaluateXPathToBoolean('"1.0" castable as xs:int', documentNode)));
});
describe('as xs:normalizedString', () => {
it('can cast integers to xs:normalizedString',
() => chai.assert.isTrue(evaluateXPathToBoolean('1234 castable as xs:normalizedString', documentNode)));
});
describe('as xs:yearMonthDuration', () => {
it('can not cast invalid untypedAtomics to xs:yearMonthDuration',
() => chai.assert.isFalse(evaluateXPathToBoolean('xs:untypedAtomic("-P1Y1M1DT1H1M1.123S") castable as xs:yearMonthDuration', documentNode)));
});
describe('as xs:yearMonthDuration', () => {
it('can not cast invalid strings to xs:yearMonthDuration',
() => chai.assert.isFalse(evaluateXPathToBoolean('"P3YT2H" castable as xs:dayTimeDuration', documentNode)));
});
describe('as xs:ENTITY', () => {
it('can cast strings to xs:ENTITY',
() => chai.assert.isTrue(evaluateXPathToBoolean('"someString" castable as xs:ENTITY', documentNode)));
it('disallows empty strings',
() => chai.assert.isFalse(evaluateXPathToBoolean('"" castable as xs:ENTITY', documentNode)));
});
describe('as xs:language', () => {
it('can cast strings to xs:language',
() => chai.assert.isTrue(evaluateXPathToBoolean('"qya" castable as xs:language', documentNode)));
it('disallows integers at the start',
() => chai.assert.isFalse(evaluateXPathToBoolean('"1234" castable as xs:language', documentNode)), 'FORG0001');
it('disallows integers as a type',
() => chai.assert.isFalse(evaluateXPathToBoolean('xs:int("1234") castable as xs:language', documentNode)), 'FORG0001');
});
describe('as xs:error', () => {
it('can not cast anything as xs:error',
() => chai.assert.isFalse(evaluateXPathToBoolean('1 castable as xs:error', documentNode)));
});
});