TAP Parser
tap-parser is a JavaScript library designed to parse the Test Anything Protocol (TAP) stream, specifically implementing version 14 of the TAP specification. It is currently at version 18.3.3 and appears to have a stable release cadence, with frequent updates to its main `tap` package dependency, suggesting active maintenance. The library provides a streaming parser, allowing users to pipe TAP output directly into it for real-time processing. Beyond streaming, it also offers utility functions (`parse` and `stringify`) for handling TAP data as strings or arrays of events, though `stringify` has limitations as TAP is not an object serialization format. Key differentiators include its focus on strict TAP v14 compliance, its streaming capabilities, and its dual-purpose API for both stream and string-based parsing, along with a command-line interface.
Common errors
-
ERR_REQUIRE_ESM: Must use import to load ES Module:
cause Attempting to `require()` `tap-parser` in a CommonJS context after it transitioned to ESM.fixChange `const { Parser } = require('tap-parser');` to `import { Parser } from 'tap-parser';`. If your file is `.js`, ensure `"type": "module"` is set in your `package.json` or rename the file to `.mjs`. -
TypeError: Parser is not a constructor
cause Attempting to `new` a `Parser` when the import was incorrect (e.g., default import instead of named import, or a failed CommonJS `require` attempt).fixVerify that you are using a named import: `import { Parser } from 'tap-parser';`. If in CJS, ensure compatibility shims are in place or that Node.js resolves correctly (which is unlikely post-v10). -
TypeError: parse is not a function
cause Attempting to call `Parser.parse` or `parse` after an incorrect import, such as `import Parser from 'tap-parser';` or a failed CJS `require` that didn't expose the static methods.fixEnsure named imports are used for static methods: `import { parse } from 'tap-parser';` or `import { Parser } from 'tap-parser'; const result = Parser.parse(data);` -
Error: Non-TAP input detected at Parser.push (path/to/tap-parser/index.js:...) (or similar strict mode error)
cause The parser's `strict` mode is enabled, and it encountered input that does not conform to the TAP specification.fixReview the input stream to ensure it is valid TAP. If non-TAP diagnostic output is expected, disable `strict` mode by passing `strict: false` to the `Parser` constructor or `Parser.parse()` options.
Warnings
- breaking Version 10 of `tap-parser` transitioned to native ES Modules (ESM). This change breaks existing CommonJS `require()` statements for users who have not updated their import mechanisms or Node.js project configuration.
- gotcha The `stringify()` static method cannot stringify arbitrary object types into valid TAP. It is designed to convert parsed TAP event arrays back into a TAP string, not to serialize general JavaScript objects, as TAP is a line-based protocol, not an object serialization format like JSON.
- gotcha The `omitVersion` option, when `true`, causes the parser to ignore `TAP version 13` or `TAP version 14` lines. This can be critical when parsing subtests, as version lines within subtest output can cause issues with some parsers, leading to incorrect interpretation of results.
- gotcha Using the `strict: true` option (either in the constructor, `Parser.parse()` options, or via a `pragma +strict` line) will cause the parser to treat any non-TAP input as a failure. This can be overly aggressive for streams that might contain non-TAP diagnostics or unrelated output.
- gotcha This package specifies Node.js engine requirements of `20 || >=22`. Running `tap-parser` on older Node.js versions (e.g., Node.js 18 or 16) is unsupported and may lead to unexpected errors or instability due to incompatible features or dependencies.
Install
-
npm install tap-parser -
yarn add tap-parser -
pnpm add tap-parser
Imports
- Parser
const Parser = require('tap-parser');import { Parser } from 'tap-parser' - parse
const { parse } = require('tap-parser');import { parse } from 'tap-parser' - stringify
const { stringify } = require('tap-parser');import { stringify } from 'tap-parser'
Quickstart
import { Parser } from 'tap-parser';
import { pipeline } from 'stream/promises';
async function parseTapStream() {
const results = [];
const p = new Parser(r => results.push(r));
// Simulate a TAP stream input
const tapInput = `TAP version 14\n# beep\nok 1 should be equal\nok 2 should be equivalent\n# boop\nok 3 should be equal\nok 4 (unnamed assert)\n1..4\n# tests 4\n# pass 4\n# ok`;
const readableStream = new (await import('stream')).Readable({
read() {
this.push(tapInput);
this.push(null);
}
});
await pipeline(readableStream, p);
console.dir(results[0]); // The 'complete' event result
}
parseTapStream().catch(console.error);