codefirst/AsakusaSatellite

View on GitHub
qunit/lib/qunit-tap.js

Summary

Maintainability
D
1 day
Test Coverage
/**
 * QUnit-TAP - A TAP Output Producer Plugin for QUnit
 *
 * http://github.com/twada/qunit-tap
 * version: 1.0.8
 *
 * Copyright (c) 2010, 2011, 2012 Takuto Wada
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPLv2 (GPL-LICENSE.txt) licenses.
 *
 * @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.
 */
var qunitTap = function qunitTap(qunitObject, printLikeFunction, options) {
    var qunitTapVersion = '1.0.8',
        initialCount,
        multipleLoggingCallbacksSupported,
        qu = qunitObject;

    if (!qu) {
        throw new Error('should pass QUnit object reference');
    }
    if (typeof printLikeFunction !== 'function') {
        throw new Error('should pass print-like function');
    }
    if (typeof qu.tap !== 'undefined') {
        return;
    }

    // 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;
    };

    // using QUnit.tap as namespace.
    qu.tap = extend(
        {
            count: 0,
            noPlan: false,
            showDetailsOnFailure: true
        },
        options
    );
    qu.tap.puts = printLikeFunction;
    qu.tap.VERSION = qunitTapVersion;
    initialCount = qu.tap.count || 0;

    // detect QUnit's multipleCallbacks feature. see jquery/qunit@34f6bc1
    multipleLoggingCallbacksSupported =
        (typeof qu.config !== 'undefined'
         && typeof qu.config.log !== 'undefined'
         && typeof qu.config.done !== 'undefined'
         && typeof qu.config.moduleStart !== 'undefined'
         && typeof qu.config.testStart !== '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 commentAfterLineEnd = function (str) {
        return str.replace(/(\r?\n)/g, '$&# ');
    };

    var formDescription = function (str) {
        if (!str) {
            return str;
        }
        return commentAfterLineEnd(' - ' + str);
    };

    var appendDetailsTo = function (desc, details) {
        if (!qu.tap.showDetailsOnFailure || details.result) {
            return desc;
        }
        if (typeof details.expected !== 'undefined') {
            if (desc) {
                desc += ', ';
            }
            desc += 'expected: \'';
            desc += details.expected;
            desc += '\' got: \'';
            desc += details.actual;
            desc += '\'';
        }
        return desc;
    };

    qu.tap.diag = function (str) {
        if (typeof qu.jsDump !== 'undefined' && typeof qu.jsDump.parse === 'function') {
            str = qu.jsDump.parse(str);
        }
        qu.tap.puts(commentAfterLineEnd('# ' + str));
    };

    qu.tap.moduleStart = function (arg) {
        var name = (typeof arg === 'string') ? arg : arg.name;
        qu.tap.puts('# module: ' + name);
    };

    qu.tap.testStart = function (arg) {
        var name = (typeof arg === 'string') ? arg : arg.name;
        qu.tap.puts('# test: ' + name);
    };

    qu.tap.log = function () {
        var details, desc, testLine = '';
        switch (arguments.length) {
        case 1:  // details
            details = arguments[0];
            break;
        case 2:  // result, message(with tags)
            details = {result: arguments[0], message: stripTags(arguments[1])};
            break;
        case 3:  // result, message, details
            details = arguments[2];
            break;
        default:
            throw new Error('QUnit-TAP does not support QUnit#log arguments like this.');
        }
        if (!details.result) {
            testLine += 'not ';
        }
        testLine += 'ok ' + (qu.tap.count += 1);
        if (details.result && !details.message) {
            qu.tap.puts(testLine);
            return;
        }
        desc = appendDetailsTo((details.message || ''), details);
        qu.tap.puts(testLine + formDescription(desc));
    };

    // prop in arg: failed,passed,total,runtime
    qu.tap.done = function (arg) {
        if (!qu.tap.noPlan) {
            return;
        }
        qu.tap.puts((initialCount + 1) + '..' + qu.tap.count);
    };

    var addListener = function (target, name, listener) {
        var originalLoggingCallback = target[name];
        if (multipleLoggingCallbacksSupported) {
            originalLoggingCallback(listener);
        } else if (typeof originalLoggingCallback === 'function') {
            // add listener, not replacing former ones.
            target[name] = function () {
                var args = Array.prototype.slice.apply(arguments);
                originalLoggingCallback.apply(target, args);
                listener.apply(target, args);
            };
        }
    };
    addListener(qu, 'moduleStart', qu.tap.moduleStart);
    addListener(qu, 'testStart', qu.tap.testStart);
    addListener(qu, 'log', qu.tap.log);
    addListener(qu, 'done', qu.tap.done);
};

if (typeof exports !== 'undefined' || typeof require !== 'undefined') {
    // exports qunitTap function to CommonJS world
    exports.qunitTap = qunitTap;
}