mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-27 15:50:29 +00:00
Implement ve.NodeFactory and add tests
Change-Id: I34fdf24c0099072fe5f7178400abbc323be975d4
This commit is contained in:
parent
a239b73746
commit
69df3eefbc
|
@ -1,15 +1,44 @@
|
|||
/**
|
||||
* Data model node factory.
|
||||
* Generic node factory.
|
||||
*
|
||||
* @class
|
||||
* @constructor
|
||||
*/
|
||||
ve.NodeFactory = function() {
|
||||
//
|
||||
this.registry = [];
|
||||
};
|
||||
|
||||
/* Methods */
|
||||
|
||||
ve.NodeFactory.prototype.register = function( name, constructor ) {
|
||||
//
|
||||
/**
|
||||
* Register a node type with the factory.
|
||||
*
|
||||
* The constructor will be called as constructor( contents, attributes ), see createNode().
|
||||
*
|
||||
* @param {String} type Node type
|
||||
* @param {Function} constructor Node constructor subclassing ve.Node
|
||||
*/
|
||||
ve.NodeFactory.prototype.register = function( type, constructor ) {
|
||||
if ( typeof constructor !== 'function' ) {
|
||||
throw 'Constructor must be a function, cannot be a ' + typeof constructor;
|
||||
}
|
||||
this.registry[type] = constructor;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a node based on a type. type is used to look up the constructor to use, contents and
|
||||
* attributes are passed to the constructor.
|
||||
*
|
||||
* @param {String} type Node type
|
||||
* @param {Array|Number} contents Either an array of child nodes (for non-leaf nodes)
|
||||
* or the length (for leaf nodes)
|
||||
* @param {Object} [attributes] Attribute key/value pairs
|
||||
* @returns {ve.Node|null} The node object, or null if type is not a registered node type.
|
||||
*/
|
||||
ve.NodeFactory.prototype.createNode = function( type, contents, attributes ) {
|
||||
if ( type in this.registry ) {
|
||||
return new this.registry[type]( contents, attributes );
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
<script src="../../modules/ve2/ve.BranchNode.js"></script>
|
||||
<script src="../../modules/ve2/ve.TwigNode.js"></script>
|
||||
<script src="../../modules/ve2/ve.LeafNode.js"></script>
|
||||
<script src="../../modules/ve2/ve.NodeFactory.js"></script>
|
||||
|
||||
<!-- VisualEditor DataModel -->
|
||||
<script src="../../modules/ve2/dm/ve.dm.js"></script>
|
||||
|
@ -37,6 +38,7 @@
|
|||
<script src="ve.BranchNode.test.js"></script>
|
||||
<script src="ve.TwigNode.test.js"></script>
|
||||
<script src="ve.LeafNode.test.js"></script>
|
||||
<script src="ve.NodeFactory.test.js"></script>
|
||||
<script src="dm/ve.dm.Node.test.js"></script>
|
||||
<script src="dm/ve.dm.BranchNode.test.js"></script>
|
||||
<script src="dm/ve.dm.TwigNode.test.js"></script>
|
||||
|
|
40
tests/ve2/ve.NodeFactory.test.js
Normal file
40
tests/ve2/ve.NodeFactory.test.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
module( 've.NodeFactory' );
|
||||
|
||||
/* Stubs */
|
||||
|
||||
ve.NodeStub1 = function( content, attributes ) {
|
||||
this.content = content;
|
||||
this.attributes = attributes;
|
||||
this.type = 'nodestub1';
|
||||
};
|
||||
|
||||
ve.NodeStub2 = function( content, attributes ) {
|
||||
this.content = content;
|
||||
this.attributes = attributes;
|
||||
this.type = 'nodestub2';
|
||||
};
|
||||
|
||||
/* Tests */
|
||||
|
||||
test( 've.NodeFactory', function() {
|
||||
var factory = new ve.NodeFactory();
|
||||
|
||||
factory.register( 'nodestub1', ve.NodeStub1 );
|
||||
var ns1 = factory.createNode( 'nodestub1', 42, { 'foo': 'bar' } );
|
||||
deepEqual( ns1, new ve.NodeStub1( 42, { 'foo': 'bar' } ), 'createNode creates a node ' +
|
||||
'using the registered constructor and passes through arguments' );
|
||||
|
||||
deepEqual( factory.createNode( 'nodestub2', 23, { 'bar': 'baz' } ), null, 'createNode ' +
|
||||
'returns null for unregistered node types' );
|
||||
factory.register( 'nodestub2', ve.NodeStub2 );
|
||||
var ns2 = factory.createNode( 'nodestub2', 16, { 'baz': 'quux' } );
|
||||
deepEqual( ns2, new ve.NodeStub2( 16, { 'baz': 'quux' } ), 'createNode creates a node ' +
|
||||
'with a previously unregistered type' );
|
||||
|
||||
raises( function() {
|
||||
factory.register( 'nodestub3', 'nodestub3' );
|
||||
},
|
||||
/^Constructor must be a function, cannot be a string$/,
|
||||
'register throws an exception when trying to register a string as a constructor'
|
||||
);
|
||||
} );
|
Loading…
Reference in a new issue