Skip to content

Instantly share code, notes, and snippets.

@GitaiQAQ
Last active February 28, 2022 15:52
Show Gist options
  • Save GitaiQAQ/51cd10d1ef03305cc52b70d9b46a1562 to your computer and use it in GitHub Desktop.
Save GitaiQAQ/51cd10d1ef03305cc52b70d9b46a1562 to your computer and use it in GitHub Desktop.
A tiny unit test module or function powered by ES6/Promise.
#!/usr/bin/env node
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004
// Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
// 0. You just DO WHAT THE FUCK YOU WANT TO.
/**
* # Dotu
* A tiny unit test module or function powered by ES6/Promise.
*
* # How to use?
* ## From gist source
* ```shell
* $ git clone https://gist.github.com/51cd10d1ef03305cc52b70d9b46a1562.git
* $ node .u.js ./example.js
* ```
* ## From npm
* ```shell
* $ npm install dotu
* $ npx dotu ./example.js
* ```
*
* @param {*} label
* @param {*} testCase fn
*/
function test(label, fn = label) {
label = label === fn ? '(anonymous)' : label;
let id = 0;
let success = 0;
process.on('exit', () => {
console.log(`# pass ${success}/${id}`);
console.log(`# fail ${id - success}/${id}`);
});
console.log('u version 0.5')
function rawTest(label, fn, id) {
let handle = (err, msg) => {
console.log(id, label);
if (err) {
console.log(`[err]`, err);
return;
}
success++;
console.log(`[ok] ${msg}`);
};
new Promise((resolve, reject) => {
let _ok = false;
let _data = null;
const fail = (msg) => (_ok = false, _data = new Error(msg));
const pass = (msg) => (_ok = true, _data = msg);
const end = (msg) => {
(_ok ? resolve : reject)(_data ?? (_ok ? pass : fail)(msg));
};
const timeoutAfter = (ms) => setTimeout(end.bind(undefined, 'timeout'), ms);
const notOk = (value, msg) => (!value ? pass(msg) : fail(msg));
const ok = (value, msg) => notOk(!value, msg);
const error = (err) => err instanceof Error ? fail(err.message) : undefined;
Promise.resolve(fn({
end,
fail, pass, timeoutAfter,
ok, notOk, error
})).then(end, error);
})
.then((msg) => handle(null, msg), (err) => handle(err));
}
test = (label, fn) => rawTest(label, fn, ++id);
test(label, fn);
}
module.exports = (label, fn) => test(label, fn);
if (!module.parent) {
const cwd = process.cwd();
const fs = require('fs');
const path = require('path');
delete require.cache[module.filename];
let _nodeModulePaths = module.__proto__.constructor._nodeModulePaths;
module.__proto__.constructor._nodeModulePaths = (...args) => {
let paths = _nodeModulePaths(...args);
paths.unshift(module.path);
return paths
}
process.argv
.slice(2)
.flatMap(p => fs.
statSync(p).isDirectory() ? fs.readdirSync(p).map(file => path.join(p, file)) : p)
.map(p => path.join(cwd, p))
.map(file => require(file));
}
const tut = require('.u');
tut((assert) => {
assert.pass('anonymous');
})
tut('assert.pass', (assert) => {
assert.pass('pass');
})
tut('assert.fail', (assert) => {
assert.fail('fail');
})
tut('logic', (assert) => {
assert.ok(true, 'basic');
assert.notOk(false, 'basic');
})
tut('throws', (assert) => {
assert.error(new Error('IO error'));
})
tut('async assert.pass', async (assert) => {
await new Promise((resolve) => setTimeout(() => {
assert.pass('pass');
resolve();
}, 100))
});
tut('async assert.fail', async (assert) => {
await new Promise((resolve) => setTimeout(() => {
assert.fail('fail');
resolve();
}, 100))
});
tut('async assert.timeoutAfter', async (assert) => {
assert.timeoutAfter(1000);
await new Promise(() => {})
});
{
"name": "dotu",
"description": "A tiny unit test module or function powered by ES6/Promise.",
"version": "0.0.5",
"main": ".u.js",
"bin": ".u.js",
"author": "Gitai<i@gitai.me>",
"license": "WTFPL",
"repository": {
"url": "https://gist.github.com/GitaiQAQ/51cd10d1ef03305cc52b70d9b46a1562"
}
}
$ node ./.u.js ./example.js
u version 0.3
1 (anonymous)
[ok] anonymous
2 assert.pass
[ok] pass
3 assert.fail
[err] Error: fail
at Object.fail (C:\Users\gitai\Desktop\tut\u.js:31:51)
at C:\Users\gitai\Desktop\tut\test.js:12:12
at C:\Users\gitai\Desktop\tut\u.js:43:23
at new Promise (<anonymous>)
at rawTest (C:\Users\gitai\Desktop\tut\u.js:27:5)
at test (C:\Users\gitai\Desktop\tut\u.js:51:25)
at module.exports (C:\Users\gitai\Desktop\tut\u.js:55:33)
at Object.<anonymous> (C:\Users\gitai\Desktop\tut\test.js:11:1)
at Module._compile (node:internal/modules/cjs/loader:1092:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1121:10)
4 logic
[ok] basic
5 throws
[err] Error: IO error
at fail (C:\Users\gitai\Desktop\tut\u.js:31:51)
at Object.error (C:\Users\gitai\Desktop\tut\u.js:41:53)
at C:\Users\gitai\Desktop\tut\test.js:21:12
at C:\Users\gitai\Desktop\tut\u.js:43:23
at new Promise (<anonymous>)
at rawTest (C:\Users\gitai\Desktop\tut\u.js:27:5)
at test (C:\Users\gitai\Desktop\tut\u.js:51:25)
at module.exports (C:\Users\gitai\Desktop\tut\u.js:55:33)
at Object.<anonymous> (C:\Users\gitai\Desktop\tut\test.js:20:1)
at Module._compile (node:internal/modules/cjs/loader:1092:14)
6 async assert.pass
[ok] pass
7 async assert.fail
[err] Error: fail
at Object.fail (C:\Users\gitai\Desktop\tut\u.js:31:51)
at Timeout._onTimeout (C:\Users\gitai\Desktop\tut\test.js:33:16)
at listOnTimeout (node:internal/timers:557:17)
at processTimers (node:internal/timers:500:7)
8 async assert.timeoutAfter
[err] Error: timeout
at fail (C:\Users\gitai\Desktop\tut\u.js:31:51)
at end (C:\Users\gitai\Desktop\tut\u.js:34:62)
at listOnTimeout (node:internal/timers:557:17)
at processTimers (node:internal/timers:500:7)
# pass 4/8
# fail 4/8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment