Commit 4fba109b authored by David Tseng's avatar David Tseng Committed by Commit Bot

Fix wrapping in settings

- uncaught error to Cursor::move. Closure should have caught this as a function
  that takes two args; only passed one.

- remove deep equivalent changes in cursor line movement. This causes us to get stuck in various circumstances.

- add AutomationUtil.getLastNode. It computes the last node visited by a predicate. The assumption is that we prefer ancestors that match the predicate. Elsewhere, this is expressed as skipping initial subtree hwne moving forward.

Bug: 784699
Test: existing chromevox_tests.
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: Ib9713acf4e749cef31c5f816407df0aa45d5f87e
Reviewed-on: https://chromium-review.googlesource.com/775083Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Commit-Queue: David Tseng <dtseng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#517506}
parent 26bf6f9f
......@@ -341,4 +341,49 @@ AutomationUtil.getEditableRoot = function(node) {
return rootEditable;
};
/**
* Gets the last (DFS) ordered node matched by a predicate assuming a preference
* for ancestors.
*
* In detail:
* Given a DFS ordering on nodes a_1, ..., a_n, applying a predicate
* from 1 to n yields a different set of nodes from that when applying
* a predicate from n to 1 if we skip the remaining descendants of a
* successfully matched node when moving forward. To recover the same
* nodes when applying the predicate from n to 1, we make the
* observation that we want the shallowest node that matches the
* predicate in a successfully matched node's ancestry chain.
* @param {!AutomationNode} root Tree to search.
* @param {AutomationPredicate.Unary} pred A predicate to apply
* @return {AutomationNode}
*/
AutomationUtil.findLastNode = function(root, pred) {
var node = root;
while (node.lastChild)
node = node.lastChild;
do {
if (AutomationPredicate.shouldIgnoreNode(node))
continue;
// Get the shallowest node matching the predicate.
var walker = node;
var shallowest = null;
while (walker) {
if (walker == root)
break;
if (pred(walker) && !AutomationPredicate.shouldIgnoreNode(walker))
shallowest = walker;
walker = walker.parent;
}
if (shallowest)
return shallowest;
} while (node = AutomationUtil.findNextNode(node, Dir.BACKWARD, pred));
return null;
};
}); // goog.scope
......@@ -5,6 +5,7 @@
// Include test fixture.
GEN_INCLUDE(['../../testing/chromevox_next_e2e_test_base.js']);
GEN_INCLUDE(['../../testing/assert_additions.js']);
GEN_INCLUDE(['../../testing/snippets.js']);
/**
......@@ -177,3 +178,38 @@ TEST_F('AutomationUtilE2ETest', 'HitTest', function() {
AutomationUtil.hitTest(r, getCP(a.parent.parent)));
});
});
TEST_F('AutomationUtilE2ETest', 'FindLastNodeSimple', function() {
this.runWithLoadedTree(function() {/*!
<p aria-label=" "><div aria-label="x"></div></p>
*/}, function(r) {
assertEquals('x',
AutomationUtil.findLastNode(r, function(n) {
return n.role == RoleType.GENERIC_CONTAINER;
}).name);
});
});
TEST_F('AutomationUtilE2ETest', 'FindLastNodeNonLeaf', function() {
this.runWithLoadedTree(function() {/*!
<div aria-label="x"><div aria-label=" "></div></div>
*/}, function(r) {
assertEquals('x',
AutomationUtil.findLastNode(r, function(n) {
return n.role == RoleType.GENERIC_CONTAINER;
}).name);
});
});
TEST_F('AutomationUtilE2ETest', 'FindLastNodeComplex', function() {
this.runWithLoadedTree(function() {/*!
<p>start</p>
<div aria-label="x"><div aria-label=" "></div></div>
<p>end</p>
*/}, function(r) {
assertEquals('x',
AutomationUtil.findLastNode(r, function(n) {
return n.role == RoleType.GENERIC_CONTAINER;
}).name);
});
});
......@@ -279,7 +279,7 @@ CommandHandler.onCommand = function(command) {
case 'previousLine':
dir = Dir.BACKWARD;
didNavigate = true;
current = current.move(cursors.Unit.LINE);
current = current.move(cursors.Unit.LINE, dir);
break;
case 'nextButton':
dir = Dir.FORWARD;
......@@ -457,13 +457,13 @@ CommandHandler.onCommand = function(command) {
break;
case 'jumpToTop':
var node = AutomationUtil.findNodePost(
current.start.node.root, Dir.FORWARD, AutomationPredicate.leaf);
current.start.node.root, Dir.FORWARD, AutomationPredicate.object);
if (node)
current = cursors.Range.fromNode(node);
break;
case 'jumpToBottom':
var node = AutomationUtil.findNodePost(
current.start.node.root, Dir.BACKWARD, AutomationPredicate.leaf);
var node = AutomationUtil.findLastNode(
current.start.node.root, AutomationPredicate.object);
if (node)
current = cursors.Range.fromNode(node);
break;
......
......@@ -407,10 +407,7 @@ cursors.Cursor.prototype = {
}
break;
case Unit.LINE:
var deepEquivalent = this.deepEquivalent;
newNode = deepEquivalent.node || newNode;
newIndex = deepEquivalent.index || 0;
newIndex = 0;
switch (movement) {
case Movement.BOUND:
newNode = AutomationUtil.findNodeUntil(
......@@ -551,9 +548,7 @@ cursors.WrappingCursor.prototype = {
// Case 2: backward (sync downwards to a leaf), if already on the root.
if (dir == Dir.BACKWARD && endpoint == this.node) {
playEarcon = true;
endpoint = AutomationUtil.findNodePre(endpoint, dir, function(n) {
return pred(n) && !AutomationPredicate.shouldIgnoreNode(n);
}) || endpoint;
endpoint = AutomationUtil.findLastNode(endpoint, pred) || endpoint;
}
if (playEarcon)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment