mirror of
https://github.com/zaphar/test-tap.git
synced 2025-07-21 20:19:49 -04:00
feat: Properly handle node async output
This commit is contained in:
parent
975d7f22af
commit
431b25cdfd
42
src/TAP.mjs
42
src/TAP.mjs
@ -21,10 +21,16 @@
|
||||
|
||||
/** @implements TapRenderer */
|
||||
class NodeRenderer {
|
||||
/** @type {Array<PromiseLike>} */
|
||||
#thunks = [];
|
||||
|
||||
out(text) {
|
||||
import('node:process').then(loaded => {;
|
||||
this.#thunks.push(
|
||||
// Because this is a ECMAScript module we have to do dynamic module loads
|
||||
// of the node ecosystem when running in Node.js.
|
||||
import('node:process').then(loaded => {
|
||||
loaded.stdout.write(text + "\n");
|
||||
})
|
||||
}));
|
||||
}
|
||||
|
||||
comment(lines) {
|
||||
@ -32,6 +38,14 @@ class NodeRenderer {
|
||||
this.out('# ' + line);
|
||||
}
|
||||
}
|
||||
|
||||
// This gives us a way to block on output. It's ghetto but async is a harsh task master.
|
||||
async renderAll() {
|
||||
for (var thunk of this.#thunks) {
|
||||
await thunk;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/** @implements TapRenderer */
|
||||
@ -90,28 +104,40 @@ class Tap {
|
||||
/** @type Number */
|
||||
failed = 0;
|
||||
/** @type TapRenderer */
|
||||
#renderer
|
||||
renderer
|
||||
|
||||
/**
|
||||
* Construct a new Tap Suite with a renderLine function.
|
||||
* @param {TapRenderer}
|
||||
*/
|
||||
constructor(renderer) {
|
||||
this.#renderer = renderer;
|
||||
this.renderer = renderer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return {{"Renderer": BrowserRenderer, "Tap": Tap}}
|
||||
*/
|
||||
static Browser() {
|
||||
var r = new BrowserRenderer();
|
||||
return {"Renderer": r, "Tap": new Tap(r)};
|
||||
return new Tap(new BrowserRenderer());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {{"Renderer": NodeRenderer, "Tap": Tap}}
|
||||
*/
|
||||
static Node() {
|
||||
return new Tap(new NodeRenderer());
|
||||
var r = new NodeRenderer();
|
||||
return {"Renderer": r, "Tap": new Tap(r)};
|
||||
}
|
||||
|
||||
isPass() {
|
||||
return this.passed != 0;
|
||||
}
|
||||
|
||||
/** Renders output for the test results */
|
||||
out(text) {
|
||||
this.#renderer.out(text);
|
||||
this.renderer.out(text);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -135,7 +161,7 @@ class Tap {
|
||||
msg = " ";
|
||||
}
|
||||
var lines = msg.split("\n");
|
||||
this.#renderer.comment(lines);
|
||||
this.renderer.comment(lines);
|
||||
};
|
||||
|
||||
/** Render a pass TAP output message.
|
||||
|
@ -14,6 +14,10 @@ class FakeRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
import('./suite.mjs').then(m => {
|
||||
m.runTest(m.Tap.Node(), "Tap dogfood test suite", m.tapSuite);
|
||||
import('./suite.mjs').then(async m => {
|
||||
const pair = m.Tap.Node();
|
||||
m.runTest(pair.Tap, "Tap dogfood test suite", m.tapSuite);
|
||||
// Note output requires some async machinery because it uses some dynamic inputs.
|
||||
await pair.Renderer.renderAll();
|
||||
process.exit(pair.Tap.isPass() ? 0 : 1);
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
/** @implements TapRenderer */
|
||||
import {Tap, runTest} from '../src/TAP.mjs';
|
||||
import {Tap, runTest, NodeRenderer, BrowserRenderer} from '../src/TAP.mjs';
|
||||
|
||||
class FakeRenderer {
|
||||
output = "nothing yet";
|
||||
|
Loading…
x
Reference in New Issue
Block a user