summaryrefslogtreecommitdiffstats
path: root/accessible/tests/mochitest/pivot
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--accessible/tests/mochitest/pivot.js663
-rw-r--r--accessible/tests/mochitest/pivot/a11y.ini8
-rw-r--r--accessible/tests/mochitest/pivot/doc_virtualcursor.html38
-rw-r--r--accessible/tests/mochitest/pivot/doc_virtualcursor_text.html33
-rw-r--r--accessible/tests/mochitest/pivot/test_virtualcursor.html119
-rw-r--r--accessible/tests/mochitest/pivot/test_virtualcursor_text.html267
6 files changed, 1128 insertions, 0 deletions
diff --git a/accessible/tests/mochitest/pivot.js b/accessible/tests/mochitest/pivot.js
new file mode 100644
index 0000000000..45973f2be2
--- /dev/null
+++ b/accessible/tests/mochitest/pivot.js
@@ -0,0 +1,663 @@
+/* import-globals-from common.js */
+/* import-globals-from events.js */
+/* import-globals-from role.js */
+/* import-globals-from states.js */
+/* import-globals-from text.js */
+
+// //////////////////////////////////////////////////////////////////////////////
+// Constants
+
+const PREFILTER_INVISIBLE = nsIAccessibleTraversalRule.PREFILTER_INVISIBLE;
+const PREFILTER_TRANSPARENT = nsIAccessibleTraversalRule.PREFILTER_TRANSPARENT;
+const FILTER_MATCH = nsIAccessibleTraversalRule.FILTER_MATCH;
+const FILTER_IGNORE = nsIAccessibleTraversalRule.FILTER_IGNORE;
+const FILTER_IGNORE_SUBTREE = nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
+const NO_BOUNDARY = nsIAccessiblePivot.NO_BOUNDARY;
+const CHAR_BOUNDARY = nsIAccessiblePivot.CHAR_BOUNDARY;
+const WORD_BOUNDARY = nsIAccessiblePivot.WORD_BOUNDARY;
+
+const NS_ERROR_NOT_IN_TREE = 0x80780026;
+const NS_ERROR_INVALID_ARG = 0x80070057;
+
+// //////////////////////////////////////////////////////////////////////////////
+// Traversal rules
+
+/**
+ * Rule object to traverse all focusable nodes and text nodes.
+ */
+var HeadersTraversalRule = {
+ getMatchRoles() {
+ return [ROLE_HEADING];
+ },
+
+ preFilter: PREFILTER_INVISIBLE,
+
+ match(aAccessible) {
+ return FILTER_MATCH;
+ },
+
+ QueryInterface: ChromeUtils.generateQI([nsIAccessibleTraversalRule]),
+};
+
+/**
+ * Traversal rule for all focusable nodes or leafs.
+ */
+var ObjectTraversalRule = {
+ getMatchRoles() {
+ return [];
+ },
+
+ preFilter: PREFILTER_INVISIBLE | PREFILTER_TRANSPARENT,
+
+ match(aAccessible) {
+ var rv = FILTER_IGNORE;
+ var role = aAccessible.role;
+ if (
+ hasState(aAccessible, STATE_FOCUSABLE) &&
+ role != ROLE_DOCUMENT &&
+ role != ROLE_INTERNAL_FRAME
+ ) {
+ rv = FILTER_IGNORE_SUBTREE | FILTER_MATCH;
+ } else if (
+ aAccessible.childCount == 0 &&
+ role != ROLE_LISTITEM_MARKER &&
+ aAccessible.name.trim()
+ ) {
+ rv = FILTER_MATCH;
+ }
+
+ return rv;
+ },
+
+ QueryInterface: ChromeUtils.generateQI([nsIAccessibleTraversalRule]),
+};
+
+// //////////////////////////////////////////////////////////////////////////////
+// Virtual state invokers and checkers
+
+/**
+ * A checker for virtual cursor changed events.
+ */
+function VCChangedChecker(
+ aDocAcc,
+ aIdOrNameOrAcc,
+ aTextOffsets,
+ aPivotMoveMethod,
+ aIsFromUserInput,
+ aBoundaryType = NO_BOUNDARY
+) {
+ this.__proto__ = new invokerChecker(EVENT_VIRTUALCURSOR_CHANGED, aDocAcc);
+
+ this.match = function VCChangedChecker_match(aEvent) {
+ var event = null;
+ try {
+ event = aEvent.QueryInterface(nsIAccessibleVirtualCursorChangeEvent);
+ } catch (e) {
+ return false;
+ }
+
+ var expectedReason =
+ VCChangedChecker.methodReasonMap[aPivotMoveMethod] ||
+ nsIAccessiblePivot.REASON_NONE;
+
+ return (
+ event.reason == expectedReason && event.boundaryType == aBoundaryType
+ );
+ };
+
+ this.check = function VCChangedChecker_check(aEvent) {
+ SimpleTest.info("VCChangedChecker_check");
+
+ var event = null;
+ try {
+ event = aEvent.QueryInterface(nsIAccessibleVirtualCursorChangeEvent);
+ } catch (e) {
+ SimpleTest.ok(false, "Does not support correct interface: " + e);
+ }
+
+ var position = aDocAcc.virtualCursor.position;
+ var idMatches = position && position.DOMNode.id == aIdOrNameOrAcc;
+ var nameMatches = position && position.name == aIdOrNameOrAcc;
+ var accMatches = position == aIdOrNameOrAcc;
+
+ SimpleTest.ok(
+ idMatches || nameMatches || accMatches,
+ "id or name matches - expecting " +
+ prettyName(aIdOrNameOrAcc) +
+ ", got '" +
+ prettyName(position)
+ );
+
+ SimpleTest.is(
+ aEvent.isFromUserInput,
+ aIsFromUserInput,
+ "Expected user input is " + aIsFromUserInput + "\n"
+ );
+
+ SimpleTest.is(
+ event.newAccessible,
+ position,
+ "new position in event is incorrect"
+ );
+
+ if (aTextOffsets) {
+ SimpleTest.is(
+ aDocAcc.virtualCursor.startOffset,
+ aTextOffsets[0],
+ "wrong start offset"
+ );
+ SimpleTest.is(
+ aDocAcc.virtualCursor.endOffset,
+ aTextOffsets[1],
+ "wrong end offset"
+ );
+ SimpleTest.is(
+ event.newStartOffset,
+ aTextOffsets[0],
+ "wrong start offset in event"
+ );
+ SimpleTest.is(
+ event.newEndOffset,
+ aTextOffsets[1],
+ "wrong end offset in event"
+ );
+ }
+
+ var prevPosAndOffset = VCChangedChecker.getPreviousPosAndOffset(
+ aDocAcc.virtualCursor
+ );
+
+ if (prevPosAndOffset) {
+ SimpleTest.is(
+ event.oldAccessible,
+ prevPosAndOffset.position,
+ "previous position does not match"
+ );
+ SimpleTest.is(
+ event.oldStartOffset,
+ prevPosAndOffset.startOffset,
+ "previous start offset does not match"
+ );
+ SimpleTest.is(
+ event.oldEndOffset,
+ prevPosAndOffset.endOffset,
+ "previous end offset does not match"
+ );
+ }
+ };
+}
+
+VCChangedChecker.prevPosAndOffset = {};
+
+VCChangedChecker.storePreviousPosAndOffset = function storePreviousPosAndOffset(
+ aPivot
+) {
+ VCChangedChecker.prevPosAndOffset[aPivot] = {
+ position: aPivot.position,
+ startOffset: aPivot.startOffset,
+ endOffset: aPivot.endOffset,
+ };
+};
+
+VCChangedChecker.getPreviousPosAndOffset = function getPreviousPosAndOffset(
+ aPivot
+) {
+ return VCChangedChecker.prevPosAndOffset[aPivot];
+};
+
+VCChangedChecker.methodReasonMap = {
+ moveNext: nsIAccessiblePivot.REASON_NEXT,
+ movePrevious: nsIAccessiblePivot.REASON_PREV,
+ moveFirst: nsIAccessiblePivot.REASON_FIRST,
+ moveLast: nsIAccessiblePivot.REASON_LAST,
+ setTextRange: nsIAccessiblePivot.REASON_NONE,
+ moveNextByText: nsIAccessiblePivot.REASON_NEXT,
+ movePreviousByText: nsIAccessiblePivot.REASON_PREV,
+ moveToPoint: nsIAccessiblePivot.REASON_POINT,
+};
+
+/**
+ * Set a text range in the pivot and wait for virtual cursor change event.
+ *
+ * @param aDocAcc [in] document that manages the virtual cursor
+ * @param aTextAccessible [in] accessible to set to virtual cursor's position
+ * @param aTextOffsets [in] start and end offsets of text range to set in
+ * virtual cursor.
+ */
+function setVCRangeInvoker(aDocAcc, aTextAccessible, aTextOffsets) {
+ this.invoke = function virtualCursorChangedInvoker_invoke() {
+ VCChangedChecker.storePreviousPosAndOffset(aDocAcc.virtualCursor);
+ SimpleTest.info(prettyName(aTextAccessible) + " " + aTextOffsets);
+ aDocAcc.virtualCursor.setTextRange(
+ aTextAccessible,
+ aTextOffsets[0],
+ aTextOffsets[1]
+ );
+ };
+
+ this.getID = function setVCRangeInvoker_getID() {
+ return (
+ "Set offset in " +
+ prettyName(aTextAccessible) +
+ " to (" +
+ aTextOffsets[0] +
+ ", " +
+ aTextOffsets[1] +
+ ")"
+ );
+ };
+
+ this.eventSeq = [
+ new VCChangedChecker(
+ aDocAcc,
+ aTextAccessible,
+ aTextOffsets,
+ "setTextRange",
+ true
+ ),
+ ];
+}
+
+/**
+ * Move the pivot and wait for virtual cursor change event.
+ *
+ * @param aDocAcc [in] document that manages the virtual cursor
+ * @param aPivotMoveMethod [in] method to test (ie. "moveNext", "moveFirst", etc.)
+ * @param aRule [in] traversal rule object
+ * @param aIdOrNameOrAcc [in] id, accessible or accessible name to expect
+ * virtual cursor to land on after performing move method.
+ * false if no move is expected.
+ * @param aIsFromUserInput [in] set user input flag when invoking method, and
+ * expect it in the event.
+ */
+function setVCPosInvoker(
+ aDocAcc,
+ aPivotMoveMethod,
+ aRule,
+ aIdOrNameOrAcc,
+ aIsFromUserInput
+) {
+ // eslint-disable-next-line mozilla/no-compare-against-boolean-literals
+ var expectMove = aIdOrNameOrAcc != false;
+ this.invoke = function virtualCursorChangedInvoker_invoke() {
+ VCChangedChecker.storePreviousPosAndOffset(aDocAcc.virtualCursor);
+ if (aPivotMoveMethod && aRule) {
+ var moved = false;
+ switch (aPivotMoveMethod) {
+ case "moveFirst":
+ case "moveLast":
+ moved = aDocAcc.virtualCursor[aPivotMoveMethod](
+ aRule,
+ aIsFromUserInput === undefined ? true : aIsFromUserInput
+ );
+ break;
+ case "moveNext":
+ case "movePrevious":
+ moved = aDocAcc.virtualCursor[aPivotMoveMethod](
+ aRule,
+ aDocAcc.virtualCursor.position,
+ false,
+ aIsFromUserInput === undefined ? true : aIsFromUserInput
+ );
+ break;
+ }
+ SimpleTest.is(
+ !!moved,
+ !!expectMove,
+ "moved pivot with " + aPivotMoveMethod + " to " + aIdOrNameOrAcc
+ );
+ } else {
+ aDocAcc.virtualCursor.position = getAccessible(aIdOrNameOrAcc);
+ }
+ };
+
+ this.getID = function setVCPosInvoker_getID() {
+ return "Do " + (expectMove ? "" : "no-op ") + aPivotMoveMethod;
+ };
+
+ if (expectMove) {
+ this.eventSeq = [
+ new VCChangedChecker(
+ aDocAcc,
+ aIdOrNameOrAcc,
+ null,
+ aPivotMoveMethod,
+ aIsFromUserInput === undefined ? !!aPivotMoveMethod : aIsFromUserInput
+ ),
+ ];
+ } else {
+ this.eventSeq = [];
+ this.unexpectedEventSeq = [
+ new invokerChecker(EVENT_VIRTUALCURSOR_CHANGED, aDocAcc),
+ ];
+ }
+}
+
+/**
+ * Move the pivot by text and wait for virtual cursor change event.
+ *
+ * @param aDocAcc [in] document that manages the virtual cursor
+ * @param aPivotMoveMethod [in] method to test (ie. "moveNext", "moveFirst", etc.)
+ * @param aBoundary [in] boundary constant
+ * @param aTextOffsets [in] start and end offsets of text range to set in
+ * virtual cursor.
+ * @param aIdOrNameOrAcc [in] id, accessible or accessible name to expect
+ * virtual cursor to land on after performing move method.
+ * false if no move is expected.
+ * @param aIsFromUserInput [in] set user input flag when invoking method, and
+ * expect it in the event.
+ */
+function setVCTextInvoker(
+ aDocAcc,
+ aPivotMoveMethod,
+ aBoundary,
+ aTextOffsets,
+ aIdOrNameOrAcc,
+ aIsFromUserInput
+) {
+ // eslint-disable-next-line mozilla/no-compare-against-boolean-literals
+ var expectMove = aIdOrNameOrAcc != false;
+ this.invoke = function virtualCursorChangedInvoker_invoke() {
+ VCChangedChecker.storePreviousPosAndOffset(aDocAcc.virtualCursor);
+ SimpleTest.info(aDocAcc.virtualCursor.position);
+ var moved = aDocAcc.virtualCursor[aPivotMoveMethod](
+ aBoundary,
+ aIsFromUserInput === undefined
+ );
+ SimpleTest.is(
+ !!moved,
+ !!expectMove,
+ "moved pivot by text with " + aPivotMoveMethod + " to " + aIdOrNameOrAcc
+ );
+ };
+
+ this.getID = function setVCPosInvoker_getID() {
+ return (
+ "Do " +
+ (expectMove ? "" : "no-op ") +
+ aPivotMoveMethod +
+ " in " +
+ prettyName(aIdOrNameOrAcc) +
+ ", " +
+ boundaryToString(aBoundary) +
+ ", [" +
+ aTextOffsets +
+ "]"
+ );
+ };
+
+ if (expectMove) {
+ this.eventSeq = [
+ new VCChangedChecker(
+ aDocAcc,
+ aIdOrNameOrAcc,
+ aTextOffsets,
+ aPivotMoveMethod,
+ aIsFromUserInput === undefined ? true : aIsFromUserInput,
+ aBoundary
+ ),
+ ];
+ } else {
+ this.eventSeq = [];
+ this.unexpectedEventSeq = [
+ new invokerChecker(EVENT_VIRTUALCURSOR_CHANGED, aDocAcc),
+ ];
+ }
+}
+
+/**
+ * Move the pivot to the position under the point.
+ *
+ * @param aDocAcc [in] document that manages the virtual cursor
+ * @param aX [in] screen x coordinate
+ * @param aY [in] screen y coordinate
+ * @param aIgnoreNoMatch [in] don't unset position if no object was found at
+ * point.
+ * @param aRule [in] traversal rule object
+ * @param aIdOrNameOrAcc [in] id, accessible or accessible name to expect
+ * virtual cursor to land on after performing move method.
+ * false if no move is expected.
+ */
+function moveVCCoordInvoker(
+ aDocAcc,
+ aX,
+ aY,
+ aIgnoreNoMatch,
+ aRule,
+ aIdOrNameOrAcc
+) {
+ // eslint-disable-next-line mozilla/no-compare-against-boolean-literals
+ var expectMove = aIdOrNameOrAcc != false;
+ this.invoke = function virtualCursorChangedInvoker_invoke() {
+ VCChangedChecker.storePreviousPosAndOffset(aDocAcc.virtualCursor);
+ var moved = aDocAcc.virtualCursor.moveToPoint(
+ aRule,
+ aX,
+ aY,
+ aIgnoreNoMatch
+ );
+ SimpleTest.ok(
+ (expectMove && moved) || (!expectMove && !moved),
+ "moved pivot"
+ );
+ };
+
+ this.getID = function setVCPosInvoker_getID() {
+ return (
+ "Do " + (expectMove ? "" : "no-op ") + "moveToPoint " + aIdOrNameOrAcc
+ );
+ };
+
+ if (expectMove) {
+ this.eventSeq = [
+ new VCChangedChecker(aDocAcc, aIdOrNameOrAcc, null, "moveToPoint", true),
+ ];
+ } else {
+ this.eventSeq = [];
+ this.unexpectedEventSeq = [
+ new invokerChecker(EVENT_VIRTUALCURSOR_CHANGED, aDocAcc),
+ ];
+ }
+}
+
+/**
+ * Change the pivot modalRoot
+ *
+ * @param aDocAcc [in] document that manages the virtual cursor
+ * @param aModalRootAcc [in] accessible of the modal root, or null
+ * @param aExpectedResult [in] error result expected. 0 if expecting success
+ */
+function setModalRootInvoker(aDocAcc, aModalRootAcc, aExpectedResult) {
+ this.invoke = function setModalRootInvoker_invoke() {
+ var errorResult = 0;
+ try {
+ aDocAcc.virtualCursor.modalRoot = aModalRootAcc;
+ } catch (x) {
+ SimpleTest.ok(
+ x.result,
+ "Unexpected exception when changing modal root: " + x
+ );
+ errorResult = x.result;
+ }
+
+ SimpleTest.is(
+ errorResult,
+ aExpectedResult,
+ "Did not get expected result when changing modalRoot"
+ );
+ };
+
+ this.getID = function setModalRootInvoker_getID() {
+ return "Set modalRoot to " + prettyName(aModalRootAcc);
+ };
+
+ this.eventSeq = [];
+ this.unexpectedEventSeq = [
+ new invokerChecker(EVENT_VIRTUALCURSOR_CHANGED, aDocAcc),
+ ];
+}
+
+/**
+ * Add invokers to a queue to test a rule and an expected sequence of element ids
+ * or accessible names for that rule in the given document.
+ *
+ * @param aQueue [in] event queue in which to push invoker sequence.
+ * @param aDocAcc [in] the managing document of the virtual cursor we are
+ * testing
+ * @param aRule [in] the traversal rule to use in the invokers
+ * @param aModalRoot [in] a modal root to use in this traversal sequence
+ * @param aSequence [in] a sequence of accessible names or element ids to expect
+ * with the given rule in the given document
+ */
+function queueTraversalSequence(aQueue, aDocAcc, aRule, aModalRoot, aSequence) {
+ aDocAcc.virtualCursor.position = null;
+
+ // Add modal root (if any)
+ aQueue.push(new setModalRootInvoker(aDocAcc, aModalRoot, 0));
+
+ aQueue.push(new setVCPosInvoker(aDocAcc, "moveFirst", aRule, aSequence[0]));
+
+ for (let i = 1; i < aSequence.length; i++) {
+ let invoker = new setVCPosInvoker(aDocAcc, "moveNext", aRule, aSequence[i]);
+ aQueue.push(invoker);
+ }
+
+ // No further more matches for given rule, expect no virtual cursor changes.
+ aQueue.push(new setVCPosInvoker(aDocAcc, "moveNext", aRule, false));
+
+ for (let i = aSequence.length - 2; i >= 0; i--) {
+ let invoker = new setVCPosInvoker(
+ aDocAcc,
+ "movePrevious",
+ aRule,
+ aSequence[i]
+ );
+ aQueue.push(invoker);
+ }
+
+ // No previous more matches for given rule, expect no virtual cursor changes.
+ aQueue.push(new setVCPosInvoker(aDocAcc, "movePrevious", aRule, false));
+
+ aQueue.push(
+ new setVCPosInvoker(
+ aDocAcc,
+ "moveLast",
+ aRule,
+ aSequence[aSequence.length - 1]
+ )
+ );
+
+ // No further more matches for given rule, expect no virtual cursor changes.
+ aQueue.push(new setVCPosInvoker(aDocAcc, "moveNext", aRule, false));
+
+ // set isFromUserInput to false, just to test..
+ aQueue.push(
+ new setVCPosInvoker(aDocAcc, "moveFirst", aRule, aSequence[0], false)
+ );
+
+ // No previous more matches for given rule, expect no virtual cursor changes.
+ aQueue.push(new setVCPosInvoker(aDocAcc, "movePrevious", aRule, false));
+
+ // Remove modal root (if any).
+ aQueue.push(new setModalRootInvoker(aDocAcc, null, 0));
+}
+
+/**
+ * A checker for removing an accessible while the virtual cursor is on it.
+ */
+function removeVCPositionChecker(aDocAcc, aHiddenParentAcc) {
+ this.__proto__ = new invokerChecker(EVENT_REORDER, aHiddenParentAcc);
+
+ this.check = function removeVCPositionChecker_check(aEvent) {
+ var errorResult = 0;
+ try {
+ aDocAcc.virtualCursor.moveNext(ObjectTraversalRule);
+ } catch (x) {
+ errorResult = x.result;
+ }
+ SimpleTest.is(
+ errorResult,
+ NS_ERROR_NOT_IN_TREE,
+ "Expecting NOT_IN_TREE error when moving pivot from invalid position."
+ );
+ };
+}
+
+/**
+ * Put the virtual cursor's position on an object, and then remove it.
+ *
+ * @param aDocAcc [in] document that manages the virtual cursor
+ * @param aPosNode [in] DOM node to hide after virtual cursor's position is
+ * set to it.
+ */
+function removeVCPositionInvoker(aDocAcc, aPosNode) {
+ this.accessible = getAccessible(aPosNode);
+ this.invoke = function removeVCPositionInvoker_invoke() {
+ aDocAcc.virtualCursor.position = this.accessible;
+ aPosNode.remove();
+ };
+
+ this.getID = function removeVCPositionInvoker_getID() {
+ return "Bring virtual cursor to accessible, and remove its DOM node.";
+ };
+
+ this.eventSeq = [
+ new removeVCPositionChecker(aDocAcc, this.accessible.parent),
+ ];
+}
+
+/**
+ * A checker for removing the pivot root and then calling moveFirst, and
+ * checking that an exception is thrown.
+ */
+function removeVCRootChecker(aPivot) {
+ this.__proto__ = new invokerChecker(EVENT_REORDER, aPivot.root.parent);
+
+ this.check = function removeVCRootChecker_check(aEvent) {
+ var errorResult = 0;
+ try {
+ aPivot.moveLast(ObjectTraversalRule);
+ } catch (x) {
+ errorResult = x.result;
+ }
+ SimpleTest.is(
+ errorResult,
+ NS_ERROR_NOT_IN_TREE,
+ "Expecting NOT_IN_TREE error when moving pivot from invalid position."
+ );
+ };
+}
+
+/**
+ * Create a pivot, remove its root, and perform an operation where the root is
+ * needed.
+ *
+ * @param aRootNode [in] DOM node of which accessible will be the root of the
+ * pivot. Should have more than one child.
+ */
+function removeVCRootInvoker(aRootNode) {
+ this.pivot = gAccService.createAccessiblePivot(getAccessible(aRootNode));
+ this.invoke = function removeVCRootInvoker_invoke() {
+ this.pivot.position = this.pivot.root.firstChild;
+ aRootNode.remove();
+ };
+
+ this.getID = function removeVCRootInvoker_getID() {
+ return "Remove root of pivot from tree.";
+ };
+
+ this.eventSeq = [new removeVCRootChecker(this.pivot)];
+}
+
+/**
+ * A debug utility for writing proper sequences for queueTraversalSequence.
+ */
+function dumpTraversalSequence(aPivot, aRule) {
+ var sequence = [];
+ if (aPivot.moveFirst(aRule)) {
+ do {
+ sequence.push("'" + prettyName(aPivot.position) + "'");
+ } while (aPivot.moveNext(aRule));
+ }
+ SimpleTest.info("\n[" + sequence.join(", ") + "]\n");
+}
diff --git a/accessible/tests/mochitest/pivot/a11y.ini b/accessible/tests/mochitest/pivot/a11y.ini
new file mode 100644
index 0000000000..8add460947
--- /dev/null
+++ b/accessible/tests/mochitest/pivot/a11y.ini
@@ -0,0 +1,8 @@
+[DEFAULT]
+support-files =
+ doc_virtualcursor.html
+ doc_virtualcursor_text.html
+ !/accessible/tests/mochitest/*.js
+
+[test_virtualcursor.html]
+[test_virtualcursor_text.html]
diff --git a/accessible/tests/mochitest/pivot/doc_virtualcursor.html b/accessible/tests/mochitest/pivot/doc_virtualcursor.html
new file mode 100644
index 0000000000..a456f2dfcd
--- /dev/null
+++ b/accessible/tests/mochitest/pivot/doc_virtualcursor.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Pivot test document</title>
+ <meta charset="utf-8" />
+</head>
+<body>
+ <h1 id="heading-1-1">Main Title</h1>
+ <h2 id="heading-2-1" aria-hidden="true">First Section Title</h2>
+ <p id="paragraph-1">
+ Lorem ipsum <strong>dolor</strong> sit amet. Integer vitae urna
+ leo, id <a href="#">semper</a> nulla.
+ </p>
+ <h2 id="heading-2-2" aria-hidden="undefined">Second Section Title</h2>
+ <p id="paragraph-2" aria-hidden="">
+ Sed accumsan luctus lacus, vitae mollis arcu tristique vulputate.</p>
+ <p id="paragraph-3" aria-hidden="true">
+ <a href="#" id="hidden-link">Maybe</a> it was the other <i>George Michael</i>.
+ You know, the <a href="#">singer-songwriter</a>.
+ </p>
+ <p style="opacity: 0;" id="paragraph-4">
+ This is completely transparent
+ </p>
+ <iframe
+ src="data:text/html,<html><body>An <i>embedded</i> document.</body></html>">
+ </iframe>
+ <div id="hide-me">Hide me</div>
+ <p id="links" aria-hidden="false">
+ <a href="http://mozilla.org" title="Link 1 title">Link 1</a>
+ <a href="http://mozilla.org" title="Link 2 title">Link 2</a>
+ <a href="http://mozilla.org" title="Link 3 title">Link 3</a>
+ </p>
+ <ul>
+ <li>Hello<span> </span></li>
+ <li>World</li>
+ </ul>
+</body>
+</html>
diff --git a/accessible/tests/mochitest/pivot/doc_virtualcursor_text.html b/accessible/tests/mochitest/pivot/doc_virtualcursor_text.html
new file mode 100644
index 0000000000..f824de34bd
--- /dev/null
+++ b/accessible/tests/mochitest/pivot/doc_virtualcursor_text.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Pivot test document</title>
+ <meta charset="utf-8" />
+</head>
+<body>
+ <div id="start-block">This is the very beginning.</div>
+ <p id="paragraph-1">
+ This <b>is</b> <a id="p1-link-1" href="#">the</a> test of text.
+ </p>
+ <div id="section-1">A <a id="s1-link-1" href="#">multiword link</a> is here. <a id="s1-link-2" href="#">We</a> will traverse</div>
+ <div id="section-2">into, out, and between the subtrees.</div>
+ <p id="paragraph-2">Singularity.</p>
+ <table>
+ <tr>
+ <td id="cell-1">Magical</td>
+ <td id="cell-2">unicorns</td>
+ </tr>
+ <tr>
+ <td id="cell-3">and wizards</td>
+ <td id="cell-4">really exist.</td>
+ </tr>
+ </table>
+ <div id="section-3">Endless fun!</div>
+ <p id="paragraph-3">Objects<a id="p3-link-1" href="#">adjacent</a>to <a id="p3-link-2" href="#">each</a><a id="p3-link-3" href="#">other</a> should be separate.</p>
+ <p id="paragraph-4">Hello <strong>real</strong><a href="#"> world</p>
+ <a href="#" id="image-desc-link">
+ <img src="../moz.png" alt="">Hello
+ </a>
+ <div id="end-block">End!</div>
+</body>
+</html>
diff --git a/accessible/tests/mochitest/pivot/test_virtualcursor.html b/accessible/tests/mochitest/pivot/test_virtualcursor.html
new file mode 100644
index 0000000000..9f3225fcf6
--- /dev/null
+++ b/accessible/tests/mochitest/pivot/test_virtualcursor.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Tests pivot functionality in virtual cursors</title>
+ <meta charset="utf-8" />
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js">
+ </script>
+ <script src="chrome://mochikit/content/chrome-harness.js">
+ </script>
+
+ <script type="application/javascript" src="../common.js"></script>
+ <script type="application/javascript" src="../browser.js"></script>
+ <script type="application/javascript" src="../events.js"></script>
+ <script type="application/javascript" src="../role.js"></script>
+ <script type="application/javascript" src="../states.js"></script>
+ <script type="application/javascript" src="../pivot.js"></script>
+ <script type="application/javascript" src="../layout.js"></script>
+
+ <script type="application/javascript">
+ var gBrowserWnd = null;
+ var gQueue = null;
+
+ function doTest() {
+ var rootAcc = getAccessible(browserDocument(), [nsIAccessibleDocument]);
+ ok(rootAcc.virtualCursor,
+ "root document does not have virtualCursor");
+
+ var doc = currentTabDocument();
+ var docAcc = getAccessible(doc, [nsIAccessibleDocument]);
+
+ // Test that embedded documents have their own virtual cursor.
+ is(docAcc.childDocumentCount, 1, "Expecting one child document");
+ ok(docAcc.getChildDocumentAt(0).virtualCursor,
+ "child document does not have virtualCursor");
+
+ gQueue = new eventQueue();
+
+ gQueue.onFinish = function onFinish() {
+ closeBrowserWindow();
+ };
+
+ queueTraversalSequence(gQueue, docAcc, HeadersTraversalRule, null,
+ ["heading-1-1", "heading-2-2"]);
+
+ queueTraversalSequence(
+ gQueue, docAcc, ObjectTraversalRule, null,
+ ["Main Title", "Lorem ipsum ",
+ "dolor", " sit amet. Integer vitae urna leo, id ",
+ "semper", " nulla. ", "Second Section Title",
+ "Sed accumsan luctus lacus, vitae mollis arcu tristique vulputate.",
+ "An ", "embedded", " document.", "Hide me", "Link 1", "Link 2",
+ "Link 3", "Hello", "World"]);
+
+ // Just a random smoke test to see if our setTextRange works.
+ gQueue.push(
+ new setVCRangeInvoker(
+ docAcc,
+ getAccessible(doc.getElementById("paragraph-2"), nsIAccessibleText),
+ [2, 6]));
+
+ gQueue.push(new removeVCPositionInvoker(
+ docAcc, doc.getElementById("hide-me")));
+
+ gQueue.push(new removeVCRootInvoker(
+ doc.getElementById("links")));
+
+ var [x, y] = getBounds(getAccessible(doc.getElementById("heading-1-1")));
+ gQueue.push(new moveVCCoordInvoker(docAcc, x + 1, y + 1, true,
+ HeadersTraversalRule, "heading-1-1"));
+
+ // Already on the point, so we should not get a move event.
+ gQueue.push(new moveVCCoordInvoker(docAcc, x + 1, y + 1, true,
+ HeadersTraversalRule, false));
+
+ // Attempting a coordinate outside any header, should not move.
+ gQueue.push(new moveVCCoordInvoker(docAcc, x - 1, y - 1, true,
+ HeadersTraversalRule, false));
+
+ // Attempting a coordinate outside any header, should move to null
+ gQueue.push(new moveVCCoordInvoker(docAcc, x - 1, y - 1, false,
+ HeadersTraversalRule, null));
+
+ queueTraversalSequence(
+ gQueue, docAcc, ObjectTraversalRule,
+ getAccessible(doc.getElementById("paragraph-1")),
+ ["Lorem ipsum ", "dolor", " sit amet. Integer vitae urna leo, id ",
+ "semper", " nulla. "]);
+
+ gQueue.push(new setModalRootInvoker(docAcc, docAcc.parent,
+ NS_ERROR_INVALID_ARG));
+
+ gQueue.push(new setVCPosInvoker(docAcc, "moveNext", ObjectTraversalRule, "dolor"));
+
+ gQueue.invoke();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(function() {
+ /* We open a new browser because we need to test with a top-level content
+ document. */
+ openBrowserWindow(
+ doTest,
+ getRootDirectory(window.location.href) + "doc_virtualcursor.html");
+ });
+ </script>
+</head>
+<body id="body">
+
+ <a target="_blank"
+ title="Introduce virtual cursor/soft focus functionality to a11y API"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=698823">Mozilla Bug 698823</a>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+</body>
+</html>
diff --git a/accessible/tests/mochitest/pivot/test_virtualcursor_text.html b/accessible/tests/mochitest/pivot/test_virtualcursor_text.html
new file mode 100644
index 0000000000..f900afff87
--- /dev/null
+++ b/accessible/tests/mochitest/pivot/test_virtualcursor_text.html
@@ -0,0 +1,267 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Tests pivot functionality in virtual cursors</title>
+ <meta charset="utf-8" />
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js">
+ </script>
+ <script src="chrome://mochikit/content/chrome-harness.js">
+ </script>
+
+ <script type="application/javascript" src="../common.js"></script>
+ <script type="application/javascript" src="../text.js"></script>
+ <script type="application/javascript" src="../browser.js"></script>
+ <script type="application/javascript" src="../events.js"></script>
+ <script type="application/javascript" src="../role.js"></script>
+ <script type="application/javascript" src="../states.js"></script>
+ <script type="application/javascript" src="../pivot.js"></script>
+ <script type="application/javascript" src="../layout.js"></script>
+
+ <script type="application/javascript">
+ var gBrowserWnd = null;
+ var gQueue = null;
+
+ function doTest() {
+ var doc = currentTabDocument();
+ var docAcc = getAccessible(doc, [nsIAccessibleDocument]);
+
+ gQueue = new eventQueue();
+
+ gQueue.onFinish = function onFinish() {
+ closeBrowserWindow();
+ };
+
+ gQueue.push(new setVCPosInvoker(docAcc, null, null,
+ getAccessible(doc.getElementById("paragraph-1"))));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 4],
+ getAccessible(doc.getElementById("paragraph-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", CHAR_BOUNDARY, [4, 5],
+ getAccessible(doc.getElementById("paragraph-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", CHAR_BOUNDARY, [3, 4],
+ getAccessible(doc.getElementById("paragraph-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [5, 7],
+ getAccessible(doc.getElementById("paragraph-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 3],
+ getAccessible(doc.getElementById("p1-link-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [10, 14],
+ getAccessible(doc.getElementById("paragraph-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 3],
+ getAccessible(doc.getElementById("p1-link-1"), nsIAccessibleText)));
+ // set user input to false, and see if it works
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [5, 7],
+ getAccessible(doc.getElementById("paragraph-1"), nsIAccessibleText)),
+ false);
+
+ gQueue.push(new setVCPosInvoker(docAcc, null, null,
+ getAccessible(doc.getElementById("section-1"))));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 1],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 9],
+ getAccessible(doc.getElementById("s1-link-1"), nsIAccessibleText)));
+ // set user input to false, and see if it works
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [10, 14],
+ getAccessible(doc.getElementById("s1-link-1"), nsIAccessibleText),
+ false));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [4, 6],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [7, 12],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 2],
+ getAccessible(doc.getElementById("s1-link-2"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [15, 19],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [20, 28],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 5],
+ getAccessible(doc.getElementById("section-2"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [6, 10],
+ getAccessible(doc.getElementById("section-2"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 5],
+ getAccessible(doc.getElementById("section-2"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [20, 28],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [15, 19],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 2],
+ getAccessible(doc.getElementById("s1-link-2"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [7, 12],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [4, 6],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [10, 14],
+ getAccessible(doc.getElementById("s1-link-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 9],
+ getAccessible(doc.getElementById("s1-link-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 1],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+
+ gQueue.push(new setVCRangeInvoker(docAcc, getAccessible(doc.getElementById("s1-link-1")), [0, 0]));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", CHAR_BOUNDARY, [1, 2],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", CHAR_BOUNDARY, [0, 1],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", CHAR_BOUNDARY, [1, 2],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", CHAR_BOUNDARY, [0, 1],
+ getAccessible(doc.getElementById("s1-link-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", CHAR_BOUNDARY, [1, 2],
+ getAccessible(doc.getElementById("s1-link-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [2, 9],
+ getAccessible(doc.getElementById("s1-link-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [10, 14],
+ getAccessible(doc.getElementById("s1-link-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", CHAR_BOUNDARY, [3, 4],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", CHAR_BOUNDARY, [13, 14],
+ getAccessible(doc.getElementById("s1-link-1"), nsIAccessibleText)));
+
+ gQueue.push(new setVCRangeInvoker(docAcc, getAccessible(doc.getElementById("section-2")), [0, 0]));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", CHAR_BOUNDARY, [27, 28],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", CHAR_BOUNDARY, [0, 1],
+ getAccessible(doc.getElementById("section-2"), nsIAccessibleText)));
+
+ gQueue.push(new setVCPosInvoker(docAcc, null, null,
+ getAccessible(doc.getElementById("paragraph-2"))));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 12],
+ getAccessible(doc.getElementById("paragraph-2"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 7],
+ getAccessible(doc.getElementById("cell-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 8],
+ getAccessible(doc.getElementById("cell-2"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 3],
+ getAccessible(doc.getElementById("cell-3"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [4, 11],
+ getAccessible(doc.getElementById("cell-3"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 6],
+ getAccessible(doc.getElementById("cell-4"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [7, 13],
+ getAccessible(doc.getElementById("cell-4"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 7],
+ getAccessible(doc.getElementById("section-3"), nsIAccessibleText)));
+
+ gQueue.push(new setVCPosInvoker(docAcc, null, null,
+ getAccessible(doc.getElementById("section-3"))));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 7],
+ getAccessible(doc.getElementById("section-3"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [7, 13],
+ getAccessible(doc.getElementById("cell-4"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 6],
+ getAccessible(doc.getElementById("cell-4"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [4, 11],
+ getAccessible(doc.getElementById("cell-3"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 3],
+ getAccessible(doc.getElementById("cell-3"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 8],
+ getAccessible(doc.getElementById("cell-2"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 7],
+ getAccessible(doc.getElementById("cell-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 12],
+ getAccessible(doc.getElementById("paragraph-2"), nsIAccessibleText)));
+
+ gQueue.push(new setVCPosInvoker(docAcc, null, null,
+ getAccessible(doc.getElementById("paragraph-3"))));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 7],
+ getAccessible(doc.getElementById("paragraph-3"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 8],
+ getAccessible(doc.getElementById("p3-link-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [8, 10],
+ getAccessible(doc.getElementById("paragraph-3"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 4],
+ getAccessible(doc.getElementById("p3-link-2"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 5],
+ getAccessible(doc.getElementById("p3-link-3"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [14, 20],
+ getAccessible(doc.getElementById("paragraph-3"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 5],
+ getAccessible(doc.getElementById("p3-link-3"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 4],
+ getAccessible(doc.getElementById("p3-link-2"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [8, 10],
+ getAccessible(doc.getElementById("paragraph-3"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 8],
+ getAccessible(doc.getElementById("p3-link-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 7],
+ getAccessible(doc.getElementById("paragraph-3"), nsIAccessibleText)));
+
+ gQueue.push(new setVCPosInvoker(docAcc, null, null,
+ getAccessible(doc.getElementById("s1-link-2"))));
+ // Start with the pivot in the middle of the paragraph
+ gQueue.push(new setVCPosInvoker(docAcc, "moveNext", ObjectTraversalRule, " will traverse"));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [15, 19],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 2],
+ getAccessible(doc.getElementById("s1-link-2"), nsIAccessibleText)));
+
+ gQueue.push(new setVCPosInvoker(docAcc, null, null,
+ getAccessible(doc.getElementById("end-block"))));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 4],
+ getAccessible(doc.getElementById("end-block"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, null, false));
+ gQueue.push(new setVCPosInvoker(docAcc, null, null,
+ getAccessible(doc.getElementById("start-block"))));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 4],
+ getAccessible(doc.getElementById("start-block"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, null, false));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, null, false));
+ gQueue.push(new setVCRangeInvoker(docAcc, getAccessible(doc.getElementById("start-block")), [0, 0]));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, null, false));
+
+ gQueue.push(new setVCPosInvoker(docAcc, null, null,
+ getAccessible(doc.getElementById("paragraph-3")).firstChild));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 7],
+ getAccessible(doc.getElementById("paragraph-3"), nsIAccessibleText)));
+
+ gQueue.push(new setVCPosInvoker(docAcc, null, null,
+ getAccessible(doc.getElementById("s1-link-1")).nextSibling));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [4, 6],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+
+ gQueue.push(new setVCPosInvoker(docAcc, null, null,
+ getAccessible(doc.getElementById("paragraph-4")).firstChild.nextSibling));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [6, 10],
+ getAccessible(doc.getElementById("paragraph-4"), nsIAccessibleText)));
+
+ gQueue.push(new setVCPosInvoker(docAcc, null, null,
+ getAccessible(doc.getElementById("section-1"))));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [20, 28],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+
+ gQueue.push(new setVCPosInvoker(docAcc, null, null,
+ getAccessible(doc.getElementById("section-1")).lastChild));
+ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [20, 28],
+ getAccessible(doc.getElementById("section-1"), nsIAccessibleText)));
+
+ gQueue.push(new setVCPosInvoker(docAcc, null, null,
+ getAccessible(doc.getElementById("image-desc-link"))));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", CHAR_BOUNDARY, [0, 1],
+ getAccessible(doc.getElementById("image-desc-link"), nsIAccessibleText)));
+ gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", CHAR_BOUNDARY, [1, 2],
+ getAccessible(doc.getElementById("image-desc-link"), nsIAccessibleText)));
+
+ gQueue.invoke();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(function() {
+ /* We open a new browser because we need to test with a top-level content
+ document. */
+ openBrowserWindow(
+ doTest,
+ getRootDirectory(window.location.href) + "doc_virtualcursor_text.html");
+ });
+ </script>
+</head>
+<body id="body">
+
+ <a target="_blank"
+ title="Support Movement By Granularity"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=886076">Mozilla Bug 886076</a>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+</body>
+</html>