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) { ...@@ -341,4 +341,49 @@ AutomationUtil.getEditableRoot = function(node) {
return rootEditable; 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 }); // goog.scope
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
// Include test fixture. // Include test fixture.
GEN_INCLUDE(['../../testing/chromevox_next_e2e_test_base.js']); GEN_INCLUDE(['../../testing/chromevox_next_e2e_test_base.js']);
GEN_INCLUDE(['../../testing/assert_additions.js']);
GEN_INCLUDE(['../../testing/snippets.js']); GEN_INCLUDE(['../../testing/snippets.js']);
/** /**
...@@ -177,3 +178,38 @@ TEST_F('AutomationUtilE2ETest', 'HitTest', function() { ...@@ -177,3 +178,38 @@ TEST_F('AutomationUtilE2ETest', 'HitTest', function() {
AutomationUtil.hitTest(r, getCP(a.parent.parent))); 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) { ...@@ -279,7 +279,7 @@ CommandHandler.onCommand = function(command) {
case 'previousLine': case 'previousLine':
dir = Dir.BACKWARD; dir = Dir.BACKWARD;
didNavigate = true; didNavigate = true;
current = current.move(cursors.Unit.LINE); current = current.move(cursors.Unit.LINE, dir);
break; break;
case 'nextButton': case 'nextButton':
dir = Dir.FORWARD; dir = Dir.FORWARD;
...@@ -457,13 +457,13 @@ CommandHandler.onCommand = function(command) { ...@@ -457,13 +457,13 @@ CommandHandler.onCommand = function(command) {
break; break;
case 'jumpToTop': case 'jumpToTop':
var node = AutomationUtil.findNodePost( var node = AutomationUtil.findNodePost(
current.start.node.root, Dir.FORWARD, AutomationPredicate.leaf); current.start.node.root, Dir.FORWARD, AutomationPredicate.object);
if (node) if (node)
current = cursors.Range.fromNode(node); current = cursors.Range.fromNode(node);
break; break;
case 'jumpToBottom': case 'jumpToBottom':
var node = AutomationUtil.findNodePost( var node = AutomationUtil.findLastNode(
current.start.node.root, Dir.BACKWARD, AutomationPredicate.leaf); current.start.node.root, AutomationPredicate.object);
if (node) if (node)
current = cursors.Range.fromNode(node); current = cursors.Range.fromNode(node);
break; break;
......
...@@ -407,10 +407,7 @@ cursors.Cursor.prototype = { ...@@ -407,10 +407,7 @@ cursors.Cursor.prototype = {
} }
break; break;
case Unit.LINE: case Unit.LINE:
var deepEquivalent = this.deepEquivalent; newIndex = 0;
newNode = deepEquivalent.node || newNode;
newIndex = deepEquivalent.index || 0;
switch (movement) { switch (movement) {
case Movement.BOUND: case Movement.BOUND:
newNode = AutomationUtil.findNodeUntil( newNode = AutomationUtil.findNodeUntil(
...@@ -551,9 +548,7 @@ cursors.WrappingCursor.prototype = { ...@@ -551,9 +548,7 @@ cursors.WrappingCursor.prototype = {
// Case 2: backward (sync downwards to a leaf), if already on the root. // Case 2: backward (sync downwards to a leaf), if already on the root.
if (dir == Dir.BACKWARD && endpoint == this.node) { if (dir == Dir.BACKWARD && endpoint == this.node) {
playEarcon = true; playEarcon = true;
endpoint = AutomationUtil.findNodePre(endpoint, dir, function(n) { endpoint = AutomationUtil.findLastNode(endpoint, pred) || endpoint;
return pred(n) && !AutomationPredicate.shouldIgnoreNode(n);
}) || endpoint;
} }
if (playEarcon) 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