You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@annotator.apache.org by ge...@apache.org on 2020/05/15 16:57:11 UTC

[incubator-annotator] 04/04: Simplify that a lot.

This is an automated email from the ASF dual-hosted git repository.

gerben pushed a commit to branch dom-tests
in repository https://gitbox.apache.org/repos/asf/incubator-annotator.git

commit 356c5263b186426a256b8de5d18103f6cdf788cd
Author: Gerben <ge...@treora.com>
AuthorDate: Fri May 15 18:52:55 2020 +0200

    Simplify that a lot.
---
 packages/dom/test/text-quote-match.ts | 96 ++++++++---------------------------
 1 file changed, 20 insertions(+), 76 deletions(-)

diff --git a/packages/dom/test/text-quote-match.ts b/packages/dom/test/text-quote-match.ts
index 2f43600..4e9eb57 100644
--- a/packages/dom/test/text-quote-match.ts
+++ b/packages/dom/test/text-quote-match.ts
@@ -24,6 +24,14 @@ import { TextQuoteSelector } from '../../selector/src';
 
 const domParser = new window.DOMParser();
 
+// RangeInfo serialises a Range’s start and end containers as XPaths.
+type RangeInfo = {
+  startContainer: string,
+  startOffset: number,
+  endContainer: string,
+  endOffset: number,
+};
+
 const testCases: {
   [name: string]: {
     html: string,
@@ -54,48 +62,14 @@ describe('createTextQuoteSelectorMatcher', () => {
       const doc = domParser.parseFromString(html, 'text/html');
       const matcher = createTextQuoteSelectorMatcher(selector);
       const matches = await asyncIterableToArray(matcher(doc.body));
-      assert.deepEqual(
-        matches.map(range => canonicalRangeSerialisation(range)),
-        expected.map(info => canonicalRangeSerialisation(info, doc)),
-      );
+      assert.equal(matches.length, expected.length);
+      matches.forEach((match, i) => {
+        assert.include(match, hydrateRange(expected[i], doc));
+      });
     });
   }
 });
 
-// RangeInfo encodes a Range’s start&end containers as XPaths.
-type RangeInfo = {
-  startContainer: string,
-  startOffset: number,
-  endContainer: string,
-  endOffset: number,
-};
-
-function canonicalRangeSerialisation(range: Range): RangeInfo
-function canonicalRangeSerialisation(range: RangeInfo, doc: Document): RangeInfo
-function canonicalRangeSerialisation(range: Range | RangeInfo, doc?: Document): RangeInfo {
-  if (!('collapsed' in range)) {
-    // range is already serialised; re-serialise to ensure it is canonical.
-    return {
-      ...range,
-      startContainer: createXPath(evaluateXPathOne(doc, range.startContainer)),
-      endContainer: createXPath(evaluateXPathOne(doc, range.endContainer)),
-    };
-  }
-  return {
-    startContainer: createXPath(range.startContainer),
-    startOffset: range.startOffset,
-    endContainer: createXPath(range.endContainer),
-    endOffset: range.endOffset,
-  };
-}
-
-function infoToRange(info: RangeInfo | Range, doc: Document): Range {
-  if ('collapsed' in info) return info;
-  const range = document.createRange();
-  range.setStart(evaluateXPathOne(doc, info.startContainer), info.startOffset);
-  range.setEnd(evaluateXPathOne(doc, info.startContainer), info.startOffset);
-}
-
 async function asyncIterableToArray<T>(source: AsyncIterable<T>): Promise<T[]> {
   const values = [];
   for await (const value of source) {
@@ -104,48 +78,18 @@ async function asyncIterableToArray<T>(source: AsyncIterable<T>): Promise<T[]> {
   return values;
 }
 
-// Return an XPath expression for the given node.
-function createXPath(node: Node): string { // wrap the actual function with a self-test.
-  const result = _createXPath(node);
-  try {
-    const selfCheck = evaluateXPathAll(node.ownerDocument || node as Document, result);
-    assert.deepEqual(selfCheck, [node]);
-  } catch (err) {
-    assert.fail(`Test suite itself created an incorrect XPath: '${result}'`);
-  }
-  return result;
-}
-function _createXPath(node: Node): string {
-  let path = ''
-  while (node.parentNode !== null) {
-    if (node.nodeType === Node.ELEMENT_NODE) {
-      const name = (node as Element).tagName.toLowerCase();
-      const matchingElements = evaluateXPathAll(node.ownerDocument || node as Document, `//${name}`);
-      if (matchingElements.length > 1)
-        return `//${name}[${matchingElements.indexOf(node) + 1}]${path}`;
-      else
-        return `//${name}${path}`;
-    }
-    const childIndex = [...node.parentNode.childNodes].indexOf(node as ChildNode);
-    const xpathNodeTypes = {
-      [Node.COMMENT_NODE]: 'comment',
-      [Node.TEXT_NODE]: 'text',
-      [Node.PROCESSING_INSTRUCTION_NODE]: 'processing-instruction',
-    }
-    const nodeType = xpathNodeTypes[node.nodeType] || 'node';
-    path = `/${nodeType}()[${childIndex + 1}]` + path;
-    node = node.parentNode;
+// Evaluate the XPath expressions to the corresponding Nodes in the DOM.
+function hydrateRange(rangeInfo: RangeInfo, doc: Document): Partial<Range> {
+  return {
+    ...rangeInfo,
+    startContainer: evaluateXPath(doc, rangeInfo.startContainer),
+    endContainer: evaluateXPath(doc, rangeInfo.endContainer),
   }
-  return path;
 }
 
-function evaluateXPathAll(doc: Document, xpath: string): Node[] {
+function evaluateXPath(doc: Document, xpath: string): Node {
   const result = doc.evaluate(xpath, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
-  return new Array(result.snapshotLength).fill(undefined).map((_, i) => result.snapshotItem(i));
-}
-
-function evaluateXPathOne(doc: Document, xpath: string): Node {
-  const nodes = evaluateXPathAll(doc, xpath);
+  const nodes = new Array(result.snapshotLength).fill(undefined).map((_, i) => result.snapshotItem(i));
   assert.equal(nodes.length, 1,
     `Test suite contains XPath with ${nodes.length} results instead of 1: '${xpath}'`
   );