Tappedout
A simple "back to basics" JavaScript test runner for producing TAP-formatted results. Built using ES Modules.
Install / Use
/learn @coreybutler/TappedoutREADME
tappedout
A simple "back to basics" JavaScript test runner for producing TAP-formatted results. It is runtime agnostic and built using ES Modules.
It is built using ES module syntax, drawing inspiration from the tape library. It shares several similarities, but should not be considered "the same". The API has several different methods. Furthermore, tappedout is runtime-agnostic. It will work in browsers, Node, Deno, and any other ECMAScript-compliant (ES5+) runtime.
This is for library authors...
There are many beautiful test runners. They often come at the price of requiring many dependencies, which may be fine for a single complex project. Library authors typically maintain multiple smaller repos containing smaller bits of code. The black hole of node_modules was way too heavy when multiplied across multiple projects. Since tappedout is written using ECMAScript standard modules, there is no need for pre-processing/transpiling just to run tests.
The name came from frustration. My patience was tapped out with one too many rollup/browserify processes.
Getting tappedout
Node.js
This library only supports versions of Node with ES Module support. This is available in Node 12 & 13 using the --experimental-modules flag. It is a native feature in Node 14+ (no flag needed). All versions need to specify "type": "module" in the package.json file.
Obtaining the module:
npm i tappedout --save-dev
Implementing it in Node:
import test from 'tappedout'
Browser, Deno
import test from 'https://cdn.pika.dev/tappedout^1.0.0' // <-- Update the version
Usage
Here's a basic example:
import test from 'tappedout'
test('My Test Suite', t => {
t.ok(true, 'I am OK.')
t.ok(false, 'I am still OK.') // Expect a failure here!
})
Output:
TAP version 13
# My Test Suite
ok 1 - I am OK.
not ok 2 - I am still OK.
1..2
Alternative output formats:
TAP (Test Anything Protocol) is a language-agnostic format for documenting test results. There is a companion formatting tool, tapfmt, providing a language/runtime-agnostic standalone formatter. There are also many different runtime-specific formatters available if you search npm/github. It's relatively easy to create your own using tap-parser or a similar library.
TAP producers generally output to stdout/stderr (console). However, there are some circumstances where an alternative output mechanism is desired. The tappedout library supports overriding the default output mechanism. For example, to use a custom handler, set the logger as:
import test from 'tappedout'
test.logger = function () {
// Prefix 'TAP:' to every line
console.log(`TAP:`, ...arguments)
}
test('title', t => { ... }})
The most common reason for overriding the output mechanism is for writing results to a file.
Pretty Output:
This library only outputs raw TAP results.
Combine it with a post-processor for "pretty" output.
<details> <summary>TAP Post-Processors/Formatters</summary> <ol> <li><a href="https://github.com/scottcorgan/tap-spec">tap-spec</a></li> <li><a href="https://github.com/scottcorgan/tap-dot">tap-dot</a></li> <li><a href="https://github.com/substack/faucet">faucet</a></li> <li><a href="https://github.com/juliangruber/tap-bail">tap-bail</a></li> <li><a href="https://github.com/kirbysayshi/tap-browser-color">tap-browser-color</a></li> <li><a href="https://github.com/gummesson/tap-json">tap-json</a></li> <li><a href="https://github.com/derhuerst/tap-min">tap-min</a></li> <li><a href="https://github.com/calvinmetcalf/tap-nyan">tap-nyan</a></li> <li><a href="https://www.npmjs.org/package/tap-pessimist">tap-pessimist</a></li> <li><a href="https://github.com/toolness/tap-prettify">tap-prettify</a></li> <li><a href="https://github.com/shuhei/colortape">colortape</a></li> <li><a href="https://github.com/aghassemi/tap-xunit">tap-xunit</a></li> <li><a href="https://github.com/namuol/tap-difflet">tap-difflet</a></li> <li><a href="https://github.com/gritzko/tape-dom">tape-dom</a></li> <li><a href="https://github.com/axross/tap-diff">tap-diff</a></li> <li><a href="https://github.com/axross/tap-notify">tap-notify</a></li> <li><a href="https://github.com/zoubin/tap-summary">tap-summary</a></li> <li><a href="https://github.com/Hypercubed/tap-markdown">tap-markdown</a></li> <li><a href="https://github.com/gabrielcsapo/tap-html">tap-html</a></li> <li><a href="https://github.com/mcnuttandrew/tap-react-browser">tap-react-browser</a></li> <li><a href="https://github.com/dhershman1/tap-junit">tap-junit</a></li> <li><a href="https://github.com/MegaArman/tap-nyc">tap-nyc</a></li> <li><a href="https://github.com/Sceat/tap-spec-emoji">tap-spec (emoji patch)</a></li> <li><a href="https://github.com/rgruesbeck/tape-repeater">tape-repeater</a></li> <li><a href="https://github.com/Josenzo/tabe">tabe</a></li> </ol> </details>Alternative startup:
By default, tappedout automatically runs tests. This behavior can be overridden by setting autostart to false, then manually invoking the start() method.
import test from 'tappedout'
test.autostart = false
test('title 1', t => { ... }})
test('title 2', t => { ... }})
test('title 3', t => { ... }})
test.start()
Overview: How to Make Simple/Awesome Tests
Really... you should read this section if you like making things easy on yourself.
The API is very simple, yet very powerful. There are some simple design principles that can make the experience of testing great. Write less code, more naturally.
-
Directives TAP directives are special/optional "notes" in the output. There are only two options:
skipandtodo. These directives can be added/removed throughout the development lifecycle, making it easier to focus on the tests that matter. This can be really helpful as test suites grow. Many methods in this library support a directive option, and there are some special functions for applying directives in bulk (test.onlyandtest.skip).<br/> -
Detailed Output Sometimes it is valuable to have detailed information about a particular test, such as info about why a test failed. The TAP protocol allows this to be embedded in the output, via YAML.<br/>
Many of the methods in this library support key/value (JSON) arguments that will be properly embedded in the output.
failinfo()andexpect()autocreate detail objects.info()supports custom details.- All assertion/response methods support custom detail objects, wherever you see "
objectdetail" as a method parameter.<br/>
A key usability feature of this library is the ability to add a
DISPLAY_OUTPUTattribute to detail objects. By default, passing tests do not output details, while non-passing tests do. To override this behavior, make sure the detail object has an attribute calledDISPLAY_OUTPUT: true/false.
API
comment (string message [, object detail])
test('suite name', t => {
t.comment('Comment goes here')
})
# Comment goes here
If the message is null, undefined, or blank, no output will be generated.
pass (string message [, string directive, object detail])
test('suite name', t => {
t.pass('Looks good')
})
ok 1 - Looks good
The directive argument is optional. It accepts todo or skip.
fail (string message [, string directive, object detail])
test('suite name', t => {
t.fail('Uh oh')
})
not ok 1 - Uh oh
The directive argument is optional. It accepts todo or skip.
failinfo (any expected, any actual, string message [, string directive])
This is the same as the fail method, but it will output a detail message in YAML format (per the TAP spec).
test('suite name', t => {
t.failinfo(1, 2, 'Should be equal')
})
TAP version 13
# suite name
not ok 1 - Should be equal
---
message: Unmet expectation
severity: fail
expected: 1
actual: 2
...
1..1
info (object)
Additional test information can be embedded in TAP results via YAML. The info method accepts a valid key/value JSON object, which will be embedded in the output in YAML format.
test('suite name', t => {
const passing = false
t.ok(passing, 'test description')
if (!passing) {
t.info({
message: 'Detail',
got: {
mytest: {
result: false
}
},
expected: {
mytest: {
result: true
}
}
})
}
})
TAP version 13
# suite name
not ok 1 - test description
---
message: Detail
got: {
"mytest": {
"result": false
}
}
expected: {
"mytest": {
"result": true
}
}
...
1..1
skip (string msg [, object detail])
Skip the test. This serves primarily as a placeholder for conditional tests. To skip an entire test suite, see test.skip and test.only.
test('suite name', t => {
t.skip('Not relevant to this runtime')
})
ok 1 # skip Not relevant to this runtime
todo (string message, [boolean pass = true, object detail])
TODO items are a special directive in TAP. They always "pass", even if a test fails, because they're [considered to be a work in progress](https://testa
Related Skills
gh-issues
344.4kFetch GitHub issues, spawn sub-agents to implement fixes and open PRs, then monitor and address PR review comments. Usage: /gh-issues [owner/repo] [--label bug] [--limit 5] [--milestone v1.0] [--assignee @me] [--fork user/repo] [--watch] [--interval 5] [--reviews-only] [--cron] [--dry-run] [--model glm-5] [--notify-channel -1002381931352]
node-connect
344.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
99.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
Writing Hookify Rules
99.2kThis skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.
