Added helpers into cb:
All checks were successful
continuous-integration/appveyor/branch AppVeyor build succeeded

* wrap() that auto captures thrown exceptions and cb's them
* finish() that auto captures thrown exception and cb's them, otherwise auto-finishes the cb for you
This commit is contained in:
Jonatan Nilsson 2022-07-04 10:23:41 +00:00
parent 2c3fc01722
commit 9d2b71339c
7 changed files with 328 additions and 10 deletions

View file

@ -42,7 +42,11 @@ on_success:
https://git.nfp.is/api/v1/repos/$APPVEYOR_REPO_NAME/releases \
-d "{\"tag_name\":\"v${CURR_VER}\",\"name\":\"v${CURR_VER}\",\"body\":\"Automatic release from Appveyor from ${APPVEYOR_REPO_COMMIT} :\n\n${APPVEYOR_REPO_COMMIT_MESSAGE}\"}")
RELEASE_ID=$(echo $RELEASE_RESULT | jq -r .id)
if [ "$RELEASE_ID" == "null" ]; then
echo $RELEASE_RESULT
else
echo "Created release ${RELEASE_ID}"
fi
echo '//registry.npmjs.org/:_authToken=${npmtoken}' > ~/.npmrc
echo "Publishing new version to npm"
npm publish

33
lib/callback.mjs Normal file
View file

@ -0,0 +1,33 @@
export function runWithCallbackSafe(test) {
return new Promise(function(res, rej) {
try {
let cb = function(err) {
if (err) {
return rej(err)
}
res()
}
let safeWrap = function(finish) {
// return a safe wrap support
return function(fun) {
return function(a, b, c) {
try {
fun(a, b, c)
if (finish) {
res()
}
}
catch (err) {
return rej(err)
}
}
}
}
cb.wrap = safeWrap(false)
cb.finish = safeWrap(true)
test.func(cb)
} catch (err) {
rej(err)
}
})
}

View file

