Henning Snater has submitted this change and it was merged. Change subject: Added tests for jQuery.valueview.ExpertFactory ......................................................................
Added tests for jQuery.valueview.ExpertFactory Change-Id: I7fe43276d789f746f0c19c7dd89eb851d2460a66 --- M ValueView/ValueView.resources.php M ValueView/ValueView.tests.qunit.php M ValueView/resources/jquery.valueview/valueview.ExpertFactory.js A ValueView/resources/jquery.valueview/valueview.experts/experts.Mock.js M ValueView/resources/jquery.valueview/valueview.experts/experts.StaticDom.js A ValueView/tests/qunit/jquery.valueview/valueview.ExpertFactory.tests.js 6 files changed, 328 insertions(+), 11 deletions(-) Approvals: Henning Snater: Verified; Looks good to me, approved jenkins-bot: Verified diff --git a/ValueView/ValueView.resources.php b/ValueView/ValueView.resources.php index afab9e2..e2a73f0 100644 --- a/ValueView/ValueView.resources.php +++ b/ValueView/ValueView.resources.php @@ -145,6 +145,15 @@ ) ), + 'jquery.valueview.experts.mock' => $moduleTemplate + array( // mock expert for tests + 'scripts' => array( + 'jquery.valueview/valueview.experts/experts.Mock.js', + ), + 'dependencies' => array( + 'jquery.valueview.experts', + ), + ), + 'jquery.valueview.experts.staticdom' => $moduleTemplate + array( 'scripts' => array( 'jquery.valueview/valueview.experts/experts.StaticDom.js', diff --git a/ValueView/ValueView.tests.qunit.php b/ValueView/ValueView.tests.qunit.php index ffdaa94..c0bc370 100644 --- a/ValueView/ValueView.tests.qunit.php +++ b/ValueView/ValueView.tests.qunit.php @@ -61,6 +61,17 @@ 'jquery.ui.suggester', ), ), + + 'jquery.valueview.ExpertFactory.tests' => array( + 'scripts' => array( + "$bp/jquery.valueview/valueview.ExpertFactory.tests.js", + ), + 'dependencies' => array( + 'jquery.valueview.experts', // contains ExpertFactory + 'jquery.valueview.experts.mock', + 'qunit.parameterize' + ), + ) ); } ); diff --git a/ValueView/resources/jquery.valueview/valueview.ExpertFactory.js b/ValueView/resources/jquery.valueview/valueview.ExpertFactory.js index 0f29bd3..5dd3131 100644 --- a/ValueView/resources/jquery.valueview/valueview.ExpertFactory.js +++ b/ValueView/resources/jquery.valueview/valueview.ExpertFactory.js @@ -4,7 +4,7 @@ * @licence GNU GPL v2+ * @author Daniel Werner < daniel.wer...@wikimedia.de > */ -( function( dv, dt, $, vv ) { +( function( DataValue, dt, $, vv ) { 'use strict'; var SELF = vv.ExpertFactory = function ValueviewExpertFactory() { @@ -32,7 +32,8 @@ * Registers a valueview expert for displaying values suitable for a certain data type or * of a certain data value type. * - * @param {dataTypes.DataType|dataValues.DataValue|Function} expertPurpose + * @param {dataTypes.DataType|Function} expertPurpose Can be either a DataType instance or a + * DataValue constructor. * @param {Function} expert Constructor of the expert */ registerExpert: function( expertPurpose, expert ) { @@ -41,7 +42,7 @@ } else if ( $.isFunction( expertPurpose ) // DataValue constructor - && expertPurpose.prototype instanceof dv.DataValue + && expertPurpose.prototype instanceof DataValue && expertPurpose.TYPE ) { this.registerDataValueExpert( expertPurpose.TYPE, expert ); @@ -56,7 +57,7 @@ * * @since 0.1 * - * @param {string} dataValueType + * @param {Function|string} dataValueType Either a DataValue constructor or its type. * @param {Function} expert Constructor of the expert */ registerDataValueExpert: function( dataValueType, expert ) { @@ -123,11 +124,13 @@ * @return string[] */ getCoveredDataTypes: function() { - var types = []; + var types = [], + dataTypeExperts = this._expertsForDataTypes, + dataValueExperts = this._expertsForDataValueTypes; $.each( dt.getDataTypeIds(), function( i, dtType ) { - if( this._expertsForDataTypes.hasOwnProperty( dtType ) - || this._expertsForDataValueTypes.hasOwnProperty( + if( dataTypeExperts.hasOwnProperty( dtType ) + || dataValueExperts.hasOwnProperty( dt.getDataType( dtType ).getDataValueType() ) ) { @@ -163,7 +166,7 @@ dataTypeId, expert; - if( onTheBasisOf instanceof dv.DataValue ) { + if( onTheBasisOf instanceof DataValue ) { valueType = onTheBasisOf.getType(); } else if( onTheBasisOf instanceof dt.DataType ) { @@ -172,7 +175,7 @@ } else if ( $.isFunction( onTheBasisOf ) // DataValue constructor - && onTheBasisOf.prototype instanceof dv.DataValue + && onTheBasisOf.prototype instanceof DataValue && onTheBasisOf.TYPE ) { valueType = onTheBasisOf.TYPE; @@ -211,4 +214,4 @@ } }; -}( dataValues, dataTypes, jQuery, jQuery.valueview ) ); +}( dataValues.DataValue, dataTypes, jQuery, jQuery.valueview ) ); diff --git a/ValueView/resources/jquery.valueview/valueview.experts/experts.Mock.js b/ValueView/resources/jquery.valueview/valueview.experts/experts.Mock.js new file mode 100644 index 0000000..0bd584b --- /dev/null +++ b/ValueView/resources/jquery.valueview/valueview.experts/experts.Mock.js @@ -0,0 +1,58 @@ +/** + * @file + * @ingroup ValueView + * @licence GNU GPL v2+ + * @author Daniel Werner < daniel.wer...@wikimedia.de > + */ +( function( $, vv ) { + 'use strict'; + + var PARENT = vv.Expert; + + /** + * Valueview expert for tests. Simply overwrites all abstract functions with some mock + * functions. A raw value can be set, all values are accepted. + * + * @since 0.1 + * + * @constructor + * @extends jQuery.valueview.Expert + */ + vv.experts.Mock = vv.expert( 'mock', PARENT, { + /** + * Current value. + * @type {*} + */ + value: null, + + /** + * @see jQuery.valueview.Expert.destroy + */ + destroy: function() { + this._value = null; + PARENT.prototype.destroy.call( this ); + }, + + /** + * @see jQuery.valueview.Expert._getRawValue + */ + _getRawValue: function() { + return this._value; + }, + + /** + * @see jQuery.valueview.Expert._setRawValue + */ + _setRawValue: function( rawValue ) { + this._value = rawValue; + }, + + /** + * @see jQuery.valueview.Expert.draw + */ + draw: function() { + this.$viewPort.empty(); + } + } ); + +}( jQuery, jQuery.valueview ) ); diff --git a/ValueView/resources/jquery.valueview/valueview.experts/experts.StaticDom.js b/ValueView/resources/jquery.valueview/valueview.experts/experts.StaticDom.js index 14e6399..53b3e03 100644 --- a/ValueView/resources/jquery.valueview/valueview.experts/experts.StaticDom.js +++ b/ValueView/resources/jquery.valueview/valueview.experts/experts.StaticDom.js @@ -5,7 +5,7 @@ * @author Daniel Werner < daniel.wer...@wikimedia.de > */ ( function( $, vv ) { - 'use strict' + 'use strict'; var PARENT = vv.Expert; diff --git a/ValueView/tests/qunit/jquery.valueview/valueview.ExpertFactory.tests.js b/ValueView/tests/qunit/jquery.valueview/valueview.ExpertFactory.tests.js new file mode 100644 index 0000000..ffde0c6 --- /dev/null +++ b/ValueView/tests/qunit/jquery.valueview/valueview.ExpertFactory.tests.js @@ -0,0 +1,236 @@ +/** + * @since 0.1 + * @ingroup ValueView + * + * @licence GNU GPL v2+ + * @author Daniel Werner < daniel.wer...@wikimedia.de > + */ + +( function( $, QUnit, dataValues, dataTypes ) { + 'use strict'; + + var dv = dataValues, + dt = dataTypes, + vv = $.valueview, + ExpertFactory = vv.ExpertFactory, + MockExpertBase = vv.experts.Mock; + + /** + * Returns a descriptive string about a valid expert base object (a DataType object, a + * DataValue object or a DataValue constructor). + * + * @param {dataTypes.DataType|dataValues.DataValue|Function} expertBasis + * @returns {string} + */ + function expertBasisInfo( expertBasis ) { + if( expertBasis instanceof dt.DataType ) { + return 'DataType with data value type "' + expertBasis.getDataValueType() + '"'; + } + if( expertBasis instanceof dv.DataValue ) { + return 'DataValue instance of type "' + expertBasis.getType() + '"'; + } + // DataValue constructor: + return 'constructor for DataValue of type "' + expertBasis.TYPE + '"'; + } + + /** + * Creates a new valueview expert constructor. + * + * @param {string} mockExpertId Used in the constructor name for simple identification if some + * assertion goes wrong. + * @returns {jQuery.valueview.Expert} + */ + function newMockExpertConstructor( mockExpertId ) { + return vv.expert( + 'mockexpert' + mockExpertId, // name + MockExpertBase, // base + {} // definition + ); + } + + var StringValue = dv.StringValue, + BoolValue = dv.BoolValue, + stringDataType = new dt.DataType( 'somestringtype', StringValue ), + numberDataType = new dt.DataType( 'somenumbertype', dv.NumberValue ), + MockExpertForStringValue = newMockExpertConstructor( 'ForStringValue' ), + MockExpertForBoolValue = newMockExpertConstructor( 'ForBoolValue' ), + MockExpertForStringDataType = newMockExpertConstructor( 'ForStringDataType' ); + + QUnit.module( 'jquery.valueview.ExpertFactory' ); + + QUnit.test( 'constructor', function( assert ) { + var expertFactory = new ExpertFactory(); + + assert.ok( + expertFactory instanceof ExpertFactory, + 'New ExpertFactory instance created' + ); + + assert.ok( + expertFactory.getCoveredDataValueTypes().length === 0, + 'Initially, new ExpertFactory has registered no experts for any data value type' + ); + + assert.ok( + expertFactory.getCoveredDataTypes().length === 0, + 'Initially, new ExpertFactory has registered no experts for any data type' + ); + } ); + + QUnit.test( 'test getCoveredDataValueTypes', function( assert ) { + var expertFactory = new ExpertFactory(); + + // Register two experts for data values: + expertFactory.registerExpert( StringValue, MockExpertForStringValue ); + expertFactory.registerExpert( BoolValue, MockExpertForBoolValue ); + + // Register one data type expert, shouldn't make any difference: + expertFactory.registerExpert( stringDataType, MockExpertForBoolValue ); + + assert.ok( + expertFactory.hasExpertFor( BoolValue ), + 'Expert registered for another data value type' + ); + + var coveredDvTypes = expertFactory.getCoveredDataValueTypes(); + + assert.equal( + coveredDvTypes.length, + 2, + 'There are experts registered for exactly two data value types' + ); + + assert.ok( + $.inArray( StringValue.TYPE, coveredDvTypes ) !== -1 + && $.inArray( BoolValue.TYPE, coveredDvTypes ) !== -1, + 'Both registered data value types are returned by getCoveredDataValueTypes()' + ); + } ); + + // tests for registration of experts: + + /** + * Array of test definitions as provider for "expertFactoryRegistrationTest" plus one "descr" + * field for each test. + * + * @type {Object[]} + */ + var expertFactoryRegistrationTestCases = [ + { + title: 'empty ExpertFactory', + register: [], + expect: [ + [ StringValue, null ], + [ stringDataType, null ] + ] + }, { + title: 'ExpertFactory with expert for string value, expert also suitable for string type', + register: [ + [ StringValue, MockExpertForStringValue ] + ], + expect: [ + [ StringValue, MockExpertForStringValue ], + [ new StringValue( 'foo' ), MockExpertForStringValue ], + [ stringDataType, MockExpertForStringValue ], // data type uses value type + [ BoolValue, null ], + [ new BoolValue( true ), null ], + [ numberDataType, null ] + ] + }, { + title: 'ExpertFactory for string data type. String value can\'t use this potentially more specialized expert', + register: [ + [ stringDataType, MockExpertForStringDataType ] + ], + expect: [ + [ StringValue, null ], + [ new StringValue( 'foo' ), null ], + [ stringDataType, MockExpertForStringDataType ] + ] + }, { + title: 'ExpertFactory with two experts: For data value and for data type using that data value type', + register: [ + [ StringValue, MockExpertForStringValue ], + [ stringDataType, MockExpertForStringDataType ] + ], + expect: [ + [ StringValue, MockExpertForStringValue ], + [ stringDataType, MockExpertForStringDataType ], + [ BoolValue, null ] + ] + }, { + title: 'ExpertFactory with two experts for two different data value types', + register: [ + [ StringValue, MockExpertForStringValue ], + [ BoolValue, MockExpertForBoolValue ] + ], + expect: [ + [ StringValue, MockExpertForStringValue ], + [ BoolValue, MockExpertForBoolValue ], + [ numberDataType, null ] + ] + } + ]; + + /** + * Test for registration of experts to ExpertFactory and expected conditions afterwards. + * + * @param {QUnit.assert} assert + * @param {Array[]} toRegister Array containing arrays where each one tells a ExpertFactory what + * experts to register. The inner array has to consist out of two objects as + * ExpertFactory.registerExpert would take them. + * @param {Array[]} toExpect Array containing arrays where each one states one expected + * condition of the ExpertFactory after registration of what is given in the first + * parameter. Each inner array should contain a data type, data value or data value + * constructor and an expert which is expected to be registered for it. + */ + function expertFactoryRegistrationTest( assert, toRegister, toExpect ) { + var expertFactory = new ExpertFactory(); + + assert.ok( + expertFactory instanceof ExpertFactory, + 'New expert factory created' + ); + + // register experts as per definition: + $.each( toRegister, function( i, registerPair ) { + var expertBasis = registerPair[0], + expert = registerPair[1]; + + expertFactory.registerExpert( expertBasis, expert ); + + assert.ok( + true, + 'Expert registered for ' + expertBasisInfo( expertBasis ) + ); + } ); + + // check for expected conditions: + $.each( toExpect, function( i, expectPair ) { + var expertBasis = expectPair[0], + expectedExpert = expectPair[1], + expertBasisInfoMsg = expertBasisInfo( expertBasis ); + + assert.strictEqual( + expertFactory.hasExpertFor( expertBasis ), + expectedExpert !== null, + 'Expert factory has ' + ( expectedExpert !== null ? '' : ' no' ) + + ' expert for' + expertBasisInfoMsg + ); + + assert.strictEqual( + expertFactory.getExpert( expertBasis ), + expectedExpert, + 'Requesting expert for ' + expertBasisInfoMsg + + ( expectedExpert !== null ? ' returns expected expert' : ' returns null' ) + ); + } ); + } + + // Run defined tests on expertFactoryRegistrationTest: + QUnit + .cases( expertFactoryRegistrationTestCases ) + .test( 'experts registration', function( params, assert ) { + expertFactoryRegistrationTest( assert, params.register, params.expect ); + } ); + +}( jQuery, QUnit, dataValues, dataTypes ) ); -- To view, visit https://gerrit.wikimedia.org/r/60811 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I7fe43276d789f746f0c19c7dd89eb851d2460a66 Gerrit-PatchSet: 4 Gerrit-Project: mediawiki/extensions/DataValues Gerrit-Branch: master Gerrit-Owner: Daniel Werner <daniel.wer...@wikimedia.de> Gerrit-Reviewer: Henning Snater <henning.sna...@wikimedia.de> Gerrit-Reviewer: Tobias Gritschacher <tobias.gritschac...@wikimedia.de> Gerrit-Reviewer: jenkins-bot _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits