pax_global_header00006660000000000000000000000064131236163260014515gustar00rootroot0000000000000052 comment=53e3b9e5adee4456fa850592cf7241797bc125e2 tap-mocha-reporter-3.0.6/000077500000000000000000000000001312361632600152345ustar00rootroot00000000000000tap-mocha-reporter-3.0.6/.gitignore000066400000000000000000000000151312361632600172200ustar00rootroot00000000000000node_modules tap-mocha-reporter-3.0.6/LICENSE000066400000000000000000000037771312361632600162570ustar00rootroot00000000000000The ISC License Copyright (c) Isaac Z. Schlueter and Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ---- The reporters in this package are based on Mocha, in accordance with the terms of Mocha's license: (The MIT License) Copyright (c) 2011-2015 TJ Holowaychuk Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tap-mocha-reporter-3.0.6/README.md000066400000000000000000000007751312361632600165240ustar00rootroot00000000000000# tap-mocha-reporter Format a TAP stream using Mocha's set of reporters ## USAGE On the command line, pipe TAP in, and it'll do its thing. ```bash tap test/*.js | tap-mocha-reporter ``` You can also specify a reporter with the first argument. The default is `spec`. ```bash tap test/*.js | tap-mocha-reporter nyan ``` Programmatically, you can use this as a transform stream. ```javascript var TSR = require('tap-mocha-reporter') fs.createReadStream('saved-test-output.tap') .pipe(TSR('dot')) ``` tap-mocha-reporter-3.0.6/index.js000077500000000000000000000047571312361632600167210ustar00rootroot00000000000000#!/usr/bin/env node module.exports = Formatter var util = require('util') var reporters = require('./lib/reporters/index.js') Formatter.types = Object.keys(reporters).sort() var Writable = require('stream').Writable if (!Writable) { try { Writable = require('readable-stream').Writable } catch (er) { throw new Error('Please install "readable-stream" to use this module ' + 'with Node.js v0.8 and before') } } var Runner = require('./lib/runner.js') var Parser = require('tap-parser') util.inherits(Formatter, Writable) var exitCode function Formatter (type, options) { if (!(this instanceof Formatter)) { return new Formatter(type, options) } if (!reporters[type]) { console.error('Unknown format type: %s\n\n%s', type, avail()) type = 'silent' } this.writable = true // don't actually need a reporter to report the tap we're getting // just parse it so that we exit with the correct code, but otherwise // dump it straight through to stdout. if (type === 'tap') { var p = new Parser() this.write = function (chunk) { process.stdout.write(chunk) return p.write(chunk) } this.end = p.end.bind(p) p.on('complete', function () { if (!p.ok) exitCode = 1 }) return this } var runner = this.runner = new Runner(options) this.reporter = new reporters[type](this.runner, {}) Writable.call(this, options) runner.on('end', function () { if (!runner.parser.ok) exitCode = 1 }) } process.on('exit', function (code) { if (!code && exitCode) process.exit(exitCode) }) Formatter.prototype.write = function () { return this.runner.write.apply(this.runner, arguments) } Formatter.prototype.end = function () { return this.runner.end.apply(this.runner, arguments) } function avail () { var types = Formatter.types.reduce(function (str, t) { var ll = str.split('\n').pop().length + t.length if (ll < 40) return str + ' ' + t else return str + '\n' + t }, '').trim() return 'Available format types:\n\n' + types } function usage (err) { console[err ? 'error' : 'log'](function () {/* Usage: tap-mocha-reporter Reads TAP data on stdin, and formats to stdout using the specified reporter. (Note that some reporters write to files instead of stdout.) %s */}.toString().split('\n').slice(1, -1).join('\n'), avail()) } if (require.main === module) { var type = process.argv[2] if (!type) return usage() process.stdin.pipe(new Formatter(type)) } tap-mocha-reporter-3.0.6/lib/000077500000000000000000000000001312361632600160025ustar00rootroot00000000000000tap-mocha-reporter-3.0.6/lib/browser/000077500000000000000000000000001312361632600174655ustar00rootroot00000000000000tap-mocha-reporter-3.0.6/lib/browser/debug.js000066400000000000000000000000751312361632600211130ustar00rootroot00000000000000module.exports = function(type){ return function(){ } }; tap-mocha-reporter-3.0.6/lib/browser/escape-string-regexp.js000066400000000000000000000003501312361632600240550ustar00rootroot00000000000000'use strict'; var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; module.exports = function (str) { if (typeof str !== 'string') { throw new TypeError('Expected a string'); } return str.replace(matchOperatorsRe, '\\$&'); }; tap-mocha-reporter-3.0.6/lib/browser/events.js000066400000000000000000000055321312361632600213340ustar00rootroot00000000000000/** * Module exports. */ exports.EventEmitter = EventEmitter; /** * Check if `obj` is an array. */ function isArray(obj) { return '[object Array]' == {}.toString.call(obj); } /** * Event emitter constructor. * * @api public */ function EventEmitter(){}; /** * Adds a listener. * * @api public */ EventEmitter.prototype.on = function (name, fn) { if (!this.$events) { this.$events = {}; } if (!this.$events[name]) { this.$events[name] = fn; } else if (isArray(this.$events[name])) { this.$events[name].push(fn); } else { this.$events[name] = [this.$events[name], fn]; } return this; }; EventEmitter.prototype.addListener = EventEmitter.prototype.on; /** * Adds a volatile listener. * * @api public */ EventEmitter.prototype.once = function (name, fn) { var self = this; function on () { self.removeListener(name, on); fn.apply(this, arguments); }; on.listener = fn; this.on(name, on); return this; }; /** * Removes a listener. * * @api public */ EventEmitter.prototype.removeListener = function (name, fn) { if (this.$events && this.$events[name]) { var list = this.$events[name]; if (isArray(list)) { var pos = -1; for (var i = 0, l = list.length; i < l; i++) { if (list[i] === fn || (list[i].listener && list[i].listener === fn)) { pos = i; break; } } if (pos < 0) { return this; } list.splice(pos, 1); if (!list.length) { delete this.$events[name]; } } else if (list === fn || (list.listener && list.listener === fn)) { delete this.$events[name]; } } return this; }; /** * Removes all listeners for an event. * * @api public */ EventEmitter.prototype.removeAllListeners = function (name) { if (name === undefined) { this.$events = {}; return this; } if (this.$events && this.$events[name]) { this.$events[name] = null; } return this; }; /** * Gets all listeners for a certain event. * * @api public */ EventEmitter.prototype.listeners = function (name) { if (!this.$events) { this.$events = {}; } if (!this.$events[name]) { this.$events[name] = []; } if (!isArray(this.$events[name])) { this.$events[name] = [this.$events[name]]; } return this.$events[name]; }; /** * Emits an event. * * @api public */ EventEmitter.prototype.emit = function (name) { if (!this.$events) { return false; } var handler = this.$events[name]; if (!handler) { return false; } var args = [].slice.call(arguments, 1); if ('function' == typeof handler) { handler.apply(this, args); } else if (isArray(handler)) { var listeners = handler.slice(); for (var i = 0, l = listeners.length; i < l; i++) { listeners[i].apply(this, args); } } else { return false; } return true; }; tap-mocha-reporter-3.0.6/lib/browser/fs.js000066400000000000000000000000001312361632600204210ustar00rootroot00000000000000tap-mocha-reporter-3.0.6/lib/browser/glob.js000066400000000000000000000000001312361632600207340ustar00rootroot00000000000000tap-mocha-reporter-3.0.6/lib/browser/path.js000066400000000000000000000000001312361632600207450ustar00rootroot00000000000000tap-mocha-reporter-3.0.6/lib/browser/progress.js000066400000000000000000000041721312361632600216730ustar00rootroot00000000000000/** * Expose `Progress`. */ module.exports = Progress; /** * Initialize a new `Progress` indicator. */ function Progress() { this.percent = 0; this.size(0); this.fontSize(11); this.font('helvetica, arial, sans-serif'); } /** * Set progress size to `n`. * * @param {Number} n * @return {Progress} for chaining * @api public */ Progress.prototype.size = function(n){ this._size = n; return this; }; /** * Set text to `str`. * * @param {String} str * @return {Progress} for chaining * @api public */ Progress.prototype.text = function(str){ this._text = str; return this; }; /** * Set font size to `n`. * * @param {Number} n * @return {Progress} for chaining * @api public */ Progress.prototype.fontSize = function(n){ this._fontSize = n; return this; }; /** * Set font `family`. * * @param {String} family * @return {Progress} for chaining */ Progress.prototype.font = function(family){ this._font = family; return this; }; /** * Update percentage to `n`. * * @param {Number} n * @return {Progress} for chaining */ Progress.prototype.update = function(n){ this.percent = n; return this; }; /** * Draw on `ctx`. * * @param {CanvasRenderingContext2d} ctx * @return {Progress} for chaining */ Progress.prototype.draw = function(ctx){ try { var percent = Math.min(this.percent, 100) , size = this._size , half = size / 2 , x = half , y = half , rad = half - 1 , fontSize = this._fontSize; ctx.font = fontSize + 'px ' + this._font; var angle = Math.PI * 2 * (percent / 100); ctx.clearRect(0, 0, size, size); // outer circle ctx.strokeStyle = '#9f9f9f'; ctx.beginPath(); ctx.arc(x, y, rad, 0, angle, false); ctx.stroke(); // inner circle ctx.strokeStyle = '#eee'; ctx.beginPath(); ctx.arc(x, y, rad - 1, 0, angle, true); ctx.stroke(); // text var text = this._text || (percent | 0) + '%' , w = ctx.measureText(text).width; ctx.fillText( text , x - w / 2 + 1 , y + fontSize / 2 - 1); } catch (ex) {} //don't fail if we can't render progress return this; }; tap-mocha-reporter-3.0.6/lib/browser/tty.js000066400000000000000000000004131312361632600206410ustar00rootroot00000000000000exports.isatty = function(){ return true; }; exports.getWindowSize = function(){ if ('innerHeight' in global) { return [global.innerHeight, global.innerWidth]; } else { // In a Web Worker, the DOM Window is not available. return [640, 480]; } }; tap-mocha-reporter-3.0.6/lib/formatter.js000066400000000000000000000041221312361632600203420ustar00rootroot00000000000000// A formatter is a Duplex stream that TAP data is written into, // and then something else (presumably not-TAP) is read from. // // See tap-classic.js for an example of a formatter in use. var Duplex = require('stream').Duplex if (!Duplex) { try { Duplex = require('readable-stream').Duplex } catch (er) { throw new Error('Please install "readable-stream" to use this module ' + 'with Node.js v0.8 and before') } } var util = require('util') var Parser = require('tap-parser') util.inherits(Formatter, Duplex) module.exports = Formatter function Formatter(options, parser, parent) { if (!(this instanceof Formatter)) return new Formatter(options, parser, parent) if (!parser) parser = new Parser() Duplex.call(this, options) this.child = null this.parent = parent || null this.level = parser.level this.parser = parser attachEvents(this, parser, options) if (options.init) options.init.call(this) } function attachEvents (self, parser, options) { var events = [ 'version', 'plan', 'assert', 'comment', 'complete', 'extra', 'bailout' ] parser.on('child', function (childparser) { self.child = new Formatter(options, childparser, self) if (options.child) options.child.call(self, self.child) }) events.forEach(function (ev) { if (typeof options[ev] === 'function') parser.on(ev, options[ev].bind(self)) }) // proxy all stream events directly var streamEvents = [ 'pipe', 'prefinish', 'finish', 'unpipe', 'close' ] streamEvents.forEach(function (ev) { parser.on(ev, function () { var args = [ev] args.push.apply(args, arguments) self.emit.apply(self, args) }) }) } Formatter.prototype.write = function (c, e, cb) { return this.parser.write(c, e, cb) } Formatter.prototype.end = function (c, e, cb) { return this.parser.end(c, e, cb) } Formatter.prototype._read = function () {} // child formatters always push data to the root obj Formatter.prototype.push = function (c) { if (this.parent) return this.parent.push(c) Duplex.prototype.push.call(this, c) } tap-mocha-reporter-3.0.6/lib/ms.js000066400000000000000000000037741312361632600167720ustar00rootroot00000000000000/** * Helpers. */ var s = 1000; var m = s * 60; var h = m * 60; var d = h * 24; var y = d * 365.25; /** * Parse or format the given `val`. * * Options: * * - `long` verbose formatting [false] * * @param {String|Number} val * @param {Object} options * @return {String|Number} * @api public */ module.exports = function(val, options){ options = options || {}; if ('string' == typeof val) return parse(val); return options['long'] ? longFormat(val) : shortFormat(val); }; /** * Parse the given `str` and return milliseconds. * * @param {String} str * @return {Number} * @api private */ function parse(str) { var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); if (!match) return; var n = parseFloat(match[1]); var type = (match[2] || 'ms').toLowerCase(); switch (type) { case 'years': case 'year': case 'y': return n * y; case 'days': case 'day': case 'd': return n * d; case 'hours': case 'hour': case 'h': return n * h; case 'minutes': case 'minute': case 'm': return n * m; case 'seconds': case 'second': case 's': return n * s; case 'ms': return n; } } /** * Short format for `ms`. * * @param {Number} ms * @return {String} * @api private */ function shortFormat(ms) { if (ms >= d) return Math.round(ms / d) + 'd'; if (ms >= h) return Math.round(ms / h) + 'h'; if (ms >= m) return Math.round(ms / m) + 'm'; if (ms >= s) return Math.round(ms / s) + 's'; return ms + 'ms'; } /** * Long format for `ms`. * * @param {Number} ms * @return {String} * @api private */ function longFormat(ms) { return plural(ms, d, 'day') || plural(ms, h, 'hour') || plural(ms, m, 'minute') || plural(ms, s, 'second') || ms + ' ms'; } /** * Pluralization helper. */ function plural(ms, n, name) { if (ms < n) return; if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name; return Math.ceil(ms / n) + ' ' + name + 's'; } tap-mocha-reporter-3.0.6/lib/reporters/000077500000000000000000000000001312361632600200275ustar00rootroot00000000000000tap-mocha-reporter-3.0.6/lib/reporters/base.js000066400000000000000000000230101312361632600212730ustar00rootroot00000000000000/** * Module dependencies. */ var tty = require('tty') , diff = require('diff') , ms = require('../ms') , utils = require('../utils') , supportsColor = require('color-support')() /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Check if both stdio streams are associated with a tty. */ var isatty = tty.isatty(1); /** * Expose `Base`. */ exports = module.exports = Base; /** * Enable coloring by default, except in the browser interface. */ exports.useColors = process.env ? (supportsColor || (process.env.TAP_COLORS !== undefined)) : false; if (exports.useColors && +process.env.TAP_COLORS === 0) exports.useColors = false /** * Inline diffs instead of +/- */ exports.inlineDiffs = false; /** * Default color map. */ exports.colors = { 'pass': 90 , 'fail': 31 , 'bright pass': 92 , 'bright fail': 91 , 'bright yellow': 93 , 'pending': 35 , 'skip': 36 , 'suite': 0 , 'error title': 0 , 'error message': 31 , 'error stack': 90 , 'checkmark': 32 , 'fast': 90 , 'medium': 33 , 'slow': 31 , 'green': 32 , 'light': 90 , 'diff gutter': 90 , 'diff added': 42 , 'diff removed': 41 }; /** * Default symbol map. */ exports.symbols = { ok: '✓', err: '✖', dot: '․' }; // With node.js on Windows: use symbols available in terminal default fonts if ('win32' == process.platform) { exports.symbols.ok = '\u221A'; exports.symbols.err = '\u00D7'; exports.symbols.dot = '.'; } /** * Color `str` with the given `type`, * allowing colors to be disabled, * as well as user-defined color * schemes. * * @param {String} type * @param {String} str * @return {String} * @api private */ var color = exports.color = function(type, str) { if (!exports.useColors) return String(str); return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; }; /** * Expose term window size, with some * defaults for when stderr is not a tty. */ exports.window = { width: isatty ? process.stdout.getWindowSize ? process.stdout.getWindowSize(1)[0] : tty.getWindowSize()[1] : 75 }; /** * Expose some basic cursor interactions * that are common among reporters. */ exports.cursor = { hide: function(){ isatty && process.stdout.write('\u001b[?25l'); }, show: function(){ isatty && process.stdout.write('\u001b[?25h'); }, deleteLine: function(){ isatty && process.stdout.write('\u001b[2K'); }, beginningOfLine: function(){ isatty && process.stdout.write('\u001b[0G'); }, CR: function(){ if (isatty) { exports.cursor.deleteLine(); exports.cursor.beginningOfLine(); } else { process.stdout.write('\r'); } } }; /** * Outut the given `failures` as a list. * * @param {Array} failures * @api public */ exports.list = function(failures){ console.log(); failures.forEach(function(test, i){ // format var fmt = color('error title', ' %s) %s:\n') + color('error message', ' %s') + color('error stack', '\n%s\n'); // msg var err = test.err , message = err.message || '' , stack = err.stack || message var index = stack.indexOf(message) + message.length , msg = stack.slice(0, index) , actual = err.actual , expected = err.expected , escape = true; // uncaught if (err.uncaught) { msg = 'Uncaught ' + msg; } // explicitly show diff if (err.showDiff && sameType(actual, expected)) { if ('string' !== typeof actual) { escape = false; err.actual = actual = utils.stringify(actual); err.expected = expected = utils.stringify(expected); } fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n'); var match = message.match(/^([^:]+): expected/); msg = '\n ' + color('error message', match ? match[1] : msg); if (exports.inlineDiffs) { msg += inlineDiff(err, escape); } else { msg += unifiedDiff(err, escape); } } // indent stack trace without msg stack = utils.stackTraceFilter()(stack.slice(index ? index + 1 : index) .replace(/^/gm, ' ')); console.log(fmt, (i + 1), test.fullTitle(), msg, stack); }); }; /** * Initialize a new `Base` reporter. * * All other reporters generally * inherit from this reporter, providing * stats such as test duration, number * of tests passed / failed etc. * * @param {Runner} runner * @api public */ function Base(runner) { var self = this , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } , failures = this.failures = []; if (!runner) return; this.runner = runner; runner.stats = stats; runner.on('start', function(){ stats.start = new Date; }); runner.on('suite', function(suite){ stats.suites = stats.suites || 0; suite.root || stats.suites++; }); runner.on('test end', function(test){ stats.tests = stats.tests || 0; stats.tests++; }); runner.on('pass', function(test){ stats.passes = stats.passes || 0; var medium = test.slow() / 2; test.speed = test.duration > test.slow() ? 'slow' : test.duration > medium ? 'medium' : 'fast'; stats.passes++; }); runner.on('fail', function(test, err){ stats.failures = stats.failures || 0; stats.failures++; test.err = err; failures.push(test); }); runner.on('end', function(){ stats.end = new Date; if (!stats.duration) stats.duration = stats.end - stats.start; }); runner.on('pending', function(){ stats.pending++; }); } /** * Output common epilogue used by many of * the bundled reporters. * * @api public */ Base.prototype.epilogue = function(){ var stats = this.stats; var tests; var fmt; console.log(); // passes fmt = color('bright pass', ' ') + color('green', ' %d passing') + color('light', ' (%s)'); console.log(fmt, stats.passes || 0, ms(stats.duration)); // pending if (stats.pending) { fmt = color('pending', ' ') + color('pending', ' %d pending'); console.log(fmt, stats.pending); } // failures if (stats.failures) { fmt = color('fail', ' %d failing'); console.log(fmt, stats.failures); Base.list(this.failures); } }; /** * Pad the given `str` to `len`. * * @param {String} str * @param {String} len * @return {String} * @api private */ function pad(str, len) { str = String(str); return Array(len - str.length + 1).join(' ') + str; } /** * Returns an inline diff between 2 strings with coloured ANSI output * * @param {Error} Error with actual/expected * @return {String} Diff * @api private */ function inlineDiff(err, escape) { var msg = errorDiff(err, 'WordsWithSpace', escape); // linenos var lines = msg.split('\n'); if (lines.length > 4) { var width = String(lines.length).length; msg = lines.map(function(str, i){ return pad(++i, width) + ' |' + ' ' + str; }).join('\n'); } // legend msg = '\n' + color('diff removed', 'actual') + ' ' + color('diff added', 'expected') + '\n\n' + msg + '\n'; // indent msg = msg.replace(/^/gm, ' '); return msg; } /** * Returns a unified diff between 2 strings * * @param {Error} Error with actual/expected * @return {String} Diff * @api private */ function unifiedDiff(err, escape) { var indent = ' '; function cleanUp(line) { if (escape) { line = escapeInvisibles(line); } if (line[0] === '+') return indent + colorLines('diff added', line); if (line[0] === '-') return indent + colorLines('diff removed', line); if (line.match(/\@\@/)) return null; if (line.match(/\\ No newline/)) return null; else return indent + line; } function notBlank(line) { return line != null; } var msg = diff.createPatch('string', err.actual, err.expected); var lines = msg.split('\n').splice(4); return '\n ' + colorLines('diff added', '+ expected') + ' ' + colorLines('diff removed', '- actual') + '\n\n' + lines.map(cleanUp).filter(notBlank).join('\n'); } /** * Return a character diff for `err`. * * @param {Error} err * @return {String} * @api private */ function errorDiff(err, type, escape) { var actual = escape ? escapeInvisibles(err.actual) : err.actual; var expected = escape ? escapeInvisibles(err.expected) : err.expected; return diff['diff' + type](actual, expected).map(function(str){ if (str.added) return colorLines('diff added', str.value); if (str.removed) return colorLines('diff removed', str.value); return str.value; }).join(''); } /** * Returns a string with all invisible characters in plain text * * @param {String} line * @return {String} * @api private */ function escapeInvisibles(line) { return line.replace(/\t/g, '') .replace(/\r/g, '') .replace(/\n/g, '\n'); } /** * Color lines for `str`, using the color `name`. * * @param {String} name * @param {String} str * @return {String} * @api private */ function colorLines(name, str) { return str.split('\n').map(function(str){ return color(name, str); }).join('\n'); } /** * Check that a / b have the same type. * * @param {Object} a * @param {Object} b * @return {Boolean} * @api private */ function sameType(a, b) { a = Object.prototype.toString.call(a); b = Object.prototype.toString.call(b); return a == b; } tap-mocha-reporter-3.0.6/lib/reporters/classic.js000066400000000000000000000253611312361632600220150ustar00rootroot00000000000000exports = module.exports = Classic var Base = require('./base') , cursor = Base.cursor , color = Base.color , yaml = require('js-yaml') , util = require('util') , fancy = Base.useColors && !process.env.TRAVIS , ms = require('../ms.js') , diff = require('diff') , utils = require('../utils.js') , uclen = require('unicode-length').get , colorSupport = require('color-support')() function repeat (n, c) { return new Array(Math.max(n + 1, 0)).join(c) } function hasOwnProperty (obj, key) { return Object.prototype.hasOwnProperty.call(obj, key) } function doDiff (found, wanted, palette) { // TODO: Make this a configurable thing or something? // // Choosing a palette for diffs in a test-runner context // is really tricky. The temptation is to make it look // exactly like `git diff`, but the default red and green // are very confusing with the colors used to indicate // pass/fail. // // So, I decided to experiment with setting a background to // distinguish the diff section from the rest of the test // output. The obvious choice, then, was to mimick GitHub's // diff styling. // // The problem there is that, while those of us with an // abundance of cones tend to find that palette most pleasing, // it's virtually impossible for people with various sorts of // red/green colorblindness to distinguish those colors. // // The resulting option, with a somewhat pink-ish red and a // somewhat yellow-ish green, seems to be a pretty good // compromise between esthetics and accessibility. In a poll // on twitter, it was the only one that no color-sighted people // strongly objected to, and no color-blind people had // significant trouble interpreting. The twitter poll agrees // with the results of Sim Daltonism, which showed that this // palette was easily distinguishable across all forms of color // deficiency. // TODO: add a TrueColor one that looks nicer palette = colorSupport.has256 ? 6 : 1 var plain = '' var reset = '\u001b[m' switch (palette) { case 1: // most git-like. r/g, no background, no bold var bg = '' var removed = '\u001b[31m' var added = '\u001b[32m' break case 2: // dark option, maybe confusing with pass/fail colors? var bg = '\u001b[48;5;234m' var removed = '\u001b[31;1m' var added = '\u001b[32;1m' break case 3: // pastel option, most githubby var removed = '\u001b[48;5;224m\u001b[38;5;52m' var added = '\u001b[48;5;194m\u001b[38;5;22m' var plain = '\u001b[38;5;233m' var bg = '\u001b[48;5;255m' break case 4: // orange/cyan pastel option, most r/g-colorblind friendly var removed = '\u001b[48;5;223m\u001b[38;5;52m' var added = '\u001b[48;5;158m\u001b[38;5;22m' var plain = '\u001b[38;5;233m' var bg = '\u001b[48;5;255m' break case 5: // pastel option, green is bluish, red is just red var removed = '\u001b[48;5;224m\u001b[38;5;52m' var added = '\u001b[48;5;158m\u001b[38;5;22m' var plain = '\u001b[38;5;233m' var bg = '\u001b[48;5;255m' break case 6: // pastel option, red is purplish, green is yellowish var removed = '\u001b[48;5;218m\u001b[38;5;52m' var added = '\u001b[48;5;193m\u001b[38;5;22m' var plain = '\u001b[38;5;233m' var bg = '\u001b[48;5;255m' break case 7: // pastel option, red is purplish, green is just green var removed = '\u001b[48;5;218m\u001b[38;5;52m' var added = '\u001b[48;5;194m\u001b[38;5;22m' var plain = '\u001b[38;5;233m' var bg = '\u001b[48;5;255m' break case 8: // pastel, red and blue var removed = '\u001b[48;5;224m\u001b[38;5;52m' var added = '\u001b[48;5;189m\u001b[38;5;17m' var plain = '\u001b[38;5;233m' var bg = '\u001b[48;5;255m' break case 9: // pastel option, red is purplish, green is yellowish var removed = '\u001b[48;5;224m\u001b[38;5;52m' var added = '\u001b[48;5;193m\u001b[38;5;22m' var plain = '\u001b[38;5;233m' var bg = '\u001b[48;5;255m' break } var maxLen = process.stdout.columns || 0 if (maxLen >= 5) maxLen -= 5 if (!Base.useColors) { bg = removed = added = reset = plain = '' maxLen = 0 } // If they are not strings, or only differ in trailing whitespace, // then stringify them so that we can see the difference. if (typeof found !== 'string' || typeof wanted !== 'string' || found.trim() === wanted.trim()) { found = utils.stringify(found) wanted = utils.stringify(wanted) } var patch = diff.createPatch('', wanted, found) //console.error(patch) var width = 0 patch = patch.split('\n').map(function (line, index) { if (uclen(line) > width) width = Math.min(maxLen, uclen(line)) if (line.match(/^\=+$/) || line === '\\ No newline at end of file') return null else return line }).filter(function (line, i) { return line && i > 4 }).map(function (line) { if (uclen(line) < width) line += repeat(width - uclen(line) + 1, ' ') return line }).map(function (line) { if (line.charAt(0) === '+') return bg + added + line + reset else if (line.charAt(0) === '-') return bg + removed + line + reset else return bg + plain + line + reset }).join('\n') var pref = bg + added + '+++ found' + (Base.useColors ? repeat(width - '+++ found'.length + 1, ' ') : '') + reset + '\n' + bg + removed + '--- wanted' + (Base.useColors ? repeat(width - '--- wanted'.length + 1, ' ') : '') + reset + '\n' return pref + patch } util.inherits(Classic, Base) function Classic (runner) { Base.call(this, runner); var self = this var grandTotal = 0 var grandPass = 0 var bailed = false var hadFails = false var currentSuite = null var tests = [] var skipped = 0 var skipMsg = [] var todo = [] var fails = [] var total = 0 var pass = 0 var tickDots = 0 var tickColor = 'checkmark' runner.on('bailout', function (bailout, suite) { if (currentSuite) runner.emit('suite end', currentSuite) if (bailed) return bailed = true console.log(Base.color('fail', 'Bail out! ' + bailout)) }) runner.on('suite', function (suite) { if (!suite.root) return if (fancy) { process.stdout.write(suite.title + ' ') tickDots = 0 tickColor = 'checkmark' } currentSuite = suite tests = [] todo = [] fails = [] skipMsg = [] skipped = 0 pass = 0 total = 0 }) runner.on('suite end', function (suite) { if (!suite.root) return if (fancy) Base.cursor.beginningOfLine() currentSuite = null var len = 60 var title = suite.title || '(unnamed)' var num = pass + '/' + total var dots = len - uclen(title) - uclen(num) - 3 if (dots < 2) dots = 2 dots = ' ' + repeat(dots, '.') + ' ' if (fails.length) num = Base.color('fail', num) else if (pass === total) num = Base.color('checkmark', num) else num = Base.color('pending', num) var fmt = title + dots + num if (suite.duration / total > 250) fmt += Base.color('slow', ' ' + ms(Math.round(suite.duration))) console.log(fmt) if (fails.length) { var failMsg = '' fails.forEach(function (t) { if (t.parent) failMsg += t.parent + '\n' failMsg += Base.color('fail', 'not ok ' + t.name) + '\n' if (t.diag) { var printDiff = false if (hasOwnProperty(t.diag, 'found') && hasOwnProperty(t.diag, 'wanted')) { printDiff = true var found = t.diag.found var wanted = t.diag.wanted failMsg += indent(doDiff(found, wanted), 2) + '\n' } var o = {} var print = false for (var i in t.diag) { // Don't re-print what we already showed in the diff if (printDiff && ( i === 'found' || i === 'wanted')) continue o[i] = t.diag[i] print = true } if (print) failMsg += indent(yaml.safeDump(o), 2) + '\n' } }) console.log(indent(failMsg, 2)) } if (todo.length) { var todoMsg = '' var bullet = Base.color('pending', '~ ') todo.forEach(function (t) { if (t.todo !== true) t.name += ' - ' + Base.color('pending', t.todo) todoMsg += bullet + t.name + '\n' if (t.diag) todoMsg += indent(yaml.safeDump(t.diag), 4) + '\n' }) console.log(indent(todoMsg, 2)) } if (skipped) { var fmt = Base.color('skip', indent('Skipped: %d', 2)) console.log(fmt, skipped) if (skipMsg.length) console.log(indent(skipMsg.join('\n'), 4)) console.log('') } }) runner.on('test', function (test) { total ++ grandTotal ++ var t = test.result if (fancy && currentSuite) { var max = 57 - uclen(currentSuite.title) if (max < 3) max = 3 if (tickDots > max) { tickDots = 0 Base.cursor.deleteLine() Base.cursor.beginningOfLine(); process.stdout.write(currentSuite.title + ' ') } tickDots ++ if (t.todo && (tickColor === 'checkmark' || tickColor === 'skip')) tickColor = 'pending' else if (t.skip && tickColor === 'checkmark') tickColor = 'skip' else if (!t.ok) tickColor = 'fail' process.stdout.write(Base.color(tickColor, '.')) } if (t.skip) { skipped += 1 if (!/^filter(( out)?: \/.+\/|: only)$/.test(t.skip)) { if (t.skip !== true) skipMsg.push(t.name + ' ' + Base.color('skip', t.skip)) else skipMsg.push(t.name) } } else if (t.todo) todo.push(t) else if (!t.ok) { t.parent = [] var p = test.parent while (p && p !== currentSuite) { var n = p.title || p.name || p.fullTitle() if (n) t.parent.unshift(n) p = p.parent } t.parent.shift() t.parent = t.parent.join(' > ') fails.push(t) hadFails = true } else { pass ++ grandPass ++ } }) runner.on('end', function () { total = grandTotal pass = grandPass tests = [] todo = [] fails = [] skipMsg = [] skipped = 0 if (hadFails) fails = [,,,] runner.emit('suite end', { title: 'total', root: true }) self.failures = [] self.epilogue(); if (grandTotal === grandPass) { console.log(Base.color('checkmark', '\n ok')) } }) } function indent (str, n) { var ind = repeat(n, ' ') str = ind + str.split('\n').join('\n' + ind) return str.replace(/(\n\s*)+$/, '\n') } tap-mocha-reporter-3.0.6/lib/reporters/doc.js000066400000000000000000000027641312361632600211430ustar00rootroot00000000000000/** * Module dependencies. */ var Base = require('./base') , utils = require('../utils'); /** * Expose `Doc`. */ exports = module.exports = Doc; /** * Initialize a new `Doc` reporter. * * @param {Runner} runner * @api public */ function Doc(runner) { Base.call(this, runner); var self = this , stats = this.stats , total = runner.total , indents = 2; function indent() { return Array(indents).join(' '); } runner.on('suite', function(suite){ if (suite.root) return; ++indents; console.log('%s
', indent()); ++indents; console.log('%s

