tap-format parser
A highly verbose parser for the Test Anything Protocol that exposes an observable and streaming interface.
This is the parser used to create the following beautiful TAP formatters:
- @tap-format/spec - Formatted TAP output the like the Mocha spec reporter
- @tap-format/dot - Formatted TAP output with dots ...
- @tap-format/failures - Formatted output for TAP assertion failures with diffs
- @tap-format/results - Formatted output for TAP runner results
Node Version Support
- 0.10
- 0.12
- iojs
-
= 4.x
Install
npm install @tap-format/parser --save
Usage
Observable Interface
The parser exposes an interface that lets you deal with the parsed TAP with Reactive Extensions. See the API section for a full list of exposed Observables.
var parse = require('@tap-format/parser')
var stream = process.stdin
var tap$ = parser.observeStream(stream)
tap$.tests$
.forEach(function (test) {
console.log(test.title)
})
tap$.asserions$
.forEach(function (assertion) {
console.log(assertion.title)
})
Streaming Interface
The parser will parse streaming data for any source.
var parser = require('@tap-format/parser')
var H = require('highland')
var tapStream = H(process.stdin.pipe(parser.stream()))
var tests = tapStream.filter(function (line) {
return line.type === 'test'
})
var assertions = tapStream.filter(function (line) {
return line.type === 'assertion'
})
tests.each(function (test) {
console.log(test.title)
})
assertions.each(function (assertion) {
console.log(assertion.title)
})
CLI
$ something-that-produces-tap | tap-format-parser
{
// Parsed TAP output as JSON here
}
API
Observable Interface
Given a streaming input, the parser will expose and RXjs Observable chunked by new lines. In addition, the parser exposes the following properties as Observables as convenience methods for the parsed TAP.
var parser = requrie('@tap-format/parser')
var stream = process.stdin
var tap$ = parser.observeStream(stream)
tap$
An Observable of all parsed output for the given input TAP stream
// This will console.log every assertion title
tap$
.filter(function (line) {
return line.type === 'assertion'
})
.forEach(function (assertion) {
console.log(assertion.title)
})
tap$.tests$
An Observable of all parsed tests.
// This will console.log all test titles
tap$.tests$
.map(function (test) {
return 'TEST: ' + test.title
})
.forEach(console.log.bind(console))
The shape of the test object is as follows:
-
raw - the raw test line TAP from the TAP input (i.e.
# My Test
) -
type - the type of the line. This will always be
test
-
title - the parsed test title.
# My Test
becomesMy Test
- lineNumber - the line number of the TAP input
- testNumber - the test number from the TAP input
tap$.assertions$
An Observable of all parsed assertions.
// This will console.log all assertion titles
tap$.assertions$
.map(function (assertion) {
return (assertion.ok ? 'OK: ' : 'NOT OK: ') + assertion
})
.forEach(console.log.bind(console))
The shape of the assertion object is as follows:
- raw - the raw test line TAP output, including any diagnostic associated with it
-
type - the type of the line. This will always be
assertion
- title - the parsed test title, excluding any diagnostic associated with it
-
ok -
true/false
- indicates whether the assertion passed or failed -
diagnostic - an object of any diagnostic associated with the assertion. If the assertion is
not ok
, this will be information about the expected and actual values, etc. The TAP input will be YAML, but this value will always be an object - rawDiagnostic - the raw diagnostic fromt he TAP input
- assertionNumber - the assertion number from the TAP input
- lineNumber - the line number of the TAP input
- testNumber - the test number that the assertion is within from the TAP input
tap$.comments$
An Observable of all output that is not tap. The parser assumes these are from console.log()
and treats them as comments.
// This will console.log all the comment titles
tap$.comments$
.map(function (comment) {
return 'COMMENT: ' + comment.title
})
.forEach(console.log.bind(console))
The shape of the comment object is as follows:
- raw - the raw comment line from the TAP input
-
type - the type of the line. This will always be
comment
- title - the parsed comment title
- lineNumber - the line number of the TAP input
tap$.results$
An Observable of the parsed TAP results. This will only ever be of type tests
, pass
, or fail
.
// This will console.log the names and counts of the results
tap$.results$
.forEach(function (result) {
console.log(result.name + ' ' + result.count)
})
The shape of the result object is as follows:
-
raw - the raw result line from the TAP input (i.e.
# pass 3
) -
type - the type of the line. This will always be
result
- name - the name of the result (i.e. pass, fail, assertions, etc.)
- count - the number of assertions associated with this result
tap$.plans$
An Observable of all parsed plans given from TAP output. This is usually only one item.
// This will console.log the 'from' and 'to' from the plan
tap$.plans$
.forEach(function (plan) {
console.log('FROM: ' + plan.from')
console.log('TO: ' + plan.to')
})
The shape of the plan object is as follows:
-
raw - the raw plan line TAP output (i.e.
1..7
) -
type - the type of the line. This will always be
plan
-
from - this will almost always be
1
- to - the total number of assertions from the TAP input
- skip - the number of assertions skipped
tap$.versions$
An Observable of the parsed TAP version
// This will console.log the TAP version
tap$.versions$
.forEach(function (version) {
console.log(version.raw)
})
The shape of the version object is as follows:
-
raw - the raw version line TAP output (i.e.
TAP version 13
) -
type - the type of the line. This will always be
version
Streaming Interface
Using require('@tap-format/parser').stream()
returns a new-line-chunked stream of parsed TAP. It is a normal stream, and therefore exposes the very useful pipe()
method.
Run Tests
git clone git@github.com:scottcorgan/tap-out.git .
npm install
npm test