Daniel Werner has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/76741


Change subject: (bug 48611) valueview expert test setups won't create instances 
anymore
......................................................................

(bug 48611) valueview expert test setups won't create instances anymore

Instead, the actual valueview instances will only created as part of the actual 
tests. This will
prevent from side-effects happening during expert's initialization. E.g. 
widgets being initialized,
causing global DOM nodes to be added to the body which would interfere with 
other tests assumptions
about the state of the DOM.

Enhanced qunit.parameterize to take an array of functions returning objects as 
test cases for this
to work conveniently.

Change-Id: Id3af61c498f4cd71e31b3424e71cce8d2eab4a83
---
M DataValues/resources/qunit.parameterize/qunit.parameterize.js
M ValueView/tests/qunit/jquery.valueview/valueview.tests.testExpert.js
2 files changed, 91 insertions(+), 70 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/DataValues 
refs/changes/41/76741/1

diff --git a/DataValues/resources/qunit.parameterize/qunit.parameterize.js 
b/DataValues/resources/qunit.parameterize/qunit.parameterize.js
index 24daae7..ad3ad73 100644
--- a/DataValues/resources/qunit.parameterize/qunit.parameterize.js
+++ b/DataValues/resources/qunit.parameterize/qunit.parameterize.js
@@ -23,24 +23,35 @@
 
        /**
         * @param {[]|Function} testCases An Array (or a callback returning 
such an object) which
-        *        has to hold different Objects where each defines what will be 
passed to tests which
-        *        will be registered to the Object returned by the function. By 
providing a callback,
+        *        has to hold different Objects and/or Functions returning an 
Object. Each of the
+        *        objects results in a test case variation and defines what 
will be passed to test
+        *        cases registered to the Object returned by the function. By 
providing a callback,
         *        the parameters provided to the tests will be created 
separately for each test. This
         *        allows to provide instances which involve state without 
running into problems when
         *        manipulating state in one test case but expecting initial 
state in another one.
         * @return {Object}
         */
        return function(testCases) {
-               var createTest = function(methodName, title, expected, 
callback, parameters) {
+               var createTest = function( methodName, title, expected, 
callback, paramsOrProvider ) {
+                       var     finalCallback = function( assert ) {
+                               var parameters =  QUnit.is( 'function', 
paramsOrProvider )
+                                       ? paramsOrProvider()
+                                       : paramsOrProvider;
+
+                               return callback.call( this, parameters, assert 
);
+                       };
+
                        QUnit[methodName](
                                title,
                                expected,
-                               function(assert) { return callback.call(this, 
parameters, assert); }
+                               finalCallback
                        );
                };
 
                var iterateTestCases = function(methodName, title, expected, 
callback) {
-                       if (!testCases) return;
+                       if (!testCases) {
+                               return;
+                       }
 
                        if (!callback) {
                                callback = expected;
@@ -52,16 +63,16 @@
                                : testCases;
 
                        for (var i = 0; i < testTestCases.length; ++i) {
-                               var parameters = testTestCases[i];
+                               var testTestCase = testTestCases[i];
 
                                var testCaseTitle = title;
-                               if (parameters.title) {
-                                       testCaseTitle += "[" + parameters.title 
+ "]";
+                               if( testTestCase.title ) {
+                                       testCaseTitle += "[" + 
testTestCase.title + "]";
                                }
 
-                               createTest(methodName, testCaseTitle, expected, 
callback, parameters);
+                               createTest( methodName, testCaseTitle, 
expected, callback, testTestCase );
                        }
-               }
+               };
 
                return {
                        test : function(title, expected, callback) {
@@ -73,7 +84,7 @@
                                iterateTestCases("asyncTest", title, expected, 
callback);
                                return this;
                        }
-               }
-       }
+               };
+       };
 
 }( QUnit ) );
diff --git 
a/ValueView/tests/qunit/jquery.valueview/valueview.tests.testExpert.js 
b/ValueView/tests/qunit/jquery.valueview/valueview.tests.testExpert.js
index 2fa30e0..6d4dac0 100644
--- a/ValueView/tests/qunit/jquery.valueview/valueview.tests.testExpert.js
+++ b/ValueView/tests/qunit/jquery.valueview/valueview.tests.testExpert.js
@@ -46,67 +46,78 @@
        }
        validRawValues.push( null );
 
-       // Used as source for expertProvider().
-       var expertDefinitions = [
-               {
-                       title: 'instance without notifier',
-                       args: [
-                               $( '<span/>' ),
-                               new valueview.MockViewState()
-                       ]
-               }, {
-                       title: 'instance with notifier',
-                       args: [
-                               $( '<div/>' ),
-                               new valueview.MockViewState(),
-                               new Notifier()
-                       ]
-               }, {
-                       title: 'instance with ViewState of disabled view',
-                       args: [
-                               $( '<div/>' ),
-                               new valueview.MockViewState( { isDisabled: true 
} ),
-                               new Notifier()
-                       ]
-               }
-       ];
+       // Used as source for expertProviders.
+       function createExpertDefinitions() {
+               return [
+                       {
+                               title: 'instance without notifier',
+                               args: [
+                                       $( '<span/>' ),
+                                       new valueview.MockViewState()
+                               ]
+                       }, {
+                               title: 'instance with notifier',
+                               args: [
+                                       $( '<div/>' ),
+                                       new valueview.MockViewState(),
+                                       new Notifier()
+                               ]
+                       }, {
+                               title: 'instance with ViewState of disabled 
view',
+                               args: [
+                                       $( '<div/>' ),
+                                       new valueview.MockViewState( { 
isDisabled: true } ),
+                                       new Notifier()
+                               ]
+                       }
+               ];
+       }
 
        /**
-        * Returns an array of Objects holding the following fields:
-        * - title: Description of the set.
+        * Returns an array of Functions. Each function returns an object with 
the following fields
+        * when executed:
         * - expert: A valueview Expert instance.
         * - constructorArgs: Arguments used to construct the expert given in 
the "expert" field.
         *
-        * @returns {Array}
+        * Each function has a "title" field which describes the expert 
instance mentioned above.
+        *
+        * @type {Function[]}
         */
-       function expertProvider() {
-               var experts = [];
+       function createExpertProviders() {
+               return $.map( createExpertDefinitions(), function( definition ) 
{
+                       // provide a setup function for cases parameter 
creation instead of creating a case
+                       // definition object directly. If we would do the 
later, the expert would already
+                       // be created and in some cases create conflicts with 
other tests since some experts
+                       // immediately instantiate certain widgets (e.g. 
inputextender).
+                       var caseSetup = function() {
+                               var $viewPort = definition.args[0],
+                                       viewState = definition.args[1],
+                                       notifier = definition.args[2];
 
-               $.each( expertDefinitions, function( i, definition ) {
-                       var $viewPort = definition.args[0],
-                               viewState = definition.args[1],
-                               notifier = definition.args[2];
+                               var expert = new Expert( $viewPort, viewState, 
notifier );
 
-                       var expert = new Expert( $viewPort, viewState, notifier 
);
-
-                       experts.push( {
-                               title: definition.title,
-                               expert: expert,
-                               constructorArgs: definition.args
-                       } );
+                               return {
+                                       expert: expert,
+                                       constructorArgs: definition.args
+                               };
+                       };
+                       caseSetup.title = definition.title;
+                       return caseSetup;
                } );
-
-               return experts;
        }
 
-       var expertCases = QUnit.cases(
-               // provide fresh instances for each test
-               function() {
-                       return expertProvider();
-               }
-       );
+       var expertCases = QUnit.cases( createExpertProviders );
 
-       expertCases.test( 'constructor', function( args, assert ) {
+       // We always have to destroy experts so all widgets used by them get 
destroyed as well in case
+       // they add something to the body.
+       function expertCasesTestAndCleanup( description, testFn ) {
+               expertCases.test( description, function( args, assert ) {
+                       testFn( args, assert );
+                       args.expert.destroy();
+               } );
+       }
+
+       expertCasesTestAndCleanup( 'constructor', function( args, assert ) {
                assert.ok(
                        args.expert instanceof Expert,
                        'expert successfully constructed'
@@ -130,7 +141,7 @@
                );
        } );
 
-       expertCases.test( 'valueCharacteristics', function( args, assert ) {
+       expertCasesTestAndCleanup( 'valueCharacteristics', function( args, 
assert ) {
                var valueCharacteristics = args.expert.valueCharacteristics();
 
                assert.ok(
@@ -139,7 +150,7 @@
                );
        } );
 
-       expertCases.test( 'viewState', function( args, assert ) {
+       expertCasesTestAndCleanup( 'viewState', function( args, assert ) {
                var viewState = args.expert.viewState();
                assert.ok(
                        viewState instanceof valueview.ViewState,
@@ -147,7 +158,7 @@
                );
        } );
 
-       expertCases.test( 'rawValueCompare: Test of different raw values', 
function( args, assert ) {
+       expertCasesTestAndCleanup( 'rawValueCompare: Test of different raw 
values', function( args, assert ) {
                $.each( validRawValues, function( i, testValue ) {
                        $.each( validRawValues, function( j, otherValue ) {
                                var successExpected = i === j;
@@ -162,7 +173,7 @@
                } );
        } );
 
-       expertCases.test( 'rawValueCompare: Works with 2nd parameter omitted', 
function( args, assert ) {
+       expertCasesTestAndCleanup( 'rawValueCompare: Works with 2nd parameter 
omitted', function( args, assert ) {
                var expert = args.expert;
 
                assert.ok(
@@ -178,7 +189,7 @@
                );
        } );
 
-       expertCases.test( 'rawValue: initial value', function( args, assert ) {
+       expertCasesTestAndCleanup( 'rawValue: initial value', function( args, 
assert ) {
                assert.equal(
                        args.expert.rawValue(),
                        null,
@@ -186,7 +197,7 @@
                );
        } );
 
-       expertCases.test( 'rawValue: setting and getting raw value', function( 
args, assert ) {
+       expertCasesTestAndCleanup( 'rawValue: setting and getting raw value', 
function( args, assert ) {
                var expert = args.expert;
 
                $.each( validRawValues, function( i, testValue ) {
@@ -203,8 +214,7 @@
                } );
        } );
 
-       expertCases.test( 'rawValue: setting value to unknown value', function( 
args, assert ) {
-
+       expertCasesTestAndCleanup( 'rawValue: setting value to unknown value', 
function( args, assert ) {
                $.each( unknownRawValues, function( i, testValue ) {
                        QUnit.stop();
 
@@ -360,7 +370,7 @@
                ]
        },
        /**
-        * Defines what kind of value parser the Expert's parse() function is 
exptected to return.
+        * Defines what kind of value parser the Expert's parse() function is 
expected to return.
         * @type Function Constructor implementation of 
valueParsers.ValueParser.
         */
        relatedValueParser: null

-- 
To view, visit https://gerrit.wikimedia.org/r/76741
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Id3af61c498f4cd71e31b3424e71cce8d2eab4a83
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/DataValues
Gerrit-Branch: master
Gerrit-Owner: Daniel Werner <daniel.wer...@wikimedia.de>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to