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 d4d560226248f686c56c87c1bf407015d2e1c190 Author: Gerben <[email protected]> AuthorDate: Mon May 25 13:30:21 2020 +0200 Move test cases into own file --- packages/dom/test/text-quote-match-cases.ts | 269 ++++++++++++++++++++++++++ packages/dom/test/text-quote-match.ts | 288 +--------------------------- packages/dom/test/utils.ts | 18 ++ 3 files changed, 291 insertions(+), 284 deletions(-) diff --git a/packages/dom/test/text-quote-match-cases.ts b/packages/dom/test/text-quote-match-cases.ts new file mode 100644 index 0000000..33d66de --- /dev/null +++ b/packages/dom/test/text-quote-match-cases.ts @@ -0,0 +1,269 @@ +import { TextQuoteSelector } from "../../selector/src"; +import { RangeInfo } from "./utils"; + +const testCases: { + [name: string]: { + html: string, + selector: TextQuoteSelector, + expected: RangeInfo[], + } +} = { + 'simple': { + html: '<b>lorem ipsum dolor amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'dolor am', + }, + expected: [ + { + startContainerXPath: '//b/text()', + startOffset: 12, + endContainerXPath: '//b/text()', + endOffset: 20, + }, + ], + }, + 'first characters': { + html: '<b>lorem ipsum dolor amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'lorem ipsum', + }, + expected: [ + { + startContainerXPath: '//b/text()', + startOffset: 0, + endContainerXPath: '//b/text()', + endOffset: 11, + }, + ], + }, + 'last characters': { + html: '<b>lorem ipsum dolor amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'yada yada', + }, + expected: [ + { + startContainerXPath: '//b/text()', + startOffset: 23, + endContainerXPath: '//b/text()', + endOffset: 32, + }, + ], + }, + 'across elements': { + html: '<b>lorem <i>ipsum</i> dolor <u>amet</u> yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'dolor am', + }, + expected: [ + { + startContainerXPath: '//b/text()[2]', + startOffset: 1, + endContainerXPath: '//u/text()', + endOffset: 2, + }, + ], + }, + 'exact element contents': { + html: '<b>lorem <i>ipsum dolor</i> amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'ipsum dolor', + }, + expected: [ + { + startContainerXPath: '//i/text()', + startOffset: 0, + endContainerXPath: '//b/text()[2]', + endOffset: 0, + }, + ], + }, + 'text inside <head>': { + html: '<head><title>The title</title></head><b>lorem ipsum dolor amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'title', + }, + expected: [ + { + startContainerXPath: '//title/text()', + startOffset: 4, + endContainerXPath: '//b/text()[1]', + endOffset: 0, + }, + ], + }, + 'two matches': { + html: '<b>lorem ipsum dolor amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'yada', + }, + expected: [ + { + startContainerXPath: '//b/text()', + startOffset: 23, + endContainerXPath: '//b/text()', + endOffset: 27, + }, + { + startContainerXPath: '//b/text()', + startOffset: 28, + endContainerXPath: '//b/text()', + endOffset: 32, + }, + ], + }, + 'overlapping matches': { + html: '<b>bananas</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'ana', + }, + expected: [ + { + startContainerXPath: '//b/text()', + startOffset: 1, + endContainerXPath: '//b/text()', + endOffset: 4, + }, + { + startContainerXPath: '//b/text()', + startOffset: 3, + endContainerXPath: '//b/text()', + endOffset: 6, + }, + ], + }, + 'no matches': { + html: '<b>lorem ipsum dolor amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'holy grail', + }, + expected: [], + }, + 'with prefix': { + html: '<b>lorem ipsum dolor amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'yada', + prefix: 't ', + }, + expected: [ + { + startContainerXPath: '//b/text()', + startOffset: 23, + endContainerXPath: '//b/text()', + endOffset: 27, + }, + ], + }, + 'with suffix': { + html: '<b>lorem ipsum dolor amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'o', + suffix: 'l', + }, + expected: [ + { + startContainerXPath: '//b/text()', + startOffset: 13, + endContainerXPath: '//b/text()', + endOffset: 14, + }, + ], + }, + 'with prefix and suffix': { + html: '<b>lorem ipsum dolor amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'o', + prefix: 'l', + suffix: 're', + }, + expected: [ + { + startContainerXPath: '//b/text()', + startOffset: 1, + endContainerXPath: '//b/text()', + endOffset: 2, + }, + ], + }, + 'with prefix and suffix, two matches': { + html: '<b>lorem ipsum dolor amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'o', + prefix: 'l', + suffix: 'r', + }, + expected: [ + { + startContainerXPath: '//b/text()', + startOffset: 1, + endContainerXPath: '//b/text()', + endOffset: 2, + }, + { + startContainerXPath: '//b/text()', + startOffset: 15, + endContainerXPath: '//b/text()', + endOffset: 16, + }, + ], + }, + 'with prefix, no matches': { + html: '<b>lorem ipsum dolor amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'dolor', + prefix: 'oopsum ', + }, + expected: [], + }, + 'with suffix, no matches': { + html: '<b>lorem ipsum dolor amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'dolor', + suffix: ' amot', + }, + expected: [], + }, + 'with suffix, no matches due to whitespace': { + html: '<b>lorem ipsum dolor amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'dolor', + suffix: 'a', + }, + expected: [], + }, + 'with empty prefix and suffix': { + html: '<b>lorem ipsum dolor amet yada yada</b>', + selector: { + type: 'TextQuoteSelector', + exact: 'dolor am', + prefix: '', + suffix: '', + }, + expected: [ + { + startContainerXPath: '//b/text()', + startOffset: 12, + endContainerXPath: '//b/text()', + endOffset: 20, + }, + ], + }, +}; + +export default testCases; diff --git a/packages/dom/test/text-quote-match.ts b/packages/dom/test/text-quote-match.ts index 77f8bd4..1144bc3 100644 --- a/packages/dom/test/text-quote-match.ts +++ b/packages/dom/test/text-quote-match.ts @@ -20,284 +20,13 @@ import { assert } from 'chai'; import { createTextQuoteSelectorMatcher } from '../src/text-quote/match'; -import { TextQuoteSelector } from '../../selector/src'; +import { TextQuoteSelector } from '../../selector/src/types'; import { DomScope } from '../src/types'; +import testCases from './text-quote-match-cases'; +import { evaluateXPath, RangeInfo } from './utils'; const domParser = new window.DOMParser(); -// RangeInfo serialises a Range’s start and end containers as XPaths. -type RangeInfo = { - startContainerXPath: string, - startOffset: number, - endContainerXPath: string, - endOffset: number, -}; - -const testCases: { - [name: string]: { - html: string, - selector: TextQuoteSelector, - expected: RangeInfo[], - } -} = { - 'simple': { - html: '<b>lorem ipsum dolor amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'dolor am', - }, - expected: [ - { - startContainerXPath: '//b/text()', - startOffset: 12, - endContainerXPath: '//b/text()', - endOffset: 20, - }, - ] - }, - 'first characters': { - html: '<b>lorem ipsum dolor amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'lorem ipsum', - }, - expected: [ - { - startContainerXPath: '//b/text()', - startOffset: 0, - endContainerXPath: '//b/text()', - endOffset: 11, - }, - ] - }, - 'last characters': { - html: '<b>lorem ipsum dolor amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'yada yada', - }, - expected: [ - { - startContainerXPath: '//b/text()', - startOffset: 23, - endContainerXPath: '//b/text()', - endOffset: 32, - }, - ] - }, - 'across elements': { - html: '<b>lorem <i>ipsum</i> dolor <u>amet</u> yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'dolor am', - }, - expected: [ - { - startContainerXPath: '//b/text()[2]', - startOffset: 1, - endContainerXPath: '//u/text()', - endOffset: 2, - }, - ] - }, - 'exact element contents': { - html: '<b>lorem <i>ipsum dolor</i> amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'ipsum dolor', - }, - expected: [ - { - startContainerXPath: '//i/text()', - startOffset: 0, - endContainerXPath: '//b/text()[2]', - endOffset: 0, - }, - ] - }, - 'text inside <head>': { - html: '<head><title>The title</title></head><b>lorem ipsum dolor amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'title', - }, - expected: [ - { - startContainerXPath: '//title/text()', - startOffset: 4, - endContainerXPath: '//b/text()[1]', - endOffset: 0, - }, - ] - }, - 'two matches': { - html: '<b>lorem ipsum dolor amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'yada', - }, - expected: [ - { - startContainerXPath: '//b/text()', - startOffset: 23, - endContainerXPath: '//b/text()', - endOffset: 27, - }, - { - startContainerXPath: '//b/text()', - startOffset: 28, - endContainerXPath: '//b/text()', - endOffset: 32, - }, - ] - }, - 'overlapping matches': { - html: '<b>bananas</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'ana', - }, - expected: [ - { - startContainerXPath: '//b/text()', - startOffset: 1, - endContainerXPath: '//b/text()', - endOffset: 4, - }, - { - startContainerXPath: '//b/text()', - startOffset: 3, - endContainerXPath: '//b/text()', - endOffset: 6, - }, - ] - }, - 'no matches': { - html: '<b>lorem ipsum dolor amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'holy grail', - }, - expected: [] - }, - 'with prefix': { - html: '<b>lorem ipsum dolor amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'yada', - prefix: 't ', - }, - expected: [ - { - startContainerXPath: '//b/text()', - startOffset: 23, - endContainerXPath: '//b/text()', - endOffset: 27, - }, - ] - }, - 'with suffix': { - html: '<b>lorem ipsum dolor amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'o', - suffix: 'l', - }, - expected: [ - { - startContainerXPath: '//b/text()', - startOffset: 13, - endContainerXPath: '//b/text()', - endOffset: 14, - }, - ] - }, - 'with prefix and suffix': { - html: '<b>lorem ipsum dolor amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'o', - prefix: 'l', - suffix: 're', - }, - expected: [ - { - startContainerXPath: '//b/text()', - startOffset: 1, - endContainerXPath: '//b/text()', - endOffset: 2, - }, - ] - }, - 'with prefix and suffix, two matches': { - html: '<b>lorem ipsum dolor amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'o', - prefix: 'l', - suffix: 'r', - }, - expected: [ - { - startContainerXPath: '//b/text()', - startOffset: 1, - endContainerXPath: '//b/text()', - endOffset: 2, - }, - { - startContainerXPath: '//b/text()', - startOffset: 15, - endContainerXPath: '//b/text()', - endOffset: 16, - }, - ] - }, - 'with prefix, no matches': { - html: '<b>lorem ipsum dolor amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'dolor', - prefix: 'oopsum ', - }, - expected: [] - }, - 'with suffix, no matches': { - html: '<b>lorem ipsum dolor amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'dolor', - suffix: ' amot', - }, - expected: [] - }, - 'with suffix, no matches due to whitespace': { - html: '<b>lorem ipsum dolor amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'dolor', - suffix: 'a', - }, - expected: [] - }, - 'with empty prefix and suffix': { - html: '<b>lorem ipsum dolor amet yada yada</b>', - selector: { - type: 'TextQuoteSelector', - exact: 'dolor am', - prefix: '', - suffix: '', - }, - expected: [ - { - startContainerXPath: '//b/text()', - startOffset: 12, - endContainerXPath: '//b/text()', - endOffset: 20, - }, - ] - }, -}; - describe('createTextQuoteSelectorMatcher', () => { for (const [name, { html, selector, expected }] of Object.entries(testCases)) { it(`works for case: '${name}'`, async () => { @@ -420,7 +149,7 @@ async function testMatcher( doc: Document, scope: DomScope, selector: TextQuoteSelector, - expected: RangeInfo[] + expected: RangeInfo[], ) { const matcher = createTextQuoteSelectorMatcher(selector); const matches = []; @@ -444,15 +173,6 @@ async function testMatcher( }); } -function evaluateXPath(doc: Document, xpath: string): Node { - const result = doc.evaluate(xpath, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - 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}'` - ); - return nodes[0]; -} - function prettyNodeName(node: Node) { switch (node.nodeType) { case Node.TEXT_NODE: diff --git a/packages/dom/test/utils.ts b/packages/dom/test/utils.ts new file mode 100644 index 0000000..7aaa9c9 --- /dev/null +++ b/packages/dom/test/utils.ts @@ -0,0 +1,18 @@ +import { assert } from "chai"; + +// RangeInfo serialises a Range’s start and end containers as XPaths. +export type RangeInfo = { + startContainerXPath: string, + startOffset: number, + endContainerXPath: string, + endOffset: number, +}; + +export function evaluateXPath(doc: Document, xpath: string): Node { + const result = doc.evaluate(xpath, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + 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}'` + ); + return nodes[0]; +}
