diff --git a/test/specs/parsing/getBucketForSelector.tests.ts b/test/specs/parsing/getBucketForSelector.tests.ts index d1d6a4476..bf345f4a8 100644 --- a/test/specs/parsing/getBucketForSelector.tests.ts +++ b/test/specs/parsing/getBucketForSelector.tests.ts @@ -37,6 +37,26 @@ describe('getBucketForSelector', () => { it('returns the correct bucket for expressions using the and operator, first not having a bucket', () => { assertBucketForSelector('true() and self::element()', 'type-1'); }); + it('returns the correct bucket for expressions using the and operator, first matching nothing', () => { + assertBucketForSelector( + '(self::element() and self::processing-instruction()) or self::element()', + 'type-1', + ); + assertBucketForSelector( + 'self::element() or (self::element() and self::processing-instruction())', + 'type-1', + ); + }); + it('returns the correct bucket for expressions using nested operators, first matching everything', () => { + assertBucketForSelector( + '(self::element() or self::processing-instruction()) or self::element()', + null, + ); + assertBucketForSelector( + 'self::element() or (self::element() or self::processing-instruction())', + null, + ); + }); it('returns the correct bucket for expressions using the or operator, first not having a bucket', () => { assertBucketForSelector('true() or self::element()', null); }); diff --git a/test/specs/parsing/operators/boolean/OrOperator.tests.ts b/test/specs/parsing/operators/boolean/OrOperator.tests.ts index 0baf104b5..9b428b43c 100644 --- a/test/specs/parsing/operators/boolean/OrOperator.tests.ts +++ b/test/specs/parsing/operators/boolean/OrOperator.tests.ts @@ -28,6 +28,13 @@ describe('or operator', () => { ); }); + it('can parse an "or" selector with different nonoverlapping buckets that does not match', () => { + jsonMlMapper.parse(['c'], documentNode); + chai.assert.isFalse( + evaluateXPathToBoolean('self::a or self::b', documentNode.documentElement), + ); + }); + it('can parse a concatenation of ors', () => chai.assert.isTrue( evaluateXPathToBoolean( diff --git a/test/specs/parsing/parseScript.tests.ts b/test/specs/parsing/parseScript.tests.ts index afdff101e..5fcb42ed6 100644 --- a/test/specs/parsing/parseScript.tests.ts +++ b/test/specs/parsing/parseScript.tests.ts @@ -270,6 +270,43 @@ declare %public function prefix:ok() as xs:string { chai.assert.isOk(ast); }); + it('can parse an XPath 4.0 script', () => { + const document = new Document(); + const ast = parseScript(`self::(a|b)`, { language: Language.XPATH_4_0_LANGUAGE }, document); + + chai.assert.isOk(ast); + }); + + it('can skip ast annotation', () => { + const document = new Document(); + const ast = parseScript( + `self::(a|b)`, + { language: Language.XPATH_4_0_LANGUAGE, annotateAst: false }, + document, + ); + + chai.assert.isOk(ast); + chai.assert.isFalse( + evaluateXPathToBoolean('.//@*:type', ast), + 'there should be no type annotations', + ); + }); + + it('can perform ast annotation', () => { + const document = new Document(); + const ast = parseScript( + `self::(a|b)`, + { language: Language.XPATH_4_0_LANGUAGE, annotateAst: true }, + document, + ); + + chai.assert.isOk(ast); + chai.assert.isTrue( + evaluateXPathToBoolean('.//@*:type', ast), + 'there should be no type annotations', + ); + }); + it('can execute a map function within an AST', () => { const ast = parseScript('map:put($week, "1", "Monday")', {}, new Document()); const result = evaluateXPathToMap(ast, null, null, { diff --git a/test/specs/parsing/xquery-updating/evaluateUpdatingExpressionSync.tests.ts b/test/specs/parsing/xquery-updating/evaluateUpdatingExpressionSync.tests.ts index 4f8d4a3dc..5012670bf 100644 --- a/test/specs/parsing/xquery-updating/evaluateUpdatingExpressionSync.tests.ts +++ b/test/specs/parsing/xquery-updating/evaluateUpdatingExpressionSync.tests.ts @@ -1,7 +1,7 @@ import * as chai from 'chai'; import * as slimdom from 'slimdom'; -import { evaluateUpdatingExpressionSync, executePendingUpdateList } from 'fontoxpath'; +import { Language, evaluateUpdatingExpressionSync, executePendingUpdateList } from 'fontoxpath'; import { IPendingUpdate } from 'fontoxpath/expressions/xquery-update/IPendingUpdate'; import { InsertPendingUpdate } from 'fontoxpath/expressions/xquery-update/pendingUpdates/InsertPendingUpdate'; import { TransferablePendingUpdate } from 'fontoxpath/expressions/xquery-update/createPendingUpdateFromTransferable'; @@ -105,6 +105,19 @@ describe('evaluateUpdatingExpressionSync', () => { chai.assert.deepEqual(result.xdmValue, []); }); + it('can evaluate an expression with XPath 4.0 used', async () => { + documentNode.appendChild(documentNode.createElement('ele')); + const result = evaluateUpdatingExpressionSync( + 'replace node not_here otherwise ele with ', + documentNode, + null, + null, + { language: Language.XQUERY_UPDATE_4_0_LANGUAGE }, + ); + + chai.assert.deepEqual(result.xdmValue, []); + }); + it('properly returns the xdmValue for updating expressions', async () => { documentNode.appendChild(documentNode.createElement('ele')); const result = evaluateUpdatingExpressionSync(