diff --git a/test/asset/qunit-extras.js b/test/asset/qunit-extras.js index 89d8221db..3f54a8939 100644 --- a/test/asset/qunit-extras.js +++ b/test/asset/qunit-extras.js @@ -21,6 +21,15 @@ ''': "'" }; + /** Detect free variable `exports` */ + var freeExports = typeof exports == 'object' && exports; + + /** Detect free variable `global`, from Node.js or Browserified code, and use it as `root` */ + var freeGlobal = typeof global == 'object' && global; + if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { + root = freeGlobal; + } + /*--------------------------------------------------------------------------*/ /** @@ -82,83 +91,108 @@ /*--------------------------------------------------------------------------*/ - /** The number of retries async tests have to succeed */ - QUnit.config.asyncRetries = 0; - - /** An object of excused tests and assertions */ - QUnit.config.excused = {}; - /** - * A callback triggered at the start of every test. + * Installs the QUnit additions on the given `context` object. * - * @memberOf QUnit - * @param {Object} details An object with `module` and `name` properties. + * @memberOf exports + * @param {Object} context The context object. */ - QUnit.testStart(function(details) { - var excused = QUnit.config.excused || {}, - excusedTests = excused[details.module], - excusedAsserts = excusedTests && excusedTests[details.name]; + function runInContext(context) { + // exit early if no `context` is provided or if `QUnit` does not exist + if (!context || !context.QUnit) { + return; + } - var test = QUnit.config.current, - finish = test.finish; + /** Shorten `context.QUnit.QUnit` to `context.QUnit` */ + var QUnit = context.QUnit = context.QUnit.QUnit || context.QUnit; - // allow async tests to retry - if (test.async && !test.retries) { - test.retries = 0; + /** The number of retries async tests have to succeed */ + QUnit.config.asyncRetries = 0; + + /** An object of excused tests and assertions */ + QUnit.config.excused = {}; + + /** + * A callback triggered at the start of every test. + * + * @memberOf QUnit + * @param {Object} details An object with `module` and `name` properties. + */ + QUnit.testStart(function(details) { + var excused = QUnit.config.excused || {}, + excusedTests = excused[details.module], + excusedAsserts = excusedTests && excusedTests[details.name]; + + var test = QUnit.config.current, + finish = test.finish; + + // allow async tests to retry + if (test.async && !test.retries) { + test.retries = 0; + test.finish = function() { + var asserts = this.assertions, + index = -1, + length = asserts.length, + queue = QUnit.config.queue; + + while (++index < length) { + var assert = asserts[index]; + if (!assert.result && this.retries < QUnit.config.asyncRetries) { + this.retries++; + asserts.length = 0; + + var oldLength = queue.length; + this.queue(); + unshift.apply(queue, queue.splice(oldLength, queue.length - oldLength)); + return; + } + } + finish.call(this); + }; + } + // nothing to excuse + if (!excusedAsserts) { + return; + } + // excuse the entire test + if (excusedAsserts === true) { + test.async = false; + test.callback = function() {}; + test.expected = 0; + return; + } + // excuse specific assertions test.finish = function() { var asserts = this.assertions, index = -1, - length = asserts.length, - queue = QUnit.config.queue; + length = asserts.length; while (++index < length) { - var assert = asserts[index]; - if (!assert.result && this.retries < QUnit.config.asyncRetries) { - this.retries++; - asserts.length = 0; + var assert = asserts[index], + message = unescape(result(reMessage.exec(assert.message), 1)), + died = result(reDied.exec(message), 0), + expected = unescape(result(reExpected.exec(assert.message), 1)); - var oldLength = queue.length; - this.queue(); - unshift.apply(queue, queue.splice(oldLength, queue.length - oldLength)); - return; + if ((message && contains(excusedAsserts, message)) || + (died && contains(excusedAsserts, died)) || + (expected && ( + contains(excusedAsserts, expected) || + contains(excusedAsserts, expected.replace(/\s+/g, '')) + ))) { + assert.result = true; } } finish.call(this); }; - } - // nothing to excuse - if (!excusedAsserts) { - return; - } - // excuse the entire test - if (excusedAsserts === true) { - test.async = false; - test.callback = function() {}; - test.expected = 0; - return; - } - // excuse specific assertions - test.finish = function() { - var asserts = this.assertions, - index = -1, - length = asserts.length; + }); + } - while (++index < length) { - var assert = asserts[index], - message = unescape(result(reMessage.exec(assert.message), 1)), - died = result(reDied.exec(message), 0), - expected = unescape(result(reExpected.exec(assert.message), 1)); + /*--------------------------------------------------------------------------*/ - if ((message && contains(excusedAsserts, message)) || - (died && contains(excusedAsserts, died)) || - (expected && ( - contains(excusedAsserts, expected) || - contains(excusedAsserts, expected.replace(/\s+/g, '')) - ))) { - assert.result = true; - } - } - finish.call(this); - }; - }); + // expose QUnit extras + if (freeExports && !freeExports.nodeType) { + freeExports.runInContext = runInContext; + } else { + runInContext(root); + } }(this)); diff --git a/test/test.js b/test/test.js index b5b19ab7d..1a093ce75 100644 --- a/test/test.js +++ b/test/test.js @@ -8,6 +8,7 @@ body = document && document.body, create = Object.create, freeze = Object.freeze, + noop = function() {}, params = root.arguments, process = root.process, push = Array.prototype.push, @@ -59,18 +60,22 @@ /** Detect if testing `npm` modules */ var isNpm = isModularize && /\bnpm\b/.test([ui.buildPath, ui.urlParams.build]); + /** Detect if running in Java */ + var isJava = !document && !!root.java; + /** Detects if running in a PhantomJS web page */ var isPhantomPage = typeof callPhantom == 'function'; /** Detect if running in Rhino */ - var isRhino = root.java && typeof global == 'function' && global().Array === root.Array; + var isRhino = isJava && typeof global == 'function' && global().Array === root.Array; /** Use a single "load" function */ - var load = !amd && typeof require == 'function' ? require : root.load; + var load = (typeof require == 'function' && !amd) + ? require + : (isJava && root.load); /** The unit testing framework */ var QUnit = (function() { - var noop = Function.prototype; return root.QUnit || ( root.addEventListener || (root.addEventListener = noop), root.setTimeout || (root.setTimeout = noop), @@ -83,6 +88,10 @@ /*--------------------------------------------------------------------------*/ + // load QUnit extras + if (load) { + (load('./asset/qunit-extras.js') || { 'runInContext': noop }).runInContext(root); + } // log params passed to `test.js` if (params) { console.log('test.js invoked with arguments: ' + JSON.stringify(slice.call(params))); @@ -586,10 +595,9 @@ }); test('ensure `new bound` is an instance of `func`', 1, function() { - var func = function() {}, - bound = _.bind(func, {}); + var bound = _.bind(noop, {}); - ok(new bound instanceof func); + ok(new bound instanceof noop); }); test('should append array arguments to partially applied arguments (test in IE < 9)', 1, function() { @@ -2660,7 +2668,7 @@ this.b = 'b' } - Foo.prototype.c = function() {}; + Foo.prototype.c = noop; deepEqual(_.functions(new Foo), ['a', 'c']); }); @@ -3144,7 +3152,7 @@ strictEqual(_.isArguments(true), false); strictEqual(_.isArguments(new Date), false); strictEqual(_.isArguments(_), false); - strictEqual(_.isArguments({ '0': 1, 'callee': _.noop, 'length': 1 }), false); + strictEqual(_.isArguments({ '0': 1, 'callee': noop, 'length': 1 }), false); strictEqual(_.isArguments(0), false); strictEqual(_.isArguments(/x/), false); strictEqual(_.isArguments('a'), false); @@ -3540,7 +3548,7 @@ 'f': ['a', new String('b'), 'c'], 'g': new Boolean(false), 'h': new Date(2012, 4, 23), - 'i': _.noop, + 'i': noop, 'j': 'a' } }; @@ -3554,7 +3562,7 @@ 'f': ['a', 'b', 'c'], 'g': false, 'h': new Date(2012, 4, 23), - 'i': _.noop, + 'i': noop, 'j': 'a' } }; @@ -5837,7 +5845,7 @@ _.forEach(empties, function(value) { try { - actual.push(func(value, _.noop)); + actual.push(func(value, noop)); } catch(e) { } }); @@ -5849,7 +5857,7 @@ var actual = _.map(empties, function(value) { try { - return func(value, _.noop, 'x'); + return func(value, noop, 'x'); } catch(e) { } }); @@ -5857,7 +5865,7 @@ }); test('`_.' + methodName + '` should handle an initial `accumulator` value of `undefined`', 1, function() { - var actual = func([], _.noop, undefined); + var actual = func([], noop, undefined); strictEqual(actual, undefined); }); }); @@ -7605,12 +7613,12 @@ test('should pass the correct `wrapper` arguments', 1, function() { var args; - var wrapped = _.wrap(_.noop, function() { + var wrapped = _.wrap(noop, function() { args || (args = slice.call(arguments)); }); wrapped(1, 2, 3); - deepEqual(args, [_.noop, 1, 2, 3]); + deepEqual(args, [noop, 1, 2, 3]); }); test('should not set a `this` binding', 1, function() {