@ -1,4 +1,5 @@
import * as readline from 'readline'
import { runWithCallbackSafe } from './callback.mjs'
import { printError } from './cli.mjs'
function Group(e, name) {
@ -155,14 +156,7 @@ Eltro.prototype.__runTest = async function(stats, test, prefix = 'Test', child =
// If the test requires callback, wrap it in a promise where callback
// either resolves or rejects that promise
if (checkIsCallback) {
promise = new Promise(function(res, rej) {
test.func(function(err) {
if (err) {
return rej(err)
}
res()
})
})
promise = runWithCallbackSafe(test)
} else {
// Function doesn't require a callback, run it directly
promise = test.func()

View file

@ -1,6 +1,6 @@
{
"name": "eltro",
"version": "1.3.1",
"version": "1.3.2",
"description": "Eltro is a tiny no-dependancy test framework for node",
"main": "index.mjs",
"scripts": {

217
test/callback.test.mjs Normal file
View file

@ -0,0 +1,217 @@
import { runWithCallbackSafe } from '../lib/callback.mjs'
import assert from '../lib/assert.mjs'
import t from '../lib/eltro.mjs'
t.describe('runCb()', function() {
t.test('cb() should work normally', async function() {
let called = false
let test = { func: function(cb) { called = true; cb() } }
await runWithCallbackSafe(test)
assert.strictEqual(called, true)
})
t.test('cb() should work with timeout', async function() {
let called = false
let test = { func: function(cb) {
setImmediate(function() {
called = true;
cb();
})
} }
await runWithCallbackSafe(test)
assert.strictEqual(called, true)
})
t.test('cb() should capture throws outside', async function() {
const assertError = new Error('a')
let test = { func: function(cb) { throw assertError } }
let err = await assert.isRejected(runWithCallbackSafe(test))
assert.strictEqual(err, assertError)
})
t.test('cb() should support callback error', async function() {
const assertError = new Error('a')
let test = { func: function(cb) { cb(assertError) } }
let err = await assert.isRejected(runWithCallbackSafe(test))
assert.strictEqual(err, assertError)
})
t.test('cb() should support callback error in immediate', async function() {
const assertError = new Error('a')
let test = { func: function(cb) {
setImmediate(function() {
cb(assertError)
})
} }
let err = await assert.isRejected(runWithCallbackSafe(test))
assert.strictEqual(err, assertError)
})
t.test('cb.wrap() should return function and work with timeout', async function() {
let calledFirst = false
let calledSecond = false
let test = { func: function(cb) {
let fun = cb.wrap(function() {
calledSecond = true
cb()
})
setImmediate(function() {
calledFirst = true;
fun()
})
} }
await runWithCallbackSafe(test)
assert.strictEqual(calledFirst, true)
assert.strictEqual(calledSecond, true)
})
t.test('cb.wrap() should pass arguments correctly', async function() {
let a = 0
let b = 0
let c = 0
let called = false
let test = { func: function(cb) {
let fun = cb.wrap(function(ina, inb, inc) {
a = ina
b = inb
c = inc
cb()
})
setImmediate(function() {
called = true
fun(1, 2, 3)
})
} }
await runWithCallbackSafe(test)
assert.strictEqual(called, true)
assert.strictEqual(a, 1)
assert.strictEqual(b, 2)
assert.strictEqual(c, 3)
await runWithCallbackSafe(test)
})
t.test('cb.wrap() should throw', async function() {
const assertError = new Error('a')
let test = { func: function(cb) {
setImmediate(cb.wrap(function() {
throw assertError
}))
} }
let err = await assert.isRejected(runWithCallbackSafe(test))
assert.strictEqual(err, assertError)
})
t.test('cb.wrap() should support nested calls', async function() {
const assertError = new Error('a')
let test = { func: function(cb) {
setImmediate(function() {
setImmediate(cb.wrap(function() {
throw assertError
}))
})
} }
let err = await assert.isRejected(runWithCallbackSafe(test))
assert.strictEqual(err, assertError)
})
t.test('cb.finish() should return function and work with timeout and finish', async function() {
let calledFirst = false
let calledSecond = false
let test = { func: function(cb) {
let fun = cb.finish(function() {
calledSecond = true
})
setImmediate(function() {
calledFirst = true;
fun()
})
} }
await runWithCallbackSafe(test)
assert.strictEqual(calledFirst, true)
assert.strictEqual(calledSecond, true)
})
t.test('cb.finish() should pass arguments correctly', async function() {
let a = 0
let b = 0
let c = 0
let called = false
let test = { func: function(cb) {
let fun = cb.finish(function(ina, inb, inc) {
a = ina
b = inb
c = inc
})
setImmediate(function() {
called = true
fun(1, 2, 3)
})
} }
await runWithCallbackSafe(test)
assert.strictEqual(called, true)
assert.strictEqual(a, 1)
assert.strictEqual(b, 2)
assert.strictEqual(c, 3)
await runWithCallbackSafe(test)
})
t.test('cb.finish() should support throw', async function() {
const assertError = new Error('a')
let test = { func: function(cb) {
setImmediate(cb.finish(function() {
throw assertError
}))
} }
let err = await assert.isRejected(runWithCallbackSafe(test))
assert.strictEqual(err, assertError)
})
t.test('cb.finish() should support nested throw calls', async function() {
const assertError = new Error('a')
let test = { func: function(cb) {
setImmediate(function() {
setImmediate(cb.finish(function() {
throw assertError
}))
})
} }
let err = await assert.isRejected(runWithCallbackSafe(test))
assert.strictEqual(err, assertError)
})
})

View file

@ -147,6 +147,38 @@ e.test('Eltro should support callback', async function() {
assert.strictEqual(assertIsTrue, true)
})
e.test('Eltro should support custom cb with finish wrap', async function() {
let actualRan = 0
const t = CreateT()
t.begin()
t.describe('', function() {
t.test('a', function(cb) {
setImmediate(() => {
setImmediate(cb.finish(() => { actualRan++; }))
})
})
t.test('b', function(cb) {
setImmediate(() => {
setImmediate(cb.finish(() => { actualRan++; }))
})
})
t.test('c', function(cb) {
setImmediate(() => {
setImmediate(cb.finish(() => { actualRan++; }))
})
})
t.test('d', function(cb) {
setImmediate(() => {
setImmediate(cb.finish(() => { actualRan++; }))
})
})
})
await t.run()
assert.strictEqual(t.failedTests.length, 0)
assert.strictEqual(actualRan, 4)
})
e.test('Eltro should support directly thrown errors', async function() {
testsWereRun = true
const assertError = new Error()

View file

@ -49,3 +49,41 @@ e.test('Eltro should support any value in throws', async function() {
assert.ok(t.failedTests[x].error.stack)
}
})
e.test('Eltro should support custom cb with safe wrap', async function() {
let actualRan = 0
const t = CreateT()
t.begin()
t.describe('', function() {
t.test('a', function(cb) {
setImmediate(() => {
setImmediate(cb.wrap(() => { actualRan++; throw null }))
})
})
t.test('b', function(cb) {
setImmediate(() => {
setImmediate(cb.wrap(() => { actualRan++; throw {} }))
})
})
t.test('c', function(cb) {
setImmediate(() => {
setImmediate(cb.wrap(() => { actualRan++; throw { message: 'test' } }))
})
})
t.test('d', function(cb) {
setImmediate(() => {
setImmediate(cb.wrap(() => { actualRan++; throw 1234 }))
})
})
})
await t.run()
assert.strictEqual(t.failedTests.length, 4)
for (let x = 0; x < t.failedTests.length; x++) {
assert.strictEqual(typeof(t.failedTests[x].error), 'object')
assert.ok(t.failedTests[x].error.message)
assert.ok(t.failedTests[x].error.stack)
}
assert.strictEqual(actualRan, t.failedTests.length)
})