tap-parser
Advanced tools
Comparing version 10.0.1 to 10.1.0
112
bin/cmd.js
@@ -79,3 +79,3 @@ #!/usr/bin/env node | ||
Parses TAP data from stdin, and outputs the parsed result | ||
in the format specified by the options. Default output is | ||
in the format specified by the options. Default output | ||
uses node's \`util.inspect()\` method. | ||
@@ -133,68 +133,10 @@ | ||
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, '') | ||
return Parser.stringify(msg, options) | ||
else if (json !== null) | ||
return JSON.stringify(msg, null, +json) | ||
else | ||
return util.inspect(events, null, Infinity) | ||
return util.inspect(msg, null, Infinity) | ||
} | ||
@@ -207,35 +149,21 @@ | ||
strict: strict, | ||
flat: flat, | ||
} | ||
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) | ||
if (json === 'lines' || json === 'silent') { | ||
const parser = new Parser(options) | ||
if (json === 'lines') | ||
parser.on('line', l => process.stdout.write(l)) | ||
parser.on('complete', () => process.exit(parser.ok ? 0 : 1)) | ||
process.stdin.pipe(parser) | ||
} else { | ||
const input = [] | ||
process.stdin.on('data', c => input.push(c)).on('end', () => { | ||
const buf = Buffer.concat(input) | ||
const result = Parser.parse(buf, options) | ||
const summary = result[ result.length - 1 ] | ||
console.log(format(result)) | ||
if (summary[0] !== 'complete' || !summary[1].ok) | ||
process.exit(1) | ||
}) | ||
process.on('exit', function () { | ||
if (json !== 'silent' && json !== 'lines') | ||
console.log(format(events)) | ||
if (!parser.ok) | ||
process.exit(1) | ||
}) | ||
process.stdin.pipe(parser) | ||
} |
139
index.js
@@ -7,5 +7,13 @@ 'use strict' | ||
// used by the Parser.parse() method | ||
const etoa = require('events-to-array') | ||
// used by Parser.stringify() and Parser.parse() in flattening mode | ||
const getId = () => { | ||
const id = () => id.current++ | ||
id.current = 1 | ||
return id | ||
} | ||
const yaml = require('tap-yaml') | ||
const util = require('util') | ||
const assert = require('assert') | ||
@@ -26,4 +34,2 @@ // every line outside of a yaml block is one of these things, or | ||
const lineTypeNames = Object.keys(lineTypes) | ||
const lineType = line => { | ||
@@ -59,3 +65,3 @@ for (let t in lineTypes) { | ||
return [ type[1].toLowerCase(), line.substr(type[1].length).trim() || true ] | ||
return [ type[1].toLowerCase(), line.substring(type[1].length).trim() || true ] | ||
} | ||
@@ -73,5 +79,5 @@ | ||
let name | ||
rest = rest.replace(/([^\\]|^)((?:\\\\)*)#/g, '$1\n$2').split('\n') | ||
rest = rest.replace(/([^\\]|^)((?:\\\\)*)# /g, '$1\n$2').split('\n') | ||
name = rest.shift() | ||
rest = rest.filter(r => r.trim()).join('#') | ||
rest = rest.filter(r => r.trim()).join('# ') | ||
@@ -81,3 +87,3 @@ // now, let's see if there's a directive in there. | ||
if (!dir) | ||
name += (rest ? '#' + rest : '') + buffered | ||
name += (rest ? '# ' + rest : '') + buffered | ||
else { | ||
@@ -105,2 +111,105 @@ // handle buffered subtests with todo/skip on them, like | ||
class Parser extends MiniPass { | ||
static parse (str, options = {}) { | ||
const { flat = false } = options | ||
const ignore = [ | ||
'pipe', | ||
'unpipe', | ||
'prefinish', | ||
'finish', | ||
'line', | ||
'pass', | ||
'fail', | ||
'todo', | ||
'skip', | ||
'result', | ||
] | ||
if (flat) | ||
ignore.push('assert', 'child', 'plan', 'complete') | ||
const parser = new Parser(options) | ||
const events = etoa(parser, ignore) | ||
if (flat) { | ||
const id = getId() | ||
parser.on('result', res => { | ||
const name = [] | ||
if (res.fullname) | ||
name.push(res.fullname) | ||
if (res.name) | ||
name.push(res.name) | ||
res.name = name.join(' > ').trim() | ||
res.fullname = '' | ||
res.id = id() | ||
events.push(['assert', res]) | ||
}) | ||
parser.on('complete', res => { | ||
if (!res.bailout) | ||
events.push(['plan', { end: id.current - 1, start: 1 }]) | ||
events.push(['complete', res]) | ||
}) | ||
} | ||
parser.end(str) | ||
return events | ||
} | ||
static stringify (msg, { flat = false, indent = '', id = getId() } = {}) { | ||
const ind = flat ? '' : indent | ||
return ind + msg.map(item => { | ||
switch (item[0]) { | ||
case 'child': | ||
const comment = item[1][0] | ||
const child = item[1].slice(1) | ||
return Parser.stringify([comment], { flat, indent: '', id }) + | ||
Parser.stringify(child, { flat, indent: ' ', id }) | ||
case 'version': | ||
return 'TAP version ' + item[1] + '\n' | ||
case 'plan': | ||
if (flat) { | ||
if (indent !== '') | ||
return '' | ||
item[1].start = 1 | ||
item[1].end = id.current - 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 'assert': | ||
const res = item[1] | ||
if (flat) { | ||
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' + ind).trim() + '\n' | ||
} | ||
constructor (options, onComplete) { | ||
@@ -365,3 +474,3 @@ if (typeof options === 'function') { | ||
if (typeof encoding === 'string' && encoding !== 'utf8') | ||
chunk = new Buffer(chunk, encoding) | ||
chunk = Buffer.from(chunk, encoding) | ||
@@ -382,3 +491,3 @@ if (Buffer.isBuffer(chunk)) | ||
this.buffer = this.buffer.substr(match[0].length) | ||
this.buffer = this.buffer.substring(match[0].length) | ||
this.parse(match[0]) | ||
@@ -656,3 +765,3 @@ } while (this.buffer.length) | ||
// then synthetically emit the Subtest comment | ||
line = line.substr(4) | ||
line = line.substring(4) | ||
let subtestComment | ||
@@ -669,3 +778,3 @@ if (indentStream) { | ||
this.maybeChild = null | ||
this.child.name = subtestComment.substr('# Subtest: '.length).trim() | ||
this.child.name = subtestComment.substring('# Subtest: '.length).trim() | ||
@@ -942,4 +1051,4 @@ // at some point, we may wish to move 100% to preferring | ||
// still belongs to the child, so pass it along. | ||
if (this.child && line.substr(0, 4) === ' ') { | ||
line = line.substr(4) | ||
if (this.child && line.substring(0, 4) === ' ') { | ||
line = line.substring(4) | ||
this.child.write(line) | ||
@@ -983,3 +1092,3 @@ return | ||
// Child tests are always indented 4 spaces. | ||
if (line.substr(0, 4) === ' ') { | ||
if (line.substring(0, 4) === ' ') { | ||
if (this.maybeChild || | ||
@@ -986,0 +1095,0 @@ this.current && this.current.buffered || |
{ | ||
"name": "tap-parser", | ||
"version": "10.0.1", | ||
"version": "10.1.0", | ||
"description": "parse the test anything protocol", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
50544
1135
420