%s

', indent(), utils.escape(suite.title)); console.log('%s
', indent()); }); runner.on('suite end', function(suite){ if (suite.root) return; console.log('%s
', indent()); --indents; console.log('%s
', indent()); --indents; }); runner.on('pass', function(test){ console.log('%s
%s
', indent(), utils.escape(test.title)); var code = utils.escape(utils.clean(test.fn.toString())); console.log('%s
%s
', indent(), code); }); runner.on('fail', function(test, err){ console.log('%s
%s
', indent(), utils.escape(test.title)); var code = utils.escape(utils.clean(test.fn.toString())); console.log('%s
%s
', indent(), code); console.log('%s
%s
', indent(), utils.escape(err)); }); } tap-mocha-reporter-3.0.6/lib/reporters/dot.js000066400000000000000000000023371312361632600211600ustar00rootroot00000000000000/** * Module dependencies. */ var Base = require('./base') , color = Base.color; /** * Expose `Dot`. */ exports = module.exports = Dot; /** * Initialize a new `Dot` matrix test reporter. * * @param {Runner} runner * @api public */ function Dot(runner) { Base.call(this, runner); var self = this , stats = this.stats , width = Base.window.width * .75 | 0 , n = -1; runner.on('start', function(){ process.stdout.write('\n'); }); runner.on('pending', function(test){ if (++n % width == 0) process.stdout.write('\n '); process.stdout.write(color('pending', Base.symbols.dot)); }); runner.on('pass', function(test){ if (++n % width == 0) process.stdout.write('\n '); if ('slow' == test.speed) { process.stdout.write(color('bright yellow', Base.symbols.dot)); } else { process.stdout.write(color(test.speed, Base.symbols.dot)); } }); runner.on('fail', function(test, err){ if (++n % width == 0) process.stdout.write('\n '); process.stdout.write(color('fail', Base.symbols.dot)); }); runner.on('end', function(){ console.log(); self.epilogue(); }); } /** * Inherit from `Base.prototype`. */ Dot.prototype.__proto__ = Base.prototype; tap-mocha-reporter-3.0.6/lib/reporters/dump.js000066400000000000000000000017131312361632600213340ustar00rootroot00000000000000exports = module.exports = Dump var Base = require('./base') , cursor = Base.cursor , color = Base.color , useColors = Base.useColors , util = require('util') function Dump(runner) { Base.call(this, runner); var events = [ 'start', 'version', 'suite', 'suite end', 'test', 'pending', 'pass', 'fail', 'test end', ]; var i = process.argv.indexOf('dump') if (i !== -1) { var args = process.argv.slice(i + 1) if (args.length) events = args } runner.on('line', function (c) { if (c.trim()) process.stderr.write(Base.color('bright yellow', c)) }) events.forEach(function (ev) { runner.on(ev, function (obj) { console.log(ev) if (arguments.length) { console.log(util.inspect(obj, false, Infinity, useColors)) console.log() } }) }) runner.on('end', function () { console.log('end') console.log(runner.stats) console.log() }) } tap-mocha-reporter-3.0.6/lib/reporters/index.js000066400000000000000000000011301312361632600214670ustar00rootroot00000000000000exports.dot = require('./dot.js') exports.doc = require('./doc.js') exports.tap = true exports.json = require('./json.js') exports.list = require('./list.js') exports.min = require('./min.js') exports.spec = require('./spec.js') exports.nyan = require('./nyan.js') exports.xunit = require('./xunit.js') exports.markdown = require('./markdown.js') exports.progress = require('./progress.js') exports.landing = require('./landing.js') exports.jsonstream = require('./json-stream.js') exports.dump = require('./dump.js') exports.classic = require('./classic.js') exports.silent = require('./silent.js') tap-mocha-reporter-3.0.6/lib/reporters/json-stream.js000066400000000000000000000021201312361632600226220ustar00rootroot00000000000000/** * Module dependencies. */ var Base = require('./base') , color = Base.color; /** * Expose `List`. */ exports = module.exports = List; /** * Initialize a new `List` test reporter. * * @param {Runner} runner * @api public */ function List(runner) { Base.call(this, runner); var self = this , stats = this.stats , total = runner.total; runner.on('start', function(){ console.log(JSON.stringify(['start', { total: total }])); }); runner.on('pass', function(test){ console.log(JSON.stringify(['pass', clean(test)])); }); runner.on('fail', function(test, err){ test = clean(test); test.err = err.message; console.log(JSON.stringify(['fail', test])); }); runner.on('end', function(){ process.stdout.write(JSON.stringify(['end', self.stats])); }); } /** * Return a plain-object representation of `test` * free of cyclic properties etc. * * @param {Object} test * @return {Object} * @api private */ function clean(test) { return { title: test.title , fullTitle: test.fullTitle() , duration: test.duration } } tap-mocha-reporter-3.0.6/lib/reporters/json.js000066400000000000000000000030431312361632600213360ustar00rootroot00000000000000/** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `JSON`. */ exports = module.exports = JSONReporter; /** * Initialize a new `JSON` reporter. * * @param {Runner} runner * @api public */ function JSONReporter(runner) { var self = this; Base.call(this, runner); var tests = [] , pending = [] , failures = [] , passes = []; runner.on('test end', function(test){ tests.push(test); }); runner.on('pass', function(test){ passes.push(test); }); runner.on('fail', function(test){ failures.push(test); }); runner.on('pending', function(test){ pending.push(test); }); runner.on('end', function(){ var obj = { stats: self.stats, tests: tests.map(clean), pending: pending.map(clean), failures: failures.map(clean), passes: passes.map(clean) }; runner.testResults = obj; process.stdout.write(JSON.stringify(obj, null, 2)); }); } /** * Return a plain-object representation of `test` * free of cyclic properties etc. * * @param {Object} test * @return {Object} * @api private */ function clean(test) { return { title: test.title, fullTitle: test.fullTitle(), duration: test.duration, err: errorJSON(test.err || {}) } } /** * Transform `error` into a JSON object. * @param {Error} err * @return {Object} */ function errorJSON(err) { var res = {}; Object.getOwnPropertyNames(err).forEach(function(key) { res[key] = err[key]; }, err); return res; } tap-mocha-reporter-3.0.6/lib/reporters/landing.js000066400000000000000000000033001312361632600217750ustar00rootroot00000000000000/** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `Landing`. */ exports = module.exports = Landing; /** * Airplane color. */ Base.colors.plane = 0; /** * Airplane crash color. */ Base.colors['plane crash'] = 31; /** * Runway color. */ Base.colors.runway = 90; /** * Initialize a new `Landing` reporter. * * @param {Runner} runner * @api public */ function Landing(runner) { Base.call(this, runner); var self = this , stats = this.stats , width = Base.window.width * .75 | 0 , total = runner.total , stream = process.stdout , plane = color('plane', '✈') , crashed = -1 , n = 0; function runway() { var buf = Array(width).join('-'); return ' ' + color('runway', buf); } runner.on('start', function(){ stream.write('\n\n\n '); cursor.hide(); }); runner.on('test end', function(test){ // check if the plane crashed var col = -1 == crashed ? width * ++n / total | 0 : crashed; // show the crash if ('failed' == test.state) { plane = color('plane crash', '✈'); crashed = col; } // render landing strip stream.write('\u001b['+(width+1)+'D\u001b[2A'); stream.write(runway()); stream.write('\n '); stream.write(color('runway', Array(col).join('⋅'))); stream.write(plane) stream.write(color('runway', Array(width - col).join('⋅') + '\n')); stream.write(runway()); stream.write('\u001b[0m'); }); runner.on('end', function(){ cursor.show(); console.log(); self.epilogue(); }); } /** * Inherit from `Base.prototype`. */ Landing.prototype.__proto__ = Base.prototype; tap-mocha-reporter-3.0.6/lib/reporters/list.js000066400000000000000000000023621312361632600213430ustar00rootroot00000000000000/** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `List`. */ exports = module.exports = List; /** * Initialize a new `List` test reporter. * * @param {Runner} runner * @api public */ function List(runner) { Base.call(this, runner); var self = this , stats = this.stats , n = 0; runner.on('start', function(){ console.log(); }); runner.on('test', function(test){ process.stdout.write(color('pass', ' ' + test.fullTitle() + ': ')); }); runner.on('pending', function(test){ var fmt = color('checkmark', ' -') + color('pending', ' %s'); console.log(fmt, test.fullTitle()); }); runner.on('pass', function(test){ var fmt = color('checkmark', ' '+Base.symbols.dot) + color('pass', ' %s') + (test.duration ? color('pass', ': ') + color(test.speed, '%dms') : ''); cursor.CR(); console.log(fmt, test.fullTitle(), test.duration || ''); }); runner.on('fail', function(test, err){ cursor.CR(); console.log(color('fail', ' %d) %s'), ++n, test.fullTitle()); }); runner.on('end', self.epilogue.bind(self)); } /** * Inherit from `Base.prototype`. */ List.prototype.__proto__ = Base.prototype; tap-mocha-reporter-3.0.6/lib/reporters/markdown.js000066400000000000000000000051071312361632600222120ustar00rootroot00000000000000/** * Module dependencies. */ var Base = require('./base') , utils = require('../utils'); /** * Constants */ var SUITE_PREFIX = '$'; /** * Expose `Markdown`. */ exports = module.exports = Markdown; /** * Initialize a new `Markdown` reporter. * * @param {Runner} runner * @api public */ function Markdown(runner) { Base.call(this, runner); var self = this , stats = this.stats , level = 0 , buf = ''; function title(str) { return Array(level + 1).join('#') + ' ' + str; } function indent() { return Array(level).join(' '); } function mapTOC(suite, obj) { var ret = obj, key = SUITE_PREFIX + suite.title; obj = obj[key] = obj[key] || { suite: suite }; suite.suites.forEach(function(suite){ mapTOC(suite, obj); }); return ret; } function stringifyTOC(obj, level) { ++level; var buf = ''; var link; for (var key in obj) { if ('suite' == key) continue; if (key !== SUITE_PREFIX) { link = ' - [' + key.substring(1) + ']'; link += '(#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; buf += Array(level).join(' ') + link; } buf += stringifyTOC(obj[key], level); } return buf; } function generateTOC() { return suites.map(generateTOC_).join('') } function generateTOC_(suite) { var obj = mapTOC(suite, {}); return stringifyTOC(obj, 0); } var suites = [] var currentSuite = null runner.on('suite', function(suite){ currentSuite = suite if (suite.root) { suites.push(suite) } ++level; var slug = utils.slug(suite.fullTitle()); buf += '' + '\n'; buf += title(suite.title) + '\n'; }); runner.on('suite end', function(suite){ if (suite.ok) { buf += '\nok - ' + suite.title + '\n' } else { buf += '\nnot ok - ' + suite.title + '\n' } --level; }); runner.on('test', function(test){ if (!test.ok || test.pending) { var code = utils.clean(test.fn.toString()); buf += test.title + '.\n'; if (code) { buf += '\n```js\n'; buf += code + '\n'; buf += '```\n'; } var stack = test.err && test.err.stack if (!stack) { stack = test.result && test.result.diag && test.result.diag.stack } if (stack) { buf += '\n```\n' + stack + '\n```\n'; } buf += '\n\n'; } }); runner.on('end', function(){ process.stdout.write('# TOC\n'); process.stdout.write(generateTOC()); process.stdout.write('\n\n'); process.stdout.write(buf); }); } tap-mocha-reporter-3.0.6/lib/reporters/min.js000066400000000000000000000011321312361632600211450ustar00rootroot00000000000000/** * Module dependencies. */ var Base = require('./base'); /** * Expose `Min`. */ exports = module.exports = Min; /** * Initialize a new `Min` minimal test reporter (best used with --watch). * * @param {Runner} runner * @api public */ function Min(runner) { Base.call(this, runner); runner.on('start', function(){ // clear screen process.stdout.write('\u001b[2J'); // set cursor position process.stdout.write('\u001b[1;3H'); }); runner.on('end', this.epilogue.bind(this)); } /** * Inherit from `Base.prototype`. */ Min.prototype.__proto__ = Base.prototype; tap-mocha-reporter-3.0.6/lib/reporters/nyan.js000066400000000000000000000114531312361632600213360ustar00rootroot00000000000000/** * Module dependencies. */ var Base = require('./base'); /** * Expose `Dot`. */ exports = module.exports = NyanCat; /** * Initialize a new `Dot` matrix test reporter. * * @param {Runner} runner * @api public */ function NyanCat(runner) { Base.call(this, runner); var self = this , stats = this.stats , width = Base.window.width * .75 | 0 , rainbowColors = this.rainbowColors = self.generateColors() , colorIndex = this.colorIndex = 0 , numerOfLines = this.numberOfLines = 4 , trajectories = this.trajectories = [[], [], [], []] , nyanCatWidth = this.nyanCatWidth = 11 , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth) , scoreboardWidth = this.scoreboardWidth = 5 , tick = this.tick = 0 , n = 0; runner.on('start', function(){ Base.cursor.hide(); self.draw(); }); runner.on('pending', function(test){ self.draw(); }); runner.on('pass', function(test){ self.draw(); }); runner.on('fail', function(test, err){ self.draw(); }); runner.on('end', function(){ Base.cursor.show(); for (var i = 0; i < self.numberOfLines; i++) write('\n'); self.epilogue(); }); } /** * Draw the nyan cat * * @api private */ NyanCat.prototype.draw = function(){ this.appendRainbow(); this.drawScoreboard(); this.drawRainbow(); this.drawNyanCat(); this.tick = !this.tick; }; /** * Draw the "scoreboard" showing the number * of passes, failures and pending tests. * * @api private */ NyanCat.prototype.drawScoreboard = function(){ var stats = this.stats; function draw(type, n) { write(' '); write(Base.color(type, n)); write('\n'); } draw('green', stats.passes); draw('fail', stats.failures); draw('pending', stats.pending); write('\n'); this.cursorUp(this.numberOfLines); }; /** * Append the rainbow. * * @api private */ NyanCat.prototype.appendRainbow = function(){ var segment = this.tick ? '_' : '-'; var rainbowified = this.rainbowify(segment); for (var index = 0; index < this.numberOfLines; index++) { var trajectory = this.trajectories[index]; if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift(); trajectory.push(rainbowified); } }; /** * Draw the rainbow. * * @api private */ NyanCat.prototype.drawRainbow = function(){ var self = this; this.trajectories.forEach(function(line, index) { write('\u001b[' + self.scoreboardWidth + 'C'); write(line.join('')); write('\n'); }); this.cursorUp(this.numberOfLines); }; /** * Draw the nyan cat * * @api private */ NyanCat.prototype.drawNyanCat = function() { var self = this; var startWidth = this.scoreboardWidth + this.trajectories[0].length; var dist = '\u001b[' + startWidth + 'C'; var padding = ''; write(dist); write('_,------,'); write('\n'); write(dist); padding = self.tick ? ' ' : ' '; write('_|' + padding + '/\\_/\\ '); write('\n'); write(dist); padding = self.tick ? '_' : '__'; var tail = self.tick ? '~' : '^'; var face; write(tail + '|' + padding + this.face() + ' '); write('\n'); write(dist); padding = self.tick ? ' ' : ' '; write(padding + '"" "" '); write('\n'); this.cursorUp(this.numberOfLines); }; /** * Draw nyan cat face. * * @return {String} * @api private */ NyanCat.prototype.face = function() { var stats = this.stats; if (stats.failures) { return '( x .x)'; } else if (stats.pending) { return '( o .o)'; } else if(stats.passes) { return '( ^ .^)'; } else { return '( - .-)'; } }; /** * Move cursor up `n`. * * @param {Number} n * @api private */ NyanCat.prototype.cursorUp = function(n) { write('\u001b[' + n + 'A'); }; /** * Move cursor down `n`. * * @param {Number} n * @api private */ NyanCat.prototype.cursorDown = function(n) { write('\u001b[' + n + 'B'); }; /** * Generate rainbow colors. * * @return {Array} * @api private */ NyanCat.prototype.generateColors = function(){ var colors = []; for (var i = 0; i < (6 * 7); i++) { var pi3 = Math.floor(Math.PI / 3); var n = (i * (1.0 / 6)); var r = Math.floor(3 * Math.sin(n) + 3); var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3); var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3); colors.push(36 * r + 6 * g + b + 16); } return colors; }; /** * Apply rainbow to the given `str`. * * @param {String} str * @return {String} * @api private */ NyanCat.prototype.rainbowify = function(str){ if (!Base.useColors) return str; var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; this.colorIndex += 1; return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m'; }; /** * Stdout helper. */ function write(string) { process.stdout.write(string); } /** * Inherit from `Base.prototype`. */ NyanCat.prototype.__proto__ = Base.prototype; tap-mocha-reporter-3.0.6/lib/reporters/progress.js000066400000000000000000000037131312361632600222350ustar00rootroot00000000000000/** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `Progress`. */ exports = module.exports = Progress; /** * General progress bar color. */ Base.colors.progress = 90; /** * Initialize a new `Progress` bar test reporter. * * @param {Runner} runner * @param {Object} options * @api public */ function Progress(runner, options) { Base.call(this, runner); var self = this , options = options || {} , stats = this.stats , width = Base.window.width * .50 | 0 , total = runner.total , complete = 0 , max = Math.max , lastN = -1; // default chars options.open = options.open || '['; options.complete = options.complete || '▬'; options.incomplete = options.incomplete || Base.symbols.dot; options.close = options.close || ']'; options.verbose = false; // tests started runner.on('start', function(){ console.log(); cursor.hide(); }); // tests complete runner.on('test end', function(){ complete++; var incomplete = total - complete , percent = complete / total , n = width * percent | 0 , i = width - n; if (lastN === n && !options.verbose) { // Don't re-render the line if it hasn't changed return; } lastN = n; cursor.CR(); process.stdout.write('\u001b[J'); process.stdout.write(color('progress', ' ' + options.open)); process.stdout.write(Array(n).join(options.complete)); process.stdout.write(Array(i).join(options.incomplete)); process.stdout.write(color('progress', options.close)); if (options.verbose) { process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); } }); // tests are complete, output some stats // and the failures if any runner.on('end', function(){ cursor.show(); console.log(); self.epilogue(); }); } /** * Inherit from `Base.prototype`. */ Progress.prototype.__proto__ = Base.prototype; tap-mocha-reporter-3.0.6/lib/reporters/silent.js000066400000000000000000000000521312361632600216600ustar00rootroot00000000000000exports = module.exports = function () {} tap-mocha-reporter-3.0.6/lib/reporters/spec.js000066400000000000000000000031321312361632600213160ustar00rootroot00000000000000/** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `Spec`. */ exports = module.exports = Spec; /** * Initialize a new `Spec` test reporter. * * @param {Runner} runner * @api public */ function Spec(runner) { Base.call(this, runner); var self = this , stats = this.stats , indents = 0 , n = 0; function indent() { return Array(indents).join(' ') } runner.on('start', function(){ console.log(); }); runner.on('suite', function(suite){ ++indents; console.log(color('suite', '%s%s'), indent(), suite.title); }); runner.on('suite end', function(suite){ --indents; if (1 == indents) console.log(); }); runner.on('pending', function(test){ var fmt = indent() + color('pending', ' - %s'); console.log(fmt, test.title); }); runner.on('pass', function(test){ if ('fast' == test.speed) { var fmt = indent() + color('checkmark', ' ' + Base.symbols.ok) + color('pass', ' %s'); cursor.CR(); console.log(fmt, test.title); } else { var fmt = indent() + color('checkmark', ' ' + Base.symbols.ok) + color('pass', ' %s') + color(test.speed, ' (%dms)'); cursor.CR(); console.log(fmt, test.title, test.duration); } }); runner.on('fail', function(test, err){ cursor.CR(); console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); }); runner.on('end', self.epilogue.bind(self)); } /** * Inherit from `Base.prototype`. */ Spec.prototype.__proto__ = Base.prototype; tap-mocha-reporter-3.0.6/lib/reporters/templates/000077500000000000000000000000001312361632600220255ustar00rootroot00000000000000tap-mocha-reporter-3.0.6/lib/reporters/templates/coverage.jade000066400000000000000000000026141312361632600244500ustar00rootroot00000000000000doctype html html head title Coverage meta(charset='utf-8') include script.html include style.html body #coverage h1#overview Coverage include menu #stats(class=coverageClass(cov.coverage)) .percentage #{cov.coverage | 0}% .sloc= cov.sloc .hits= cov.hits .misses= cov.misses #files for file in cov.files .file h2(id=file.filename)= file.filename #stats(class=coverageClass(file.coverage)) .percentage #{file.coverage | 0}% .sloc= file.sloc .hits= file.hits .misses= file.misses table#source thead tr th Line th Hits th Source tbody for line, number in file.source if line.coverage > 0 tr.hit td.line= number td.hits= line.coverage td.source= line.source else if 0 === line.coverage tr.miss td.line= number td.hits 0 td.source= line.source else tr td.line= number td.hits td.source= line.source || ' ' tap-mocha-reporter-3.0.6/lib/reporters/templates/menu.jade000066400000000000000000000006461312361632600236240ustar00rootroot00000000000000#menu li a(href='#overview') overview for file in cov.files li span.cov(class=coverageClass(file.coverage)) #{file.coverage | 0} a(href='##{file.filename}') segments = file.filename.split('/') basename = segments.pop() if segments.length span.dirname= segments.join('/') + '/' span.basename= basename a#logo(href='http://visionmedia.github.io/mocha/') m tap-mocha-reporter-3.0.6/lib/reporters/templates/script.html000066400000000000000000000011401312361632600242130ustar00rootroot00000000000000 tap-mocha-reporter-3.0.6/lib/reporters/templates/style.html000066400000000000000000000412771312361632600240660ustar00rootroot00000000000000 tap-mocha-reporter-3.0.6/lib/reporters/xunit.js000066400000000000000000000061261312361632600215410ustar00rootroot00000000000000/** * Module dependencies. */ var Base = require('./base') , utils = require('../utils') , fs = require('fs') , escape = utils.escape; /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Expose `XUnit`. */ exports = module.exports = XUnit; /** * Initialize a new `XUnit` reporter. * * @param {Runner} runner * @api public */ function XUnit(runner, options) { Base.call(this, runner); var stats = this.stats , tests = [] , self = this; if (options.reporterOptions && options.reporterOptions.output) { if (! fs.createWriteStream) { throw new Error('file output not supported in browser'); } self.fileStream = fs.createWriteStream(options.reporterOptions.output); } runner.on('pending', function(test){ tests.push(test); }); runner.on('pass', function(test){ tests.push(test); }); runner.on('fail', function(test){ tests.push(test); }); runner.on('end', function(){ self.write(tag('testsuite', { name: 'TAP Tests' , tests: stats.tests , failures: stats.failures , errors: stats.failures , skipped: stats.tests - stats.failures - stats.passes , timestamp: (new Date).toUTCString() , time: (stats.duration / 1000) || 0 }, false)); tests.forEach(function(t) { self.test(t); }); self.write(''); }); } /** * Override done to close the stream (if it's a file). */ XUnit.prototype.done = function(failures, fn) { if (this.fileStream) { this.fileStream.end(function() { fn(failures); }); } else { fn(failures); } }; /** * Inherit from `Base.prototype`. */ XUnit.prototype.__proto__ = Base.prototype; /** * Write out the given line */ XUnit.prototype.write = function(line) { if (this.fileStream) { this.fileStream.write(line + '\n'); } else { console.log(line); } }; /** * Output tag for the given `test.` */ XUnit.prototype.test = function(test, ostream) { var attrs = { classname: test.parent.fullTitle() , name: test.title , time: (test.duration / 1000) || 0 }; if ('failed' == test.state) { var err = test.err; this.write(tag('testcase', attrs, false, tag('failure', {}, false, cdata(escape(err.message) + "\n" + err.stack)))); } else if (test.pending) { this.write(tag('testcase', attrs, false, tag('skipped', {}, true))); } else { this.write(tag('testcase', attrs, true) ); } }; /** * HTML tag helper. */ function tag(name, attrs, close, content) { var end = close ? '/>' : '>' , pairs = [] , tag; for (var key in attrs) { pairs.push(key + '="' + escape(attrs[key]) + '"'); } tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end; if (content) tag += content + ''; } tap-mocha-reporter-3.0.6/lib/runner.js000066400000000000000000000206021312361632600176510ustar00rootroot00000000000000// A facade from the tap-parser to the Mocha "Runner" object. // Note that pass/fail/suite events need to also mock the "Runnable" // objects (either "Suite" or "Test") since these have functions // which are called by the formatters. module.exports = Runner // relevant events: // // start() // Start of the top-level test set // // end() // End of the top-level test set. // // fail(test, err) // any "not ok" test that is not the trailing test for a suite // of >0 test points. // // pass(test) // any "ok" test point that is not the trailing test for a suite // of >0 tests // // pending(test) // Any "todo" test // // suite(suite) // A suite is a child test with >0 test points. This is a little bit // tricky, because TAP will provide a "child" event before we know // that it's a "suite". We see the "# Subtest: name" comment as the // first thing in the subtest. Then, when we get our first test point, // we know that it's a suite, and can emit the event with the mock suite. // // suite end(suite) // Emitted when we end the subtest // // test(test) // Any test point which is not the trailing test for a suite. // // test end(test) // Emitted immediately after the "test" event because test points are // not async in TAP. var util = require('util') var Test = require('./test.js') var Suite = require('./suite.js') var Writable = require('stream').Writable if (!Writable) { try { Writable = require('readable-stream').Writable } catch (er) { throw new Error('Please install "readable-stream" to use this module ' + 'with Node.js v0.8 and before') } } var Parser = require('tap-parser') // $1 = number, $2 = units var timere = /^#\s*time=((?:0|[1-9][0-9]*?)(?:\.[0-9]+)?)(ms|s)?$/ util.inherits(Runner, Writable) function Runner (options) { if (!(this instanceof Runner)) return new Runner(options) var parser = this.parser = new Parser(options) this.startTime = new Date() attachEvents(this, parser, 0) Writable.call(this, options) } Runner.prototype.write = function () { if (!this.emittedStart) { this.emittedStart = true this.emit('start') } return this.parser.write.apply(this.parser, arguments) } Runner.prototype.end = function () { return this.parser.end.apply(this.parser, arguments) } Parser.prototype.fullTitle = function () { if (!this.parent) return this.name || '' else return (this.parent.fullTitle() + ' ' + (this.name || '')).trim() } function attachEvents (runner, parser, level) { parser.runner = runner if (level === 0) { parser.on('line', function (c) { runner.emit('line', c) }) parser.on('version', function (v) { runner.emit('version', v) }) parser.on('complete', function (res) { runner.emit('end') }) parser.on('comment', function (c) { var tmatch = c.trim().match(timere) if (tmatch) { var t = +tmatch[1] if (tmatch[2] === 's') t *= 1000 parser.time = t if (runner.stats) runner.stats.duration = t } }) } parser.emittedSuite = false parser.didAssert = false parser.name = parser.name || '' parser.doingChild = null parser.on('complete', function (res) { if (!res.ok) { var fail = { ok: false, diag: {} } var count = res.count if (res.plan) { var plan = res.plan.end - res.plan.start + 1 if (count !== plan) { fail.name = 'test count !== plan' fail.diag = { found: count, wanted: plan } } else { // probably handled on child parser return } } else { fail.name = 'missing plan' } fail.diag.results = res emitTest(parser, fail) } }) parser.on('child', function (child) { child.parent = parser attachEvents(runner, child, level + 1) // if we're in a suite, but we haven't emitted it yet, then we // know that an assert will follow this child, even if there are // no others. That means that we will definitely have a 'suite' // event to emit. emitSuite(this) this.didAssert = true this.doingChild = child }) if (!parser.name) { parser.on('comment', function (c) { if (!this.name && c.match(/^# Subtest: /)) { c = c.trim().replace(/^# Subtest: /, '') this.name = c } }) } // Just dump all non-parsing stuff to stderr parser.on('extra', function (c) { process.stderr.write(c) }) parser.on('assert', function (result) { emitSuite(this) // no need to print the trailing assert for subtests // we've already emitted a 'suite end' event for this. // UNLESS, there were no other asserts, AND it's root level if (this.doingChild) { var suite = this.doingChild.suite if (this.doingChild.name === result.name) { if (suite) { if (result.time) suite.duration = result.time // If it's ok so far, but the ending result is not-ok, then // that means that it exited non-zero. Emit the test so // that we can print it as a failure. if (suite.ok && !result.ok) emitTest(this, result) } } var emitOn = this var dc = this.doingChild this.doingChild = null if (!dc.didAssert && dc.level === 1) { emitOn = dc } else if (dc.didAssert) { if (dc.suite) runner.emit('suite end', dc.suite) return } else { emitOn = this } emitSuite(emitOn) emitTest(emitOn, result) if (emitOn !== this && emitOn.suite) { runner.emit('suite end', emitOn.suite) delete emitOn.suite } if (dc.suite) { runner.emit('suite end', dc.suite) } return } this.didAssert = true this.doingChild = null emitTest(this, result) }) parser.on('complete', function (results) { this.results = results }) parser.on('bailout', function (reason) { var suite = this.suite runner.emit('bailout', reason, suite) if (suite) this.suite = suite.parent }) // proxy all stream events directly var streamEvents = [ 'pipe', 'prefinish', 'finish', 'unpipe', 'close' ] streamEvents.forEach(function (ev) { parser.on(ev, function () { var args = [ev] args.push.apply(args, arguments) runner.emit.apply(runner, args) }) }) } function emitSuite (parser) { if (!parser.emittedSuite && parser.name) { parser.emittedSuite = true var suite = parser.suite = new Suite(parser) if (parser.parent && parser.parent.suite) parser.parent.suite.suites.push(suite) if (parser.runner.stats) parser.runner.stats.suites ++ parser.runner.emit('suite', suite) } } function emitTest (parser, result) { var runner = parser.runner var test = new Test(result, parser) if (parser.suite) { parser.suite.tests.push(test) if (!result.ok) { for (var p = parser; p && p.suite; p = p.parent) { p.suite.ok = false } } parser.suite.ok = parser.suite.ok && result.ok } runner.emit('test', test) if (result.skip || result.todo) { runner.emit('pending', test) } else if (result.ok) { runner.emit('pass', test) } else { var error = getError(result) runner.emit('fail', test, error) } runner.emit('test end', test) } function getError (result) { var err function reviveStack (stack) { if (!stack) return null return stack.trim().split('\n').map(function (line) { return ' at ' + line }).join('\n') } if (result.diag && result.diag.error) { err = { name: result.diag.error.name || 'Error', message: result.diag.error.message, toString: function () { return this.name + ': ' + this.message }, stack: result.diag.error.stack } } else { err = { message: (result.name || '(unnamed error)').replace(/^Error: /, ''), toString: function () { return 'Error: ' + this.message }, stack: result.diag && result.diag.stack } } var diag = result.diag if (err.stack) err.stack = err.toString() + '\n' + reviveStack(err.stack) if (diag) { var hasFound = diag.hasOwnProperty('found') var hasWanted = diag.hasOwnProperty('wanted') if (hasFound) err.actual = diag.found if (hasWanted) err.expected = diag.wanted if (hasFound && hasWanted) err.showDiff = true } return err } tap-mocha-reporter-3.0.6/lib/suite.js000066400000000000000000000007361312361632600174770ustar00rootroot00000000000000// minimal mock of mocha's Suite class for formatters module.exports = Suite function Suite (parent) { if (!parent.parent || !parent.parent.emittedSuite) this.root = true else this.root = false this.title = parent.name || '' this.suites = [] this.tests = [] this.ok = true } Suite.prototype.fullTitle = function () { if (!this.parent) return (this.title || '').trim() else return (this.parent.fullTitle() + ' ' + (this.title || '')).trim() } tap-mocha-reporter-3.0.6/lib/test.js000066400000000000000000000015621312361632600173230ustar00rootroot00000000000000// minimal mock of the mocha Test class for formatters module.exports = Test function Test (result, parent) { this.result = result this._slow = 75 this.duration = result.time this.title = result.name this.state = result.ok ? 'pass' : 'failed' this.pending = result.todo || result.skip || false if (result.diag && result.diag.source) { var source = result.diag.source this.fn = { toString: function () { return 'function(){' + source + '\n}' } } } Object.defineProperty(this, 'parent', { value: parent, writable: true, configurable: true, enumerable: false }) } Test.prototype.fullTitle = function () { return (this.parent.fullTitle() + ' ' + (this.title || '')).trim() } Test.prototype.slow = function (ms){ return 75 } Test.prototype.fn = { toString: function () { return 'function () {\n}' } } tap-mocha-reporter-3.0.6/lib/utils.js000066400000000000000000000404501312361632600175030ustar00rootroot00000000000000/** * Module dependencies. */ var fs = require('fs') , path = require('path') , basename = path.basename , exists = fs.existsSync || path.existsSync , glob = require('glob') , join = path.join , debug = require('debug')('mocha:watch'); /** * Ignored directories. */ var ignore = ['node_modules', '.git']; /** * Escape special characters in the given string of html. * * @param {String} html * @return {String} * @api private */ exports.escape = function(html){ return String(html) .replace('&', '&') .replace('"', '"') .replace('<', '<') .replace('>', '>'); }; /** * Array#forEach (<=IE8) * * @param {Array} array * @param {Function} fn * @param {Object} scope * @api private */ exports.forEach = function(arr, fn, scope){ for (var i = 0, l = arr.length; i < l; i++) fn.call(scope, arr[i], i); }; /** * Array#map (<=IE8) * * @param {Array} array * @param {Function} fn * @param {Object} scope * @api private */ exports.map = function(arr, fn, scope){ var result = []; for (var i = 0, l = arr.length; i < l; i++) result.push(fn.call(scope, arr[i], i, arr)); return result; }; /** * Array#indexOf (<=IE8) * * @parma {Array} arr * @param {Object} obj to find index of * @param {Number} start * @api private */ exports.indexOf = function(arr, obj, start){ for (var i = start || 0, l = arr.length; i < l; i++) { if (arr[i] === obj) return i; } return -1; }; /** * Array#reduce (<=IE8) * * @param {Array} array * @param {Function} fn * @param {Object} initial value * @api private */ exports.reduce = function(arr, fn, val){ var rval = val; for (var i = 0, l = arr.length; i < l; i++) { rval = fn(rval, arr[i], i, arr); } return rval; }; /** * Array#filter (<=IE8) * * @param {Array} array * @param {Function} fn * @api private */ exports.filter = function(arr, fn){ var ret = []; for (var i = 0, l = arr.length; i < l; i++) { var val = arr[i]; if (fn(val, i, arr)) ret.push(val); } return ret; }; /** * Object.keys (<=IE8) * * @param {Object} obj * @return {Array} keys * @api private */ exports.keys = Object.keys || function(obj) { var keys = [] , has = Object.prototype.hasOwnProperty; // for `window` on <=IE8 for (var key in obj) { if (has.call(obj, key)) { keys.push(key); } } return keys; }; /** * Watch the given `files` for changes * and invoke `fn(file)` on modification. * * @param {Array} files * @param {Function} fn * @api private */ exports.watch = function(files, fn){ var options = { interval: 100 }; files.forEach(function(file){ debug('file %s', file); fs.watchFile(file, options, function(curr, prev){ if (prev.mtime < curr.mtime) fn(file); }); }); }; /** * Array.isArray (<=IE8) * * @param {Object} obj * @return {Boolean} * @api private */ var isArray = Array.isArray || function (obj) { return '[object Array]' == {}.toString.call(obj); }; /** * @description * Buffer.prototype.toJSON polyfill * @type {Function} */ if(typeof Buffer !== 'undefined' && Buffer.prototype) { Buffer.prototype.toJSON = Buffer.prototype.toJSON || function () { return Array.prototype.slice.call(this, 0); }; } /** * Ignored files. */ function ignored(path){ return !~ignore.indexOf(path); } /** * Lookup files in the given `dir`. * * @return {Array} * @api private */ exports.files = function(dir, ext, ret){ ret = ret || []; ext = ext || ['js']; var re = new RegExp('\\.(' + ext.join('|') + ')$'); fs.readdirSync(dir) .filter(ignored) .forEach(function(path){ path = join(dir, path); if (fs.statSync(path).isDirectory()) { exports.files(path, ext, ret); } else if (path.match(re)) { ret.push(path); } }); return ret; }; /** * Compute a slug from the given `str`. * * @param {String} str * @return {String} * @api private */ exports.slug = function(str){ return str .toLowerCase() .replace(/ +/g, '-') .replace(/[^-\w]/g, ''); }; /** * Strip the function definition from `str`, * and re-indent for pre whitespace. */ exports.clean = function(str) { str = str .replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '') .replace(/^function *\(.*\) *{|\(.*\) *=> *{?/, '') .replace(/\s+\}$/, ''); var spaces = str.match(/^\n?( *)/)[1].length , tabs = str.match(/^\n?(\t*)/)[1].length , re = new RegExp('^\n?' + (tabs ? '\t' : ' ') + '{' + (tabs ? tabs : spaces) + '}', 'gm'); str = str.replace(re, ''); return exports.trim(str); }; /** * Trim the given `str`. * * @param {String} str * @return {String} * @api private */ exports.trim = function(str){ return str.replace(/^\s+|\s+$/g, ''); }; /** * Parse the given `qs`. * * @param {String} qs * @return {Object} * @api private */ exports.parseQuery = function(qs){ return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){ var i = pair.indexOf('=') , key = pair.slice(0, i) , val = pair.slice(++i); obj[key] = decodeURIComponent(val); return obj; }, {}); }; /** * Highlight the given string of `js`. * * @param {String} js * @return {String} * @api private */ function highlight(js) { return js .replace(//g, '>') .replace(/\/\/(.*)/gm, '//$1') .replace(/('.*?')/gm, '$1') .replace(/(\d+\.\d+)/gm, '$1') .replace(/(\d+)/gm, '$1') .replace(/\bnew[ \t]+(\w+)/gm, 'new $1') .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1') } /** * Highlight the contents of tag `name`. * * @param {String} name * @api private */ exports.highlightTags = function(name) { var code = document.getElementById('mocha').getElementsByTagName(name); for (var i = 0, len = code.length; i < len; ++i) { code[i].innerHTML = highlight(code[i].innerHTML); } }; /** * If a value could have properties, and has none, this function is called, which returns * a string representation of the empty value. * * Functions w/ no properties return `'[Function]'` * Arrays w/ length === 0 return `'[]'` * Objects w/ no properties return `'{}'` * All else: return result of `value.toString()` * * @param {*} value Value to inspect * @param {string} [type] The type of the value, if known. * @returns {string} */ var emptyRepresentation = function emptyRepresentation(value, type) { type = type || exports.type(value); switch(type) { case 'function': return '[Function]'; case 'object': return '{}'; case 'array': return '[]'; default: return value.toString(); } }; /** * Takes some variable and asks `{}.toString()` what it thinks it is. * @param {*} value Anything * @example * type({}) // 'object' * type([]) // 'array' * type(1) // 'number' * type(false) // 'boolean' * type(Infinity) // 'number' * type(null) // 'null' * type(new Date()) // 'date' * type(/foo/) // 'regexp' * type('type') // 'string' * type(global) // 'global' * @api private * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString * @returns {string} */ exports.type = function type(value) { if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { return 'buffer'; } return Object.prototype.toString.call(value) .replace(/^\[.+\s(.+?)\]$/, '$1') .toLowerCase(); }; /** * @summary Stringify `value`. * @description Different behavior depending on type of value. * - If `value` is undefined or null, return `'[undefined]'` or `'[null]'`, respectively. * - If `value` is not an object, function or array, return result of `value.toString()` wrapped in double-quotes. * - If `value` is an *empty* object, function, or array, return result of function * {@link emptyRepresentation}. * - If `value` has properties, call {@link exports.canonicalize} on it, then return result of * JSON.stringify(). * * @see exports.type * @param {*} value * @return {string} * @api private */ exports.stringify = function(value) { var type = exports.type(value); if (!~exports.indexOf(['object', 'array', 'function'], type)) { if(type != 'buffer') { return jsonStringify(value); } var json = value.toJSON(); // Based on the toJSON result return jsonStringify(json.data && json.type ? json.data : json, 2) .replace(/,(\n|$)/g, '$1'); } for (var prop in value) { if (Object.prototype.hasOwnProperty.call(value, prop)) { return jsonStringify(exports.canonicalize(value), 2) .replace(/,(\n|$)/g, '$1'); } } return emptyRepresentation(value, type); }; /** * @description * like JSON.stringify but more sense. * @param {Object} object * @param {Number=} spaces * @param {number=} depth * @returns {*} * @private */ function jsonStringify(object, spaces, depth) { if(typeof spaces == 'undefined') return _stringify(object); // primitive types depth = depth || 1; var space = spaces * depth , str = isArray(object) ? '[' : '{' , end = isArray(object) ? ']' : '}' , length = object.length || exports.keys(object).length , repeat = function(s, n) { return new Array(n).join(s); }; // `.repeat()` polyfill function _stringify(val) { switch (exports.type(val)) { case 'null': case 'undefined': val = '[' + val + ']'; break; case 'array': case 'object': val = jsonStringify(val, spaces, depth + 1); break; case 'boolean': case 'regexp': case 'number': val = val === 0 && (1/val) === -Infinity // `-0` ? '-0' : val.toString(); break; case 'date': val = '[Date: ' + val.toISOString() + ']'; break; case 'buffer': var json = val.toJSON(); // Based on the toJSON result json = json.data && json.type ? json.data : json; val = '[Buffer: ' + jsonStringify(json, 2, depth + 1) + ']'; break; default: val = (val == '[Function]' || val == '[Circular]') ? val : '"' + val + '"'; //string } return val; } for(var i in object) { if(!Object.prototype.hasOwnProperty.call(object, i)) continue; // not my business --length; str += '\n ' + repeat(' ', space) + (isArray(object) ? '' : '"' + i + '": ') // key + _stringify(object[i]) // value + (length ? ',' : ''); // comma } return str + (str.length != 1 // [], {} ? '\n' + repeat(' ', --space) + end : end); } /** * Return if obj is a Buffer * @param {Object} arg * @return {Boolean} * @api private */ exports.isBuffer = function (arg) { return typeof Buffer !== 'undefined' && Buffer.isBuffer(arg); }; /** * @summary Return a new Thing that has the keys in sorted order. Recursive. * @description If the Thing... * - has already been seen, return string `'[Circular]'` * - is `undefined`, return string `'[undefined]'` * - is `null`, return value `null` * - is some other primitive, return the value * - is not a primitive or an `Array`, `Object`, or `Function`, return the value of the Thing's `toString()` method * - is a non-empty `Array`, `Object`, or `Function`, return the result of calling this function again. * - is an empty `Array`, `Object`, or `Function`, return the result of calling `emptyRepresentation()` * * @param {*} value Thing to inspect. May or may not have properties. * @param {Array} [stack=[]] Stack of seen values * @return {(Object|Array|Function|string|undefined)} * @see {@link exports.stringify} * @api private */ exports.canonicalize = function(value, stack) { var canonicalizedObj, type = exports.type(value), prop, withStack = function withStack(value, fn) { stack.push(value); fn(); stack.pop(); }; stack = stack || []; if (exports.indexOf(stack, value) !== -1) { return '[Circular]'; } switch(type) { case 'undefined': case 'buffer': case 'null': canonicalizedObj = value; break; case 'array': withStack(value, function () { canonicalizedObj = exports.map(value, function (item) { return exports.canonicalize(item, stack); }); }); break; case 'function': for (prop in value) { canonicalizedObj = {}; break; } if (!canonicalizedObj) { canonicalizedObj = emptyRepresentation(value, type); break; } /* falls through */ case 'object': canonicalizedObj = canonicalizedObj || {}; withStack(value, function () { exports.forEach(exports.keys(value).sort(), function (key) { canonicalizedObj[key] = exports.canonicalize(value[key], stack); }); }); break; case 'date': case 'number': case 'regexp': case 'boolean': canonicalizedObj = value; break; default: canonicalizedObj = value.toString(); } return canonicalizedObj; }; /** * Lookup file names at the given `path`. */ exports.lookupFiles = function lookupFiles(path, extensions, recursive) { var files = []; var re = new RegExp('\\.(' + extensions.join('|') + ')$'); if (!exists(path)) { if (exists(path + '.js')) { path += '.js'; } else { files = glob.sync(path); if (!files.length) throw new Error("cannot resolve path (or pattern) '" + path + "'"); return files; } } try { var stat = fs.statSync(path); if (stat.isFile()) return path; } catch (ignored) { return; } fs.readdirSync(path).forEach(function(file) { file = join(path, file); try { var stat = fs.statSync(file); if (stat.isDirectory()) { if (recursive) { files = files.concat(lookupFiles(file, extensions, recursive)); } return; } } catch (ignored) { return; } if (!stat.isFile() || !re.test(file) || basename(file)[0] === '.') return; files.push(file); }); return files; }; /** * Generate an undefined error with a message warning the user. * * @return {Error} */ exports.undefinedError = function() { return new Error('Caught undefined error, did you throw without specifying what?'); }; /** * Generate an undefined error if `err` is not defined. * * @param {Error} err * @return {Error} */ exports.getError = function(err) { return err || exports.undefinedError(); }; /** * @summary * This Filter based on `mocha-clean` module.(see: `github.com/rstacruz/mocha-clean`) * @description * When invoking this function you get a filter function that get the Error.stack as an input, * and return a prettify output. * (i.e: strip Mocha, node_modules, bower and componentJS from stack trace). * @returns {Function} */ exports.stackTraceFilter = function() { var slash = '/' , is = typeof document === 'undefined' ? { node: true } : { browser: true } , cwd = is.node ? process.cwd() + slash : location.href.replace(/\/[^\/]*$/, '/'); function isNodeModule (line) { return (~line.indexOf('node_modules')); } function isMochaInternal (line) { return (~line.indexOf('node_modules' + slash + 'tap-mocha-reporter')) || (~line.indexOf('components' + slash + 'mochajs')) || (~line.indexOf('components' + slash + 'mocha')); } // node_modules, bower, componentJS function isBrowserModule(line) { return (~line.indexOf('node_modules')) || (~line.indexOf('components')); } function isNodeInternal (line) { return (~line.indexOf('(timers.js:')) || (~line.indexOf('(domain.js:')) || (~line.indexOf('(events.js:')) || (~line.indexOf('(node.js:')) || (~line.indexOf('(module.js:')) || (~line.indexOf('at node.js:')) || (~line.indexOf('GeneratorFunctionPrototype.next (native)')) || false } return function(stack) { stack = stack.split('\n'); stack = stack.reduce(function (list, line) { if (is.node && (isNodeModule(line) || isMochaInternal(line) || isNodeInternal(line))) return list; if (is.browser && (isBrowserModule(line))) return list; // Clean up cwd(absolute) list.push(line.replace(cwd, '')); return list; }, []); return stack.join('\n'); } }; tap-mocha-reporter-3.0.6/package.json000066400000000000000000000016701312361632600175260ustar00rootroot00000000000000{ "name": "tap-mocha-reporter", "version": "3.0.6", "description": "Format a TAP stream using Mocha's set of reporters", "main": "index.js", "scripts": { "test": "tap test/*.js" }, "repository": { "type": "git", "url": "https://github.com/isaacs/tap-mocha-reporter" }, "author": "Isaac Z. Schlueter (http://blog.izs.me/)", "license": "ISC", "bugs": { "url": "https://github.com/isaacs/tap-mocha-reporter/issues" }, "homepage": "https://github.com/isaacs/tap-mocha-reporter", "dependencies": { "color-support": "^1.1.0", "debug": "^2.1.3", "diff": "^1.3.2", "escape-string-regexp": "^1.0.3", "glob": "^7.0.5", "js-yaml": "^3.3.1", "tap-parser": "^5.1.0", "unicode-length": "^1.0.0" }, "devDependencies": { "tap": "^6.2.0" }, "bin": "index.js", "optionalDependencies": { "readable-stream": "^2.1.5" }, "files": [ "index.js", "lib" ] } tap-mocha-reporter-3.0.6/test/000077500000000000000000000000001312361632600162135ustar00rootroot00000000000000tap-mocha-reporter-3.0.6/test/index.js000066400000000000000000000000641312361632600176600ustar00rootroot00000000000000var tap = require('tap') tap.pass('this is a test')