Compare commits

...

2 Commits

Author SHA1 Message Date
4d73f75ec8 packaging: npm configuration 2024-04-03 17:47:01 -04:00
431b25cdfd feat: Properly handle node async output 2024-04-03 17:15:43 -04:00
6 changed files with 151 additions and 77 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules/

24
package-lock.json generated Normal file
View File

@ -0,0 +1,24 @@
{
"name": "test-tap",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "test-tap",
"version": "0.0.1",
"license": "Artistic-2.0",
"dependencies": {
"esm": "^3.2.25"
}
},
"node_modules/esm": {
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
"integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==",
"engines": {
"node": ">=6"
}
}
}
}

34
package.json Normal file
View File

@ -0,0 +1,34 @@
{
"name": "test-tap",
"version": "0.0.1",
"description": "Test-Tap a 0 dependency single file Test Anything Protocol library",
"type": "module",
"directories": {
"test": "tests",
"lib": "src"
},
"files": [
"src/*.mjs",
"src/*.js"
],
"scripts": {
"test": "node tests/01_tap.t.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/zaphar/test-tap.git"
},
"keywords": [
"testing",
"tap"
],
"author": "Jeremy Wall (jeremy@marzhillstudios.com)",
"license": "Artistic-2.0",
"bugs": {
"url": "https://github.com/zaphar/test-tap/issues"
},
"homepage": "https://github.com/zaphar/test-tap#readme",
"dependencies": {
"esm": "^3.2.25"
}
}

View File

@ -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.

View File

@ -1,19 +1,8 @@
/** @implements TapRenderer */
class FakeRenderer {
output = "nothing yet";
commentOutput = "";
import { Tap, runTest } from '../src/Tap.mjs';
import { tapSuite } from './suite.mjs';
out(text) {
this.output = text;
}
comment(lines) {
for (var line of lines) {
this.commentOutput += line;
}
}
}
import('./suite.mjs').then(m => {
m.runTest(m.Tap.Node(), "Tap dogfood test suite", m.tapSuite);
});
const pair = Tap.Node();
runTest(pair.Tap, "Tap dogfood test suite", tapSuite);
// Note output requires some async machinery because it uses some dynamic inputs.
await pair.Renderer.renderAll();
process.exit(pair.Tap.isPass() ? 0 : 1);

View File

@ -1,5 +1,5 @@
/** @implements TapRenderer */
import {Tap, runTest} from '../src/TAP.mjs';
import { Tap } from '../src/Tap.mjs';
class FakeRenderer {
output = "nothing yet";
@ -159,4 +159,4 @@ function tapSuite(t) {
return t;
}
export { tapSuite, runTest, Tap };
export { tapSuite };