Compare commits
No commits in common. "ee6ef75765db6bf6bde7ac00d5761f3372bc32f2" and "05cc68d84c9e8b02540ff78ebbde0fc1f4008ec9" have entirely different histories.
ee6ef75765
...
05cc68d84c
|
@ -2,9 +2,8 @@
|
||||||
|
|
||||||
import { suite } from 'metaltest'
|
import { suite } from 'metaltest'
|
||||||
|
|
||||||
const run = async (folder) => {
|
const run = async () => {
|
||||||
if (!folder) folder = process.cwd()
|
await suite(process.cwd())
|
||||||
await suite(folder)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const [, , folder] = process.argv
|
const [, , folder] = process.argv
|
1
index.js
1
index.js
|
@ -1,5 +1,4 @@
|
||||||
export * from './reporter/index.js'
|
export * from './reporter/index.js'
|
||||||
export * from './lib/mock.js'
|
|
||||||
export { suite } from './lib/suite.js'
|
export { suite } from './lib/suite.js'
|
||||||
|
|
||||||
import { metaltest } from './lib/metaltest.js'
|
import { metaltest } from './lib/metaltest.js'
|
||||||
|
|
|
@ -40,11 +40,11 @@ const metaltest = (title) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const runner = (name, fn) => {
|
const runner = (name, fn) => {
|
||||||
suite.push({ name, fn, at: getAt() })
|
suite.push({ name, fn })
|
||||||
}
|
}
|
||||||
|
|
||||||
runner.only = (name, fn) => { only.push({ name, fn, at: getAt() }) }
|
runner.only = (name, fn) => { only.push({ name, fn }) }
|
||||||
runner.skip = (name, fn) => { skipped.push({ name, fn, at: getAt() }) }
|
runner.skip = (name, fn) => { skipped.push({ name, fn }) }
|
||||||
runner.before = (fn) => { before.push(fn) }
|
runner.before = (fn) => { before.push(fn) }
|
||||||
runner.after = (fn) => { after.push(fn) }
|
runner.after = (fn) => { after.push(fn) }
|
||||||
runner.end = (name, fn) => { end.push({ name, fn }) }
|
runner.end = (name, fn) => { end.push({ name, fn }) }
|
||||||
|
@ -74,7 +74,7 @@ const metaltest = (title) => {
|
||||||
for (const fn of before) await fn()
|
for (const fn of before) await fn()
|
||||||
await test.fn(test)
|
await test.fn(test)
|
||||||
stats('success', test)
|
stats('success', test)
|
||||||
await notify(reporters, 'success', test)
|
notify(reporters, 'success', test)
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
stats('fail', test, error)
|
stats('fail', test, error)
|
||||||
|
|
56
lib/mock.js
56
lib/mock.js
|
@ -1,56 +0,0 @@
|
||||||
|
|
||||||
const capture = (actions, name, fn) => async (...args) => {
|
|
||||||
const count = actions.reduce((count, curr) => {
|
|
||||||
if (curr.name === name) return count + 1
|
|
||||||
|
|
||||||
return count
|
|
||||||
}, 1)
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await fn(...args, { count })
|
|
||||||
actions.push({ name, args, result })
|
|
||||||
return result
|
|
||||||
} catch (error) {
|
|
||||||
actions.push({ name, args, result: error })
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const mock = async (mocks, fn) => {
|
|
||||||
const olds = {}
|
|
||||||
const actions = []
|
|
||||||
|
|
||||||
for (const mock of mocks) {
|
|
||||||
if (mock.package in olds === false) olds[mock.package] = {}
|
|
||||||
const old = olds[mock.package]
|
|
||||||
|
|
||||||
for (const name in mock.funcs) {
|
|
||||||
//Save
|
|
||||||
old[name] = mock.package[name]
|
|
||||||
|
|
||||||
//Capture
|
|
||||||
mock.package[name] = capture(actions, name, mock.funcs[name])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Restore even when an error occurs
|
|
||||||
//Like with a failed assert
|
|
||||||
try {
|
|
||||||
await fn()
|
|
||||||
} catch (error) {
|
|
||||||
throw error
|
|
||||||
} finally {
|
|
||||||
for (const mock of mocks) {
|
|
||||||
const old = olds[mock.package]
|
|
||||||
|
|
||||||
for (const name in mock.funcs) {
|
|
||||||
//Restore
|
|
||||||
mock.package[name] = old[name]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return actions
|
|
||||||
}
|
|
||||||
|
|
||||||
export { mock }
|
|
|
@ -1,13 +1,9 @@
|
||||||
const regAssertParser = /(?<title>.*?)\n+(?<diff>.*?)\n+(?<stacktrace> (?<where>at.*?file:\/\/(?<file>.*?):(?<line>\d+):(?<column>\d+)\)?)\n.*)/s
|
const regAssertParser = /(?<title>.*?)\n+(?<diff>.*?)\n+(?<stacktrace> (?<where>at.*?file:\/\/(?<file>.*?):(?<line>\d+):(?<column>\d+)\)?)\n.*)/s
|
||||||
|
|
||||||
const regStack = /(?<=^ )at.*/gm
|
|
||||||
|
|
||||||
const stackParser = (stack) => {
|
const stackParser = (stack) => {
|
||||||
const m = stack.match(regAssertParser)
|
const m = stack.match(regAssertParser)
|
||||||
|
|
||||||
const stacks = stack.match(regStack)
|
return m.groups
|
||||||
|
|
||||||
return { ...m.groups, stacks }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { stackParser }
|
export { stackParser }
|
43
lib/suite.js
43
lib/suite.js
|
@ -1,17 +1,47 @@
|
||||||
import path from 'node:path'
|
import { readdir } from 'node:fs/promises'
|
||||||
import { walkDir } from './walkDir.js'
|
import { join } from 'node:path'
|
||||||
import { summaryreporter, totalreporter, totalerrorreporter } from 'metaltest'
|
const walkDir = async function* (dir = '.', exclude = []) {
|
||||||
|
const files = await readdir(dir, { withFileTypes: true })
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
if (exclude.includes(file.name)) continue
|
||||||
|
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
yield* walkDir(join(dir, file.name))
|
||||||
|
} else if (file.isSymbolicLink()) {
|
||||||
|
yield* walkDir(join(dir, file.name))
|
||||||
|
} else {
|
||||||
|
yield join(dir, file.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
import { dirname } from 'node:path'
|
||||||
|
const getStackAbsolutePaths = () => {
|
||||||
|
const old = Error.prepareStackTrace
|
||||||
|
Error.prepareStackTrace = (_, stack) => stack
|
||||||
|
const stack = new Error().stack
|
||||||
|
Error.prepareStackTrace = old
|
||||||
|
|
||||||
|
return stack
|
||||||
|
.map(cs => cs.getFileName())
|
||||||
|
.filter(filename => filename?.startsWith('file://'))
|
||||||
|
.map(filename => dirname(fileURLToPath(filename)))
|
||||||
|
}
|
||||||
|
|
||||||
|
import { summaryreporter, errorreporter, totalreporter } from 'metaltest'
|
||||||
const suite = async (folder = '.') => {
|
const suite = async (folder = '.') => {
|
||||||
|
const absolutePaths = getStackAbsolutePaths()
|
||||||
|
const absolutePath = absolutePaths[2]
|
||||||
const fileIgnored = []
|
const fileIgnored = []
|
||||||
|
|
||||||
const total = totalreporter()
|
const total = totalreporter()
|
||||||
const error = totalerrorreporter()
|
|
||||||
|
|
||||||
for await (const file of walkDir(folder, ['node_modules', '.git'])) {
|
for await (const file of walkDir(folder, ['node_modules', '.git'])) {
|
||||||
if (!file.endsWith('.test.js')) continue
|
if (!file.endsWith('.test.js')) continue
|
||||||
|
|
||||||
const module = path.resolve(folder, file)
|
const module = join(absolutePath, file)
|
||||||
const { test } = await import(module)
|
const { test } = await import(module)
|
||||||
|
|
||||||
if (test === undefined) {
|
if (test === undefined) {
|
||||||
|
@ -19,14 +49,13 @@ const suite = async (folder = '.') => {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
await test.run(summaryreporter(), error, total)
|
await test.run(summaryreporter(), errorreporter(), total)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const file of fileIgnored) {
|
for (const file of fileIgnored) {
|
||||||
console.log(`The file ${file} doesn't export the metaltest object`)
|
console.log(`The file ${file} doesn't export the metaltest object`)
|
||||||
}
|
}
|
||||||
|
|
||||||
error.msg()
|
|
||||||
console.log(total.msg())
|
console.log(total.msg())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
import { readdir, stat } from 'fs/promises'
|
|
||||||
import { join } from 'path/posix'
|
|
||||||
|
|
||||||
const walkDir = async function* (dir = '.', exclude = []) {
|
|
||||||
const files = await readdir(dir)
|
|
||||||
|
|
||||||
for await (const file of files) {
|
|
||||||
if (exclude.includes(file)) continue
|
|
||||||
|
|
||||||
try {
|
|
||||||
const stats = await stat(join(dir, file))
|
|
||||||
|
|
||||||
if (stats.isDirectory()) {
|
|
||||||
yield* walkDir(join(dir, file))
|
|
||||||
} else {
|
|
||||||
yield join(dir, file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (err) { } //Like file not found when symlink to a file that do not exist
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export { walkDir }
|
|
|
@ -4,7 +4,6 @@
|
||||||
"description": "Clone of baretest with reporting",
|
"description": "Clone of baretest with reporting",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": "./index.js",
|
"exports": "./index.js",
|
||||||
"bin": "./cli/suite.js",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node suite.js"
|
"test": "node suite.js"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,14 +1,37 @@
|
||||||
import { showError } from './showError.js'
|
import chalk from 'chalk'
|
||||||
|
import { log } from '../lib/log.js'
|
||||||
|
|
||||||
const errorreporter = () => {
|
const errorreporter = () => {
|
||||||
const report = {
|
const report = {
|
||||||
end: (stats) => {
|
end: (stats) => {
|
||||||
const { testFail } = stats
|
const { testFail } = stats
|
||||||
showError(testFail)
|
|
||||||
|
for (const test of testFail) {
|
||||||
|
log('\n' + chalk.redBright(test.name) + '\n')
|
||||||
|
prettyError(test.error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return report
|
return report
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import { stackParser } from '../lib/stackparser.js'
|
||||||
|
const prettyError = (error) => {
|
||||||
|
if (typeof error == 'string') {
|
||||||
|
log(chalk.yellowBright(error))
|
||||||
|
log('\n')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const stack = stackParser(error.stack)
|
||||||
|
log(chalk.yellowBright(stack.title) + '\n')
|
||||||
|
|
||||||
|
if (stack.diff != '')
|
||||||
|
log(chalk.white(stack.diff) + '\n')
|
||||||
|
|
||||||
|
if (stack.where != '')
|
||||||
|
log(chalk.gray(stack.where) + '\n')
|
||||||
|
}
|
||||||
|
|
||||||
export { errorreporter }
|
export { errorreporter }
|
|
@ -2,5 +2,4 @@ export { summaryreporter } from './summaryreporter.js'
|
||||||
export { linereporter } from './linereporter.js'
|
export { linereporter } from './linereporter.js'
|
||||||
export { totalreporter } from './totalreporter.js'
|
export { totalreporter } from './totalreporter.js'
|
||||||
export { errorreporter } from './errorreporter.js'
|
export { errorreporter } from './errorreporter.js'
|
||||||
export { totalerrorreporter } from './totalerrorreporter.js'
|
|
||||||
export { endreporter } from './endreporter.js'
|
export { endreporter } from './endreporter.js'
|
||||||
|
|
|
@ -15,7 +15,7 @@ const linereporter = () => {
|
||||||
fail: (test, e) => {
|
fail: (test, e) => {
|
||||||
const line = e.stack.match(/at.*:(.*):/)[1]
|
const line = e.stack.match(/at.*:(.*):/)[1]
|
||||||
lines.push(line)
|
lines.push(line)
|
||||||
log(chalk.redBright('✗'), test.name, `(line ${line})`)
|
log(chalk.redBright('✗'), line, test.name)
|
||||||
},
|
},
|
||||||
end: (stats) => {
|
end: (stats) => {
|
||||||
const { success, fail, testFail } = stats
|
const { success, fail, testFail } = stats
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
import chalk from 'chalk'
|
|
||||||
import { log } from '../lib/log.js'
|
|
||||||
import { stackParser } from '../lib/stackparser.js'
|
|
||||||
|
|
||||||
const showError = (testsFail) => {
|
|
||||||
for (const test of testsFail) {
|
|
||||||
log('\n' + chalk.redBright(test.name) + '\n')
|
|
||||||
prettyError(test)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const prettyError = (test) => {
|
|
||||||
const { error } = test
|
|
||||||
if (typeof error == 'string') {
|
|
||||||
log(chalk.yellowBright(error))
|
|
||||||
log('\n')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const stack = stackParser(error.stack)
|
|
||||||
log(chalk.yellowBright(stack.title) + '\n')
|
|
||||||
|
|
||||||
if (stack.diff != '')
|
|
||||||
log(chalk.white(stack.diff) + '\n')
|
|
||||||
|
|
||||||
// if (stack.where != '')
|
|
||||||
// log(chalk.gray(stack.where) + '\n')
|
|
||||||
|
|
||||||
log(chalk.gray(test.at.summary) + '\n')
|
|
||||||
log(chalk.gray(stack.stacks.join('\n')) + '\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
export { showError }
|
|
|
@ -1,16 +0,0 @@
|
||||||
import { showError } from "./showError.js"
|
|
||||||
|
|
||||||
const totalerrorreporter = () => {
|
|
||||||
const testFails = []
|
|
||||||
|
|
||||||
const report = {
|
|
||||||
end: (stats) => testFails.push(...stats.testFail),
|
|
||||||
msg: () => {
|
|
||||||
showError(testFails)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return report
|
|
||||||
}
|
|
||||||
|
|
||||||
export { totalerrorreporter }
|
|
Loading…
Reference in New Issue