UNPKG

ractive

Version:

Next-generation DOM manipulation

298 lines (266 loc) 10.2 kB
/** * QUnit-TAP - A TAP Output Producer Plugin for QUnit * * https://github.com/twada/qunit-tap * version: 1.3.1pre * * Copyright (c) 2010-2013 Takuto Wada * Dual licensed under the MIT and GPLv2 licenses. * https://raw.github.com/twada/qunit-tap/master/MIT-LICENSE.txt * https://raw.github.com/twada/qunit-tap/master/GPL-LICENSE.txt * * A part of extend function is: * Copyright 2012 jQuery Foundation and other contributors * Released under the MIT license. * http://jquery.org/license * * A part of stripTags function is: * Copyright (c) 2005-2010 Sam Stephenson * Released under the MIT license. * http://prototypejs.org * * @param qunitObject QUnit object reference. * @param printLikeFunction print-like function for TAP output (assumes line-separator is added by this function for each call). * @param options configuration options to customize default behavior. * @return object to provide QUnit-TAP API and customization subject. */ var qunitTap = function qunitTap(qunitObject, printLikeFunction, options) { 'use strict'; var qunitTapVersion = '1.3.1pre', detailsExtractor, tap = {}, qu = qunitObject; if (!qu) { throw new Error('should pass QUnit object reference. Please check QUnit\'s "require" path if you are using Node.js (or any CommonJS env).'); } if (typeof printLikeFunction !== 'function') { throw new Error('should pass print-like function'); } // borrowed from qunit.js var extend = function (a, b) { var prop; for (prop in b) { if (b.hasOwnProperty(prop)) { if (typeof b[prop] === 'undefined') { delete a[prop]; } else { a[prop] = b[prop]; } } } return a; }; // option deprecation and fallback function var deprecateOption = function (optionName, fallback) { if (!options || typeof options !== 'object') { return; } if (typeof options[optionName] === 'undefined') { return; } printLikeFunction('# WARNING: Option "' + optionName + '" is deprecated and will be removed in future version.'); fallback(options[optionName]); }; tap.config = extend( { initialCount: 1, showModuleNameOnFailure: true, showTestNameOnFailure: true, showExpectationOnFailure: true, showSourceOnFailure: true }, options ); deprecateOption('noPlan', function (flag) { printLikeFunction('# Now QUnit-TAP works as with "noPlan: true" by default. If you want to delare plan explicitly, please use "QUnit.config.requireExpects" option instead.'); tap.config.noPlan = flag; }); deprecateOption('count', function (count) { tap.config.initialCount = (count + 1); }); deprecateOption('showDetailsOnFailure', function (flag) { tap.config.showModuleNameOnFailure = flag; tap.config.showTestNameOnFailure = flag; tap.config.showExpectationOnFailure = flag; tap.config.showSourceOnFailure = flag; }); tap.VERSION = qunitTapVersion; tap.puts = printLikeFunction; tap.count = tap.config.initialCount - 1; tap.expectedCount = tap.config.initialCount - 1; var isPlanRequired = function (conf) { return (typeof conf !== 'undefined' && typeof conf.requireExpects !== 'undefined' && conf.requireExpects); }; var isPassed = function (details) { return !!(details.result); }; var isFailed = function (details) { return !(isPassed(details)); }; var isAssertOkFailed = function (details) { return isFailed(details) && typeof details.expected === 'undefined' && typeof details.actual === 'undefined'; }; // borrowed from prototype.js // not required since QUnit.log receives raw data (details). see jquery/qunit@c2cde34 var stripTags = function (str) { if (!str) { return str; } return str.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); }; var escapeLineEndings = function (str) { return str.replace(/(\r?\n)/g, '$&# '); }; var ltrim = function (str) { return str.replace(/^\s+/, ''); }; var quote = function (obj) { return '\'' + obj + '\''; }; var noop = function (obj) { return obj; }; var explain = noop; if (typeof qu.jsDump !== 'undefined' && typeof qu.jsDump.parse === 'function') { explain = function (obj) { return qu.jsDump.parse(obj); }; } var render = function (desc, fieldName, fieldValue, formatter) { desc.push(fieldName + ': ' + formatter(fieldValue)); }; var renderIf = function (configName, desc, fieldName, fieldValue, formatter) { if (!tap.config[configName] || typeof fieldValue === 'undefined') { return; } render(desc, fieldName, fieldValue, formatter); }; var formatDetails = function (details) { if (isPassed(details)) { return details.message; } var desc = []; if (details.message) { desc.push(details.message); } if (tap.config.showExpectationOnFailure && !(isAssertOkFailed(details))) { render(desc, 'expected', details.expected, explain); render(desc, 'got', details.actual, explain); } renderIf('showTestNameOnFailure', desc, 'test', details.name, noop); renderIf('showModuleNameOnFailure', desc, 'module', details.module, noop); renderIf('showSourceOnFailure', desc, 'source', details.source, ltrim); return desc.join(', '); }; var formatTestLine = function (testLine, rest) { if (!rest) { return testLine; } return testLine + ' - ' + escapeLineEndings(rest); }; var setupExtractor = function (logArguments) { switch (logArguments.length) { case 1: // details detailsExtractor = function (args) { return args[0]; }; break; case 2: // result, message(with tags) detailsExtractor = function (args) { return {result: args[0], message: stripTags(args[1])}; }; break; case 3: // result, message, details detailsExtractor = function (args) { return args[2]; }; break; default: throw new Error('QUnit-TAP does not support QUnit#log arguments like this.'); } }; var extractDetailsFrom = function (logArguments) { if (detailsExtractor) { return detailsExtractor(logArguments); } setupExtractor(logArguments); return detailsExtractor(logArguments); }; var printPlanLine = function (toCount) { tap.puts(tap.config.initialCount + '..' + toCount); }; tap.explain = explain; tap.note = function note (obj) { tap.puts(escapeLineEndings('# ' + obj)); }; tap.diag = function diag (obj) { tap.note(obj); return false; }; tap.moduleStart = function moduleStart (arg) { var name = (typeof arg === 'string') ? arg : arg.name; tap.note('module: ' + name); }; tap.testStart = function testStart (arg) { var name = (typeof arg === 'string') ? arg : arg.name; tap.note('test: ' + name); }; tap.log = function log () { var details = extractDetailsFrom(arguments), testLine = ''; tap.count += 1; if (isFailed(details)) { testLine += 'not '; } testLine += ('ok ' + tap.count); tap.puts(formatTestLine(testLine, formatDetails(details))); }; // prop in arg: name,module,failed,passed,total tap.testDone = function testDone (arg) { if (isPlanRequired(qu.config)) { tap.expectedCount += qu.config.current.expected; } }; // prop in arg: failed,passed,total,runtime tap.done = function done (arg) { if (typeof tap.config.noPlan !== 'undefined' && !(tap.config.noPlan)) { // Do nothing until removal of 'noPlan' option. } else if (isPlanRequired(qu.config)) { printPlanLine(tap.expectedCount); } else { printPlanLine(tap.count); } }; var addListener = function (config) { // detect QUnit's multipleCallbacks feature. see jquery/qunit@34f6bc1 var isMultipleLoggingCallbacksSupported = (typeof config !== 'undefined' && typeof config.log !== 'undefined' && typeof config.done !== 'undefined' && typeof config.testDone !== 'undefined' && typeof config.moduleStart !== 'undefined' && typeof config.testStart !== 'undefined'), slice = Array.prototype.slice; return function (subject, observer, event) { var originalLoggingCallback = subject[event]; if (isMultipleLoggingCallbacksSupported) { originalLoggingCallback(function () { // make listener methods (moduleStart,testStart,log, ...) overridable. observer[event].apply(observer, slice.apply(arguments)); }); } else if (typeof originalLoggingCallback === 'function') { // do not overwrite old-style logging callbacks subject[event] = function () { var args = slice.apply(arguments); originalLoggingCallback.apply(subject, args); observer[event].apply(observer, args); }; } }; }(qu.config); addListener(qu, tap, 'moduleStart'); addListener(qu, tap, 'testStart'); addListener(qu, tap, 'log'); addListener(qu, tap, 'testDone'); addListener(qu, tap, 'done'); return tap; }; /*global exports:false*/ if (typeof exports !== 'undefined') { // exports qunitTap function to CommonJS world exports.qunitTap = qunitTap; }