blob: c0f1d96f67d3bc84d31c9ed6bff82f99ec6673c0 [file] [log] [blame]
// 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)
}