🧪 Run node:test
suites in the browser
💡 Inspired by nodejs/node-core-test
👨🔬 Great for browser compat with existing node:test
tests
🌲 Lets you run tests against an isolated <iframe>
DOM
🏷️ Implements node:test
as of Node.js v20.0.0 (see below)
❓ You may be looking for nodejs/node-core-test instead. It's node:test
extracted into an npm package for use on older Node.js versions.
You can download this package locally using npm, Yarn, pnpm, or your other
favorite Node.js package manager. Just make sure that you plan on using it in
the browser! You can use a bundler like Vite or webpack to bundle npm
packages into a nice JavaScript bundle for use in a <script>
tag.
npm install @jcbhmr/node-test
Or, if you prefer to go buildless, you can import this module directly from an
npm CDN like ESM>CDN or jsDelivr. You'll probably also want the browser
version of node:assert
from browserify/commonjs-assert or another
browser-compatible assertion package.
import { ... } from "https://esm.sh/assert@2"
import { ... } from "https://esm.sh/@jcbhmr/node-test@1"
🛑 In Node.js, you can juse use the included node:test
module that's built
right into Node.js! If you're using Deno or Bun, you can use their included
node:
compatability layer to also import node:test
and get started with no
fuss. The browser is the only really tricky part, and that's what this module is
for!
You can even use package.json
's imports
key to declaratively switch from a
native implementation to a browser-compatible implementation:
// package.json
{
"imports": {
"#node:test": {
"browser": "@jcbhmr/node-test",
"default": "node:test"
}
}
}
import { run } from "@jcbhmr/node-test";
const stream = run({ files: ["./app.test.js"] });
Tests created via the test
module consist of a single function that is
processed in one of three ways:
- A synchronous function that is considered failing if it throws an exception, and is considered passing otherwise.
- A function that returns a
Promise
that is considered failing if thePromise
rejects, and is considered passing if thePromise
resolves. - A function that receives a callback function. If the callback receives any
truthy value as its first argument, the test is considered failing. If a
falsy value is passed as the first argument to the callback, the test is
considered passing. If the test function receives a callback function and
also returns a
Promise
, the test will fail.
The following example illustrates how tests are written using the test
module:
import assert from "assert";
import test from "@jcbhmr/node-test";
test("synchronous passing test", (t) => {
// This test passes because it does not throw an exception.
assert.strictEqual(1, 1);
});
test("failing async test", async (t) => {
// When a function returns a promise (like an async function), we wait for it
// to asynchronously resolve or reject.
await new Promise((r) => setTimeout(r, 1000));
assert.strictEqual(5, 800);
});
test("callback passing test", (t, done) => {
// done() is the callback function. When the setTimeout() runs, it invokes
// done() with no arguments.
setTimeout(done, 100);
});
📗 Since we mirror node:test
so closely, it's better to consult the official
Node.js node:test
docs. If you find a problem or inconsistency, don't
hesitate to open an Issue! ❤️
- We can't hide our internal stack frames on non-Chrome browsers.
- You must use the
run()
function yourself. There's no--test
flag in the browser! 😉 - Instead of using Node.js' subprocesses to run tests, we use a hidden
<iframe>
to isolate the test environment.
This package is written in TypeScript and uses Vite to create a JavaScript
bundle for publication to npmjs.com. We use Vitest for testing in a headless
Chrome browser. You can start up the test watcher by running npm start
. Check
out the dev wiki for more info.