UNPKG

zoroaster

Version:

A Modern Testing Framework For Node.js With Support For Test Contexts Which Can Be Reused Across Test Suites And Packages. Zoroaster Improves Developer Productivity And Experience With IDE Hints, And Test Reliability.

108 lines (98 loc) 2.96 kB
let erte = require('erte'); if (erte && erte.__esModule) erte = erte.default; const { equal } = require('assert'); let mismatch = require('mismatch'); if (mismatch && mismatch.__esModule) mismatch = mismatch.default; const { readFileSync } = require('fs'); /** * @typedef {Object} Conf * @prop {string} path Path to the mask file. * @prop {RegExp} splitRe The regular expression to split the file by. */ /** * A function to construct tests from a mask file. * @param {Conf} conf */ const getTests = (conf) => { const { path, splitRe = /^\/\/ /gm, } = conf const m = `${readFileSync(path)}` const mi = splitRe.exec(m) if (!mi) throw new Error(`${path} does not contain tests.`) const mm = m.slice(mi.index) splitRe.lastIndex = 0 const t = mm.split(splitRe).filter(a => a) const tests = t.map((test) => { const [name, total] = split(test, '\n') const [i, body] = split(total, '\n/*') const input = i.replace(/\n$/, '') const expected = mismatch( /\/\* +(.+) +\*\/(\n?)([\s\S]*?)\n\/\*\*\//g, body, ['key', 'newLine', 'value'], ).reduce((acc, { key, newLine, value }) => { const val = (!value && newLine) ? newLine : value return { ...acc, [key]: val, } }, {}) return { name, input, ...expected, } }) const lines = m.split('\n') /** * A function to be called on error in a test. * @param {string} name * @param {Error} error * @throws {Error} An error with a stack trace pointing at the line in the mask file. */ const onError = (name, error) => { const lineRe = new RegExp(`^// +${name}`) const lineNumber = lines.reduce((acc, current, index) => { if (acc) return acc // found if (lineRe.test(current)) return index + 1 return acc }, null) const err = new Error(error.message) // possibly also remember custom test stack later const stack = makeStack(error.message, name, path, lineNumber) err.stack = stack throw err } const testsWithOnError = tests.map(({ name, ...rest }) => { /** * @type {function} * @param {Error} error An error with a stack trace pointing at the line in the mask file. */ const boundOnError = onError.bind(null, name) return { ...rest, name, onError: boundOnError, } }) return testsWithOnError } const makeStack = (message, name, path, lineNumber) => { return `Error: ${message}\n at ${name} (${path}:${lineNumber}:1)` } const split = (s, del) => { const nl = s.indexOf(del) const first = s.substr(0, nl) const second = s.substr(nl + 1) return [first, second] } const assertExpected = (result, expected) => { try { equal(result, expected) } catch (err) { const e = erte(result, expected) console.log(e) // eslint-disable-line no-console throw err } } module.exports=getTests module.exports.assertExpected = assertExpected