Skip to content

Commit

Permalink
Add -o --output-file option to store raw TAP
Browse files Browse the repository at this point in the history
Fix #352

Needed to refactor the process hijacking stuff a little bit, otherwise
the pipe to the output file would conflict with piping to the stdout
reporter (or just stdout directly).
  • Loading branch information
isaacs committed Mar 2, 2017
1 parent c9f4671 commit 65a425f
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 9 deletions.
24 changes: 18 additions & 6 deletions bin/run.js
Expand Up @@ -134,7 +134,8 @@ function constructDefaultArgs () {
functions: 0,
lines: 0,
statements: 0,
jobs: 1
jobs: 1,
outputFile: null
}

if (process.env.TAP_COLORS !== undefined)
Expand Down Expand Up @@ -162,7 +163,8 @@ function parseArgs (args, defaults) {
j: 'jobs',
R: 'reporter',
t: 'timeout',
s: 'save'
s: 'save',
o: 'output-file'
}

// If we're running under Travis-CI with a Coveralls.io token,
Expand Down Expand Up @@ -350,6 +352,12 @@ function parseArgs (args, defaults) {
options.color = false
continue

case '--output-file':
val = val || args[++i]
if (val !== undefined)
options.outputFile = val
continue

case '--no-timeout':
options.timeout = 0
continue
Expand Down Expand Up @@ -727,12 +735,16 @@ function runTests (options) {
var tap = require('../lib/tap.js')

tap.jobs = options.jobs
tap.patchProcess()

// if not -Rtap, then output what the user wants.
if (options.reporter !== 'tap') {
tap.unpipe(process.stdout)
tap.pipe(makeReporter(options))
}
// otherwise just dump to stdout
tap.pipe(options.reporter === 'tap' ? process.stdout: makeReporter(options))

// need to replay the first version line, because the previous
// line will have flushed it out to stdout or the reporter already.
if (options.outputFile !== null)
tap.pipe(fs.createWriteStream(options.outputFile)).write('TAP version 13\n')

saveFails(options, tap)

Expand Down
6 changes: 6 additions & 0 deletions bin/usage.txt
Expand Up @@ -44,6 +44,12 @@ Options:
Available reporters:
@@REPORTERS@@

-o<file> Send the raw TAP output to the specified
--output-file=<file> file. Reporter output will still be
printed to stdout, but the file will
contain the raw TAP for later reply or
analysis.

-s<file> --save=<file> If <file> exists, then it should be a line-
delimited list of test files to run. If
<file> is not present, then all command-line
Expand Down
6 changes: 4 additions & 2 deletions lib/tap.js
Expand Up @@ -74,15 +74,17 @@ function onExitEvent (code) {
TAP.prototype.push = function push () {
// this resets push and pipe to standard values
this.pipe(process.stdout)
this.patchProcess()
return this.push.apply(this, arguments)
}

TAP.prototype.patchProcess = function () {
monkeypatchEpipe()
monkeypatchExit()
process.on('uncaughtException', this.threw)
process.on('unhandledRejection', function (er) {
this.threw(er)
}.bind(this))

return this.push.apply(this, arguments)
}

TAP.prototype.onbail = function () {
Expand Down
3 changes: 2 additions & 1 deletion test/rcfiles.js
Expand Up @@ -29,7 +29,8 @@ var defaults = {
jobs: 1,
lines: 0,
statements: 0,
rcFile: osHomedir() + '/.taprc'
rcFile: osHomedir() + '/.taprc',
outputFile: null
}

function runTest (rcFile, expect) { return function (t) {
Expand Down
43 changes: 43 additions & 0 deletions test/runner-output-file.js
@@ -0,0 +1,43 @@
var t = require('../')
var spawn = require('child_process').spawn
var run = require.resolve('../bin/run.js')
var fs = require('fs')
var node = process.execPath
var ok = require.resolve('./test/ok.js')

var args = [
'-ofile.txt',
'-Co file.txt',
'-bCco=file.txt',
'-o=file.txt',
'--output-file=file.txt',
'--output-file file.txt'
]

args.forEach(function (arg) {
t.test(arg, function (t) {
try { fs.unlinkSync('file.txt') } catch (er) {}
arg = arg.split(' ')
var child = spawn(node, [run, '-c', ok].concat(arg))
var gotStdout = false
child.stdout.on('data', function (c) {
gotStdout = true
})
child.stderr.on('data', function (c) {
throw new Error('should not write to stderr')
})
child.on('close', function (code, sig) {
t.equal(code, 0)
t.equal(sig, null)
t.ok(gotStdout, 'got standard output')
t.match(fs.readFileSync('file.txt', 'utf8'), /^TAP version 13\n/)
t.end()
})
})
})

t.test('cleanup', function (t) {
try { fs.unlinkSync('file.txt') } catch (er) {}
t.done()
})

0 comments on commit 65a425f

Please sign in to comment.