Introduce es.DocumentNode.getCommonAncestorPaths(), with tests

This commit is contained in:
Roan Kattouw 2011-11-24 15:34:12 +00:00
parent 6c36ddcbce
commit 6f3c407314
3 changed files with 81 additions and 0 deletions

View file

@ -69,6 +69,40 @@ es.DocumentNode.traverseUpstream = function( node, callback ) {
}
};
/**
* Find the common ancestor of two equal-depth nodes, and return the
* path from each node to the common ancestor.
* @param {es.DocumentNode} node1
* @param {es.DocumentNode} node2
* @returns {Object|Boolean} Object with keys 'commonAncestor', 'node1Path' and 'node2Path',
* or false if there is no common ancestor or if the nodes have unequal depth
*/
es.DocumentNode.getCommonAncestorPaths = function( node1, node2 ) {
var path1 = [],
path2 = [],
n1 = node1,
n2 = node2;
// Move up from n1 and n2 simultaneously until we find the
// common ancestor
while ( n1 !== n2 ) {
// Add these nodes to their respective paths
path1.push( n1 );
path2.push( n2 );
// Move up
n1 = n1.getParent();
n2 = n2.getParent();
if ( n1 === null || n2 === null ) {
// Reached a root, so no common ancestor or unequal depth
return false;
}
}
// If we got here, we've found the common ancestor, and because we did
// simultaneous traversal we also know node1 and node2 have the same depth.
return { 'commonAncestor': n1, 'node1Path': path1, 'node2Path': path2 };
};
/* Inheritance */
es.extendClass( es.DocumentNode, es.EventEmitter );

View file

@ -0,0 +1,46 @@
module( 'es/bases' );
test( 'es.DocumentNode.getCommonAncestorPaths', 14, function() {
var documentModel = es.DocumentModel.newFromPlainObject( esTest.obj ), result;
var list = documentModel.children[1].children[0].children[0].children[1];
result = es.DocumentNode.getCommonAncestorPaths( list, list );
// Test 1
ok( result.commonAncestor == list, 'same nodes (commonAncestor)' );
// Test 2
ok( es.compareArrays( result.node1Path, [] ), 'adjacent list items (node1Path)' );
// Test 3
ok( es.compareArrays( result.node2Path, [] ), 'adjacent list items (node2Path)' );
result = es.DocumentNode.getCommonAncestorPaths( list.children[0], list.children[1] );
// Test 4
ok( result.commonAncestor == list, 'adjacent list items (commonAncestor)' );
// Test 5
ok( es.compareArrays( result.node1Path, [ list.children[0] ] ), 'adjacent list items (node1Path)' );
// Test 6
ok( es.compareArrays( result.node2Path, [ list.children[1] ] ), 'adjacent list items (node2Path)' );
result = es.DocumentNode.getCommonAncestorPaths( list.children[0], list.children[2] );
// Test 7
ok( result.commonAncestor == list, 'non-adjacent sibling list items (commonAncestor)' );
// Test 8
ok( es.compareArrays( result.node1Path, [ list.children[0] ] ), 'non-adjacent sibling list items (node1Path)' );
// Test 9
ok( es.compareArrays( result.node2Path, [ list.children[2] ] ), 'non-adjacent sibling list items (node2Path)' );
result = es.DocumentNode.getCommonAncestorPaths( list.children[0].children[0], list.children[2].children[0] );
// Test 10
ok( result.commonAncestor == list, 'paragraphs inside list items (commonAncestor)' );
// Test 11
ok( es.compareArrays( result.node1Path, [ list.children[0].children[0], list.children[0] ] ), 'paragraphs inside list items (node1Path)' );
// Test 12
ok( es.compareArrays( result.node2Path, [ list.children[2].children[0], list.children[2] ] ), 'paragraphs inside list items (node2Path)' );
result = es.DocumentNode.getCommonAncestorPaths( list.children[0].children[0], list.children[2] );
// Test 13
equal( result, false, 'nodes of unequal depth' );
result = es.DocumentNode.getCommonAncestorPaths( list, es.DocumentModel.newFromPlainObject( esTest.obj ).children[1] );
// Test 14
equal( result, false, 'nodes in different trees' );
} );

View file

@ -46,5 +46,6 @@
<script src="es.DocumentBranchNode.test.js"></script>
<script src="es.DocumentModelBranchNode.test.js"></script>
<script src="es.DocumentModel.test.js"></script>
<script src="es.DocumentNode.test.js"></script>
</body>
</html>