UNPKG

tap

Version:

A Test-Anything-Protocol library for JavaScript

239 lines (202 loc) 5.74 kB
#!/usr/bin/env node const Parser = require('../') const etoa = require('events-to-array') const util = require('util') const args = process.argv.slice(2) let json = null let flat = false let bail = false let preserveWhitespace = true let omitVersion = false let strict = false function version () { console.log(require('../package.json').version) process.exit(0) } for (let i = 0; i < args.length; i++) { const arg = args[i] if (arg === '-j') { const val = +args[i + 1] if (val >= 0) { json = val i += 1 } else json = 2 continue } else { const m = arg.match(/^--json(?:=([0-9]+))?$/) if (m) { if (+m[1] >= 0) json = +m[1] else if (+args[i + 1] >= 0) { json = +args[i + 1] i += 1 } else json = 2 continue } } if (arg === '-v' || arg === '--version') version() else if (arg === '-o' || arg === '--omit-version') omitVersion = true else if (arg === '-w' || arg === '--ignore-all-whitespace') preserveWhitespace = false else if (arg === '-b' || arg === '--bail') bail = true else if (arg === '-B' || arg === '--no-bail') bail = false else if (arg === '-t' || arg === '--tap') json = 'tap' else if (arg === '-l' || arg === '--lines') json = 'lines' else if (arg === '-h' || arg === '--help') usage() else if (arg === '-f' || arg === '--flat') flat = true else if (arg === '-F' || arg === '--no-flat') flat = false else if (arg === '--strict') strict = true else if (arg === '--no-strict') strict = false else if (arg === '-s' || arg === '--silent') json = 'silent' else console.error('Unrecognized arg: %j', arg) } function usage () { console.log(`Usage: tap-parser <options> Parses TAP data from stdin, and outputs the parsed result in the format specified by the options. Default output is uses node's \`util.inspect()\` method. Options: -j [<indent>] | --json[=indent] Output event data as JSON with the specified indentation (default=2) -t | --tap Output data as reconstituted TAP based on parsed results -l | --lines Output each parsed line as it is recognized by the parser -b | --bail Emit a \`Bail out!\` at the first failed test point encountered -B | --no-bail Do not bail out at the first failed test point encountered (Default) -f | --flat Flatten all assertions to the top level parser -F | --no-flat Do not flatten all assertions to the top level parser (Default) -w | --ignore-all-whitespace Skip over blank lines outside of YAML blocks -o | --omit-version Ignore the \`TAP version 13\` line at the start of tests --strict Run the parser in strict mode --no-strict Do not run the parser in strict mode -s | --silent Do not print output, just exit success/failure based on TAP stream `) // prevent the EPIPE upstream when the data drops on the floor /* istanbul ignore else */ if (!process.stdin.isTTY) process.stdin.resume() process.exit() } const yaml = require('tap-yaml') let id = 1 function tapFormat (msg, indent) { return indent + msg.map(function (item) { switch (item[0]) { case 'child': const comment = item[1][0] const child = item[1].slice(1) return tapFormat([comment], '') + tapFormat(child, ' ') case 'version': return 'TAP version ' + item[1] + '\n' case 'plan': if (flat) { item[1].start = 1 item[1].end = id - 1 } return item[1].start + '..' + item[1].end + (item[1].comment ? ' # ' + item[1].comment : '') + '\n' case 'pragma': return 'pragma ' + (item[2] ? '+' : '-') + item[1] + '\n' case 'bailout': return 'Bail out!' + (item[1] ? (' ' + item[1]) : '') + '\n' case 'result': case 'assert': const res = item[1] if (item[0] === 'result') { res.id = id++ const name = [] if (res.fullname) name.push(res.fullname) if (res.name) name.push(res.name) res.name = name.join(' > ').trim() } return (res.ok ? '' : 'not ') + 'ok ' + res.id + (res.name ? ' - ' + res.name.replace(/ \{$/, '') : '') + (res.skip ? ' # SKIP' + (res.skip === true ? '' : ' ' + res.skip) : '') + (res.todo ? ' # TODO' + (res.todo === true ? '' : ' ' + res.todo) : '') + (res.time ? ' # time=' + res.time + 'ms' : '') + '\n' + (res.diag ? ' ---\n ' + yaml.stringify(res.diag).split('\n').join('\n ').trim() + '\n ...\n' : '') case 'extra': case 'comment': return item[1] } }).join('').split('\n').join('\n' + indent).trim() + '\n' } function format (msg) { if (json === 'tap') return tapFormat(msg, '') else if (json !== null) return JSON.stringify(msg, null, +json) else return util.inspect(events, null, Infinity) } const options = { bail: bail, preserveWhitespace: preserveWhitespace, omitVersion: omitVersion, strict: strict, } const parser = new Parser(options) const ignore = [ 'pipe', 'unpipe', 'prefinish', 'finish', 'line', 'pass', 'fail', 'todo', 'skip', ] if (flat) ignore.push('assert', 'child') else ignore.push('result') const events = etoa(parser, ignore) if (json === 'lines') parser.on('line', function (l) { process.stdout.write(l) }) process.on('exit', function () { if (json !== 'silent' && json !== 'lines') console.log(format(events)) if (!parser.ok) process.exit(1) }) process.stdin.pipe(parser)