Krinkle has uploaded a new change for review. https://gerrit.wikimedia.org/r/291789
Change subject: Remove jquery.qunit.completenessTest ...................................................................... Remove jquery.qunit.completenessTest Originally added in r89853 (540419a82e; MediaWiki 1.17.1). I created it as an experiment but it never quite worked. Frontend modules moved into seperate project as part of librarisation have proper code coverage through Karma already. For MediaWiki core this is still a work in progress, but CompletenessTest has been unmaintained for a while now. Change-Id: I5647b23500d26b0d8a831fd69ceaaf4a2cea555e --- M includes/specials/SpecialJavaScriptTest.php M resources/Resources.php D resources/src/jquery/jquery.qunit.completenessTest.js M tests/qunit/data/testrunner.js 4 files changed, 3 insertions(+), 361 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core refs/changes/89/291789/1 diff --git a/includes/specials/SpecialJavaScriptTest.php b/includes/specials/SpecialJavaScriptTest.php index ecb166a..c1d5c03 100644 --- a/includes/specials/SpecialJavaScriptTest.php +++ b/includes/specials/SpecialJavaScriptTest.php @@ -171,7 +171,7 @@ $out->addHtml( Html::inlineScript( ResourceLoader::makeLoaderConditionalScript( Xml::encodeJsCall( 'mw.loader.using', array( - array( 'jquery.qunit', 'jquery.qunit.completenessTest' ), + array( 'jquery.qunit' ), new XmlJsCode( 'function () {' . Xml::encodeJsCall( 'mw.loader.load', array( $modules ) ) . '}' ) diff --git a/resources/Resources.php b/resources/Resources.php index e56d557..1f7b80b 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -278,11 +278,6 @@ 'position' => 'top', 'targets' => array( 'desktop', 'mobile' ), ), - 'jquery.qunit.completenessTest' => array( - 'scripts' => 'resources/src/jquery/jquery.qunit.completenessTest.js', - 'dependencies' => 'jquery.qunit', - 'targets' => array( 'desktop', 'mobile' ), - ), 'jquery.spinner' => array( 'scripts' => 'resources/src/jquery/jquery.spinner.js', 'styles' => 'resources/src/jquery/jquery.spinner.css', diff --git a/resources/src/jquery/jquery.qunit.completenessTest.js b/resources/src/jquery/jquery.qunit.completenessTest.js deleted file mode 100644 index 556bf8c..0000000 --- a/resources/src/jquery/jquery.qunit.completenessTest.js +++ /dev/null @@ -1,305 +0,0 @@ -/** - * jQuery QUnit CompletenessTest 0.4 - * - * Tests the completeness of test suites for object oriented javascript - * libraries. Written to be used in environments with jQuery and QUnit. - * Requires jQuery 1.7.2 or higher. - * - * Built for and tested with: - * - Chrome 19 - * - Firefox 4 - * - Safari 5 - * - * @author Timo Tijhof, 2011-2012 - */ -( function ( mw, $ ) { - 'use strict'; - - var util, - hasOwn = Object.prototype.hasOwnProperty, - log = ( window.console && window.console.log ) - ? function () { return window.console.log.apply( window.console, arguments ); } - : function () {}; - - // Simplified version of a few jQuery methods, except that they don't - // call other jQuery methods. Required to be able to run the CompletenessTest - // on jQuery itself as well. - util = { - keys: Object.keys || function ( object ) { - var key, keys = []; - for ( key in object ) { - if ( hasOwn.call( object, key ) ) { - keys.push( key ); - } - } - return keys; - }, - each: function ( object, callback ) { - var name; - for ( name in object ) { - if ( callback.call( object[ name ], name, object[ name ] ) === false ) { - break; - } - } - }, - // $.type and $.isEmptyObject are safe as is, they don't call - // other $.* methods. Still need to be derefenced into `util` - // since the CompletenessTest will overload them with spies. - type: $.type, - isEmptyObject: $.isEmptyObject - }; - - /** - * CompletenessTest - * @constructor - * - * @example - * var myTester = new CompletenessTest( myLib ); - * @param masterVariable {Object} The root variable that contains all object - * members. CompletenessTest will recursively traverse objects and keep track - * of all methods. - * @param ignoreFn {Function} Optionally pass a function to filter out certain - * methods. Example: You may want to filter out instances of jQuery or some - * other constructor. Otherwise "missingTests" will include all methods that - * were not called from that instance. - */ - function CompletenessTest( masterVariable, ignoreFn ) { - var warn, - that = this; - - // Keep track in these objects. Keyed by strings with the - // method names (ie. 'my.foo', 'my.bar', etc.) values are boolean true. - this.injectionTracker = {}; - this.methodCallTracker = {}; - this.missingTests = {}; - - this.ignoreFn = ignoreFn === undefined ? function () { return false; } : ignoreFn; - - // Lazy limit in case something weird happends (like recurse (part of) ourself). - this.lazyLimit = 2000; - this.lazyCounter = 0; - - // Bind begin and end to QUnit. - QUnit.begin( function () { - // Suppress warnings (e.g. deprecation notices for accessing the properties) - warn = mw.log.warn; - mw.log.warn = $.noop; - - that.walkTheObject( masterVariable, null, masterVariable, [] ); - log( 'CompletenessTest/walkTheObject', that ); - - // Restore warnings - mw.log.warn = warn; - warn = undefined; - } ); - - QUnit.done( function () { - that.populateMissingTests(); - log( 'CompletenessTest/populateMissingTests', that ); - - var toolbar, testResults, cntTotal, cntCalled, cntMissing; - - cntTotal = util.keys( that.injectionTracker ).length; - cntCalled = util.keys( that.methodCallTracker ).length; - cntMissing = util.keys( that.missingTests ).length; - - function makeTestResults( blob, title, style ) { - var elOutputWrapper, elTitle, elContainer, elList, elFoot; - - elTitle = document.createElement( 'strong' ); - elTitle.textContent = title || 'Values'; - - elList = document.createElement( 'ul' ); - util.each( blob, function ( key ) { - var elItem = document.createElement( 'li' ); - elItem.textContent = key; - elList.appendChild( elItem ); - } ); - - elFoot = document.createElement( 'p' ); - elFoot.innerHTML = '<em>— CompletenessTest</em>'; - - elContainer = document.createElement( 'div' ); - elContainer.appendChild( elTitle ); - elContainer.appendChild( elList ); - elContainer.appendChild( elFoot ); - - elOutputWrapper = document.getElementById( 'qunit-completenesstest' ); - if ( !elOutputWrapper ) { - elOutputWrapper = document.createElement( 'div' ); - elOutputWrapper.id = 'qunit-completenesstest'; - } - elOutputWrapper.appendChild( elContainer ); - - util.each( style, function ( key, value ) { - elOutputWrapper.style[key] = value; - } ); - return elOutputWrapper; - } - - if ( cntMissing === 0 ) { - // Good - testResults = makeTestResults( - {}, - 'Detected calls to ' + cntCalled + '/' + cntTotal + ' methods. No missing tests!', - { - backgroundColor: '#D2E0E6', - color: '#366097', - paddingTop: '1em', - paddingRight: '1em', - paddingBottom: '1em', - paddingLeft: '1em' - } - ); - } else { - // Bad - testResults = makeTestResults( - that.missingTests, - 'Detected calls to ' + cntCalled + '/' + cntTotal + ' methods. ' + cntMissing + ' methods not covered:', - { - backgroundColor: '#EE5757', - color: 'black', - paddingTop: '1em', - paddingRight: '1em', - paddingBottom: '1em', - paddingLeft: '1em' - } - ); - } - - toolbar = document.getElementById( 'qunit-testrunner-toolbar' ); - if ( toolbar ) { - toolbar.insertBefore( testResults, toolbar.firstChild ); - } - } ); - - return this; - } - - /* Public methods */ - CompletenessTest.fn = CompletenessTest.prototype = { - - /** - * CompletenessTest.fn.walkTheObject - * - * This function recursively walks through the given object, calling itself as it goes. - * Depending on the action it either injects our listener into the methods, or - * reads from our tracker and records which methods have not been called by the test suite. - * - * @param currName {String|Null} Name of the given object member (Initially this is null). - * @param currVar {mixed} The variable to check (initially an object, - * further down it could be anything). - * @param masterVariable {Object} Throughout our interation, always keep track of the master/root. - * Initially this is the same as currVar. - * @param parentPathArray {Array} Array of names that indicate our breadcrumb path starting at - * masterVariable. Not including currName. - */ - walkTheObject: function ( currObj, currName, masterVariable, parentPathArray ) { - var key, currVal, type, - ct = this, - currPathArray = parentPathArray; - - if ( currName ) { - currPathArray.push( currName ); - currVal = currObj[currName]; - } else { - currName = '(root)'; - currVal = currObj; - } - - type = util.type( currVal ); - - // Hard ignores - if ( this.ignoreFn( currVal, this, currPathArray ) ) { - return null; - } - - // Handle the lazy limit - this.lazyCounter++; - if ( this.lazyCounter > this.lazyLimit ) { - log( 'CompletenessTest.fn.walkTheObject> Limit reached: ' + this.lazyCounter, currPathArray ); - return null; - } - - // Functions - if ( type === 'function' ) { - // Don't put a spy in constructor functions as it messes with - // instanceof etc. - if ( !currVal.prototype || util.isEmptyObject( currVal.prototype ) ) { - this.injectionTracker[ currPathArray.join( '.' ) ] = true; - this.injectCheck( currObj, currName, function () { - ct.methodCallTracker[ currPathArray.join( '.' ) ] = true; - } ); - } - } - - // Recursively. After all, this is the *completeness* test - // This also traverses static properties and the prototype of a constructor - if ( type === 'object' || type === 'function' ) { - for ( key in currVal ) { - if ( hasOwn.call( currVal, key ) ) { - this.walkTheObject( currVal, key, masterVariable, currPathArray.slice() ); - } - } - } - }, - - populateMissingTests: function () { - var ct = this; - util.each( ct.injectionTracker, function ( key ) { - ct.hasTest( key ); - } ); - }, - - /** - * CompletenessTest.fn.hasTest - * - * Checks if the given method name (ie. 'my.foo.bar') - * was called during the test suite (as far as the tracker knows). - * If not it adds it to missingTests. - * - * @param fnName {String} - * @return {Boolean} - */ - hasTest: function ( fnName ) { - if ( !( fnName in this.methodCallTracker ) ) { - this.missingTests[fnName] = true; - return false; - } - return true; - }, - - /** - * CompletenessTest.fn.injectCheck - * - * Injects a function (such as a spy that updates methodCallTracker when - * it's called) inside another function. - * - * @param masterVariable {Object} - * @param objectPathArray {Array} - * @param injectFn {Function} - */ - injectCheck: function ( obj, key, injectFn ) { - var spy, - val = obj[ key ]; - - spy = function () { - injectFn(); - return val.apply( this, arguments ); - }; - - // Make the spy inherit from the original so that its static methods are also - // visible in the spy (e.g. when we inject a check into mw.log, mw.log.warn - // must remain accessible). - /*jshint proto:true */ - spy.__proto__ = val; - - // Objects are by reference, members (unless objects) are not. - obj[ key ] = spy; - } - }; - - /* Expose */ - window.CompletenessTest = CompletenessTest; - -}( mediaWiki, jQuery ) ); diff --git a/tests/qunit/data/testrunner.js b/tests/qunit/data/testrunner.js index 03aaf4a..1bc395a 100644 --- a/tests/qunit/data/testrunner.js +++ b/tests/qunit/data/testrunner.js @@ -1,10 +1,9 @@ -/*global CompletenessTest, sinon */ +/*global sinon */ /*jshint evil: true */ ( function ( $, mw, QUnit ) { 'use strict'; - var mwTestIgnore, mwTester, - addons, + var addons, ELEMENT_NODE = 1, TEXT_NODE = 3; @@ -38,17 +37,6 @@ label: 'Enable ResourceLoaderDebug', tooltip: 'Enable debug mode in ResourceLoader', value: 'true' - } ); - - /** - * CompletenessTest - * - * Adds toggle checkbox to header - */ - QUnit.config.urlConfig.push( { - id: 'completenesstest', - label: 'Run CompletenessTest', - tooltip: 'Run the completeness test' } ); /** @@ -127,42 +115,6 @@ } ); }; }() ); - - // Initiate when enabled - if ( QUnit.urlParams.completenesstest ) { - - // Return true to ignore - mwTestIgnore = function ( val, tester ) { - - // Don't record methods of the properties of constructors, - // to avoid getting into a loop (prototype.constructor.prototype..). - // Since we're therefor skipping any injection for - // "new mw.Foo()", manually set it to true here. - if ( val instanceof mw.Map ) { - tester.methodCallTracker.Map = true; - return true; - } - if ( val instanceof mw.Title ) { - tester.methodCallTracker.Title = true; - return true; - } - - // Don't record methods of the properties of a jQuery object - if ( val instanceof $ ) { - return true; - } - - // Don't iterate over the module registry (the 'script' references would - // be listed as untested methods otherwise) - if ( val === mw.loader.moduleRegistry ) { - return true; - } - - return false; - }; - - mwTester = new CompletenessTest( mw, mwTestIgnore ); - } /** * Test environment recommended for all QUnit test modules -- To view, visit https://gerrit.wikimedia.org/r/291789 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I5647b23500d26b0d8a831fd69ceaaf4a2cea555e Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/core Gerrit-Branch: master Gerrit-Owner: Krinkle <krinklem...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits