Greatly simplified selection and node tree comparison tests

By first summarizing a node tree or node selection and then using the normal deepEqual function we are able to take advantage of native QUnit functionality to make diagnosing a problem easier under failing conditions and reduce the verbosity of the output under passing conditions.

Change-Id: I4af5d69596cf5459aa32f61ee6d5b8355233c3df
This commit is contained in:
Trevor Parscal 2012-05-15 00:25:27 -07:00
parent d6cf4fff7f
commit 6d0a24bec6
5 changed files with 87 additions and 64 deletions

View file

@ -6,6 +6,10 @@ test( 'selectNodes', function() {
var doc = new ve.ce.Document( new ve.dm.Document( ve.dm.example.data ) ),
cases = ve.example.getSelectNodesCases( doc );
for ( var i = 0; i < cases.length; i++ ) {
ve.example.nodeSelectionEqual( cases[i].actual, cases[i].expected, cases[i].msg );
deepEqual(
ve.example.getNodeSelectionSummary( cases[i].actual ),
ve.example.getNodeSelectionSummary( cases[i].expected ),
cases[i].msg
);
}
} );

View file

@ -256,7 +256,11 @@ test( 'rebuildNodes', function() {
documentNode = doc.getDocumentNode();
// Rebuild without changes
doc.rebuildNodes( documentNode, 1, 1, 5, 30 );
ve.example.nodeTreeEqual( documentNode, ve.dm.example.tree, 'rebuild without changes' );
deepEqual(
ve.example.getNodeTreeSummary( documentNode ),
ve.example.getNodeTreeSummary( ve.dm.example.tree ),
'rebuild without changes'
);
// XXX: Create a new document node tree from the old one
var tree = new ve.dm.DocumentNode( ve.dm.example.tree.getChildren() );
@ -266,7 +270,11 @@ test( 'rebuildNodes', function() {
tree.splice( 1, 1, new ve.dm.ParagraphNode( [new ve.dm.TextNode( 3 )] ) );
// Rebuild with changes
doc.rebuildNodes( documentNode, 1, 1, 5, 5 );
ve.example.nodeTreeEqual( documentNode, tree, 'replace table with paragraph' );
deepEqual(
ve.example.getNodeTreeSummary( documentNode ),
ve.example.getNodeTreeSummary( tree ),
'replace table with paragraph'
);
} );
test( 'getRelativeContentOffset', 1, function() {
@ -347,6 +355,10 @@ test( 'selectNodes', function() {
var doc = new ve.dm.Document( ve.dm.example.data ),
cases = ve.example.getSelectNodesCases( doc );
for ( var i = 0; i < cases.length; i++ ) {
ve.example.nodeSelectionEqual( cases[i].actual, cases[i].expected, cases[i].msg );
deepEqual(
ve.example.getNodeSelectionSummary( cases[i].actual ),
ve.example.getNodeSelectionSummary( cases[i].expected ),
cases[i].msg
);
}
} );

View file

@ -2,13 +2,13 @@ module( 've.dm.DocumentFragment' );
/* Tests */
test( 'constructor', 156, function() {
test( 'constructor', 2, function() {
var fragment = new ve.dm.DocumentFragment( ve.dm.example.data );
// Test count: 5 tests x 31 nodes = 155
ve.example.nodeTreeEqual( fragment.getDocumentNode(), ve.dm.example.tree,
deepEqual(
ve.example.getNodeTreeSummary( fragment.getDocumentNode() ),
ve.example.getNodeTreeSummary( ve.dm.example.tree ),
'node tree matches example data'
);
raises(
function() {
fragment = new ve.dm.DocumentFragment( [

View file

@ -149,35 +149,42 @@ test( 'commit/rollback', function() {
}
}
};
// Generate original document
var originalData = ve.dm.example.data,
originalDoc = new ve.dm.Document( originalData );
// Run tests
var originalDoc = new ve.dm.Document( ve.dm.example.data );
for ( var msg in cases ) {
var doc = new ve.dm.Document( ve.copyArray( ve.dm.example.data ) ),
var testDocument = new ve.dm.Document( ve.copyArray( originalData ) ),
tx = new ve.dm.Transaction();
for ( var i = 0; i < cases[msg].calls.length; i++ ) {
tx[cases[msg].calls[i][0]].apply( tx, cases[msg].calls[i].slice( 1 ) );
}
if ( 'expected' in cases[msg] ) {
ve.dm.TransactionProcessor.commit( doc, tx );
var expected = ve.copyArray( ve.dm.example.data );
cases[msg].expected( expected );
deepEqual( doc.getData(), expected, 'commit (data): ' + msg );
var expectedDoc = new ve.dm.Document( expected );
ve.example.nodeTreeEqual( doc.getDocumentNode(),
expectedDoc.getDocumentNode(),
// Generate expected document
var expectedData = ve.copyArray( originalData );
cases[msg].expected( expectedData );
var expectedDocument = new ve.dm.Document( expectedData );
// Commit
ve.dm.TransactionProcessor.commit( testDocument, tx );
deepEqual( testDocument.getData(), expectedData, 'commit (data): ' + msg );
deepEqual(
ve.example.getNodeTreeSummary( testDocument.getDocumentNode() ),
ve.example.getNodeTreeSummary( expectedDocument.getDocumentNode() ),
'commit (tree): ' + msg
);
ve.dm.TransactionProcessor.rollback( doc, tx );
deepEqual( doc.getData(), ve.dm.example.data, 'rollback (data): ' + msg );
ve.example.nodeTreeEqual( doc.getDocumentNode(),
originalDoc.getDocumentNode(),
// Rollback
ve.dm.TransactionProcessor.rollback( testDocument, tx );
deepEqual( testDocument.getData(), ve.dm.example.data, 'rollback (data): ' + msg );
deepEqual(
ve.example.getNodeTreeSummary( testDocument.getDocumentNode() ),
ve.example.getNodeTreeSummary( originalDoc.getDocumentNode() ),
'rollback (tree): ' + msg
);
} else if ( 'exception' in cases[msg] ) {
/*jshint loopfunc:true */
raises(
function() {
ve.dm.TransactionProcessor.commit( doc, tx );
ve.dm.TransactionProcessor.commit( testDocument, tx );
},
cases[msg].exception,
'commit: ' + msg

View file

@ -19,7 +19,7 @@ ve.example.getSelectNodesCases = function( doc ) {
'nodeRange': new ve.Range( 1, 4 )
}
],
'msg': 'partial leaf results have ranges with global offsets',
'msg': 'partial leaf results have ranges with global offsets'
},
{
'actual': doc.selectNodes( new ve.Range( 0, 10 ), 'leaves' ),
@ -192,62 +192,62 @@ ve.example.getSelectNodesCases = function( doc ) {
};
/**
* Asserts that two node trees are equivalent.
* Builds a summary of a node tree.
*
* This will perform 5 assertions on each node
* Generated summaries contain node types, lengths, outer lengths, attributes and summaries for
* each child recusively. It's simple and fast to use deepEqual on this.
*
* @method
* @param {ve.Node} node Node tree to summarize
* @param {Boolean} [shallow] Do not summarize each child recursively
* @returns {Object} Summary of node tree
*/
ve.example.nodeTreeEqual = function( a, b, desc, typePath ) {
typePath = typePath ? typePath + '/' + a.getType() : a.getType();
var descPrefix = desc + ': (' + typePath + ') ';
equal( a.getType(), b.getType(), descPrefix + 'type match' );
equal( a.getLength(), b.getLength(), descPrefix + 'length match' );
equal( a.getOuterLength(), b.getOuterLength(), descPrefix + 'outer length match' );
deepEqual( a.attributes, b.attributes, descPrefix + 'attributes match' );
if ( a.children && b.children ) {
// Prevent crashes if a.children and b.children have different lengths
var minLength = a.children.length < b.children.length ? a.children.length : b.children.length;
equal( a.children.length, b.children.length, descPrefix + 'children count match' );
for ( var i = 0; i < minLength; i++ ) {
ve.example.nodeTreeEqual( a.children[i], b.children[i], desc, typePath );
ve.example.getNodeTreeSummary = function( node, shallow ) {
var summary = {
'getType': node.getType(),
'getLength': node.getLength(),
'getOuterLength': node.getOuterLength(),
'attributes': node.attributes
};
if ( node.children !== undefined ) {
summary['children.length'] = node.children.length;
if ( !shallow ) {
summary.children = [];
for ( var i = 0; i < node.children.length; i++ ) {
summary.children.push( ve.example.getNodeTreeSummary( node.children[i] ) );
}
}
} else if ( a.children ) {
ok( false, descPrefix + 'children array expected but not present' );
} else if ( b.children ) {
ok( false, descPrefix + 'children array present but not expected' );
} else {
ok( true, descPrefix + 'node is childless' );
}
return summary;
};
/**
* Asserts that two node selections are equivalent.
* Builds a summary of a node selection.
*
* This will perform 1 assertion to check the number of results in the selection and then 2
* assertions on each result
* Generated summaries contain length of results as well as node summaries, ranges, indexes, indexes
* within parent and node ranges for each result. It's simple and fast to use deepEqual on this.
*
* @method
* @param {Object[]} selection Selection to summarize
* @returns {Object} Summary of selection
*/
ve.example.nodeSelectionEqual = function( a, b, desc ) {
var descPrefix = desc ? desc + ': ' : '';
// Prevent crashes if a and b have different lengths
var minLength = a.length < b.length ? a.length : b.length;
equal( a.length, b.length, descPrefix + 'length match' );
for ( var i = 0; i < minLength; i++ ) {
ok( a[i].node === b[i].node, descPrefix + 'node match (element ' + i + ')' );
if ( a[i].range && b[i].range ) {
deepEqual( a[i].range, b[i].range, descPrefix + 'range match (element ' + i + ')' );
} else {
strictEqual( 'range' in a[i], 'range' in b[i],
descPrefix + 'range existence match (element ' + i + ')' );
ve.example.getNodeSelectionSummary = function( selection ) {
var summary = {
'length': selection.length
};
if ( selection.length ) {
summary.results = [];
for ( var i = 0; i < selection.length; i++ ) {
summary.results.push( {
'node': ve.example.getNodeTreeSummary( selection[i].node, true ),
'range': selection[i].range,
'index': selection[i].index,
'indexInNode': selection[i].indexInNode,
'nodeRange': selection[i].nodeRange
} );
}
deepEqual( a[i].index, b[i].index, descPrefix + 'index match (element ' + i + ')' );
deepEqual( a[i].indexInNode, b[i].indexInNode,
descPrefix + 'indexInNode match (element ' + i + ')' );
deepEqual( a[i].nodeRange, b[i].nodeRange,
descPrefix + 'nodeRange match (element ' + i +')' );
}
return summary;
};
/**