From df484719a3e14fe36b06c03dfd2485cf3f286f6e Mon Sep 17 00:00:00 2001 From: Chris Barth Date: Tue, 19 Sep 2023 00:30:48 -0500 Subject: [PATCH] Add more tests to ensure proper handling of undefined --- test.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ xpath.d.ts | 26 +++++++++++++++++--------- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/test.js b/test.js index 962586d..a6a6123 100644 --- a/test.js +++ b/test.js @@ -156,6 +156,54 @@ describe('xpath', () => { assert.strictEqual('JKR', xpath.selectWithResolver('//ns:field[@ns:type="author"]/text()', doc, resolver)[0].nodeValue); }); + it('should select empty set with undefined xpath, using a resolver', () => { + var xml = 'Harry PotterJKR'; + var doc = parseXml(xml); + var resolver = { + mappings: { + 'ns': 'http://example.com/test' + }, + lookupNamespaceURI: function (prefix) { + return this.mappings[prefix]; + } + } + var nodes = xpath.selectWithResolver(undefined, doc, resolver); + assert.deepStrictEqual(nodes, []); + + var node = xpath.selectWithResolver(undefined, doc, resolver, true); + assert.strictEqual(node, undefined); + }); + + it('should throw if undefined doc, using a resolver', () => { + var resolver = { + mappings: { + 'ns': 'http://example.com/test' + }, + lookupNamespaceURI: function (prefix) { + return this.mappings[prefix]; + } + } + assert.throws(() => xpath.selectWithResolver(undefined, undefined, resolver)); + }); + + it('should select empty set with undefined resolver', () => { + var xml = 'Harry PotterJKR'; + var doc = parseXml(xml); + var resolver = { + mappings: { + 'ns': 'http://example.com/test' + }, + lookupNamespaceURI: function (prefix) { + return this.mappings[prefix]; + } + } + var nodes = xpath.selectWithResolver(undefined, doc, undefined); + assert.deepStrictEqual(nodes, []); + + var node = xpath.selectWithResolver(undefined, doc, undefined, true); + assert.strictEqual(node, undefined); + }); + it('should select with namespaces, using namespace mappings', () => { var xml = 'Harry PotterJKR'; var doc = parseXml(xml); diff --git a/xpath.d.ts b/xpath.d.ts index 9d1a734..9556294 100644 --- a/xpath.d.ts +++ b/xpath.d.ts @@ -1,34 +1,42 @@ /// -export type SelectedValue = Node | string | number | boolean | null; +export type ScalarValue = string | number | boolean; -export type SelectReturnType = Array | SelectedValue; -export type SelectSingleReturnType = SelectedValue; +export type SelectReturnType = Array | ScalarValue; +export type SelectSingleReturnType = ScalarValue | Node | undefined; + +type Nullable = T | null | undefined; export interface XPathSelect { + (expression: Nullable, node: Node): []; + (expression: Nullable, node: Node, single: false): []; (expression: string, node: Node): SelectReturnType; (expression: string, node: Node, single: false): SelectReturnType; - (expression: string, node: Node, single: true): SelectSingleReturnType; + (expression: Nullable, node: Node, single: true): SelectSingleReturnType; } /** * Evaluate an XPath expression against a DOM node. */ +export function select(expression: Nullable, node: Node): []; +export function select(expression: Nullable, node: Node, single: false): []; export function select(expression: string, node: Node): SelectReturnType; export function select(expression: string, node: Node, single: false): SelectReturnType; -export function select(expression: string, node: Node, single: true): SelectSingleReturnType; +export function select(expression: Nullable, node: Node, single: true): SelectSingleReturnType; /** * Evaluate an xpath expression against a DOM node, returning the first result only. */ -export function select1(expression: string, node: Node): SelectSingleReturnType; +export function select1(expression: Nullable, node: Node): SelectSingleReturnType; /** * Evaluate an XPath expression against a DOM node using a given namespace resolver. */ -export function selectWithResolver(expression: string, node: Node, resolver?: XPathNSResolver | null): SelectReturnType; -export function selectWithResolver(expression: string, node: Node, resolver: XPathNSResolver | null, single: false): SelectReturnType; -export function selectWithResolver(expression: string, node: Node, resolver: XPathNSResolver | null, single: true): SelectSingleReturnType; +export function selectWithResolver(expression: Nullable, node: Node, resolver?: Nullable): []; +export function selectWithResolver(expression: Nullable, node: Node, resolver: Nullable, single: false): []; +export function selectWithResolver(expression: string, node: Node, resolver?: Nullable): SelectReturnType; +export function selectWithResolver(expression: string, node: Node, resolver: Nullable, single: false): SelectReturnType; +export function selectWithResolver(expression: string, node: Node, resolver: Nullable, single: true): SelectSingleReturnType; /** * Creates a `select` function that uses the given namespace prefix to URI mappings when evaluating queries.