First implementation of the metaltest
parent
16f2281e77
commit
f953f607bb
|
@ -0,0 +1 @@
|
||||||
|
node_modules
|
|
@ -0,0 +1,59 @@
|
||||||
|
import chalk from 'chalk'
|
||||||
|
const log = (...args) => process.stdout.write(...args)
|
||||||
|
|
||||||
|
const consolereporter = () => {
|
||||||
|
|
||||||
|
const report = {
|
||||||
|
start: (title) => {
|
||||||
|
log(chalk.cyanBright(title) + ' ')
|
||||||
|
},
|
||||||
|
success: (test) => {
|
||||||
|
log(chalk.greenBright('✓ '))
|
||||||
|
},
|
||||||
|
fail: (test, e) => {
|
||||||
|
log(chalk.redBright('✗ '))
|
||||||
|
},
|
||||||
|
end: (stats) => {
|
||||||
|
const { success, fail, total, testFail } = stats
|
||||||
|
|
||||||
|
log(' ' + chalk.redBright(fail))
|
||||||
|
log(' ' + chalk.greenBright(success))
|
||||||
|
log(' ' + chalk.gray('total:', total) + '\n')
|
||||||
|
|
||||||
|
for (const test of testFail) {
|
||||||
|
log('\n' + chalk.redBright(test.name) + '\n')
|
||||||
|
prettyError(test.error)
|
||||||
|
log('\n')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return report
|
||||||
|
}
|
||||||
|
|
||||||
|
const prettyError = (error) => {
|
||||||
|
if (typeof error == 'string') {
|
||||||
|
log(chalk.yellowBright(error))
|
||||||
|
log('\n')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const msg = error.stack
|
||||||
|
const i = msg.indexOf('\n')
|
||||||
|
|
||||||
|
const title = msg.slice(0, i)
|
||||||
|
log(chalk.yellowBright(title) + '\n')
|
||||||
|
|
||||||
|
const at = msg.indexOf(' at ')
|
||||||
|
const diff = msg.slice(i + 1, at - 1)
|
||||||
|
if (diff != '\n ')
|
||||||
|
log(chalk.white(diff))
|
||||||
|
|
||||||
|
const atEnd = msg.slice(at).indexOf('\n')
|
||||||
|
const where = msg.slice(at + 3, at + atEnd)
|
||||||
|
|
||||||
|
if (where != '')
|
||||||
|
log(chalk.gray(where) + '\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
export { consolereporter }
|
|
@ -0,0 +1,70 @@
|
||||||
|
|
||||||
|
import { consolereporter } from './consolereporter.js'
|
||||||
|
import { totalreporter } from './totalreporter.js'
|
||||||
|
import { runifmain } from './runifmain.js'
|
||||||
|
|
||||||
|
const noreporter = {
|
||||||
|
start: (title) => { },
|
||||||
|
before: () => { },
|
||||||
|
success: (test) => { },
|
||||||
|
fail: (test, e) => { },
|
||||||
|
after: () => { },
|
||||||
|
end: (stats) => { },
|
||||||
|
}
|
||||||
|
|
||||||
|
const metaltest = (title) => {
|
||||||
|
const suite = []
|
||||||
|
const only = []
|
||||||
|
const before = []
|
||||||
|
const after = []
|
||||||
|
|
||||||
|
let success = 0
|
||||||
|
let fail = 0
|
||||||
|
const testSuccess = []
|
||||||
|
const testFail = []
|
||||||
|
|
||||||
|
const runner = (name, fn) => {
|
||||||
|
suite.push({ name, fn })
|
||||||
|
}
|
||||||
|
|
||||||
|
runner.only = (fn) => { only.push(fn) }
|
||||||
|
runner.before = (fn) => { before.push(fn) }
|
||||||
|
runner.after = (fn) => { after.push(fn) }
|
||||||
|
|
||||||
|
runner.run = async (...reporters) => {
|
||||||
|
const rs = reporters.map(r => Object.assign({}, noreporter, r))
|
||||||
|
|
||||||
|
rs.forEach(r => r.start(title))
|
||||||
|
rs.forEach(r => r.before())
|
||||||
|
|
||||||
|
const tests = only.length ? only : suite
|
||||||
|
for (const test of tests) {
|
||||||
|
try {
|
||||||
|
for (const fn of before) await fn()
|
||||||
|
await test.fn()
|
||||||
|
success++
|
||||||
|
rs.forEach(r => r.success(test))
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
fail++
|
||||||
|
testFail.push(Object.assign({}, test, { error: e }))
|
||||||
|
rs.forEach(r => r.fail(test, e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const fn of after) await fn()
|
||||||
|
|
||||||
|
rs.forEach(r => r.after())
|
||||||
|
|
||||||
|
const stats = { title, success, fail, total: success + fail, testSuccess, testFail }
|
||||||
|
|
||||||
|
rs.forEach(r => r.end(stats))
|
||||||
|
|
||||||
|
return stats
|
||||||
|
}
|
||||||
|
|
||||||
|
return runner
|
||||||
|
}
|
||||||
|
|
||||||
|
export { metaltest, consolereporter, totalreporter, runifmain }
|
||||||
|
export default metaltest
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"name": "metaltest",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "metaltest",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "AGPL-3.0-or-later",
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": "^5.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chalk": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-E5CkT4jWURs1Vy5qGJye+XwCkNj7Od3Af7CP6SujMetSMkLs8Do2RWJK5yx1wamHV/op8Rz+9rltjaTQWDnEFQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-E5CkT4jWURs1Vy5qGJye+XwCkNj7Od3Af7CP6SujMetSMkLs8Do2RWJK5yx1wamHV/op8Rz+9rltjaTQWDnEFQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"name": "metaltest",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Clone of baretest with reporting",
|
||||||
|
"type": "module",
|
||||||
|
"exports": "./index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "node test.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.tranche.ca/fmatte/metaltest"
|
||||||
|
},
|
||||||
|
"author": "Frédéric Matte <fmatte@gmail.com>",
|
||||||
|
"license": "AGPL-3.0-or-later",
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": "^5.1.2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
|
const isMain = (meta) => {
|
||||||
|
const path = fileURLToPath(meta.url)
|
||||||
|
|
||||||
|
return path.includes(process.argv[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
const runifmain = async (meta, fn) => {
|
||||||
|
if (isMain(meta)) {
|
||||||
|
await fn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { runifmain }
|
|
@ -0,0 +1,26 @@
|
||||||
|
import assert from 'node:assert/strict'
|
||||||
|
import { metaltest, consolereporter } from './index.js'
|
||||||
|
|
||||||
|
const test = metaltest('Metaltest')
|
||||||
|
|
||||||
|
let count = 0
|
||||||
|
test.before(() => count++)
|
||||||
|
|
||||||
|
test('success', () => new Promise((s, f) => setTimeout(s, 500)))
|
||||||
|
test('not equal', () => assert.notEqual({ a: 1 }, { a: 2 }))
|
||||||
|
test('fail with the message', () => new Promise((s, f) => setTimeout(s, 500)))
|
||||||
|
test('throw', () => {
|
||||||
|
return assert.rejects(async () => {
|
||||||
|
throw new Error('message')
|
||||||
|
}, { name: 'Error', message: 'message' })
|
||||||
|
})
|
||||||
|
|
||||||
|
export { test }
|
||||||
|
|
||||||
|
import { runifmain } from './runifmain.js'
|
||||||
|
await runifmain(import.meta, async () => {
|
||||||
|
const stats = await test.run(consolereporter())
|
||||||
|
assert.equal(count, 4)
|
||||||
|
assert.equal(stats.success, 4)
|
||||||
|
assert.equal(stats.fail, 0)
|
||||||
|
})
|
|
@ -0,0 +1,17 @@
|
||||||
|
import chalk from 'chalk'
|
||||||
|
|
||||||
|
const totalreporter = () => {
|
||||||
|
let totalSuccess = 0, totalFail = 0
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: (test) => { totalSuccess++ },
|
||||||
|
fail: (test, e) => { totalFail++ },
|
||||||
|
msg: () => `
|
||||||
|
${chalk.redBright(`Total fail: ${totalFail}`)}
|
||||||
|
${chalk.greenBright(`Total sucess: ${totalSuccess}`)}
|
||||||
|
${chalk.yellowBright(`Ratio ${(totalSuccess / (totalSuccess + totalFail)) * 100}%`)}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { totalreporter }
|
Loading…
Reference in New Issue